summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/QtCore.dynlist10
-rw-r--r--src/corelib/animation/animation.pri25
-rw-r--r--src/corelib/animation/qabstractanimation.cpp1055
-rw-r--r--src/corelib/animation/qabstractanimation.h172
-rw-r--r--src/corelib/animation/qabstractanimation_p.h233
-rw-r--r--src/corelib/animation/qanimationgroup.cpp302
-rw-r--r--src/corelib/animation/qanimationgroup.h88
-rw-r--r--src/corelib/animation/qanimationgroup_p.h96
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp347
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h86
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h93
-rw-r--r--src/corelib/animation/qpauseanimation.cpp155
-rw-r--r--src/corelib/animation/qpauseanimation.h84
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp317
-rw-r--r--src/corelib/animation/qpropertyanimation.h89
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h90
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp588
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h96
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h114
-rw-r--r--src/corelib/animation/qvariantanimation.cpp701
-rw-r--r--src/corelib/animation/qvariantanimation.h130
-rw-r--r--src/corelib/animation/qvariantanimation_p.h124
-rw-r--r--src/corelib/arch/alpha/arch.pri4
-rw-r--r--src/corelib/arch/alpha/qatomic_alpha.s239
-rw-r--r--src/corelib/arch/arch.pri38
-rw-r--r--src/corelib/arch/arm/arch.pri4
-rw-r--r--src/corelib/arch/arm/qatomic_arm.cpp72
-rw-r--r--src/corelib/arch/avr32/arch.pri3
-rw-r--r--src/corelib/arch/bfin/arch.pri3
-rw-r--r--src/corelib/arch/generic/arch.pri6
-rw-r--r--src/corelib/arch/generic/qatomic_generic_unix.cpp123
-rw-r--r--src/corelib/arch/generic/qatomic_generic_windows.cpp131
-rw-r--r--src/corelib/arch/i386/arch.pri4
-rw-r--r--src/corelib/arch/i386/qatomic_i386.s103
-rw-r--r--src/corelib/arch/ia64/arch.pri4
-rw-r--r--src/corelib/arch/ia64/qatomic_ia64.s74
-rw-r--r--src/corelib/arch/integrity/arch.pri3
-rw-r--r--src/corelib/arch/macosx/arch.pri6
-rw-r--r--src/corelib/arch/macosx/qatomic32_ppc.s169
-rw-r--r--src/corelib/arch/mips/arch.pri8
-rw-r--r--src/corelib/arch/mips/qatomic_mips32.s150
-rw-r--r--src/corelib/arch/mips/qatomic_mips64.s138
-rw-r--r--src/corelib/arch/parisc/arch.pri5
-rw-r--r--src/corelib/arch/parisc/q_ldcw.s62
-rw-r--r--src/corelib/arch/parisc/qatomic_parisc.cpp88
-rw-r--r--src/corelib/arch/powerpc/arch.pri10
-rw-r--r--src/corelib/arch/powerpc/qatomic32.s525
-rw-r--r--src/corelib/arch/powerpc/qatomic64.s533
-rw-r--r--src/corelib/arch/qatomic_alpha.h642
-rw-r--r--src/corelib/arch/qatomic_arch.h101
-rw-r--r--src/corelib/arch/qatomic_arm.h76
-rw-r--r--src/corelib/arch/qatomic_armv5.h431
-rw-r--r--src/corelib/arch/qatomic_armv6.h559
-rw-r--r--src/corelib/arch/qatomic_armv7.h61
-rw-r--r--src/corelib/arch/qatomic_avr32.h252
-rw-r--r--src/corelib/arch/qatomic_bfin.h343
-rw-r--r--src/corelib/arch/qatomic_bootstrap.h99
-rw-r--r--src/corelib/arch/qatomic_generic.h282
-rw-r--r--src/corelib/arch/qatomic_i386.h361
-rw-r--r--src/corelib/arch/qatomic_ia64.h813
-rw-r--r--src/corelib/arch/qatomic_integrity.h289
-rw-r--r--src/corelib/arch/qatomic_macosx.h57
-rw-r--r--src/corelib/arch/qatomic_mips.h892
-rw-r--r--src/corelib/arch/qatomic_parisc.h305
-rw-r--r--src/corelib/arch/qatomic_powerpc.h648
-rw-r--r--src/corelib/arch/qatomic_s390.h426
-rw-r--r--src/corelib/arch/qatomic_sh.h330
-rw-r--r--src/corelib/arch/qatomic_sh4a.h537
-rw-r--r--src/corelib/arch/qatomic_sparc.h525
-rw-r--r--src/corelib/arch/qatomic_symbian.h313
-rw-r--r--src/corelib/arch/qatomic_vxworks.h318
-rw-r--r--src/corelib/arch/qatomic_windows.h496
-rw-r--r--src/corelib/arch/qatomic_windowsce.h56
-rw-r--r--src/corelib/arch/qatomic_x86_64.h363
-rw-r--r--src/corelib/arch/s390/arch.pri3
-rw-r--r--src/corelib/arch/sh/arch.pri4
-rw-r--r--src/corelib/arch/sh/qatomic_sh.cpp72
-rw-r--r--src/corelib/arch/sh4a/arch.pri3
-rw-r--r--src/corelib/arch/sparc/arch.pri10
-rw-r--r--src/corelib/arch/sparc/qatomic32.s103
-rw-r--r--src/corelib/arch/sparc/qatomic64.s327
-rw-r--r--src/corelib/arch/sparc/qatomic_sparc.cpp92
-rw-r--r--src/corelib/arch/symbian/arch.pri18
-rw-r--r--src/corelib/arch/symbian/common_p.h106
-rw-r--r--src/corelib/arch/symbian/debugfunction.cpp1143
-rw-r--r--src/corelib/arch/symbian/dla_p.h969
-rw-r--r--src/corelib/arch/symbian/heap_hybrid.cpp3346
-rw-r--r--src/corelib/arch/symbian/heap_hybrid_p.h406
-rw-r--r--src/corelib/arch/symbian/page_alloc_p.h68
-rw-r--r--src/corelib/arch/symbian/qatomic_generic_armv6.cpp472
-rw-r--r--src/corelib/arch/symbian/qatomic_symbian.cpp527
-rw-r--r--src/corelib/arch/symbian/qt_heapsetup_symbian.cpp105
-rw-r--r--src/corelib/arch/symbian/qt_hybridheap_symbian_p.h178
-rw-r--r--src/corelib/arch/symbian/slab_p.h125
-rw-r--r--src/corelib/arch/vxworks/arch.pri6
-rw-r--r--src/corelib/arch/vxworks/qatomic_ppc.s415
-rw-r--r--src/corelib/arch/windows/arch.pri3
-rw-r--r--src/corelib/arch/x86_64/arch.pri4
-rw-r--r--src/corelib/arch/x86_64/qatomic_sun.s91
-rw-r--r--src/corelib/codecs/codecs.pri59
-rw-r--r--src/corelib/codecs/codecs.qdoc532
-rw-r--r--src/corelib/codecs/qfontlaocodec.cpp123
-rw-r--r--src/corelib/codecs/qfontlaocodec_p.h78
-rw-r--r--src/corelib/codecs/qiconvcodec.cpp548
-rw-r--r--src/corelib/codecs/qiconvcodec_p.h104
-rw-r--r--src/corelib/codecs/qisciicodec.cpp285
-rw-r--r--src/corelib/codecs/qisciicodec_p.h81
-rw-r--r--src/corelib/codecs/qlatincodec.cpp244
-rw-r--r--src/corelib/codecs/qlatincodec_p.h94
-rw-r--r--src/corelib/codecs/qsimplecodec.cpp735
-rw-r--r--src/corelib/codecs/qsimplecodec_p.h91
-rw-r--r--src/corelib/codecs/qtextcodec.cpp1878
-rw-r--r--src/corelib/codecs/qtextcodec.h198
-rw-r--r--src/corelib/codecs/qtextcodec_p.h111
-rw-r--r--src/corelib/codecs/qtextcodec_symbian.cpp689
-rw-r--r--src/corelib/codecs/qtextcodecplugin.cpp161
-rw-r--r--src/corelib/codecs/qtextcodecplugin.h96
-rw-r--r--src/corelib/codecs/qtsciicodec.cpp498
-rw-r--r--src/corelib/codecs/qtsciicodec_p.h106
-rw-r--r--src/corelib/codecs/qutfcodec.cpp670
-rw-r--r--src/corelib/codecs/qutfcodec_p.h170
-rw-r--r--src/corelib/concurrent/concurrent.pri42
-rw-r--r--src/corelib/concurrent/qfuture.cpp697
-rw-r--r--src/corelib/concurrent/qfuture.h278
-rw-r--r--src/corelib/concurrent/qfutureinterface.cpp565
-rw-r--r--src/corelib/concurrent/qfutureinterface.h313
-rw-r--r--src/corelib/concurrent/qfutureinterface_p.h167
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.cpp156
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.h121
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp592
-rw-r--r--src/corelib/concurrent/qfuturewatcher.h222
-rw-r--r--src/corelib/concurrent/qfuturewatcher_p.h90
-rw-r--r--src/corelib/concurrent/qrunnable.cpp107
-rw-r--r--src/corelib/concurrent/qrunnable.h73
-rw-r--r--src/corelib/concurrent/qtconcurrentcompilertest.h65
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.cpp223
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.h128
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.cpp330
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.h736
-rw-r--r--src/corelib/concurrent/qtconcurrentfilterkernel.h351
-rw-r--r--src/corelib/concurrent/qtconcurrentfunctionwrappers.h173
-rw-r--r--src/corelib/concurrent/qtconcurrentiteratekernel.cpp199
-rw-r--r--src/corelib/concurrent/qtconcurrentiteratekernel.h340
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.cpp402
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.h780
-rw-r--r--src/corelib/concurrent/qtconcurrentmapkernel.h273
-rw-r--r--src/corelib/concurrent/qtconcurrentmedian.h130
-rw-r--r--src/corelib/concurrent/qtconcurrentreducekernel.h255
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.cpp256
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.h239
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.cpp152
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.h297
-rw-r--r--src/corelib/concurrent/qtconcurrentrunbase.h155
-rw-r--r--src/corelib/concurrent/qtconcurrentstoredfunctioncall.h1328
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.cpp299
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.h285
-rw-r--r--src/corelib/concurrent/qthreadpool.cpp651
-rw-r--r--src/corelib/concurrent/qthreadpool.h96
-rw-r--r--src/corelib/concurrent/qthreadpool_p.h107
-rw-r--r--src/corelib/corelib.pro48
-rw-r--r--src/corelib/eval.pri4
-rw-r--r--src/corelib/global/global.pri34
-rw-r--r--src/corelib/global/qconfig-dist.h50
-rw-r--r--src/corelib/global/qconfig-large.h173
-rw-r--r--src/corelib/global/qconfig-medium.h297
-rw-r--r--src/corelib/global/qconfig-minimal.h600
-rw-r--r--src/corelib/global/qconfig-nacl.h371
-rw-r--r--src/corelib/global/qconfig-small.h335
-rw-r--r--src/corelib/global/qendian.h370
-rw-r--r--src/corelib/global/qendian.qdoc154
-rw-r--r--src/corelib/global/qfeatures.h893
-rw-r--r--src/corelib/global/qfeatures.txt1487
-rw-r--r--src/corelib/global/qglobal.cpp3653
-rw-r--r--src/corelib/global/qglobal.h2767
-rw-r--r--src/corelib/global/qlibraryinfo.cpp555
-rw-r--r--src/corelib/global/qlibraryinfo.h94
-rw-r--r--src/corelib/global/qmalloc.cpp127
-rw-r--r--src/corelib/global/qnamespace.h1882
-rw-r--r--src/corelib/global/qnamespace.qdoc3008
-rw-r--r--src/corelib/global/qnumeric.cpp93
-rw-r--r--src/corelib/global/qnumeric.h71
-rw-r--r--src/corelib/global/qnumeric_p.h243
-rw-r--r--src/corelib/global/qt_pch.h67
-rw-r--r--src/corelib/global/qt_windows.h151
-rw-r--r--src/corelib/io/io.pri119
-rw-r--r--src/corelib/io/qabstractfileengine.cpp1233
-rw-r--r--src/corelib/io/qabstractfileengine.h248
-rw-r--r--src/corelib/io/qabstractfileengine_p.h81
-rw-r--r--src/corelib/io/qbuffer.cpp493
-rw-r--r--src/corelib/io/qbuffer.h112
-rw-r--r--src/corelib/io/qdatastream.cpp1325
-rw-r--r--src/corelib/io/qdatastream.h440
-rw-r--r--src/corelib/io/qdatastream_p.h72
-rw-r--r--src/corelib/io/qdataurl.cpp101
-rw-r--r--src/corelib/io/qdataurl_p.h67
-rw-r--r--src/corelib/io/qdebug.cpp307
-rw-r--r--src/corelib/io/qdebug.h300
-rw-r--r--src/corelib/io/qdir.cpp2386
-rw-r--r--src/corelib/io/qdir.h271
-rw-r--r--src/corelib/io/qdir_p.h98
-rw-r--r--src/corelib/io/qdiriterator.cpp561
-rw-r--r--src/corelib/io/qdiriterator.h97
-rw-r--r--src/corelib/io/qfile.cpp1884
-rw-r--r--src/corelib/io/qfile.h218
-rw-r--r--src/corelib/io/qfile_p.h99
-rw-r--r--src/corelib/io/qfileinfo.cpp1399
-rw-r--r--src/corelib/io/qfileinfo.h206
-rw-r--r--src/corelib/io/qfileinfo_p.h160
-rw-r--r--src/corelib/io/qfilesystemengine.cpp391
-rw-r--r--src/corelib/io/qfilesystemengine_mac.cpp48
-rw-r--r--src/corelib/io/qfilesystemengine_p.h133
-rw-r--r--src/corelib/io/qfilesystemengine_symbian.cpp408
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp660
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp1218
-rw-r--r--src/corelib/io/qfilesystementry.cpp383
-rw-r--r--src/corelib/io/qfilesystementry_p.h126
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h120
-rw-r--r--src/corelib/io/qfilesystemiterator_symbian.cpp127
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp117
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp148
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h400
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp640
-rw-r--r--src/corelib/io/qfilesystemwatcher.h89
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify.cpp461
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify_p.h131
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.cpp492
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents_p.h132
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp410
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h95
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp334
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue_p.h97
-rw-r--r--src/corelib/io/qfilesystemwatcher_p.h121
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian.cpp273
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian_p.h130
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp425
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h166
-rw-r--r--src/corelib/io/qfsfileengine.cpp965
-rw-r--r--src/corelib/io/qfsfileengine.h129
-rw-r--r--src/corelib/io/qfsfileengine_iterator.cpp106
-rw-r--r--src/corelib/io/qfsfileengine_iterator_p.h91
-rw-r--r--src/corelib/io/qfsfileengine_p.h202
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp1108
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp1008
-rw-r--r--src/corelib/io/qiodevice.cpp1846
-rw-r--r--src/corelib/io/qiodevice.h254
-rw-r--r--src/corelib/io/qiodevice_p.h245
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp545
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h190
-rw-r--r--src/corelib/io/qprocess.cpp2371
-rw-r--r--src/corelib/io/qprocess.h245
-rw-r--r--src/corelib/io/qprocess_p.h260
-rw-r--r--src/corelib/io/qprocess_symbian.cpp1067
-rw-r--r--src/corelib/io/qprocess_unix.cpp1297
-rw-r--r--src/corelib/io/qprocess_win.cpp855
-rw-r--r--src/corelib/io/qresource.cpp1496
-rw-r--r--src/corelib/io/qresource.h104
-rw-r--r--src/corelib/io/qresource_iterator.cpp90
-rw-r--r--src/corelib/io/qresource_iterator_p.h80
-rw-r--r--src/corelib/io/qresource_p.h119
-rw-r--r--src/corelib/io/qsettings.cpp3843
-rw-r--r--src/corelib/io/qsettings.h313
-rw-r--r--src/corelib/io/qsettings_mac.cpp654
-rw-r--r--src/corelib/io/qsettings_p.h316
-rw-r--r--src/corelib/io/qsettings_win.cpp847
-rw-r--r--src/corelib/io/qtemporaryfile.cpp713
-rw-r--r--src/corelib/io/qtemporaryfile.h108
-rw-r--r--src/corelib/io/qtextstream.cpp3413
-rw-r--r--src/corelib/io/qtextstream.h377
-rw-r--r--src/corelib/io/qurl.cpp6544
-rw-r--r--src/corelib/io/qurl.h302
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp171
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h162
-rw-r--r--src/corelib/kernel/kernel.pri164
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp556
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h107
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher_p.h79
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp3454
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h410
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h176
-rw-r--r--src/corelib/kernel/qbasictimer.cpp138
-rw-r--r--src/corelib/kernel/qbasictimer.h74
-rw-r--r--src/corelib/kernel/qcore_mac.cpp82
-rw-r--r--src/corelib/kernel/qcore_mac_p.h163
-rw-r--r--src/corelib/kernel/qcore_symbian_p.cpp317
-rw-r--r--src/corelib/kernel/qcore_symbian_p.h282
-rw-r--r--src/corelib/kernel/qcore_unix.cpp106
-rw-r--r--src/corelib/kernel/qcore_unix_p.h333
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2730
-rw-r--r--src/corelib/kernel/qcoreapplication.h297
-rw-r--r--src/corelib/kernel/qcoreapplication_mac.cpp66
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h146
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp1060
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h171
-rw-r--r--src/corelib/kernel/qcoreevent.cpp612
-rw-r--r--src/corelib/kernel/qcoreevent.h396
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp53
-rw-r--r--src/corelib/kernel/qcoreglobaldata_p.h72
-rw-r--r--src/corelib/kernel/qcrashhandler.cpp423
-rw-r--r--src/corelib/kernel/qcrashhandler_p.h81
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp601
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h119
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp1310
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h327
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp979
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h208
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp1158
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h110
-rw-r--r--src/corelib/kernel/qeventloop.cpp329
-rw-r--r--src/corelib/kernel/qeventloop.h101
-rw-r--r--src/corelib/kernel/qfunctions_nacl.cpp156
-rw-r--r--src/corelib/kernel/qfunctions_nacl.h97
-rw-r--r--src/corelib/kernel/qfunctions_p.h79
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.cpp202
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.h153
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp451
-rw-r--r--src/corelib/kernel/qfunctions_wince.h397
-rw-r--r--src/corelib/kernel/qmath.cpp305
-rw-r--r--src/corelib/kernel/qmath.h288
-rw-r--r--src/corelib/kernel/qmath.qdoc155
-rw-r--r--src/corelib/kernel/qmetaobject.cpp2778
-rw-r--r--src/corelib/kernel/qmetaobject.h242
-rw-r--r--src/corelib/kernel/qmetaobject_p.h326
-rw-r--r--src/corelib/kernel/qmetatype.cpp1509
-rw-r--r--src/corelib/kernel/qmetatype.h416
-rw-r--r--src/corelib/kernel/qmimedata.cpp627
-rw-r--r--src/corelib/kernel/qmimedata.h104
-rw-r--r--src/corelib/kernel/qobject.cpp4310
-rw-r--r--src/corelib/kernel/qobject.h411
-rw-r--r--src/corelib/kernel/qobject_p.h305
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.cpp148
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.h78
-rw-r--r--src/corelib/kernel/qobjectdefs.h506
-rw-r--r--src/corelib/kernel/qpointer.cpp270
-rw-r--r--src/corelib/kernel/qpointer.h168
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp612
-rw-r--r--src/corelib/kernel/qsharedmemory.h121
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h179
-rw-r--r--src/corelib/kernel/qsharedmemory_symbian.cpp173
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp302
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp195
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp321
-rw-r--r--src/corelib/kernel/qsignalmapper.h100
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp323
-rw-r--r--src/corelib/kernel/qsocketnotifier.h93
-rw-r--r--src/corelib/kernel/qsystemerror.cpp220
-rw-r--r--src/corelib/kernel/qsystemerror_p.h107
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp363
-rw-r--r--src/corelib/kernel/qsystemsemaphore.h103
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h118
-rw-r--r--src/corelib/kernel/qsystemsemaphore_symbian.cpp138
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp238
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp135
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp571
-rw-r--r--src/corelib/kernel/qtimer.cpp394
-rw-r--r--src/corelib/kernel/qtimer.h116
-rw-r--r--src/corelib/kernel/qtranslator.cpp979
-rw-r--r--src/corelib/kernel/qtranslator.h104
-rw-r--r--src/corelib/kernel/qtranslator_p.h79
-rw-r--r--src/corelib/kernel/qvariant.cpp3237
-rw-r--r--src/corelib/kernel/qvariant.h618
-rw-r--r--src/corelib/kernel/qvariant_p.h153
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.cpp134
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h94
-rw-r--r--src/corelib/plugin/plugin.pri35
-rw-r--r--src/corelib/plugin/qelfparser_p.cpp240
-rw-r--r--src/corelib/plugin/qelfparser_p.h108
-rw-r--r--src/corelib/plugin/qfactoryinterface.h67
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp269
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h93
-rw-r--r--src/corelib/plugin/qlibrary.cpp1295
-rw-r--r--src/corelib/plugin/qlibrary.h120
-rw-r--r--src/corelib/plugin/qlibrary_p.h124
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp305
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp131
-rw-r--r--src/corelib/plugin/qplugin.h152
-rw-r--r--src/corelib/plugin/qplugin.qdoc121
-rw-r--r--src/corelib/plugin/qpluginloader.cpp434
-rw-r--r--src/corelib/plugin/qpluginloader.h100
-rw-r--r--src/corelib/plugin/qsystemlibrary.cpp141
-rw-r--r--src/corelib/plugin/qsystemlibrary_p.h110
-rw-r--r--src/corelib/plugin/quuid.cpp676
-rw-r--r--src/corelib/plugin/quuid.h190
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp215
-rw-r--r--src/corelib/statemachine/qabstractstate.h97
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h95
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp335
-rw-r--r--src/corelib/statemachine/qabstracttransition.h118
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h92
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp260
-rw-r--r--src/corelib/statemachine/qeventtransition.h95
-rw-r--r--src/corelib/statemachine/qeventtransition_p.h79
-rw-r--r--src/corelib/statemachine/qfinalstate.cpp140
-rw-r--r--src/corelib/statemachine/qfinalstate.h80
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp230
-rw-r--r--src/corelib/statemachine/qhistorystate.h95
-rw-r--r--src/corelib/statemachine/qhistorystate_p.h79
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h78
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp264
-rw-r--r--src/corelib/statemachine/qsignaltransition.h90
-rw-r--r--src/corelib/statemachine/qsignaltransition_p.h82
-rw-r--r--src/corelib/statemachine/qstate.cpp526
-rw-r--r--src/corelib/statemachine/qstate.h122
-rw-r--r--src/corelib/statemachine/qstate_p.h112
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp2401
-rw-r--r--src/corelib/statemachine/qstatemachine.h196
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h250
-rw-r--r--src/corelib/statemachine/statemachine.pri28
-rw-r--r--src/corelib/thread/qatomic.cpp1125
-rw-r--r--src/corelib/thread/qatomic.h227
-rw-r--r--src/corelib/thread/qbasicatomic.h230
-rw-r--r--src/corelib/thread/qmutex.cpp515
-rw-r--r--src/corelib/thread/qmutex.h248
-rw-r--r--src/corelib/thread/qmutex_p.h107
-rw-r--r--src/corelib/thread/qmutex_symbian.cpp101
-rw-r--r--src/corelib/thread/qmutex_unix.cpp209
-rw-r--r--src/corelib/thread/qmutex_win.cpp75
-rw-r--r--src/corelib/thread/qmutexpool.cpp156
-rw-r--r--src/corelib/thread/qmutexpool_p.h93
-rw-r--r--src/corelib/thread/qorderedmutexlocker_p.h121
-rw-r--r--src/corelib/thread/qreadwritelock.cpp581
-rw-r--r--src/corelib/thread/qreadwritelock.h239
-rw-r--r--src/corelib/thread/qreadwritelock_p.h87
-rw-r--r--src/corelib/thread/qsemaphore.cpp240
-rw-r--r--src/corelib/thread/qsemaphore.h83
-rw-r--r--src/corelib/thread/qthread.cpp772
-rw-r--r--src/corelib/thread/qthread.h166
-rw-r--r--src/corelib/thread/qthread_p.h237
-rw-r--r--src/corelib/thread/qthread_symbian.cpp609
-rw-r--r--src/corelib/thread/qthread_unix.cpp716
-rw-r--r--src/corelib/thread/qthread_win.cpp637
-rw-r--r--src/corelib/thread/qthreadstorage.cpp329
-rw-r--r--src/corelib/thread/qthreadstorage.h164
-rw-r--r--src/corelib/thread/qwaitcondition.h105
-rw-r--r--src/corelib/thread/qwaitcondition.qdoc173
-rw-r--r--src/corelib/thread/qwaitcondition_symbian.cpp196
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp192
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp233
-rw-r--r--src/corelib/thread/thread.pri41
-rw-r--r--src/corelib/tools/qalgorithms.h526
-rw-r--r--src/corelib/tools/qalgorithms.qdoc637
-rw-r--r--src/corelib/tools/qbitarray.cpp738
-rw-r--r--src/corelib/tools/qbitarray.h180
-rw-r--r--src/corelib/tools/qbytearray.cpp4394
-rw-r--r--src/corelib/tools/qbytearray.h622
-rw-r--r--src/corelib/tools/qbytearraymatcher.cpp324
-rw-r--r--src/corelib/tools/qbytearraymatcher.h103
-rw-r--r--src/corelib/tools/qbytedata_p.h220
-rw-r--r--src/corelib/tools/qcache.h217
-rw-r--r--src/corelib/tools/qcache.qdoc230
-rw-r--r--src/corelib/tools/qchar.cpp1654
-rw-r--r--src/corelib/tools/qchar.h404
-rw-r--r--src/corelib/tools/qcontainerfwd.h71
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp474
-rw-r--r--src/corelib/tools/qcontiguouscache.h466
-rw-r--r--src/corelib/tools/qcryptographichash.cpp200
-rw-r--r--src/corelib/tools/qcryptographichash.h84
-rw-r--r--src/corelib/tools/qdatetime.cpp5881
-rw-r--r--src/corelib/tools/qdatetime.h340
-rw-r--r--src/corelib/tools/qdatetime_p.h289
-rw-r--r--src/corelib/tools/qeasingcurve.cpp937
-rw-r--r--src/corelib/tools/qeasingcurve.h125
-rw-r--r--src/corelib/tools/qelapsedtimer.cpp264
-rw-r--r--src/corelib/tools/qelapsedtimer.h95
-rw-r--r--src/corelib/tools/qelapsedtimer_generic.cpp194
-rw-r--r--src/corelib/tools/qelapsedtimer_mac.cpp132
-rw-r--r--src/corelib/tools/qelapsedtimer_symbian.cpp131
-rw-r--r--src/corelib/tools/qelapsedtimer_unix.cpp209
-rw-r--r--src/corelib/tools/qelapsedtimer_win.cpp183
-rw-r--r--src/corelib/tools/qharfbuzz.cpp140
-rw-r--r--src/corelib/tools/qharfbuzz_p.h77
-rw-r--r--src/corelib/tools/qhash.cpp1914
-rw-r--r--src/corelib/tools/qhash.h1043
-rw-r--r--src/corelib/tools/qiterator.h202
-rw-r--r--src/corelib/tools/qiterator.qdoc1417
-rw-r--r--src/corelib/tools/qline.cpp867
-rw-r--r--src/corelib/tools/qline.h424
-rw-r--r--src/corelib/tools/qlinkedlist.cpp1170
-rw-r--r--src/corelib/tools/qlinkedlist.h525
-rw-r--r--src/corelib/tools/qlist.cpp1919
-rw-r--r--src/corelib/tools/qlist.h900
-rw-r--r--src/corelib/tools/qlocale.cpp3281
-rw-r--r--src/corelib/tools/qlocale.h818
-rw-r--r--src/corelib/tools/qlocale.qdoc905
-rw-r--r--src/corelib/tools/qlocale_data_p.h6518
-rw-r--r--src/corelib/tools/qlocale_icu.cpp224
-rw-r--r--src/corelib/tools/qlocale_mac.mm463
-rw-r--r--src/corelib/tools/qlocale_p.h283
-rw-r--r--src/corelib/tools/qlocale_symbian.cpp929
-rw-r--r--src/corelib/tools/qlocale_tools.cpp2961
-rw-r--r--src/corelib/tools/qlocale_tools_p.h122
-rw-r--r--src/corelib/tools/qlocale_unix.cpp226
-rw-r--r--src/corelib/tools/qlocale_win.cpp988
-rw-r--r--src/corelib/tools/qmap.cpp1646
-rw-r--r--src/corelib/tools/qmap.h1090
-rw-r--r--src/corelib/tools/qmargins.cpp167
-rw-r--r--src/corelib/tools/qmargins.h147
-rw-r--r--src/corelib/tools/qpair.h127
-rw-r--r--src/corelib/tools/qpair.qdoc215
-rw-r--r--src/corelib/tools/qpodlist_p.h115
-rw-r--r--src/corelib/tools/qpoint.cpp741
-rw-r--r--src/corelib/tools/qpoint.h389
-rw-r--r--src/corelib/tools/qqueue.cpp137
-rw-r--r--src/corelib/tools/qqueue.h70
-rw-r--r--src/corelib/tools/qrect.cpp2465
-rw-r--r--src/corelib/tools/qrect.h858
-rw-r--r--src/corelib/tools/qregexp.cpp4503
-rw-r--r--src/corelib/tools/qregexp.h169
-rw-r--r--src/corelib/tools/qringbuffer_p.h451
-rw-r--r--src/corelib/tools/qscopedpointer.cpp283
-rw-r--r--src/corelib/tools/qscopedpointer.h245
-rw-r--r--src/corelib/tools/qscopedpointer_p.h151
-rw-r--r--src/corelib/tools/qscopedvaluerollback.cpp84
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h81
-rw-r--r--src/corelib/tools/qset.h371
-rw-r--r--src/corelib/tools/qset.qdoc946
-rw-r--r--src/corelib/tools/qshareddata.cpp568
-rw-r--r--src/corelib/tools/qshareddata.h286
-rw-r--r--src/corelib/tools/qsharedpointer.cpp1501
-rw-r--r--src/corelib/tools/qsharedpointer.h152
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h898
-rw-r--r--src/corelib/tools/qsimd.cpp413
-rw-r--r--src/corelib/tools/qsimd_p.h172
-rw-r--r--src/corelib/tools/qsize.cpp828
-rw-r--r--src/corelib/tools/qsize.h368
-rw-r--r--src/corelib/tools/qstack.cpp137
-rw-r--r--src/corelib/tools/qstack.h83
-rw-r--r--src/corelib/tools/qstring.cpp9129
-rw-r--r--src/corelib/tools/qstring.h1295
-rw-r--r--src/corelib/tools/qstringbuilder.cpp193
-rw-r--r--src/corelib/tools/qstringbuilder.h455
-rw-r--r--src/corelib/tools/qstringlist.cpp692
-rw-r--r--src/corelib/tools/qstringlist.h262
-rw-r--r--src/corelib/tools/qstringmatcher.cpp322
-rw-r--r--src/corelib/tools/qstringmatcher.h103
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp479
-rw-r--r--src/corelib/tools/qtextboundaryfinder.h114
-rw-r--r--src/corelib/tools/qtimeline.cpp787
-rw-r--r--src/corelib/tools/qtimeline.h147
-rw-r--r--src/corelib/tools/qtools_p.h65
-rw-r--r--src/corelib/tools/qunicodetables.cpp9486
-rw-r--r--src/corelib/tools/qunicodetables_p.h232
-rw-r--r--src/corelib/tools/qvarlengtharray.h404
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc547
-rw-r--r--src/corelib/tools/qvector.cpp1017
-rw-r--r--src/corelib/tools/qvector.h829
-rw-r--r--src/corelib/tools/qvsnprintf.cpp133
-rw-r--r--src/corelib/tools/tools.pri124
-rw-r--r--src/corelib/xml/.gitignore1
-rwxr-xr-xsrc/corelib/xml/make-parser.sh53
-rw-r--r--src/corelib/xml/qxmlstream.cpp3954
-rw-r--r--src/corelib/xml/qxmlstream.g1847
-rw-r--r--src/corelib/xml/qxmlstream.h491
-rw-r--r--src/corelib/xml/qxmlstream_p.h1965
-rw-r--r--src/corelib/xml/qxmlutils.cpp390
-rw-r--r--src/corelib/xml/qxmlutils_p.h92
-rw-r--r--src/corelib/xml/xml.pri10
556 files changed, 282993 insertions, 0 deletions
diff --git a/src/corelib/QtCore.dynlist b/src/corelib/QtCore.dynlist
new file mode 100644
index 0000000000..51e4c5a34e
--- /dev/null
+++ b/src/corelib/QtCore.dynlist
@@ -0,0 +1,10 @@
+{
+ 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
new file mode 100644
index 0000000000..cb7850c7d6
--- /dev/null
+++ b/src/corelib/animation/animation.pri
@@ -0,0 +1,25 @@
+# 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
new file mode 100644
index 0000000000..602cf8a6fd
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -0,0 +1,1055 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAbstractAnimation
+ \ingroup animation
+ \brief The QAbstractAnimation class is the base of all animations.
+ \since 4.6
+
+ The class defines the functions for the functionality shared by
+ all animations. By inheriting this class, you can create custom
+ animations that plug into the rest of the animation framework.
+
+ The progress of an animation is given by its current time
+ (currentLoopTime()), which is measured in milliseconds from the start
+ of the animation (0) to its end (duration()). The value is updated
+ automatically while the animation is running. It can also be set
+ directly with setCurrentTime().
+
+ At any point an animation is in one of three states:
+ \l{QAbstractAnimation::}{Running},
+ \l{QAbstractAnimation::}{Stopped}, or
+ \l{QAbstractAnimation::}{Paused}--as defined by the
+ \l{QAbstractAnimation::}{State} enum. The current state can be
+ changed by calling start(), stop(), pause(), or resume(). An
+ animation will always reset its \l{currentTime()}{current time}
+ when it is started. If paused, it will continue with the same
+ current time when resumed. When an animation is stopped, it cannot
+ be resumed, but will keep its current time (until started again).
+ QAbstractAnimation will emit stateChanged() whenever its state
+ changes.
+
+ An animation can loop any number of times by setting the loopCount
+ property. When an animation's current time reaches its duration(),
+ it will reset the current time and keep running. A loop count of 1
+ (the default value) means that the animation will run one time.
+ Note that a duration of -1 means that the animation will run until
+ stopped; the current time will increase indefinitely. When the
+ current time equals duration() and the animation is in its
+ final loop, the \l{QAbstractAnimation::}{Stopped} state is
+ entered, and the finished() signal is emitted.
+
+ QAbstractAnimation provides pure virtual functions used by
+ subclasses to track the progress of the animation: duration() and
+ updateCurrentTime(). The duration() function lets you report a
+ duration for the animation (as discussed above). The animation
+ framework calls updateCurrentTime() when current time has changed.
+ By reimplementing this function, you can track the animation
+ progress. Note that neither the interval between calls nor the
+ number of calls to this function are defined; though, it will
+ normally be 60 updates per second.
+
+ By reimplementing updateState(), you can track the animation's
+ state changes, which is particularly useful for animations that
+ are not driven by time.
+
+ \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+/*!
+ \enum QAbstractAnimation::DeletionPolicy
+
+ \value KeepWhenStopped The animation will not be deleted when stopped.
+ \value DeleteWhenStopped The animation will be automatically deleted when
+ stopped.
+*/
+
+/*!
+ \fn QAbstractAnimation::finished()
+
+ QAbstractAnimation emits this signal after the animation has stopped and
+ has reached the end.
+
+ This signal is emitted after stateChanged().
+
+ \sa stateChanged()
+*/
+
+/*!
+ \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+
+ QAbstractAnimation emits this signal whenever the state of the animation has
+ changed from \a oldState to \a newState. This signal is emitted after the virtual
+ updateState() function is called.
+
+ \sa updateState()
+*/
+
+/*!
+ \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
+
+ QAbstractAnimation emits this signal whenever the current loop
+ changes. \a currentLoop is the current loop.
+
+ \sa currentLoop(), loopCount()
+*/
+
+/*!
+ \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
+
+ QAbstractAnimation emits this signal whenever the direction has been
+ changed. \a newDirection is the new direction.
+
+ \sa direction
+*/
+
+#include "qabstractanimation.h"
+#include "qanimationgroup.h"
+
+#include <QtCore/qdebug.h>
+
+#include "qabstractanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#ifndef QT_NO_ANIMATION
+
+#define DEFAULT_TIMER_INTERVAL 16
+#define STARTSTOP_TIMER_DELAY 0
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_THREAD
+Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
+#endif
+
+QUnifiedTimer::QUnifiedTimer() :
+ QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
+ currentAnimationIdx(0), insideTick(false), consistentTiming(false), slowMode(false),
+ slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0)
+{
+ time.invalidate();
+ driver = &defaultDriver;
+}
+
+
+QUnifiedTimer *QUnifiedTimer::instance(bool create)
+{
+ QUnifiedTimer *inst;
+#ifndef QT_NO_THREAD
+ if (create && !unifiedTimer()->hasLocalData()) {
+ inst = new QUnifiedTimer;
+ unifiedTimer()->setLocalData(inst);
+ } else {
+ inst = unifiedTimer()->localData();
+ }
+#else
+ static QUnifiedTimer unifiedTimer;
+ inst = &unifiedTimer;
+#endif
+ return inst;
+}
+
+QUnifiedTimer *QUnifiedTimer::instance()
+{
+ return instance(true);
+}
+
+void QUnifiedTimer::ensureTimerUpdate()
+{
+ QUnifiedTimer *inst = QUnifiedTimer::instance(false);
+ if (inst && inst->isPauseTimerActive)
+ inst->updateAnimationsTime();
+}
+
+void QUnifiedTimer::updateAnimationsTime()
+{
+ //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
+ if(insideTick)
+ return;
+
+ qint64 totalElapsed = time.elapsed();
+ // ignore consistentTiming in case the pause timer is active
+ int delta = (consistentTiming && !isPauseTimerActive) ?
+ timingInterval : totalElapsed - lastTick;
+ if (slowMode) {
+ if (slowdownFactor > 0)
+ delta = qRound(delta / slowdownFactor);
+ else
+ delta = 0;
+ }
+
+ lastTick = totalElapsed;
+
+ //we make sure we only call update time if the time has actually changed
+ //it might happen in some cases that the time doesn't change because events are delayed
+ //when the CPU load is high
+ if (delta) {
+ insideTick = true;
+ for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
+ QAbstractAnimation *animation = animations.at(currentAnimationIdx);
+ int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
+ animation->setCurrentTime(elapsed);
+ }
+ insideTick = false;
+ currentAnimationIdx = 0;
+ }
+}
+
+void QUnifiedTimer::updateAnimationTimer()
+{
+ QUnifiedTimer *inst = QUnifiedTimer::instance(false);
+ if (inst)
+ inst->restartAnimationTimer();
+}
+
+void QUnifiedTimer::restartAnimationTimer()
+{
+ if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) {
+ int closestTimeToFinish = closestPauseAnimationTimeToFinish();
+ if (closestTimeToFinish < 0) {
+ qDebug() << runningPauseAnimations;
+ qDebug() << closestPauseAnimationTimeToFinish();
+ }
+ driver->stop();
+ animationTimer.start(closestTimeToFinish, this);
+ isPauseTimerActive = true;
+ } else if (!driver->isRunning() || isPauseTimerActive) {
+ driver->start();
+ isPauseTimerActive = false;
+ }
+}
+
+void QUnifiedTimer::setTimingInterval(int interval)
+{
+ timingInterval = interval;
+
+ if (driver->isRunning() && !isPauseTimerActive) {
+ //we changed the timing interval
+ driver->stop();
+ driver->start();
+ }
+}
+
+
+void QUnifiedTimer::timerEvent(QTimerEvent *event)
+{
+ //in the case of consistent timing we make sure the orders in which events come is always the same
+ //for that purpose we do as if the startstoptimer would always fire before the animation timer
+ if ((consistentTiming && startStopAnimationTimer.isActive()) ||
+ event->timerId() == startStopAnimationTimer.timerId()) {
+ startStopAnimationTimer.stop();
+
+ //we transfer the waiting animations into the "really running" state
+ animations += animationsToStart;
+ animationsToStart.clear();
+ if (animations.isEmpty()) {
+ animationTimer.stop();
+ isPauseTimerActive = false;
+ // invalidate the start reference time
+ time.invalidate();
+ } else {
+ restartAnimationTimer();
+ if (!time.isValid()) {
+ lastTick = 0;
+ time.start();
+ }
+ }
+ }
+
+ if (event->timerId() == animationTimer.timerId()) {
+ // update current time on all top level animations
+ updateAnimationsTime();
+ restartAnimationTimer();
+ }
+}
+
+void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
+{
+ QUnifiedTimer *inst = instance(true); //we create the instance if needed
+ inst->registerRunningAnimation(animation);
+ if (isTopLevel) {
+ Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
+ QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
+ inst->animationsToStart << animation;
+ if (!inst->startStopAnimationTimer.isActive())
+ inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
+ }
+}
+
+void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
+{
+ QUnifiedTimer *inst = QUnifiedTimer::instance(false);
+ if (inst) {
+ //at this point the unified timer should have been created
+ //but it might also have been already destroyed in case the application is shutting down
+
+ inst->unregisterRunningAnimation(animation);
+
+ if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
+ return;
+
+ int idx = inst->animations.indexOf(animation);
+ if (idx != -1) {
+ inst->animations.removeAt(idx);
+ // this is needed if we unregister an animation while its running
+ if (idx <= inst->currentAnimationIdx)
+ --inst->currentAnimationIdx;
+
+ if (inst->animations.isEmpty() && !inst->startStopAnimationTimer.isActive())
+ inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
+ } else {
+ inst->animationsToStart.removeOne(animation);
+ }
+ }
+ QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
+}
+
+void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation)
+{
+ if (QAbstractAnimationPrivate::get(animation)->isGroup)
+ return;
+
+ if (QAbstractAnimationPrivate::get(animation)->isPause) {
+ runningPauseAnimations << animation;
+ } else
+ runningLeafAnimations++;
+}
+
+void QUnifiedTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
+{
+ if (QAbstractAnimationPrivate::get(animation)->isGroup)
+ return;
+
+ if (QAbstractAnimationPrivate::get(animation)->isPause)
+ runningPauseAnimations.removeOne(animation);
+ else
+ runningLeafAnimations--;
+ Q_ASSERT(runningLeafAnimations >= 0);
+}
+
+int QUnifiedTimer::closestPauseAnimationTimeToFinish()
+{
+ int closestTimeToFinish = INT_MAX;
+ for (int i = 0; i < runningPauseAnimations.size(); ++i) {
+ QAbstractAnimation *animation = runningPauseAnimations.at(i);
+ int timeToFinish;
+
+ if (animation->direction() == QAbstractAnimation::Forward)
+ timeToFinish = animation->duration() - animation->currentLoopTime();
+ else
+ timeToFinish = animation->currentLoopTime();
+
+ if (timeToFinish < closestTimeToFinish)
+ closestTimeToFinish = timeToFinish;
+ }
+ return closestTimeToFinish;
+}
+
+void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
+{
+ if (driver->isRunning()) {
+ qWarning("QUnifiedTimer: Cannot change animation driver while animations are running");
+ return;
+ }
+
+ if (driver && driver != &defaultDriver)
+ delete driver;
+
+ driver = d;
+}
+
+/*!
+ \class QAnimationDriver
+
+ \brief The QAnimationDriver class is used to exchange the mechanism that drives animations.
+
+ The default animation system is driven by a timer that fires at regular intervals.
+ In some scenarios, it is better to drive the animation based on other synchronization
+ mechanisms, such as the vertical refresh rate of the screen.
+
+ \internal
+ */
+
+QAnimationDriver::QAnimationDriver(QObject *parent)
+ : QObject(*(new QAnimationDriverPrivate), parent)
+{
+}
+
+QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+
+/*!
+ Advances the animation based on the current time. This function should
+ be continuously called by the driver while the animation is running.
+
+ \internal
+ */
+void QAnimationDriver::advance()
+{
+ QUnifiedTimer *instance = QUnifiedTimer::instance();
+
+ // update current time on all top level animations
+ instance->updateAnimationsTime();
+ instance->restartAnimationTimer();
+}
+
+
+/*!
+ Installs this animation driver. The animation driver is thread local and
+ will only apply for the thread its installed in.
+
+ \internal
+ */
+void QAnimationDriver::install()
+{
+ QUnifiedTimer *timer = QUnifiedTimer::instance(true);
+ timer->installAnimationDriver(this);
+}
+
+bool QAnimationDriver::isRunning() const
+{
+ return d_func()->running;
+}
+
+
+void QAnimationDriver::start()
+{
+ Q_D(QAnimationDriver);
+ if (!d->running) {
+ started();
+ d->running = true;
+ }
+}
+
+
+void QAnimationDriver::stop()
+{
+ Q_D(QAnimationDriver);
+ if (d->running) {
+ stopped();
+ d->running = false;
+ }
+}
+
+/*!
+ \fn QAnimationDriver::started()
+
+ This function is called by the animation framework to notify the driver
+ that it should start running.
+
+ \internal
+ */
+
+/*!
+ \fn QAnimationDriver::stopped()
+
+ This function is called by the animation framework to notify the driver
+ that it should stop running.
+
+ \internal
+ */
+
+/*!
+ The default animation driver just spins the timer...
+ */
+QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
+ : QAnimationDriver(0), m_unified_timer(timer)
+{
+}
+
+void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
+{
+ Q_ASSERT(e->timerId() == m_timer.timerId());
+ Q_UNUSED(e); // if the assertions are disabled
+ advance();
+}
+
+void QDefaultAnimationDriver::started()
+{
+ m_timer.start(m_unified_timer->timingInterval, this);
+}
+
+void QDefaultAnimationDriver::stopped()
+{
+ m_timer.stop();
+}
+
+
+
+void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
+{
+ Q_Q(QAbstractAnimation);
+ if (state == newState)
+ return;
+
+ if (loopCount == 0)
+ return;
+
+ QAbstractAnimation::State oldState = state;
+ int oldCurrentTime = currentTime;
+ int oldCurrentLoop = currentLoop;
+ QAbstractAnimation::Direction oldDirection = direction;
+
+ // check if we should Rewind
+ if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
+ && oldState == QAbstractAnimation::Stopped) {
+ //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());
+ }
+
+ state = newState;
+ QWeakPointer<QAbstractAnimation> guard(q);
+
+ //(un)registration of the animation must always happen before calls to
+ //virtual function (updateState) to ensure a correct state of the timer
+ bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
+ if (oldState == QAbstractAnimation::Running) {
+ if (newState == QAbstractAnimation::Paused && hasRegisteredTimer)
+ QUnifiedTimer::ensureTimerUpdate();
+ //the animation, is not running any more
+ QUnifiedTimer::unregisterAnimation(q);
+ } else if (newState == QAbstractAnimation::Running) {
+ QUnifiedTimer::registerAnimation(q, isTopLevel);
+ }
+
+ q->updateState(newState, oldState);
+ if (!guard || newState != state) //this is to be safe if updateState changes the state
+ return;
+
+ // Notify state change
+ emit q->stateChanged(newState, oldState);
+ if (!guard || newState != state) //this is to be safe if updateState changes the state
+ return;
+
+ switch (state) {
+ case QAbstractAnimation::Paused:
+ break;
+ case QAbstractAnimation::Running:
+ {
+
+ // this ensures that the value is updated now that the animation is running
+ if (oldState == QAbstractAnimation::Stopped) {
+ if (isTopLevel) {
+ // currentTime needs to be updated if pauseTimer is active
+ QUnifiedTimer::ensureTimerUpdate();
+ q->setCurrentTime(totalCurrentTime);
+ }
+ }
+ }
+ break;
+ case QAbstractAnimation::Stopped:
+ // Leave running state.
+ int dura = q->duration();
+
+ if (deleteWhenStopped)
+ q->deleteLater();
+
+ if (dura == -1 || loopCount < 0
+ || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
+ || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
+ emit q->finished();
+ }
+ break;
+ }
+}
+
+/*!
+ Constructs the QAbstractAnimation base class, and passes \a parent to
+ QObject's constructor.
+
+ \sa QVariantAnimation, QAnimationGroup
+*/
+QAbstractAnimation::QAbstractAnimation(QObject *parent)
+ : QObject(*new QAbstractAnimationPrivate, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ \internal
+*/
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : QObject(dd, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ Stops the animation if it's running, then destroys the
+ QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
+ automatically removed before it's destroyed.
+*/
+QAbstractAnimation::~QAbstractAnimation()
+{
+ Q_D(QAbstractAnimation);
+ //we can't call stop here. Otherwise we get pure virtual calls
+ if (d->state != Stopped) {
+ QAbstractAnimation::State oldState = d->state;
+ d->state = Stopped;
+ emit stateChanged(oldState, d->state);
+ if (oldState == QAbstractAnimation::Running)
+ QUnifiedTimer::unregisterAnimation(this);
+ }
+}
+
+/*!
+ \property QAbstractAnimation::state
+ \brief state of the animation.
+
+ This property describes the current state of the animation. When the
+ animation state changes, QAbstractAnimation emits the stateChanged()
+ signal.
+*/
+QAbstractAnimation::State QAbstractAnimation::state() 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 0.
+
+ \sa QAnimationGroup::addAnimation()
+*/
+QAnimationGroup *QAbstractAnimation::group() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->group;
+}
+
+/*!
+ \enum QAbstractAnimation::State
+
+ This enum describes the state of the animation.
+
+ \value Stopped The animation is not running. This is the initial state
+ of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
+ time remain unchanged until either setCurrentTime() is
+ called, or the animation is started by calling start().
+
+ \value Paused The animation is paused (i.e., temporarily
+ suspended). Calling resume() will resume animation activity.
+
+ \value Running The animation is running. While control is in the event
+ loop, QAbstractAnimation will update its current time at regular intervals,
+ calling updateCurrentTime() when appropriate.
+
+ \sa state(), stateChanged()
+*/
+
+/*!
+ \enum QAbstractAnimation::Direction
+
+ This enum describes the direction of the animation when in \l Running state.
+
+ \value Forward The current time of the animation increases with time (i.e.,
+ moves from 0 and towards the end / duration).
+
+ \value Backward The current time of the animation decreases with time (i.e.,
+ moves from the end / duration and towards 0).
+
+ \sa direction
+*/
+
+/*!
+ \property QAbstractAnimation::direction
+ \brief the direction of the animation when it is in \l Running
+ state.
+
+ This direction indicates whether the time moves from 0 towards the
+ animation duration, or from the value of the duration and towards 0 after
+ start() has been called.
+
+ By default, this property is set to \l Forward.
+*/
+QAbstractAnimation::Direction QAbstractAnimation::direction() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->direction;
+}
+void QAbstractAnimation::setDirection(Direction direction)
+{
+ Q_D(QAbstractAnimation);
+ if (d->direction == direction)
+ return;
+
+ if (state() == Stopped) {
+ if (direction == Backward) {
+ d->currentTime = duration();
+ d->currentLoop = d->loopCount - 1;
+ } else {
+ d->currentTime = 0;
+ d->currentLoop = 0;
+ }
+ }
+
+ // the commands order below is important: first we need to setCurrentTime with the old direction,
+ // then update the direction on this and all children and finally restart the pauseTimer if needed
+ if (d->hasRegisteredTimer)
+ QUnifiedTimer::ensureTimerUpdate();
+
+ d->direction = direction;
+ updateDirection(direction);
+
+ if (d->hasRegisteredTimer)
+ // needed to update the timer interval in case of a pause animation
+ QUnifiedTimer::updateAnimationTimer();
+
+ emit directionChanged(direction);
+}
+
+/*!
+ \property QAbstractAnimation::duration
+ \brief the duration of the animation.
+
+ If the duration is -1, it means that the duration is undefined.
+ In this case, loopCount is ignored.
+*/
+
+/*!
+ \property QAbstractAnimation::loopCount
+ \brief the loop count of the animation
+
+ This property describes the loop count of the animation as an integer.
+ By default this value is 1, indicating that the animation
+ should run once only, and then stop. By changing it you can let the
+ animation loop several times. With a value of 0, the animation will not
+ run at all, and with a value of -1, the animation will loop forever
+ until stopped.
+ It is not supported to have loop on an animation that has an undefined
+ duration. It will only run once.
+*/
+int QAbstractAnimation::loopCount() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->loopCount;
+}
+void QAbstractAnimation::setLoopCount(int loopCount)
+{
+ Q_D(QAbstractAnimation);
+ d->loopCount = loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentLoop
+ \brief the current loop of the animation
+
+ This property describes the current loop of the animation. By default,
+ the animation's loop count is 1, and so the current loop will
+ always be 0. If the loop count is 2 and the animation runs past its
+ duration, it will automatically rewind and restart at current time 0, and
+ current loop 1, and so on.
+
+ When the current loop changes, QAbstractAnimation emits the
+ currentLoopChanged() signal.
+*/
+int QAbstractAnimation::currentLoop() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentLoop;
+}
+
+/*!
+ \fn virtual int QAbstractAnimation::duration() const = 0
+
+ This pure virtual function returns the duration of the animation, and
+ defines for how long QAbstractAnimation should update the current
+ time. This duration is local, and does not include the loop count.
+
+ A return value of -1 indicates that the animation has no defined duration;
+ the animation should run forever until stopped. This is useful for
+ animations that are not time driven, or where you cannot easily predict
+ its duration (e.g., event driven audio playback in a game).
+
+ If the animation is a parallel QAnimationGroup, the duration will be the longest
+ duration of all its animations. If the animation is a sequential QAnimationGroup,
+ the duration will be the sum of the duration of all its animations.
+ \sa loopCount
+*/
+
+/*!
+ Returns the total and effective duration of the animation, including the
+ loop count.
+
+ \sa duration(), currentTime
+*/
+int QAbstractAnimation::totalDuration() const
+{
+ int dura = duration();
+ if (dura <= 0)
+ return dura;
+ int loopcount = loopCount();
+ if (loopcount < 0)
+ return -1;
+ return dura * loopcount;
+}
+
+/*!
+ Returns the current time inside the current loop. It can go from 0 to duration().
+
+ \sa duration(), currentTime
+*/
+
+int QAbstractAnimation::currentLoopTime() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentTime;
+}
+
+/*!
+ \property QAbstractAnimation::currentTime
+ \brief the current time and progress of the animation
+
+ This property describes the animation's current time. You can change the
+ current time by calling setCurrentTime, or you can call start() and let
+ the animation run, setting the current time automatically as the animation
+ progresses.
+
+ The animation's current time starts at 0, and ends at totalDuration().
+
+ \sa loopCount, currentLoopTime()
+ */
+int QAbstractAnimation::currentTime() const
+{
+ Q_D(const 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);
+ if (totalDura != -1)
+ msecs = qMin(totalDura, msecs);
+ d->totalCurrentTime = msecs;
+
+ // Update new values.
+ int oldLoop = d->currentLoop;
+ d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
+ if (d->currentLoop == d->loopCount) {
+ //we're at the end
+ d->currentTime = qMax(0, dura);
+ d->currentLoop = qMax(0, d->loopCount - 1);
+ } else {
+ if (d->direction == Forward) {
+ d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
+ } else {
+ d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
+ if (d->currentTime == dura)
+ --d->currentLoop;
+ }
+ }
+
+ updateCurrentTime(d->currentTime);
+ if (d->currentLoop != oldLoop)
+ emit currentLoopChanged(d->currentLoop);
+
+ // 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)) {
+ stop();
+ }
+}
+
+/*!
+ Starts the animation. The \a policy argument says whether or not the
+ animation should be deleted when it's done. When the animation starts, the
+ stateChanged() signal is emitted, and state() returns Running. When control
+ reaches the event loop, the animation will run by itself, periodically
+ calling updateCurrentTime() as the animation progresses.
+
+ If the animation is currently stopped or has already reached the end,
+ calling start() will rewind the animation and start again from the beginning.
+ When the animation reaches the end, the animation will either stop, or
+ if the loop level is more than 1, it will rewind and continue from the beginning.
+
+ If the animation is already running, this function does nothing.
+
+ \sa stop(), state()
+*/
+void QAbstractAnimation::start(DeletionPolicy policy)
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Running)
+ return;
+ d->deleteWhenStopped = policy;
+ d->setState(Running);
+}
+
+/*!
+ Stops the animation. When the animation is stopped, it emits the stateChanged()
+ signal, and state() returns Stopped. The current time is not changed.
+
+ If the animation stops by itself after reaching the end (i.e.,
+ currentLoopTime() == duration() and currentLoop() > loopCount() - 1), the
+ finished() signal is emitted.
+
+ \sa start(), state()
+ */
+void QAbstractAnimation::stop()
+{
+ Q_D(QAbstractAnimation);
+
+ if (d->state == Stopped)
+ return;
+
+ d->setState(Stopped);
+}
+
+/*!
+ Pauses the animation. When the animation is paused, state() returns Paused.
+ The value of currentTime will remain unchanged until resume() or start()
+ is called. If you want to continue from the current time, call resume().
+
+ \sa start(), state(), resume()
+ */
+void QAbstractAnimation::pause()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Stopped) {
+ qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
+ return;
+ }
+
+ d->setState(Paused);
+}
+
+/*!
+ Resumes the animation after it was paused. When the animation is resumed,
+ it emits the resumed() and stateChanged() signals. The currenttime is not
+ changed.
+
+ \sa start(), pause(), state()
+ */
+void QAbstractAnimation::resume()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state != Paused) {
+ qWarning("QAbstractAnimation::resume: "
+ "Cannot resume an animation that is not paused");
+ return;
+ }
+
+ d->setState(Running);
+}
+
+/*!
+ If \a paused is true, the animation is paused.
+ If \a paused is false, the animation is resumed.
+
+ \sa state(), pause(), resume()
+*/
+void QAbstractAnimation::setPaused(bool paused)
+{
+ if (paused)
+ pause();
+ else
+ resume();
+}
+
+
+/*!
+ \reimp
+*/
+bool QAbstractAnimation::event(QEvent *event)
+{
+ return QObject::event(event);
+}
+
+/*!
+ \fn virtual void QAbstractAnimation::updateCurrentTime(int currentTime) = 0;
+
+ This pure virtual function is called every time the animation's
+ \a currentTime changes.
+
+ \sa updateState()
+*/
+
+/*!
+ This virtual function is called by QAbstractAnimation when the state
+ of the animation is changed from \a oldState to \a newState.
+
+ \sa start(), stop(), pause(), resume()
+*/
+void QAbstractAnimation::updateState(QAbstractAnimation::State newState,
+ QAbstractAnimation::State oldState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+ This virtual function is called by QAbstractAnimation when the direction
+ of the animation is changed. The \a direction argument is the new direction.
+
+ \sa setDirection(), direction()
+*/
+void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_UNUSED(direction);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qabstractanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
new file mode 100644
index 0000000000..0900870ce2
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_H
+#define QABSTRACTANIMATION_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroup;
+class QSequentialAnimationGroup;
+class QAnimationDriver;
+
+class QAbstractAnimationPrivate;
+class Q_CORE_EXPORT QAbstractAnimation : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(State)
+ Q_ENUMS(Direction)
+ 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(int duration READ duration)
+
+public:
+ enum Direction {
+ Forward,
+ Backward
+ };
+
+ enum State {
+ Stopped,
+ Paused,
+ Running
+ };
+
+ enum DeletionPolicy {
+ KeepWhenStopped = 0,
+ DeleteWhenStopped
+ };
+
+ QAbstractAnimation(QObject *parent = 0);
+ virtual ~QAbstractAnimation();
+
+ State state() const;
+
+ QAnimationGroup *group() const;
+
+ Direction direction() const;
+ void setDirection(Direction direction);
+
+ int currentTime() const;
+ int currentLoopTime() const;
+
+ int loopCount() const;
+ void setLoopCount(int loopCount);
+ int currentLoop() const;
+
+ virtual int duration() const = 0;
+ int totalDuration() const;
+
+Q_SIGNALS:
+ void finished();
+ void stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+ void currentLoopChanged(int currentLoop);
+ void directionChanged(QAbstractAnimation::Direction);
+
+public Q_SLOTS:
+ void start(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped);
+ void pause();
+ void resume();
+ void setPaused(bool);
+ void stop();
+ void setCurrentTime(int msecs);
+
+protected:
+ QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ virtual void updateCurrentTime(int currentTime) = 0;
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+ virtual void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QAbstractAnimation)
+ Q_DECLARE_PRIVATE(QAbstractAnimation)
+};
+
+class QAnimationDriverPrivate;
+class Q_CORE_EXPORT QAnimationDriver : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAnimationDriver)
+
+public:
+ QAnimationDriver(QObject *parent = 0);
+
+ void advance();
+ void install();
+
+ bool isRunning() const;
+
+protected:
+ virtual void started() {};
+ virtual void stopped() {};
+
+ QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent = 0);
+
+private:
+ friend class QUnifiedTimer;
+
+ void start();
+ void stop();
+};
+
+
+
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTANIMATION_H
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
new file mode 100644
index 0000000000..ba92960f6b
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_P_H
+#define QABSTRACTANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qelapsedtimer.h>
+#include <private/qobject_p.h>
+#include <qabstractanimation.h>
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroup;
+class QAbstractAnimation;
+class 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(0)
+ {
+ }
+
+ virtual ~QAbstractAnimationPrivate() {}
+
+ static QAbstractAnimationPrivate *get(QAbstractAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ QAbstractAnimation::State state;
+ QAbstractAnimation::Direction direction;
+ void setState(QAbstractAnimation::State state);
+
+ int totalCurrentTime;
+ int currentTime;
+ int loopCount;
+ int currentLoop;
+
+ bool deleteWhenStopped;
+ bool hasRegisteredTimer;
+ bool isPause;
+ bool isGroup;
+
+ QAnimationGroup *group;
+
+private:
+ Q_DECLARE_PUBLIC(QAbstractAnimation)
+};
+
+
+class QUnifiedTimer;
+class QDefaultAnimationDriver : public QAnimationDriver
+{
+ Q_OBJECT
+public:
+ QDefaultAnimationDriver(QUnifiedTimer *timer);
+ void timerEvent(QTimerEvent *e);
+
+ void started();
+ void stopped();
+
+private:
+ QBasicTimer m_timer;
+ QUnifiedTimer *m_unified_timer;
+};
+
+class Q_CORE_EXPORT QAnimationDriverPrivate : public QObjectPrivate
+{
+public:
+ QAnimationDriverPrivate() : running(false) {}
+ bool running;
+};
+
+typedef QElapsedTimer ElapsedTimer;
+
+class Q_CORE_EXPORT QUnifiedTimer : public QObject
+{
+private:
+ QUnifiedTimer();
+
+public:
+ //XXX this is needed by dui
+ static QUnifiedTimer *instance();
+ static QUnifiedTimer *instance(bool create);
+
+ static void registerAnimation(QAbstractAnimation *animation, bool isTopLevel);
+ static void unregisterAnimation(QAbstractAnimation *animation);
+
+ //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL
+ void setTimingInterval(int interval);
+
+ /*
+ this allows to have a consistent timer interval at each tick from the timer
+ not taking the real time that passed into account.
+ */
+ void setConsistentTiming(bool consistent) { consistentTiming = consistent; }
+
+ //these facilitate fine-tuning of complex animations
+ void setSlowModeEnabled(bool enabled) { slowMode = enabled; }
+ void setSlowdownFactor(qreal factor) { slowdownFactor = factor; }
+
+ /*
+ this is used for updating the currentTime of all animations in case the pause
+ timer is active or, otherwise, only of the animation passed as parameter.
+ */
+ static void ensureTimerUpdate();
+
+ /*
+ this will evaluate the need of restarting the pause timer in case there is still
+ some pause animations running.
+ */
+ static void updateAnimationTimer();
+
+ void installAnimationDriver(QAnimationDriver *driver);
+
+ void restartAnimationTimer();
+ void updateAnimationsTime();
+
+protected:
+ void timerEvent(QTimerEvent *);
+
+private:
+ friend class QDefaultAnimationDriver;
+
+ QAnimationDriver *driver;
+ QDefaultAnimationDriver defaultDriver;
+
+ QBasicTimer animationTimer;
+ // timer used to delay the check if we should start/stop the animation timer
+ QBasicTimer startStopAnimationTimer;
+
+ ElapsedTimer time;
+
+ qint64 lastTick;
+ int timingInterval;
+ int currentAnimationIdx;
+ bool insideTick;
+ bool consistentTiming;
+ bool slowMode;
+
+ // 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)
+ // stops all animations.
+ qreal slowdownFactor;
+
+ // bool to indicate that only pause animations are active
+ bool isPauseTimerActive;
+
+ QList<QAbstractAnimation*> animations, animationsToStart;
+
+ // this is the count of running animations that are not a group neither a pause animation
+ int runningLeafAnimations;
+ QList<QAbstractAnimation*> runningPauseAnimations;
+
+ void registerRunningAnimation(QAbstractAnimation *animation);
+ void unregisterRunningAnimation(QAbstractAnimation *animation);
+
+ int closestPauseAnimationTimeToFinish();
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QABSTRACTANIMATION_P_H
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
new file mode 100644
index 0000000000..f3b4f9576e
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAnimationGroup
+ \brief The QAnimationGroup class is an abstract base class for groups of animations.
+ \since 4.6
+ \ingroup animation
+
+ An animation group is a container for animations (subclasses of
+ QAbstractAnimation). A group is usually responsible for managing
+ the \l{QAbstractAnimation::State}{state} of its animations, i.e.,
+ it decides when to start, stop, resume, and pause them. Currently,
+ Qt provides two such groups: QParallelAnimationGroup and
+ QSequentialAnimationGroup. Look up their class descriptions for
+ details.
+
+ Since QAnimationGroup inherits from QAbstractAnimation, you can
+ combine groups, and easily construct complex animation graphs.
+ You can query QAbstractAnimation for the group it belongs to
+ (using the \l{QAbstractAnimation::}{group()} function).
+
+ To start a top-level animation group, you simply use the
+ \l{QAbstractAnimation::}{start()} function from
+ QAbstractAnimation. By a top-level animation group, we think of a
+ group that itself is not contained within another group. Starting
+ sub groups directly is not supported, and may lead to unexpected
+ behavior.
+
+ \omit OK, we'll put in a snippet on this here \endomit
+
+ QAnimationGroup provides methods for adding and retrieving
+ animations. Besides that, you can remove animations by calling
+ remove(), and clear the animation group by calling
+ clear(). You may keep track of changes in the group's
+ animations by listening to QEvent::ChildAdded and
+ QEvent::ChildRemoved events.
+
+ \omit OK, let's find a snippet here as well. \endomit
+
+ QAnimationGroup takes ownership of the animations it manages, and
+ ensures that they are deleted when the animation group is deleted.
+
+ \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework}
+*/
+
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include "qanimationgroup_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ Constructs a QAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QAbstractAnimation(*new QAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
+ : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QAnimationGroup::~QAnimationGroup()
+{
+}
+
+/*!
+ Returns a pointer to the animation at \a index in this group. This
+ function is useful when you need access to a particular animation. \a
+ index is between 0 and animationCount() - 1.
+
+ \sa animationCount(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::animationAt(int index) const
+{
+ Q_D(const QAnimationGroup);
+
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::animationAt: index is out of bounds");
+ return 0;
+ }
+
+ return d->animations.at(index);
+}
+
+
+/*!
+ Returns the number of animations managed by this group.
+
+ \sa indexOfAnimation(), addAnimation(), animationAt()
+*/
+int QAnimationGroup::animationCount() const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.size();
+}
+
+/*!
+ Returns the index of \a animation. The returned index can be passed
+ to the other functions that take an index as an argument.
+
+ \sa insertAnimation(), animationAt(), takeAnimation()
+*/
+int QAnimationGroup::indexOfAnimation(QAbstractAnimation *animation) const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.indexOf(animation);
+}
+
+/*!
+ Adds \a animation to this group. This will call insertAnimation with
+ index equals to animationCount().
+
+ \note The group takes ownership of the animation.
+
+ \sa removeAnimation()
+*/
+void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ insertAnimation(d->animations.count(), animation);
+}
+
+/*!
+ Inserts \a animation into this animation group at \a index.
+ If \a index is 0 the animation is inserted at the beginning.
+ If \a index is animationCount(), the animation is inserted at the end.
+
+ \note The group takes ownership of the animation.
+
+ \sa takeAnimation(), addAnimation(), indexOfAnimation(), removeAnimation()
+*/
+void QAnimationGroup::insertAnimation(int index, QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QAnimationGroup::insertAnimation: index is out of bounds");
+ return;
+ }
+
+ if (QAnimationGroup *oldGroup = animation->group())
+ oldGroup->removeAnimation(animation);
+
+ d->animations.insert(index, animation);
+ QAbstractAnimationPrivate::get(animation)->group = this;
+ // this will make sure that ChildAdded event is sent to 'this'
+ animation->setParent(this);
+ d->animationInsertedAt(index);
+}
+
+/*!
+ Removes \a animation from this group. The ownership of \a animation is
+ transferred to the caller.
+
+ \sa takeAnimation(), insertAnimation(), addAnimation()
+*/
+void QAnimationGroup::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (!animation) {
+ qWarning("QAnimationGroup::remove: cannot remove null animation");
+ return;
+ }
+ int index = d->animations.indexOf(animation);
+ if (index == -1) {
+ qWarning("QAnimationGroup::remove: animation is not part of this group");
+ return;
+ }
+
+ takeAnimation(index);
+}
+
+/*!
+ Returns the animation at \a index and removes it from the animation group.
+
+ \note The ownership of the animation is transferred to the caller.
+
+ \sa removeAnimation(), addAnimation(), insertAnimation(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
+{
+ Q_D(QAnimationGroup);
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::takeAnimation: no animation at index %d", index);
+ return 0;
+ }
+ QAbstractAnimation *animation = d->animations.at(index);
+ QAbstractAnimationPrivate::get(animation)->group = 0;
+ // ### removing from list before doing setParent to avoid inifinite recursion
+ // in ChildRemoved event
+ d->animations.removeAt(index);
+ animation->setParent(0);
+ d->animationRemoved(index, animation);
+ return animation;
+}
+
+/*!
+ Removes and deletes all animations in this animation group, and resets the current
+ time to 0.
+
+ \sa addAnimation(), removeAnimation()
+*/
+void QAnimationGroup::clear()
+{
+ Q_D(QAnimationGroup);
+ qDeleteAll(d->animations);
+}
+
+/*!
+ \reimp
+*/
+bool QAnimationGroup::event(QEvent *event)
+{
+ Q_D(QAnimationGroup);
+ if (event->type() == QEvent::ChildAdded) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ if (QAbstractAnimation *a = qobject_cast<QAbstractAnimation *>(childEvent->child())) {
+ if (a->group() != this)
+ addAnimation(a);
+ }
+ } else if (event->type() == QEvent::ChildRemoved) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ QAbstractAnimation *a = static_cast<QAbstractAnimation *>(childEvent->child());
+ // You can only rely on the child being a QObject because in the QEvent::ChildRemoved
+ // case it might be called from the destructor.
+ int index = d->animations.indexOf(a);
+ if (index != -1)
+ takeAnimation(index);
+ }
+ return QAbstractAnimation::event(event);
+}
+
+
+void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
+{
+ Q_Q(QAnimationGroup);
+ Q_UNUSED(index);
+ if (animations.isEmpty()) {
+ currentTime = 0;
+ q->stop();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
new file mode 100644
index 0000000000..b3cc10579e
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_H
+#define QANIMATIONGROUP_H
+
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroupPrivate;
+class Q_CORE_EXPORT QAnimationGroup : public QAbstractAnimation
+{
+ Q_OBJECT
+
+public:
+ QAnimationGroup(QObject *parent = 0);
+ ~QAnimationGroup();
+
+ QAbstractAnimation *animationAt(int index) const;
+ int animationCount() const;
+ int indexOfAnimation(QAbstractAnimation *animation) const;
+ void addAnimation(QAbstractAnimation *animation);
+ void insertAnimation(int index, QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QAbstractAnimation *takeAnimation(int index);
+ void clear();
+
+protected:
+ QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QAnimationGroup)
+ Q_DECLARE_PRIVATE(QAnimationGroup)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
new file mode 100644
index 0000000000..278019abb0
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_P_H
+#define QANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qanimationgroup.h"
+
+#include <QtCore/qlist.h>
+
+#include "private/qabstractanimation_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroupPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QAnimationGroup)
+public:
+ QAnimationGroupPrivate()
+ {
+ isGroup = true;
+ }
+
+ virtual void animationInsertedAt(int) { }
+ virtual void animationRemoved(int, QAbstractAnimation *);
+
+ void disconnectUncontrolledAnimation(QAbstractAnimation *anim)
+ {
+ //0 for the signal here because we might be called from the animation destructor
+ QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished()));
+ }
+
+ void connectUncontrolledAnimation(QAbstractAnimation *anim)
+ {
+ QObject::connect(anim, SIGNAL(finished()), q_func(), SLOT(_q_uncontrolledAnimationFinished()));
+ }
+
+ QList<QAbstractAnimation *> animations;
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
new file mode 100644
index 0000000000..414cdde23e
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QParallelAnimationGroup
+ \brief The QParallelAnimationGroup class provides a parallel group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QParallelAnimationGroup--a \l{QAnimationGroup}{container for
+ animations}--starts all its animations when it is
+ \l{QAbstractAnimation::start()}{started} itself, i.e., runs all
+ animations in parallel. The animation group finishes when the
+ longest lasting animation has finished.
+
+ You can treat QParallelAnimation as any other QAbstractAnimation,
+ e.g., pause, resume, or add it to other animation groups.
+
+ \code
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two
+ \l{QPropertyAnimation}s that have already been set up.
+
+ \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework}
+*/
+
+
+#include "qparallelanimationgroup.h"
+#include "qparallelanimationgroup_p.h"
+//#define QANIMATION_DEBUG
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a QParallelAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QParallelAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QParallelAnimationGroup::~QParallelAnimationGroup()
+{
+}
+
+/*!
+ \reimp
+*/
+int QParallelAnimationGroup::duration() const
+{
+ Q_D(const QParallelAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret = qMax(ret, currentDuration);
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateCurrentTime(int currentTime)
+{
+ Q_D(QParallelAnimationGroup);
+ if (d->animations.isEmpty())
+ return;
+
+ if (d->currentLoop > d->lastLoop) {
+ // simulate completion of the loop
+ int dura = duration();
+ if (dura > 0) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ if (animation->state() != QAbstractAnimation::Stopped)
+ d->animations.at(i)->setCurrentTime(dura); // will stop
+ }
+ }
+ } else if (d->currentLoop < d->lastLoop) {
+ // simulate completion of the loop seeking backwards
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ //we need to make sure the animation is in the right state
+ //and then rewind it
+ d->applyGroupState(animation);
+ animation->setCurrentTime(0);
+ animation->stop();
+ }
+ }
+
+#ifdef QANIMATION_DEBUG
+ qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d",
+ __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
+#endif
+ // finally move into the actual time of the current loop
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int dura = animation->totalDuration();
+ //if the loopcount is bigger we should always start all animations
+ if (d->currentLoop > d->lastLoop
+ //if we're at the end of the animation, we need to start it if it wasn't already started in this loop
+ //this happens in Backward direction where not all animations are started at the same time
+ || d->shouldAnimationStart(animation, d->lastCurrentTime > dura /*startIfAtEnd*/)) {
+ d->applyGroupState(animation);
+ }
+
+ if (animation->state() == state()) {
+ animation->setCurrentTime(currentTime);
+ if (dura > 0 && currentTime > dura)
+ animation->stop();
+ }
+ }
+ d->lastLoop = d->currentLoop;
+ d->lastCurrentTime = currentTime;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateState(QAbstractAnimation::State newState,
+ QAbstractAnimation::State oldState)
+{
+ Q_D(QParallelAnimationGroup);
+ QAnimationGroup::updateState(newState, oldState);
+
+ switch (newState) {
+ case Stopped:
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->stop();
+ d->disconnectUncontrolledAnimations();
+ break;
+ case Paused:
+ for (int i = 0; i < d->animations.size(); ++i)
+ if (d->animations.at(i)->state() == Running)
+ d->animations.at(i)->pause();
+ break;
+ case Running:
+ d->connectUncontrolledAnimations();
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ if (oldState == Stopped)
+ animation->stop();
+ animation->setDirection(d->direction);
+ if (d->shouldAnimationStart(animation, oldState == Stopped))
+ animation->start();
+ }
+ break;
+ }
+}
+
+void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender());
+ Q_ASSERT(animation);
+
+ int uncontrolledRunningCount = 0;
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ if (it.key() == animation) {
+ *it = animation->currentTime();
+ }
+ if (it.value() == -1)
+ ++uncontrolledRunningCount;
+ ++it;
+ }
+ }
+
+ if (uncontrolledRunningCount > 0)
+ return;
+
+ int maxDuration = 0;
+ for (int i = 0; i < animations.size(); ++i)
+ maxDuration = qMax(maxDuration, animations.at(i)->totalDuration());
+
+ if (currentTime >= maxDuration)
+ q->stop();
+}
+
+void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
+{
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ disconnectUncontrolledAnimation(it.key());
+ ++it;
+ }
+
+ uncontrolledFinishTime.clear();
+}
+
+void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
+{
+ for (int i = 0; i < animations.size(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ uncontrolledFinishTime[animation] = -1;
+ connectUncontrolledAnimation(animation);
+ }
+ }
+}
+
+bool QParallelAnimationGroupPrivate::shouldAnimationStart(QAbstractAnimation *animation, bool startIfAtEnd) const
+{
+ const int dura = animation->totalDuration();
+ if (dura == -1)
+ return !isUncontrolledAnimationFinished(animation);
+ if (startIfAtEnd)
+ return currentTime <= dura;
+ if (direction == QAbstractAnimation::Forward)
+ return currentTime < dura;
+ else //direction == QAbstractAnimation::Backward
+ return currentTime && currentTime <= dura;
+}
+
+void QParallelAnimationGroupPrivate::applyGroupState(QAbstractAnimation *animation)
+{
+ switch (state)
+ {
+ case QAbstractAnimation::Running:
+ animation->start();
+ break;
+ case QAbstractAnimation::Paused:
+ animation->pause();
+ break;
+ case QAbstractAnimation::Stopped:
+ default:
+ break;
+ }
+}
+
+
+bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
+{
+ return uncontrolledFinishTime.value(anim, -1) >= 0;
+}
+
+void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
+{
+ QAnimationGroupPrivate::animationRemoved(index, anim);
+ disconnectUncontrolledAnimation(anim);
+ uncontrolledFinishTime.remove(anim);
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QParallelAnimationGroup);
+ //we need to update the direction of the current animation
+ if (state() != Stopped) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ animation->setDirection(direction);
+ }
+ } else {
+ if (direction == Forward) {
+ d->lastLoop = 0;
+ d->lastCurrentTime = 0;
+ } else {
+ // Looping backwards with loopCount == -1 does not really work well...
+ d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1);
+ d->lastCurrentTime = duration();
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QParallelAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qparallelanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
new file mode 100644
index 0000000000..5e0fb71799
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_H
+#define QPARALLELANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QParallelAnimationGroupPrivate;
+class Q_CORE_EXPORT QParallelAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+
+public:
+ QParallelAnimationGroup(QObject *parent = 0);
+ ~QParallelAnimationGroup();
+
+ int duration() const;
+
+protected:
+ QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int currentTime);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QParallelAnimationGroup)
+ Q_DECLARE_PRIVATE(QParallelAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPARALLELANIMATIONGROUP
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
new file mode 100644
index 0000000000..680d41ea21
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_P_H
+#define QPARALLELANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qparallelanimationgroup.h"
+#include "private/qanimationgroup_p.h"
+#include <QtCore/qhash.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QParallelAnimationGroup)
+public:
+ QParallelAnimationGroupPrivate()
+ : lastLoop(0), lastCurrentTime(0)
+ {
+ }
+
+ QHash<QAbstractAnimation*, int> uncontrolledFinishTime;
+ int lastLoop;
+ int lastCurrentTime;
+
+ bool shouldAnimationStart(QAbstractAnimation *animation, bool startIfAtEnd) const;
+ void applyGroupState(QAbstractAnimation *animation);
+ bool isUncontrolledAnimationFinished(QAbstractAnimation *anim) const;
+ void connectUncontrolledAnimations();
+ void disconnectUncontrolledAnimations();
+
+ void animationRemoved(int index, QAbstractAnimation *);
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
new file mode 100644
index 0000000000..418cb5321d
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPauseAnimation
+ \brief The QPauseAnimation class provides a pause for QSequentialAnimationGroup.
+ \since 4.6
+ \ingroup animation
+
+ If you wish to introduce a delay between animations in a
+ QSequentialAnimationGroup, you can insert a QPauseAnimation. This
+ class does not animate anything, but does not
+ \l{QAbstractAnimation::finished()}{finish} before a specified
+ number of milliseconds have elapsed from when it was started. You
+ specify the duration of the pause in the constructor. It can also
+ be set directly with setDuration().
+
+ It is not necessary to construct a QPauseAnimation yourself.
+ QSequentialAnimationGroup provides the convenience functions
+ \l{QSequentialAnimationGroup::}{addPause()} and
+ \l{QSequentialAnimationGroup::}{insertPause()}. These functions
+ simply take the number of milliseconds the pause should last.
+
+ \sa QSequentialAnimationGroup
+*/
+
+#include "qpauseanimation.h"
+#include "qabstractanimation_p.h"
+
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QPauseAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QPauseAnimationPrivate() : QAbstractAnimationPrivate(), duration(250)
+ {
+ isPause = true;
+ }
+
+ int duration;
+};
+
+/*!
+ Constructs a QPauseAnimation.
+ \a parent is passed to QObject's constructor.
+ The default duration is 0.
+*/
+
+QPauseAnimation::QPauseAnimation(QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+}
+
+/*!
+ Constructs a QPauseAnimation.
+ \a msecs is the duration of the pause.
+ \a parent is passed to QObject's constructor.
+*/
+
+QPauseAnimation::QPauseAnimation(int msecs, QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+ setDuration(msecs);
+}
+
+/*!
+ Destroys the pause animation.
+*/
+QPauseAnimation::~QPauseAnimation()
+{
+}
+
+/*!
+ \property QPauseAnimation::duration
+ \brief the duration of the pause.
+
+ The duration of the pause. The duration should not be negative.
+ The default duration is 250 milliseconds.
+*/
+int QPauseAnimation::duration() const
+{
+ Q_D(const QPauseAnimation);
+ return d->duration;
+}
+
+void QPauseAnimation::setDuration(int msecs)
+{
+ if (msecs < 0) {
+ qWarning("QPauseAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ Q_D(QPauseAnimation);
+ d->duration = msecs;
+}
+
+/*!
+ \reimp
+ */
+bool QPauseAnimation::event(QEvent *e)
+{
+ return QAbstractAnimation::event(e);
+}
+
+/*!
+ \reimp
+ */
+void QPauseAnimation::updateCurrentTime(int)
+{
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qpauseanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
new file mode 100644
index 0000000000..1da7865256
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAUSEANIMATION_P_H
+#define QPAUSEANIMATION_P_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimationPrivate;
+
+class Q_CORE_EXPORT QPauseAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+public:
+ QPauseAnimation(QObject *parent = 0);
+ QPauseAnimation(int msecs, QObject *parent = 0);
+ ~QPauseAnimation();
+
+ int duration() const;
+ void setDuration(int msecs);
+
+protected:
+ bool event(QEvent *e);
+ void updateCurrentTime(int);
+
+private:
+ Q_DISABLE_COPY(QPauseAnimation)
+ Q_DECLARE_PRIVATE(QPauseAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPAUSEANIMATION_P_H
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
new file mode 100644
index 0000000000..cc642358f0
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPropertyAnimation
+ \brief The QPropertyAnimation class animates Qt properties
+ \since 4.6
+
+ \ingroup animation
+
+ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt
+ properties}. As property values are stored in \l{QVariant}s, the
+ class inherits QVariantAnimation, and supports animation of the
+ same \l{QVariant::Type}{variant types} as its super class.
+
+ A class declaring properties must be a QObject. To make it
+ possible to animate a property, it must provide a setter (so that
+ QPropertyAnimation can set the property's value). Note that this
+ makes it possible to animate many of Qt's widgets. Let's look at
+ an example:
+
+ \code
+ QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
+ animation->setDuration(10000);
+ animation->setStartValue(QRect(0, 0, 100, 30));
+ animation->setEndValue(QRect(250, 250, 100, 30));
+
+ animation->start();
+ \endcode
+
+ 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
+ equal for properties in classes you have implemented
+ yourself--just check with QVariantAnimation that your QVariant
+ type is supported.
+
+ The QVariantAnimation class description explains how to set up the
+ animation in detail. Note, however, that if a start value is not
+ set, the property will start at the value it had when the
+ QPropertyAnimation instance was created.
+
+ QPropertyAnimation works like a charm on its own. For complex
+ animations that, for instance, contain several objects,
+ QAnimationGroup is provided. An animation group is an animation
+ that can contain other animations, and that can manage when its
+ animations are played. Look at QParallelAnimationGroup for an
+ example.
+
+ \sa QVariantAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include "qpropertyanimation_p.h"
+
+#include <private/qmutexpool_p.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+void QPropertyAnimationPrivate::updateMetaProperty()
+{
+ if (!target || propertyName.isEmpty()) {
+ propertyType = QVariant::Invalid;
+ propertyIndex = -1;
+ return;
+ }
+
+ //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);
+
+ if (propertyType != QVariant::Invalid)
+ convertValues(propertyType);
+ if (propertyIndex == -1) {
+ //there is no Q_PROPERTY on the object
+ propertyType = QVariant::Invalid;
+ 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());
+ }
+}
+
+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
+ return;
+ }
+
+ if (newValue.userType() == propertyType) {
+ //no conversion is needed, we directly call the QMetaObject::metacall
+ void *data = const_cast<void*>(newValue.constData());
+ QMetaObject::metacall(targetValue, QMetaObject::WriteProperty, propertyIndex, &data);
+ } else {
+ targetValue->setProperty(propertyName.constData(), newValue);
+ }
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor.
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor. The animation changes the property \a propertyName on \a
+ target. The default duration is 250ms.
+
+ \sa targetObject, propertyName
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+ setTargetObject(target);
+ setPropertyName(propertyName);
+}
+
+/*!
+ Destroys the QPropertyAnimation instance.
+ */
+QPropertyAnimation::~QPropertyAnimation()
+{
+ stop();
+}
+
+/*!
+ \property QPropertyAnimation::targetObject
+ \brief the target QObject for this animation.
+
+ This property defines the target QObject for this animation.
+ */
+QObject *QPropertyAnimation::targetObject() const
+{
+ return d_func()->target.data();
+}
+
+void QPropertyAnimation::setTargetObject(QObject *target)
+{
+ Q_D(QPropertyAnimation);
+ if (d->targetValue == 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->updateMetaProperty();
+}
+
+/*!
+ \property QPropertyAnimation::propertyName
+ \brief the target property name for this animation
+
+ This property defines the target property name for this animation. The
+ property name is required for the animation to operate.
+ */
+QByteArray QPropertyAnimation::propertyName() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->propertyName;
+}
+
+void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
+{
+ Q_D(QPropertyAnimation);
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
+ return;
+ }
+
+ d->propertyName = propertyName;
+ d->updateMetaProperty();
+}
+
+
+/*!
+ \reimp
+ */
+bool QPropertyAnimation::event(QEvent *event)
+{
+ return QVariantAnimation::event(event);
+}
+
+/*!
+ This virtual function is called by QVariantAnimation whenever the current value
+ changes. \a value is the new, updated value. It updates the current value
+ of the property on the target object.
+
+ \sa currentValue, currentTime
+ */
+void QPropertyAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(QPropertyAnimation);
+ d->updateProperty(value);
+}
+
+/*!
+ \reimp
+
+ If the startValue is not defined when the state of the animation changes from Stopped to Running,
+ the current property value is used as the initial value for the animation.
+*/
+void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
+ QAbstractAnimation::State oldState)
+{
+ Q_D(QPropertyAnimation);
+
+ if (!d->target && oldState == Stopped) {
+ qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without target",
+ d->propertyName.constData());
+ return;
+ }
+
+ QVariantAnimation::updateState(newState, oldState);
+
+ QPropertyAnimation *animToStop = 0;
+ {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&staticMetaObject));
+#endif
+ typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
+ 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);
+ if (newState == Running) {
+ d->updateMetaProperty();
+ animToStop = hash.value(key, 0);
+ hash.insert(key, this);
+ // update the default start value
+ if (oldState == Stopped) {
+ d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData()));
+ //let's check if we have a start value and an end value
+ if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) {
+ qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without start value",
+ d->propertyName.constData(), d->target.data()->metaObject()->className(),
+ qPrintable(d->target.data()->objectName()));
+ }
+ if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) {
+ qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without end value",
+ d->propertyName.constData(), d->target.data()->metaObject()->className(),
+ qPrintable(d->target.data()->objectName()));
+ }
+ }
+ } else if (hash.value(key) == this) {
+ hash.remove(key);
+ }
+ }
+
+ //we need to do that after the mutex was unlocked
+ if (animToStop) {
+ // try to stop the top level group
+ QAbstractAnimation *current = animToStop;
+ while (current->group() && current->state() != Stopped)
+ current = current->group();
+ current->stop();
+ }
+}
+
+#include "moc_qpropertyanimation.cpp"
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
new file mode 100644
index 0000000000..379efe10f7
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_H
+#define QPROPERTYANIMATION_H
+
+#include <QtCore/qvariantanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+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)
+
+public:
+ QPropertyAnimation(QObject *parent = 0);
+ QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0);
+ ~QPropertyAnimation();
+
+ QObject *targetObject() const;
+ void setTargetObject(QObject *target);
+
+ QByteArray propertyName() const;
+ void setPropertyName(const QByteArray &propertyName);
+
+protected:
+ bool event(QEvent *event);
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+
+private:
+ Q_DISABLE_COPY(QPropertyAnimation)
+ Q_DECLARE_PRIVATE(QPropertyAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROPERTYANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
new file mode 100644
index 0000000000..f1df91ed1f
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_P_H
+#define QPROPERTYANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpropertyanimation.h"
+
+#include "private/qvariantanimation_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QPropertyAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QPropertyAnimation)
+public:
+ QPropertyAnimationPrivate()
+ : targetValue(0), propertyType(0), propertyIndex(-1)
+ {
+ }
+
+ QWeakPointer<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 updateProperty(const QVariant &);
+ void updateMetaProperty();
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QPROPERTYANIMATION_P_H
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
new file mode 100644
index 0000000000..2e73104c6e
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -0,0 +1,588 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSequentialAnimationGroup
+ \brief The QSequentialAnimationGroup class provides a sequential group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QSequentialAnimationGroup is a QAnimationGroup that runs its
+ animations in sequence, i.e., it starts one animation after
+ another has finished playing. The animations are played in the
+ order they are added to the group (using
+ \l{QAnimationGroup::}{addAnimation()} or
+ \l{QAnimationGroup::}{insertAnimation()}). The animation group
+ finishes when its last animation has finished.
+
+ At each moment there is at most one animation that is active in
+ the group; it is returned by currentAnimation(). An empty group
+ has no current animation.
+
+ A sequential animation group can be treated as any other
+ animation, i.e., it can be started, stopped, and added to other
+ groups. You can also call addPause() or insertPause() to add a
+ pause to a sequential animation group.
+
+ \code
+ QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
+
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two already set up
+ \l{QPropertyAnimation}s.
+
+ \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework}
+*/
+
+#include "qsequentialanimationgroup.h"
+#include "qsequentialanimationgroup_p.h"
+
+#include "qpauseanimation.h"
+
+#include <QtCore/qdebug.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+bool QSequentialAnimationGroupPrivate::atEnd() const
+{
+ // we try to detect if we're at the end of the group
+ //this is true if the following conditions are true:
+ // 1. we're in the last loop
+ // 2. the direction is forward
+ // 3. the current animation is the last one
+ // 4. the current animation has reached its end
+ const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ return (currentLoop == loopCount - 1
+ && direction == QAbstractAnimation::Forward
+ && currentAnimation == animations.last()
+ && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex));
+}
+
+int QSequentialAnimationGroupPrivate::animationActualTotalDuration(int index) const
+{
+ QAbstractAnimation *anim = animations.at(index);
+ int ret = anim->totalDuration();
+ if (ret == -1 && actualDuration.size() > index)
+ ret = actualDuration.at(index); //we can try the actual duration there
+ return ret;
+}
+
+QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForCurrentTime() const
+{
+ Q_ASSERT(!animations.isEmpty());
+
+ AnimationIndex ret;
+ int duration = 0;
+
+ for (int i = 0; i < animations.size(); ++i) {
+ duration = animationActualTotalDuration(i);
+
+ // 'animation' is the current animation if one of these reasons is true:
+ // 1. it's duration is undefined
+ // 2. it ends after msecs
+ // 3. it is the last animation (this can happen in case there is at least 1 uncontrolled animation)
+ // 4. it ends exactly in msecs and the direction is backwards
+ if (duration == -1 || currentTime < (ret.timeOffset + duration)
+ || (currentTime == (ret.timeOffset + duration) && direction == QAbstractAnimation::Backward)) {
+ ret.index = i;
+ return ret;
+ }
+
+ // 'animation' has a non-null defined duration and is not the one at time 'msecs'.
+ ret.timeOffset += duration;
+ }
+
+ // this can only happen when one of those conditions is true:
+ // 1. the duration of the group is undefined and we passed its actual duration
+ // 2. there are only 0-duration animations in the group
+ ret.timeOffset -= duration;
+ ret.index = animations.size() - 1;
+ return ret;
+}
+
+void QSequentialAnimationGroupPrivate::restart()
+{
+ // restarting the group by making the first/last animation the current one
+ if (direction == QAbstractAnimation::Forward) {
+ lastLoop = 0;
+ if (currentAnimationIndex == 0)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0);
+ } else { // direction == QAbstractAnimation::Backward
+ lastLoop = loopCount - 1;
+ int index = animations.size() - 1;
+ if (currentAnimationIndex == index)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(index);
+ }
+}
+
+/*!
+ \internal
+ This manages advancing the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for rewinding the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop < currentLoop) {
+ // we need to fast forward to the end
+ for (int i = currentAnimationIndex; i < animations.size(); ++i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // this will make sure the current animation is reset to the beginning
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0, true);
+ }
+
+ // and now we need to fast forward from the current position to
+ for (int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) { //### WRONG,
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \internal
+ This manages rewinding the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for advancing the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop > currentLoop) {
+ // we need to fast rewind to the beginning
+ for (int i = currentAnimationIndex; i >= 0 ; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // this will make sure the current animation is reset to the end
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(animations.count() - 1, true);
+ }
+
+ // and now we need to fast rewind from the current position to
+ for (int i = currentAnimationIndex; i > newAnimationIndex.index; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \fn QSequentialAnimationGroup::currentAnimationChanged(QAbstractAnimation *current)
+
+ QSequentialAnimationGroup emits this signal when currentAnimation
+ has been changed. \a current is the current animation.
+
+ \sa currentAnimation()
+*/
+
+
+/*!
+ Constructs a QSequentialAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QSequentialAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QSequentialAnimationGroup::~QSequentialAnimationGroup()
+{
+}
+
+/*!
+ Adds a pause of \a msecs to this animation group.
+ The pause is considered as a special type of animation, thus
+ \l{QAnimationGroup::animationCount()}{animationCount} will be
+ increased by one.
+
+ \sa insertPause(), QAnimationGroup::addAnimation()
+*/
+QPauseAnimation *QSequentialAnimationGroup::addPause(int msecs)
+{
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ addAnimation(pause);
+ return pause;
+}
+
+/*!
+ Inserts a pause of \a msecs milliseconds at \a index in this animation
+ group.
+
+ \sa addPause(), QAnimationGroup::insertAnimation()
+*/
+QPauseAnimation *QSequentialAnimationGroup::insertPause(int index, int msecs)
+{
+ Q_D(const QSequentialAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QSequentialAnimationGroup::insertPause: index is out of bounds");
+ return 0;
+ }
+
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ insertAnimation(index, pause);
+ return pause;
+}
+
+
+/*!
+ \property QSequentialAnimationGroup::currentAnimation
+ Returns the animation in the current time.
+
+ \sa currentAnimationChanged()
+*/
+QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ return d->currentAnimation;
+}
+
+/*!
+ \reimp
+*/
+int QSequentialAnimationGroup::duration() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret += currentDuration;
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateCurrentTime(int currentTime)
+{
+ Q_D(QSequentialAnimationGroup);
+ if (!d->currentAnimation)
+ return;
+
+ const QSequentialAnimationGroupPrivate::AnimationIndex newAnimationIndex = d->indexForCurrentTime();
+
+ // remove unneeded animations from actualDuration list
+ while (newAnimationIndex.index < d->actualDuration.size())
+ d->actualDuration.removeLast();
+
+ // newAnimationIndex.index is the new current animation
+ if (d->lastLoop < d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) {
+ // advancing with forward direction is the same as rewinding with backwards direction
+ d->advanceForwards(newAnimationIndex);
+ } else if (d->lastLoop > d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) {
+ // rewinding with forward direction is the same as advancing with backwards direction
+ d->rewindForwards(newAnimationIndex);
+ }
+
+ d->setCurrentAnimation(newAnimationIndex.index);
+
+ const int newCurrentTime = currentTime - newAnimationIndex.timeOffset;
+
+ if (d->currentAnimation) {
+ d->currentAnimation->setCurrentTime(newCurrentTime);
+ if (d->atEnd()) {
+ //we make sure that we don't exceed the duration here
+ d->currentTime += QAbstractAnimationPrivate::get(d->currentAnimation)->totalCurrentTime - newCurrentTime;
+ stop();
+ }
+ } else {
+ //the only case where currentAnimation could be null
+ //is when all animations have been removed
+ Q_ASSERT(d->animations.isEmpty());
+ d->currentTime = 0;
+ stop();
+ }
+
+ d->lastLoop = d->currentLoop;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateState(QAbstractAnimation::State newState,
+ QAbstractAnimation::State oldState)
+{
+ Q_D(QSequentialAnimationGroup);
+ QAnimationGroup::updateState(newState, oldState);
+
+ if (!d->currentAnimation)
+ return;
+
+ switch (newState) {
+ case Stopped:
+ d->currentAnimation->stop();
+ break;
+ case Paused:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Running) {
+ d->currentAnimation->pause();
+ }
+ else
+ d->restart();
+ break;
+ case Running:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Paused)
+ d->currentAnimation->start();
+ else
+ d->restart();
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QSequentialAnimationGroup);
+ // we need to update the direction of the current animation
+ if (state() != Stopped && d->currentAnimation)
+ d->currentAnimation->setDirection(direction);
+}
+
+/*!
+ \reimp
+*/
+bool QSequentialAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ index = qMin(index, animations.count() - 1);
+
+ if (index == -1) {
+ Q_ASSERT(animations.isEmpty());
+ currentAnimationIndex = -1;
+ currentAnimation = 0;
+ return;
+ }
+
+ // need these two checks below because this func can be called after the current animation
+ // has been removed
+ if (index == currentAnimationIndex && animations.at(index) == currentAnimation)
+ return;
+
+ // stop the old current animation
+ if (currentAnimation)
+ currentAnimation->stop();
+
+ currentAnimation = animations.at(index);
+ currentAnimationIndex = index;
+
+ emit q->currentAnimationChanged(currentAnimation);
+
+ activateCurrentAnimation(intermediate);
+}
+
+void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediate)
+{
+ if (!currentAnimation || state == QSequentialAnimationGroup::Stopped)
+ return;
+
+ currentAnimation->stop();
+
+ // we ensure the direction is consistent with the group's direction
+ currentAnimation->setDirection(direction);
+
+ // connects to the finish signal of uncontrolled animations
+ if (currentAnimation->totalDuration() == -1)
+ connectUncontrolledAnimation(currentAnimation);
+
+ currentAnimation->start();
+ if (!intermediate && state == QSequentialAnimationGroup::Paused)
+ currentAnimation->pause();
+}
+
+void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QSequentialAnimationGroup);
+ Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);
+
+ // we trust the duration returned by the animation
+ while (actualDuration.size() < (currentAnimationIndex + 1))
+ actualDuration.append(-1);
+ actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
+
+ disconnectUncontrolledAnimation(currentAnimation);
+
+ if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
+ || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
+ // we don't handle looping of a group with undefined duration
+ q->stop();
+ } else if (direction == QAbstractAnimation::Forward) {
+ // set the current animation to be the next one
+ setCurrentAnimation(currentAnimationIndex + 1);
+ } else {
+ // set the current animation to be the previous one
+ setCurrentAnimation(currentAnimationIndex - 1);
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is added to
+ the group at index \a index.
+ Note: We only support insertion after the current animation
+*/
+void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
+{
+ if (currentAnimation == 0)
+ setCurrentAnimation(0); // initialize the current animation
+
+ if (currentAnimationIndex == index
+ && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
+ //in this case we simply insert an animation before the current one has actually started
+ setCurrentAnimation(index);
+ }
+
+ //we update currentAnimationIndex in case it has changed (the animation pointer is still valid)
+ currentAnimationIndex = animations.indexOf(currentAnimation);
+
+ if (index < currentAnimationIndex || currentLoop != 0) {
+ qWarning("QSequentialGroup::insertAnimation only supports to add animations after the current one.");
+ return; //we're not affected because it is added after the current one
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is removed from
+ the group at index \a index. The animation is no more listed when this
+ method is called.
+*/
+void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
+{
+ Q_Q(QSequentialAnimationGroup);
+ QAnimationGroupPrivate::animationRemoved(index, anim);
+
+ Q_ASSERT(currentAnimation); // currentAnimation should always be set
+
+ if (actualDuration.size() > index)
+ actualDuration.removeAt(index);
+
+ const int currentIndex = animations.indexOf(currentAnimation);
+ if (currentIndex == -1) {
+ //we're removing the current animation
+
+ disconnectUncontrolledAnimation(currentAnimation);
+
+ if (index < animations.count())
+ setCurrentAnimation(index); //let's try to take the next one
+ else if (index > 0)
+ setCurrentAnimation(index - 1);
+ else// case all animations were removed
+ setCurrentAnimation(-1);
+ } else if (currentAnimationIndex > index) {
+ currentAnimationIndex--;
+ }
+
+ // duration of the previous animations up to the current animation
+ currentTime = 0;
+ for (int i = 0; i < currentAnimationIndex; ++i) {
+ const int current = animationActualTotalDuration(i);
+ currentTime += current;
+ }
+
+ if (currentIndex != -1) {
+ //the current animation is not the one being removed
+ //so we add its current time to the current time of this group
+ currentTime += QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ }
+
+ //let's also update the total current time
+ totalCurrentTime = currentTime + loopCount * q->duration();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsequentialanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
new file mode 100644
index 0000000000..3bb766183f
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_H
+#define QSEQUENTIALANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimation;
+class QSequentialAnimationGroupPrivate;
+
+class Q_CORE_EXPORT QSequentialAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractAnimation* currentAnimation READ currentAnimation NOTIFY currentAnimationChanged)
+
+public:
+ QSequentialAnimationGroup(QObject *parent = 0);
+ ~QSequentialAnimationGroup();
+
+ QPauseAnimation *addPause(int msecs);
+ QPauseAnimation *insertPause(int index, int msecs);
+
+ QAbstractAnimation *currentAnimation() const;
+ int duration() const;
+
+Q_SIGNALS:
+ void currentAnimationChanged(QAbstractAnimation *current);
+
+protected:
+ QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QSequentialAnimationGroup)
+ Q_DECLARE_PRIVATE(QSequentialAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QSEQUENTIALANIMATIONGROUP_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
new file mode 100644
index 0000000000..2337e845f3
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_P_H
+#define QSEQUENTIALANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsequentialanimationgroup.h"
+#include "private/qanimationgroup_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
+public:
+ QSequentialAnimationGroupPrivate()
+ : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0)
+ { }
+
+
+ struct AnimationIndex
+ {
+ AnimationIndex() : index(0), timeOffset(0) {}
+ // index points to the animation at timeOffset, skipping 0 duration animations.
+ // Note that the index semantic is slightly different depending on the direction.
+ int index; // the index of the animation in timeOffset
+ int timeOffset; // time offset when the animation at index starts.
+ };
+
+ int animationActualTotalDuration(int index) const;
+ AnimationIndex indexForCurrentTime() const;
+
+ void setCurrentAnimation(int index, bool intermediate = false);
+ void activateCurrentAnimation(bool intermediate = false);
+
+ void animationInsertedAt(int index);
+ void animationRemoved(int index, QAbstractAnimation *anim);
+
+ bool atEnd() const;
+
+ QAbstractAnimation *currentAnimation;
+ int currentAnimationIndex;
+
+ // this is the actual duration of uncontrolled animations
+ // it helps seeking and even going forward
+ QList<int> actualDuration;
+
+ void restart();
+ int lastLoop;
+
+ // handle time changes
+ void rewindForwards(const AnimationIndex &newAnimationIndex);
+ void advanceForwards(const AnimationIndex &newAnimationIndex);
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
new file mode 100644
index 0000000000..c76cb89ff9
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -0,0 +1,701 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvariantanimation.h"
+#include "qvariantanimation_p.h"
+
+#include <QtCore/qrect.h>
+#include <QtCore/qline.h>
+#include <QtCore/qmutex.h>
+#include <private/qmutexpool_p.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVariantAnimation
+ \ingroup animation
+ \brief The QVariantAnimation class provides an abstract base class for animations.
+ \since 4.6
+
+ This class is part of \l{The Animation Framework}. It serves as a
+ base class for property and item animations, with functions for
+ shared functionality.
+
+ QVariantAnimation cannot be used directly as it is an abstract
+ class; it has a pure virtual method called updateCurrentValue().
+ The class performs interpolation over
+ \l{QVariant}s, but leaves using the interpolated values to its
+ subclasses. Currently, Qt provides QPropertyAnimation, which
+ animates Qt \l{Qt's Property System}{properties}. See the
+ QPropertyAnimation class description if you wish to animate such
+ properties.
+
+ You can then set start and end values for the property by calling
+ setStartValue() and setEndValue(), and finally call start() to
+ start the animation. QVariantAnimation will interpolate the
+ property of the target object and emit valueChanged(). To react to
+ a change in the current value you have to reimplement the
+ updateCurrentValue() virtual function.
+
+ It is also possible to set values at specified steps situated
+ between the start and end value. The interpolation will then
+ touch these points at the specified steps. Note that the start and
+ end values are defined as the key values at 0.0 and 1.0.
+
+ There are two ways to affect how QVariantAnimation interpolates
+ the values. You can set an easing curve by calling
+ setEasingCurve(), and configure the duration by calling
+ setDuration(). You can change how the QVariants are interpolated
+ by creating a subclass of QVariantAnimation, and reimplementing
+ the virtual interpolated() function.
+
+ Subclassing QVariantAnimation can be an alternative if you have
+ \l{QVariant}s that you do not wish to declare as Qt properties.
+ Note, however, that you in most cases will be better off declaring
+ your QVariant as a property.
+
+ Not all QVariant types are supported. Below is a list of currently
+ supported QVariant types:
+
+ \list
+ \o \l{QMetaType::}{Int}
+ \o \l{QMetaType::}{Double}
+ \o \l{QMetaType::}{Float}
+ \o \l{QMetaType::}{QLine}
+ \o \l{QMetaType::}{QLineF}
+ \o \l{QMetaType::}{QPoint}
+ \o \l{QMetaType::}{QPointF}
+ \o \l{QMetaType::}{QSize}
+ \o \l{QMetaType::}{QSizeF}
+ \o \l{QMetaType::}{QRect}
+ \o \l{QMetaType::}{QRectF}
+ \o \l{QMetaType::}{QColor}
+ \endlist
+
+ If you need to interpolate other variant types, including custom
+ types, you have to implement interpolation for these yourself.
+ To do this, you can register an interpolator function for a given
+ type. This function takes 3 parameters: the start value, the end value
+ and the current progress.
+
+ Example:
+ \code
+ QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
+ {
+ ...
+ return QColor(...);
+ }
+ ...
+ qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
+ \endcode
+
+ Another option is to reimplement interpolated(), which returns
+ interpolation values for the value being interpolated.
+
+ \omit We need some snippets around here. \endomit
+
+ \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
+*/
+
+/*!
+ \fn void QVariantAnimation::valueChanged(const QVariant &value)
+
+ QVariantAnimation emits this signal whenever the current \a value changes.
+
+ \sa currentValue, startValue, endValue
+*/
+
+/*!
+ \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
+
+ This pure virtual function is called every time the animation's current
+ value changes. The \a value argument is the new current value.
+
+ \sa currentValue
+*/
+
+static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
+{
+ return p1.first < p2.first;
+}
+
+static QVariant defaultInterpolator(const void *, const void *, qreal)
+{
+ return QVariant();
+}
+
+template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
+{
+ QRect ret;
+ ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
+ _q_interpolate(f.top(), t.top(), progress),
+ _q_interpolate(f.right(), t.right(), progress),
+ _q_interpolate(f.bottom(), t.bottom(), progress));
+ return ret;
+}
+
+template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
+{
+ qreal x1, y1, w1, h1;
+ f.getRect(&x1, &y1, &w1, &h1);
+ qreal x2, y2, w2, h2;
+ t.getRect(&x2, &y2, &w2, &h2);
+ return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
+ _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
+{
+ return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
+{
+ return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolator(&defaultInterpolator)
+{ }
+
+void QVariantAnimationPrivate::convertValues(int t)
+{
+ //this ensures that all the keyValues are of type t
+ for (int i = 0; i < keyValues.count(); ++i) {
+ QVariantAnimation::KeyValue &pair = keyValues[i];
+ pair.second.convert(static_cast<QVariant::Type>(t));
+ }
+ //we also need update to the current interval if needed
+ currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
+ currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
+
+ //... and the interpolator
+ updateInterpolator();
+}
+
+void QVariantAnimationPrivate::updateInterpolator()
+{
+ int type = currentInterval.start.second.userType();
+ if (type == currentInterval.end.second.userType())
+ interpolator = getInterpolator(type);
+ else
+ interpolator = 0;
+
+ //we make sure that the interpolator is always set to something
+ if (!interpolator)
+ interpolator = &defaultInterpolator;
+}
+
+/*!
+ \internal
+ The goal of this function is to update the currentInterval member. As a consequence, we also
+ need to update the currentValue.
+ Set \a force to true to always recalculate the interval.
+*/
+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)
+ return;
+
+ const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
+
+ //0 and 1 are still the boundaries
+ if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
+ || (currentInterval.end.first < 1 && progress > currentInterval.end.first)) {
+ //let's update currentInterval
+ QVariantAnimation::KeyValues::const_iterator it = qLowerBound(keyValues.constBegin(),
+ keyValues.constEnd(),
+ qMakePair(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) {
+ currentInterval.start = *it;
+ currentInterval.end = *(it+1);
+ } else {
+ currentInterval.start = qMakePair(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) {
+ //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);
+ }
+ } else {
+ currentInterval.start = *(it-1);
+ currentInterval.end = *it;
+ }
+
+ // update all the values of the currentInterval
+ updateInterpolator();
+ }
+ setCurrentValueForProgress(progress);
+}
+
+void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
+{
+ Q_Q(QVariantAnimation);
+
+ const qreal startProgress = currentInterval.start.first;
+ const qreal endProgress = currentInterval.end.first;
+ const qreal localProgress = (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);
+ if (!changedSignalIndex) {
+ //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
+ changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
+ }
+ if (isSignalConnected(changedSignalIndex) && currentValue != ret) {
+ //the value has changed
+ emit q->valueChanged(currentValue);
+ }
+}
+
+QVariant QVariantAnimationPrivate::valueAt(qreal step) const
+{
+ QVariantAnimation::KeyValues::const_iterator result =
+ qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
+ if (result != keyValues.constEnd())
+ return result->second;
+
+ return QVariant();
+}
+
+void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
+{
+ if (step < qreal(0.0) || step > qreal(1.0)) {
+ qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
+ return;
+ }
+
+ QVariantAnimation::KeyValue pair(step, value);
+
+ QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
+ if (result == keyValues.end() || result->first != step) {
+ keyValues.insert(result, pair);
+ } else {
+ if (value.isValid())
+ result->second = value; // replaces the previous value
+ else
+ keyValues.erase(result); // removes the previous value
+ }
+
+ recalculateCurrentInterval(/*force=*/true);
+}
+
+void QVariantAnimationPrivate::setDefaultStartEndValue(const QVariant &value)
+{
+ defaultStartEndValue = value;
+ recalculateCurrentInterval(/*force=*/true);
+}
+
+/*!
+ Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
+ constructor.
+*/
+QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation.
+*/
+QVariantAnimation::~QVariantAnimation()
+{
+}
+
+/*!
+ \property QVariantAnimation::easingCurve
+ \brief the easing curve of the animation
+
+ This property defines the easing curve of the animation. By
+ default, a linear easing curve is used, resulting in linear
+ interpolation. Other curves are provided, for instance,
+ QEasingCurve::InCirc, which provides a circular entry curve.
+ Another example is QEasingCurve::InOutElastic, which provides an
+ elastic effect on the values of the interpolated variant.
+
+ QVariantAnimation will use the QEasingCurve::valueForProgress() to
+ transform the "normalized progress" (currentTime / totalDuration)
+ of the animation into the effective progress actually
+ used by the animation. It is this effective progress that will be
+ the progress when interpolated() is called. Also, the steps in the
+ keyValues are referring to this effective progress.
+
+ The easing curve is used with the interpolator, the interpolated()
+ virtual function, the animation's duration, and iterationCount, to
+ control how the current value changes as the animation progresses.
+*/
+QEasingCurve QVariantAnimation::easingCurve() const
+{
+ Q_D(const QVariantAnimation);
+ return d->easing;
+}
+
+void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
+{
+ Q_D(QVariantAnimation);
+ d->easing = easing;
+ d->recalculateCurrentInterval();
+}
+
+typedef QVector<QVariantAnimation::Interpolator> QInterpolatorVector;
+Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
+
+/*!
+ \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+ \relates QVariantAnimation
+ \threadsafe
+
+ Registers a custom interpolator \a func for the template type \c{T}.
+ The interpolator has to be registered before the animation is constructed.
+ To unregister (and use the default interpolator) set \a func to 0.
+ */
+
+/*!
+ \internal
+ \typedef QVariantAnimation::Interpolator
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+ \code
+ QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
+ \endcode
+
+*/
+
+/*! \internal
+ * Registers a custom interpolator \a func for the specific \a interpolationType.
+ * The interpolator has to be registered before the animation is constructed.
+ * To unregister (and use the default interpolator) set \a func to 0.
+ */
+void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
+{
+ // will override any existing interpolators
+ QInterpolatorVector *interpolators = registeredInterpolators();
+ // When built on solaris with GCC, the destructors can be called
+ // in such an order that we get here with interpolators == NULL,
+ // to continue causes the app to crash on exit with a SEGV
+ if (interpolators) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
+#endif
+ if (int(interpolationType) >= interpolators->count())
+ interpolators->resize(int(interpolationType) + 1);
+ interpolators->replace(interpolationType, func);
+ }
+}
+
+
+template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+{
+ return reinterpret_cast<QVariantAnimation::Interpolator>(func);
+}
+
+QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
+{
+ QInterpolatorVector *interpolators = registeredInterpolators();
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
+#endif
+ QVariantAnimation::Interpolator ret = 0;
+ if (interpolationType < interpolators->count()) {
+ ret = interpolators->at(interpolationType);
+ if (ret) return ret;
+ }
+
+ switch(interpolationType)
+ {
+ case QMetaType::Int:
+ return castToInterpolator(_q_interpolateVariant<int>);
+ case QMetaType::Double:
+ return castToInterpolator(_q_interpolateVariant<double>);
+ case QMetaType::Float:
+ return castToInterpolator(_q_interpolateVariant<float>);
+ case QMetaType::QLine:
+ return castToInterpolator(_q_interpolateVariant<QLine>);
+ case QMetaType::QLineF:
+ return castToInterpolator(_q_interpolateVariant<QLineF>);
+ case QMetaType::QPoint:
+ return castToInterpolator(_q_interpolateVariant<QPoint>);
+ case QMetaType::QPointF:
+ return castToInterpolator(_q_interpolateVariant<QPointF>);
+ case QMetaType::QSize:
+ return castToInterpolator(_q_interpolateVariant<QSize>);
+ case QMetaType::QSizeF:
+ return castToInterpolator(_q_interpolateVariant<QSizeF>);
+ case QMetaType::QRect:
+ return castToInterpolator(_q_interpolateVariant<QRect>);
+ case QMetaType::QRectF:
+ return castToInterpolator(_q_interpolateVariant<QRectF>);
+ default:
+ return 0; //this type is not handled
+ }
+}
+
+/*!
+ \property QVariantAnimation::duration
+ \brief the duration of the animation
+
+ This property describes the duration in milliseconds of the
+ animation. The default duration is 250 milliseconds.
+
+ \sa QAbstractAnimation::duration()
+ */
+int QVariantAnimation::duration() const
+{
+ Q_D(const QVariantAnimation);
+ return d->duration;
+}
+
+void QVariantAnimation::setDuration(int msecs)
+{
+ Q_D(QVariantAnimation);
+ if (msecs < 0) {
+ qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ if (d->duration == msecs)
+ return;
+ d->duration = msecs;
+ d->recalculateCurrentInterval();
+}
+
+/*!
+ \property QVariantAnimation::startValue
+ \brief the optional start value of the animation
+
+ This property describes the optional start value of the animation. If
+ omitted, or if a null QVariant is assigned as the start value, the
+ animation will use the current position of the end when the animation
+ is started.
+
+ \sa endValue
+*/
+QVariant QVariantAnimation::startValue() const
+{
+ return keyValueAt(0);
+}
+
+void QVariantAnimation::setStartValue(const QVariant &value)
+{
+ setKeyValueAt(0, value);
+}
+
+/*!
+ \property QVariantAnimation::endValue
+ \brief the end value of the animation
+
+ This property describes the end value of the animation.
+
+ \sa startValue
+ */
+QVariant QVariantAnimation::endValue() const
+{
+ return keyValueAt(1);
+}
+
+void QVariantAnimation::setEndValue(const QVariant &value)
+{
+ setKeyValueAt(1, value);
+}
+
+
+/*!
+ Returns the key frame value for the given \a step. The given \a step
+ must be in the range 0 to 1. If there is no KeyValue for \a step,
+ it returns an invalid QVariant.
+
+ \sa keyValues(), setKeyValueAt()
+*/
+QVariant QVariantAnimation::keyValueAt(qreal step) const
+{
+ return d_func()->valueAt(step);
+}
+
+/*!
+ \typedef QVariantAnimation::KeyValue
+
+ This is a typedef for QPair<qreal, QVariant>.
+*/
+/*!
+ \typedef QVariantAnimation::KeyValues
+
+ This is a typedef for QVector<KeyValue>
+*/
+
+/*!
+ Creates a key frame at the given \a step with the given \a value.
+ The given \a step must be in the range 0 to 1.
+
+ \sa setKeyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
+{
+ d_func()->setValueAt(step, value);
+}
+
+/*!
+ Returns the key frames of this animation.
+
+ \sa keyValueAt(), setKeyValues()
+*/
+QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
+{
+ return d_func()->keyValues;
+}
+
+/*!
+ Replaces the current set of key frames with the given \a keyValues.
+ the step of the key frames must be in the range 0 to 1.
+
+ \sa keyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
+{
+ Q_D(QVariantAnimation);
+ d->keyValues = keyValues;
+ qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
+ d->recalculateCurrentInterval(/*force=*/true);
+}
+
+/*!
+ \property QVariantAnimation::currentValue
+ \brief the current value of the animation.
+
+ This property describes the current value; an interpolated value
+ between the \l{startValue}{start value} and the \l{endValue}{end
+ value}, using the current time for progress. The value itself is
+ obtained from interpolated(), which is called repeatedly as the
+ animation is running.
+
+ QVariantAnimation calls the virtual updateCurrentValue() function
+ when the current value changes. This is particularly useful for
+ subclasses that need to track updates. For example,
+ QPropertyAnimation uses this function to animate Qt \l{Qt's
+ Property System}{properties}.
+
+ \sa startValue, endValue
+*/
+QVariant QVariantAnimation::currentValue() const
+{
+ Q_D(const QVariantAnimation);
+ if (!d->currentValue.isValid())
+ const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
+ return d->currentValue;
+}
+
+/*!
+ \reimp
+ */
+bool QVariantAnimation::event(QEvent *event)
+{
+ return QAbstractAnimation::event(event);
+}
+
+/*!
+ \reimp
+*/
+void QVariantAnimation::updateState(QAbstractAnimation::State newState,
+ QAbstractAnimation::State oldState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+
+ This virtual function returns the linear interpolation between
+ variants \a from and \a to, at \a progress, usually a value
+ between 0 and 1. You can reimplement this function in a subclass
+ of QVariantAnimation to provide your own interpolation algorithm.
+
+ Note that in order for the interpolation to work with a
+ QEasingCurve that return a value smaller than 0 or larger than 1
+ (such as QEasingCurve::InBack) you should make sure that it can
+ extrapolate. If the semantic of the datatype does not allow
+ extrapolation this function should handle that gracefully.
+
+ You should call the QVariantAnimation implementation of this
+ function if you want your class to handle the types already
+ supported by Qt (see class QVariantAnimation description for a
+ list of supported types).
+
+ \sa QEasingCurve
+ */
+QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ return d_func()->interpolator(from.constData(), to.constData(), progress);
+}
+
+/*!
+ \reimp
+ */
+void QVariantAnimation::updateCurrentTime(int)
+{
+ d_func()->recalculateCurrentInterval();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qvariantanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
new file mode 100644
index 0000000000..d6badf513a
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_H
+#define QANIMATION_H
+
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qabstractanimation.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QVariantAnimationPrivate;
+class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ 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)
+
+public:
+ typedef QPair<qreal, QVariant> KeyValue;
+ typedef QVector<KeyValue> KeyValues;
+
+ QVariantAnimation(QObject *parent = 0);
+ ~QVariantAnimation();
+
+ QVariant startValue() const;
+ void setStartValue(const QVariant &value);
+
+ QVariant endValue() const;
+ void setEndValue(const QVariant &value);
+
+ QVariant keyValueAt(qreal step) const;
+ void setKeyValueAt(qreal step, const QVariant &value);
+
+ KeyValues keyValues() const;
+ void setKeyValues(const KeyValues &values);
+
+ QVariant currentValue() const;
+
+ int duration() const;
+ void setDuration(int msecs);
+
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &easing);
+
+ typedef QVariant (*Interpolator)(const void *from, const void *to, qreal progress);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &value);
+
+protected:
+ QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+
+ virtual void updateCurrentValue(const QVariant &value) = 0;
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+
+private:
+ template <typename T> friend void qRegisterAnimationInterpolator(QVariant (*func)(const T &, const T &, qreal));
+ static void registerInterpolator(Interpolator func, int interpolationType);
+
+ Q_DISABLE_COPY(QVariantAnimation)
+ Q_DECLARE_PRIVATE(QVariantAnimation)
+};
+
+template <typename T>
+void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress)) {
+ QVariantAnimation::registerInterpolator(reinterpret_cast<QVariantAnimation::Interpolator>(func), qMetaTypeId<T>());
+}
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATION_H
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
new file mode 100644
index 0000000000..2a8d9d4f07
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_P_H
+#define QANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qvariantanimation.h"
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvector.h>
+
+#include "private/qabstractanimation_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QVariantAnimationPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QVariantAnimation)
+public:
+
+ QVariantAnimationPrivate();
+
+ static QVariantAnimationPrivate *get(QVariantAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ void setDefaultStartEndValue(const QVariant &value);
+
+
+ QVariant currentValue;
+ QVariant defaultStartEndValue;
+
+ //this is used to keep track of the KeyValue interval in which we currently are
+ struct
+ {
+ QVariantAnimation::KeyValue start, end;
+ } currentInterval;
+
+ QEasingCurve easing;
+ int duration;
+ QVariantAnimation::KeyValues keyValues;
+ QVariantAnimation::Interpolator interpolator;
+
+ void setCurrentValueForProgress(const qreal progress);
+ void recalculateCurrentInterval(bool force=false);
+ void setValueAt(qreal, const QVariant &);
+ QVariant valueAt(qreal step) const;
+ void convertValues(int t);
+
+ void updateInterpolator();
+
+ //XXX this is needed by dui
+ static Q_CORE_EXPORT QVariantAnimation::Interpolator getInterpolator(int interpolationType);
+};
+
+//this should make the interpolation faster
+template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
+{
+ return T(f + (t - f) * progress);
+}
+
+template<typename T > inline QVariant _q_interpolateVariant(const T &from, const T &to, qreal progress)
+{
+ return _q_interpolate(from, to, progress);
+}
+
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
+
+#endif //QANIMATION_P_H
diff --git a/src/corelib/arch/alpha/arch.pri b/src/corelib/arch/alpha/arch.pri
new file mode 100644
index 0000000000..448a531f07
--- /dev/null
+++ b/src/corelib/arch/alpha/arch.pri
@@ -0,0 +1,4 @@
+#
+# Alpha architecture
+#
+!*-g++*:SOURCES += $$QT_ARCH_CPP/qatomic_alpha.s
diff --git a/src/corelib/arch/alpha/qatomic_alpha.s b/src/corelib/arch/alpha/qatomic_alpha.s
new file mode 100644
index 0000000000..d225de794b
--- /dev/null
+++ b/src/corelib/arch/alpha/qatomic_alpha.s
@@ -0,0 +1,239 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .set noreorder
+ .set volatile
+ .set noat
+ .arch ev4
+ .text
+ .align 2
+ .align 4
+ .globl q_atomic_test_and_set_int
+ .ent q_atomic_test_and_set_int
+q_atomic_test_and_set_int:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ cmpeq $0,$17,$0
+ beq $0,3f
+ mov $18,$0
+ stl_c $0,0($16)
+ beq $0,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_test_and_set_int
+ .align 2
+ .align 4
+ .globl q_atomic_test_and_set_acquire_int
+ .ent q_atomic_test_and_set_acquire_int
+q_atomic_test_and_set_acquire_int:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ cmpeq $0,$17,$0
+ beq $0,3f
+ mov $18,$0
+ stl_c $0,0($16)
+ beq $0,2f
+ br 3f
+2: br 1b
+3: mb
+ addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_test_and_set_acquire_int
+ .align 2
+ .align 4
+ .globl q_atomic_test_and_set_release_int
+ .ent q_atomic_test_and_set_release_int
+q_atomic_test_and_set_release_int:
+ .frame $30,0,$26,0
+ .prologue 0
+ mb
+1: ldl_l $0,0($16)
+ cmpeq $0,$17,$0
+ beq $0,3f
+ mov $18,$0
+ stl_c $0,0($16)
+ beq $0,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_test_and_set_release_int
+ .align 2
+ .align 4
+ .globl q_atomic_test_and_set_ptr
+ .ent q_atomic_test_and_set_ptr
+q_atomic_test_and_set_ptr:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldq_l $0,0($16)
+ cmpeq $0,$17,$0
+ beq $0,3f
+ mov $18,$0
+ stq_c $0,0($16)
+ beq $0,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_test_and_set_ptr
+ .align 2
+ .align 4
+ .globl q_atomic_increment
+ .ent q_atomic_increment
+q_atomic_increment:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ addl $0,1,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ cmpeq $0,$1,$0
+ xor $0,1,$0
+ ret $31,($26),1
+ .end q_atomic_increment
+ .align 2
+ .align 4
+ .globl q_atomic_decrement
+ .ent q_atomic_decrement
+q_atomic_decrement:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ subl $0,1,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ cmpeq $0,1,$0
+ xor $0,1,$0
+ ret $31,($26),1
+ .end q_atomic_decrement
+ .align 2
+ .align 4
+ .globl q_atomic_set_int
+ .ent q_atomic_set_int
+q_atomic_set_int:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ mov $17,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_set_int
+ .align 2
+ .align 4
+ .globl q_atomic_set_ptr
+ .ent q_atomic_set_ptr
+q_atomic_set_ptr:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldq_l $0,0($16)
+ mov $17,$1
+ stq_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: ret $31,($26),1
+ .end q_atomic_set_ptr
+
+ .align 2
+ .align 4
+ .globl q_atomic_fetch_and_add_int
+ .ent q_atomic_fetch_and_add_int
+q_atomic_fetch_and_add_int:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ addl $0,$17,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_fetch_and_add_int
+
+ .align 2
+ .align 4
+ .globl q_atomic_fetch_and_add_acquire_int
+ .ent q_atomic_fetch_and_add_acquire_int
+q_atomic_fetch_and_add_acquire_int:
+ .frame $30,0,$26,0
+ .prologue 0
+1: ldl_l $0,0($16)
+ addl $0,$17,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: mb
+ addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_fetch_and_add_acquire_int
+
+ .align 2
+ .align 4
+ .globl q_atomic_fetch_and_add_release_int
+ .ent q_atomic_fetch_and_add_release_int
+q_atomic_fetch_and_add_release_int:
+ .frame $30,0,$26,0
+ .prologue 0
+ mb
+1: ldl_l $0,0($16)
+ addl $0,$17,$1
+ stl_c $1,0($16)
+ beq $1,2f
+ br 3f
+2: br 1b
+3: addl $31,$0,$0
+ ret $31,($26),1
+ .end q_atomic_fetch_and_add_release_int
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri
new file mode 100644
index 0000000000..cd23e5e855
--- /dev/null
+++ b/src/corelib/arch/arch.pri
@@ -0,0 +1,38 @@
+win32:HEADERS += arch/qatomic_windows.h \
+ arch/qatomic_generic.h
+
+win32-g++*:HEADERS += arch/qatomic_i386.h \
+ arch/qatomic_x86_64.h
+
+mac:HEADERS += arch/qatomic_macosx.h \
+ arch/qatomic_generic.h
+
+symbian:HEADERS += arch/qatomic_symbian.h \
+ arch/qatomic_generic.h
+
+vxworks:HEADERS += arch/qatomic_vxworks.h
+
+integrity:HEADERS += arch/qatomic_integrity.h
+
+!wince*:!win32:!mac:!symbian:HEADERS += arch/qatomic_alpha.h \
+ arch/qatomic_avr32.h \
+ arch/qatomic_ia64.h \
+ arch/qatomic_parisc.h \
+ arch/qatomic_sparc.h \
+ arch/qatomic_arch.h \
+ arch/qatomic_generic.h \
+ arch/qatomic_powerpc.h \
+ arch/qatomic_arm.h \
+ arch/qatomic_armv5.h \
+ arch/qatomic_armv6.h \
+ arch/qatomic_armv7.h \
+ arch/qatomic_i386.h \
+ arch/qatomic_mips.h \
+ arch/qatomic_s390.h \
+ arch/qatomic_x86_64.h \
+ arch/qatomic_sh.h \
+ arch/qatomic_sh4a.h
+
+QT_ARCH_CPP = $$QT_SOURCE_TREE/src/corelib/arch/$$QT_ARCH
+DEPENDPATH += $$QT_ARCH_CPP
+include($$QT_ARCH_CPP/arch.pri, "", true)
diff --git a/src/corelib/arch/arm/arch.pri b/src/corelib/arch/arm/arch.pri
new file mode 100644
index 0000000000..79e4bfc115
--- /dev/null
+++ b/src/corelib/arch/arm/arch.pri
@@ -0,0 +1,4 @@
+#
+# ARM architecture
+#
+SOURCES += $$QT_ARCH_CPP/qatomic_arm.cpp
diff --git a/src/corelib/arch/arm/qatomic_arm.cpp b/src/corelib/arch/arm/qatomic_arm.cpp
new file mode 100644
index 0000000000..8f06515247
--- /dev/null
+++ b/src/corelib/arch/arm/qatomic_arm.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+# include <sched.h>
+#endif
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+Q_CORE_EXPORT char q_atomic_lock = 0;
+
+Q_CORE_EXPORT void qt_atomic_yield(int *count)
+{
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ if((*count)++ < 50) {
+ sched_yield();
+ } else
+#endif
+ {
+ struct timespec tm;
+ tm.tv_sec = 0;
+ tm.tv_nsec = 2000001;
+ nanosleep(&tm, NULL);
+ *count = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/arch/avr32/arch.pri b/src/corelib/arch/avr32/arch.pri
new file mode 100644
index 0000000000..37f231ee61
--- /dev/null
+++ b/src/corelib/arch/avr32/arch.pri
@@ -0,0 +1,3 @@
+#
+# AVR32 architecture
+#
diff --git a/src/corelib/arch/bfin/arch.pri b/src/corelib/arch/bfin/arch.pri
new file mode 100644
index 0000000000..fa198ae8bb
--- /dev/null
+++ b/src/corelib/arch/bfin/arch.pri
@@ -0,0 +1,3 @@
+#
+# Blackfin architecture
+#
diff --git a/src/corelib/arch/generic/arch.pri b/src/corelib/arch/generic/arch.pri
new file mode 100644
index 0000000000..8fee63fa5d
--- /dev/null
+++ b/src/corelib/arch/generic/arch.pri
@@ -0,0 +1,6 @@
+#
+# 'generic' architecture
+#
+
+unix:SOURCES += qatomic_generic_unix.cpp
+win32:SOURCES += qatomic_generic_windows.cpp
diff --git a/src/corelib/arch/generic/qatomic_generic_unix.cpp b/src/corelib/arch/generic/qatomic_generic_unix.cpp
new file mode 100644
index 0000000000..5ab4c6b943
--- /dev/null
+++ b/src/corelib/arch/generic/qatomic_generic_unix.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(Q_OS_SYMBIAN) || (defined(Q_OS_SYMBIAN) && !defined(Q_CC_RVCT))
+
+#include "qplatformdefs.h"
+
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_NAMESPACE
+static pthread_mutex_t qAtomicMutex = PTHREAD_MUTEX_INITIALIZER;
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ bool returnValue = false;
+ pthread_mutex_lock(&qAtomicMutex);
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ int returnValue;
+ pthread_mutex_lock(&qAtomicMutex);
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ int returnValue;
+ pthread_mutex_lock(&qAtomicMutex);
+ returnValue = *_q_value;
+ *_q_value += valueToAdd;
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ bool returnValue = false;
+ pthread_mutex_lock(&qAtomicMutex);
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ void *returnValue;
+ pthread_mutex_lock(&qAtomicMutex);
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ void *returnValue;
+ pthread_mutex_lock(&qAtomicMutex);
+ returnValue = *_q_value;
+ *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd;
+ pthread_mutex_unlock(&qAtomicMutex);
+ return returnValue;
+}
+QT_END_NAMESPACE
+#endif //!defined(Q_OS_SYMBIAN) && !defined(Q_CC_RVCT)
diff --git a/src/corelib/arch/generic/qatomic_generic_windows.cpp b/src/corelib/arch/generic/qatomic_generic_windows.cpp
new file mode 100644
index 0000000000..c2496db45c
--- /dev/null
+++ b/src/corelib/arch/generic/qatomic_generic_windows.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include <QtCore/qatomic.h>
+
+
+class QCriticalSection
+{
+public:
+ QCriticalSection() { InitializeCriticalSection(&section); }
+ ~QCriticalSection() { DeleteCriticalSection(&section); }
+ void lock() { EnterCriticalSection(&section); }
+ void unlock() { LeaveCriticalSection(&section); }
+
+private:
+ CRITICAL_SECTION section;
+};
+
+static QCriticalSection qAtomicCriticalSection;
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value += valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
diff --git a/src/corelib/arch/i386/arch.pri b/src/corelib/arch/i386/arch.pri
new file mode 100644
index 0000000000..3101dae01b
--- /dev/null
+++ b/src/corelib/arch/i386/arch.pri
@@ -0,0 +1,4 @@
+#
+# i386 architecture
+#
+!*-g++*:!*-icc*:SOURCES += $$QT_ARCH_CPP/qatomic_i386.s
diff --git a/src/corelib/arch/i386/qatomic_i386.s b/src/corelib/arch/i386/qatomic_i386.s
new file mode 100644
index 0000000000..08158f926b
--- /dev/null
+++ b/src/corelib/arch/i386/qatomic_i386.s
@@ -0,0 +1,103 @@
+ .text
+
+ .align 4,0x90
+ .globl q_atomic_test_and_set_int
+q_atomic_test_and_set_int:
+ movl 4(%esp),%ecx
+ movl 8(%esp),%eax
+ movl 12(%esp),%edx
+ lock
+ cmpxchgl %edx,(%ecx)
+ mov $0,%eax
+ sete %al
+ ret
+ .align 4,0x90
+ .type q_atomic_test_and_set_int,@function
+ .size q_atomic_test_and_set_int,.-q_atomic_test_and_set_int
+
+ .align 4,0x90
+ .globl q_atomic_test_and_set_ptr
+q_atomic_test_and_set_ptr:
+ movl 4(%esp),%ecx
+ movl 8(%esp),%eax
+ movl 12(%esp),%edx
+ lock
+ cmpxchgl %edx,(%ecx)
+ mov $0,%eax
+ sete %al
+ ret
+ .align 4,0x90
+ .type q_atomic_test_and_set_ptr,@function
+ .size q_atomic_test_and_set_ptr,.-q_atomic_test_and_set_ptr
+
+ .align 4,0x90
+ .globl q_atomic_increment
+q_atomic_increment:
+ movl 4(%esp), %ecx
+ lock
+ incl (%ecx)
+ mov $0,%eax
+ setne %al
+ ret
+ .align 4,0x90
+ .type q_atomic_increment,@function
+ .size q_atomic_increment,.-q_atomic_increment
+
+ .align 4,0x90
+ .globl q_atomic_decrement
+q_atomic_decrement:
+ movl 4(%esp), %ecx
+ lock
+ decl (%ecx)
+ mov $0,%eax
+ setne %al
+ ret
+ .align 4,0x90
+ .type q_atomic_decrement,@function
+ .size q_atomic_decrement,.-q_atomic_decrement
+
+ .align 4,0x90
+ .globl q_atomic_set_int
+q_atomic_set_int:
+ mov 4(%esp),%ecx
+ mov 8(%esp),%eax
+ xchgl %eax,(%ecx)
+ ret
+ .align 4,0x90
+ .type q_atomic_set_int,@function
+ .size q_atomic_set_int,.-q_atomic_set_int
+
+ .align 4,0x90
+ .globl q_atomic_set_ptr
+q_atomic_set_ptr:
+ mov 4(%esp),%ecx
+ mov 8(%esp),%eax
+ xchgl %eax,(%ecx)
+ ret
+ .align 4,0x90
+ .type q_atomic_set_ptr,@function
+ .size q_atomic_set_ptr,.-q_atomic_set_ptr
+
+ .align 4,0x90
+ .globl q_atomic_fetch_and_add_int
+q_atomic_fetch_and_add_int:
+ mov 4(%esp),%ecx
+ mov 8(%esp),%eax
+ lock
+ xadd %eax,(%ecx)
+ ret
+ .align 4,0x90
+ .type q_atomic_fetch_and_add_int,@function
+ .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int
+
+ .align 4,0x90
+ .globl q_atomic_fetch_and_add_ptr
+q_atomic_fetch_and_add_ptr:
+ mov 4(%esp),%ecx
+ mov 8(%esp),%eax
+ lock
+ xadd %eax,(%ecx)
+ ret
+ .align 4,0x90
+ .type q_atomic_fetch_and_add_ptr,@function
+ .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr
diff --git a/src/corelib/arch/ia64/arch.pri b/src/corelib/arch/ia64/arch.pri
new file mode 100644
index 0000000000..63afa967a4
--- /dev/null
+++ b/src/corelib/arch/ia64/arch.pri
@@ -0,0 +1,4 @@
+#
+# Intel Itanium architecture
+#
+!*-g++:!*-icc:!hpuxi-acc-*:SOURCES += $$QT_ARCH_CPP/qatomic_ia64.s
diff --git a/src/corelib/arch/ia64/qatomic_ia64.s b/src/corelib/arch/ia64/qatomic_ia64.s
new file mode 100644
index 0000000000..c988cfcd10
--- /dev/null
+++ b/src/corelib/arch/ia64/qatomic_ia64.s
@@ -0,0 +1,74 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .pred.safe_across_calls p1-p5,p16-p63
+.text
+ .align 16
+ .global q_atomic_test_and_set_int#
+ .proc q_atomic_test_and_set_int#
+q_atomic_test_and_set_int:
+ .prologue
+ .body
+ mov ar.ccv=r33
+ ;;
+ cmpxchg4.acq r34=[r32],r34,ar.ccv
+ ;;
+ cmp4.eq p6, p7 = r33, r34
+ ;;
+ (p6) addl r8 = 1, r0
+ (p7) mov r8 = r0
+ br.ret.sptk.many b0
+ .endp q_atomic_test_and_set_int#
+ .align 16
+ .global q_atomic_test_and_set_ptr#
+ .proc q_atomic_test_and_set_ptr#
+q_atomic_test_and_set_ptr:
+ .prologue
+ .body
+ mov ar.ccv=r33
+ ;;
+ cmpxchg8.acq r34=[r32],r34,ar.ccv
+ ;;
+ cmp.eq p6, p7 = r33, r34
+ ;;
+ (p6) addl r8 = 1, r0
+ (p7) mov r8 = r0
+ br.ret.sptk.many b0
+ .endp q_atomic_test_and_set_ptr#
diff --git a/src/corelib/arch/integrity/arch.pri b/src/corelib/arch/integrity/arch.pri
new file mode 100644
index 0000000000..2c4196ec32
--- /dev/null
+++ b/src/corelib/arch/integrity/arch.pri
@@ -0,0 +1,3 @@
+#
+# INTEGRITY RTOS architecture
+#
diff --git a/src/corelib/arch/macosx/arch.pri b/src/corelib/arch/macosx/arch.pri
new file mode 100644
index 0000000000..a2b1bf759a
--- /dev/null
+++ b/src/corelib/arch/macosx/arch.pri
@@ -0,0 +1,6 @@
+#
+# Mac OS X architecture
+#
+
+# Left blank intentionally since all the current compilers that we support can
+# handle in-line assembly.
diff --git a/src/corelib/arch/macosx/qatomic32_ppc.s b/src/corelib/arch/macosx/qatomic32_ppc.s
new file mode 100644
index 0000000000..c9a318dccd
--- /dev/null
+++ b/src/corelib/arch/macosx/qatomic32_ppc.s
@@ -0,0 +1,169 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .section __TEXT,__text,regular,pure_instructions
+ .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+ .align 2
+ .globl _q_atomic_test_and_set_int
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_test_and_set_int:
+ lwarx r6,0,r3
+ cmpw r6,r4
+ bne- $+20
+ stwcx. r5,0,r3
+ bne- $-16
+ addi r3,0,1
+ blr
+ addi r3,0,0
+ blr
+
+ .align 2
+ .globl _q_atomic_test_and_set_acquire_int
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_test_and_set_acquire_int:
+ lwarx r6,0,r3
+ cmpw r6,r4
+ bne- $+20
+ stwcx. r5,0,r3
+ bne- $-16
+ addi r3,0,1
+ b $+8
+ addi r3,0,0
+ eieio
+ blr
+
+ .align 2
+ .globl _q_atomic_test_and_set_release_int
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_test_and_set_release_int:
+ eieio
+ lwarx r6,0,r3
+ cmpw r6,r4
+ bne- $+20
+ stwcx. r5,0,r3
+ bne- $-16
+ addi r3,0,1
+ blr
+ addi r3,0,0
+ blr
+
+ .align 2
+ .globl _q_atomic_test_and_set_ptr
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_test_and_set_ptr:
+ lwarx r6,0,r3
+ cmpw r6,r4
+ bne- $+20
+ stwcx. r5,0,r3
+ bne- $-16
+ addi r3,0,1
+ blr
+ addi r3,0,0
+ blr
+
+ .align 2
+ .globl _q_atomic_increment
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_increment:
+ lwarx r4,0,r3
+ addi r4,r4,1
+ stwcx. r4,0,r3
+ bne- $-12
+ mr r3,r4
+ blr
+
+ .align 2
+ .globl _q_atomic_decrement
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_decrement:
+ lwarx r4,0,r3
+ subi r4,r4,1
+ stwcx. r4,0,r3
+ bne- $-12
+ mr r3,r4
+ blr
+
+ .align 2
+ .globl _q_atomic_set_int
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_set_int:
+ lwarx r5,0,r3
+ stwcx. r4,0,r3
+ bne- $-8
+ mr r3,r5
+ blr
+
+ .align 2
+ .globl _q_atomic_set_ptr
+ .section __TEXT,__text,regular,pure_instructions
+ .align 2
+_q_atomic_set_ptr:
+ lwarx r5,0,r3
+ stwcx. r4,0,r3
+ bne- $-8
+ mr r3,r5
+ blr
+
+.globl q_atomic_test_and_set_int.eh
+ q_atomic_test_and_set_int.eh = 0
+.globl q_atomic_test_and_set_ptr.eh
+ q_atomic_test_and_set_ptr.eh = 0
+.globl q_atomic_increment.eh
+ q_atomic_increment.eh = 0
+.globl q_atomic_decrement.eh
+ q_atomic_decrement.eh = 0
+.globl q_atomic_set_int.eh
+ q_atomic_set_int.eh = 0
+.globl q_atomic_set_ptr.eh
+ q_atomic_set_ptr.eh = 0
+.data
+.constructor
+.data
+.destructor
+.align 1
diff --git a/src/corelib/arch/mips/arch.pri b/src/corelib/arch/mips/arch.pri
new file mode 100644
index 0000000000..296c845ab3
--- /dev/null
+++ b/src/corelib/arch/mips/arch.pri
@@ -0,0 +1,8 @@
+#
+# MIPS 3/4 architecture
+#
+
+# note: even though we use inline assembler with gcc, we always
+# include the compiled version to keep binary compatibility
+*-64:SOURCES += $$QT_ARCH_CPP/qatomic_mips64.s
+else:SOURCES += $$QT_ARCH_CPP/qatomic_mips32.s
diff --git a/src/corelib/arch/mips/qatomic_mips32.s b/src/corelib/arch/mips/qatomic_mips32.s
new file mode 100644
index 0000000000..d4c0191cfa
--- /dev/null
+++ b/src/corelib/arch/mips/qatomic_mips32.s
@@ -0,0 +1,150 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .set nobopt
+ .set noreorder
+ .option pic2
+ .text
+
+ .globl q_atomic_test_and_set_int
+ .ent q_atomic_test_and_set_int
+ .set mips2
+q_atomic_test_and_set_int:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_int
+
+ .globl q_atomic_test_and_set_acquire_int
+ .ent q_atomic_test_and_set_acquire_int
+ .set mips2
+q_atomic_test_and_set_acquire_int:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: sync
+ jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_acquire_int
+
+ .globl q_atomic_test_and_set_release_int
+ .ent q_atomic_test_and_set_release_int
+ .set mips2
+q_atomic_test_and_set_release_int:
+ sync
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_release_int
+
+ .globl q_atomic_test_and_set_ptr
+ .ent q_atomic_test_and_set_ptr
+ .set mips2
+q_atomic_test_and_set_ptr:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_ptr
+
+ .globl q_atomic_test_and_set_acquire_ptr
+ .ent q_atomic_test_and_set_acquire_ptr
+ .set mips2
+q_atomic_test_and_set_acquire_ptr:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: sync
+ jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_acquire_ptr
+
+ .globl q_atomic_test_and_set_release_ptr
+ .ent q_atomic_test_and_set_release_ptr
+ .set mips2
+q_atomic_test_and_set_release_ptr:
+ sync
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .set mips0
+ .end q_atomic_test_and_set_release_ptr
diff --git a/src/corelib/arch/mips/qatomic_mips64.s b/src/corelib/arch/mips/qatomic_mips64.s
new file mode 100644
index 0000000000..993991f0b7
--- /dev/null
+++ b/src/corelib/arch/mips/qatomic_mips64.s
@@ -0,0 +1,138 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .set nobopt
+ .set noreorder
+ .option pic2
+ .text
+
+ .globl q_atomic_test_and_set_int
+ .ent q_atomic_test_and_set_int
+q_atomic_test_and_set_int:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_int
+
+ .globl q_atomic_test_and_set_acquire_int
+ .ent q_atomic_test_and_set_acquire_int
+q_atomic_test_and_set_acquire_int:
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: sync
+ jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_acquire_int
+
+ .globl q_atomic_test_and_set_release_int
+ .ent q_atomic_test_and_set_release_int
+q_atomic_test_and_set_release_int:
+ sync
+1: ll $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ sc $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_release_int
+
+ .globl q_atomic_test_and_set_ptr
+ .ent q_atomic_test_and_set_ptr
+q_atomic_test_and_set_ptr:
+1: lld $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ scd $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_ptr
+
+ .globl q_atomic_test_and_set_acquire_ptr
+ .ent q_atomic_test_and_set_acquire_ptr
+q_atomic_test_and_set_acquire_ptr:
+1: lld $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ scd $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: sync
+ jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_acquire_ptr
+
+ .globl q_atomic_test_and_set_release_ptr
+ .ent q_atomic_test_and_set_release_ptr
+q_atomic_test_and_set_release_ptr:
+ sync
+1: lld $8,0($4)
+ bne $8,$5,2f
+ move $2,$6
+ scd $2,0($4)
+ beqz $2,1b
+ nop
+ jr $31
+ nop
+2: jr $31
+ move $2,$0
+ .end q_atomic_test_and_set_release_ptr
diff --git a/src/corelib/arch/parisc/arch.pri b/src/corelib/arch/parisc/arch.pri
new file mode 100644
index 0000000000..fab2897f04
--- /dev/null
+++ b/src/corelib/arch/parisc/arch.pri
@@ -0,0 +1,5 @@
+#
+# HP PA-RISC architecture
+#
+SOURCES += $$QT_ARCH_CPP/q_ldcw.s \
+ $$QT_ARCH_CPP/qatomic_parisc.cpp
diff --git a/src/corelib/arch/parisc/q_ldcw.s b/src/corelib/arch/parisc/q_ldcw.s
new file mode 100644
index 0000000000..f8f40467ec
--- /dev/null
+++ b/src/corelib/arch/parisc/q_ldcw.s
@@ -0,0 +1,62 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+;** All rights reserved.
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the Technology Preview License Agreement accompanying
+;** this package.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain additional
+;** rights. These rights are described in the Nokia Qt LGPL Exception
+;** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+;**
+;** If you have questions regarding the use of this file, please contact
+;** Nokia at qt-info@nokia.com.
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;**
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT q_ldcw,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+q_ldcw
+ .PROC
+ .CALLINFO FRAME=0,CALLS,SAVE_RP
+ .ENTRY
+ ldcw 0(%r26),%r1
+ bv %r0(%r2)
+ copy %r1,%r28
+ .EXIT
+ .PROCEND
diff --git a/src/corelib/arch/parisc/qatomic_parisc.cpp b/src/corelib/arch/parisc/qatomic_parisc.cpp
new file mode 100644
index 0000000000..fa446c5d7b
--- /dev/null
+++ b/src/corelib/arch/parisc/qatomic_parisc.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#define UNLOCKED {-1,-1,-1,-1}
+#define UNLOCKED2 UNLOCKED,UNLOCKED
+#define UNLOCKED4 UNLOCKED2,UNLOCKED2
+#define UNLOCKED8 UNLOCKED4,UNLOCKED4
+#define UNLOCKED16 UNLOCKED8,UNLOCKED8
+#define UNLOCKED32 UNLOCKED16,UNLOCKED16
+#define UNLOCKED64 UNLOCKED32,UNLOCKED32
+#define UNLOCKED128 UNLOCKED64,UNLOCKED64
+#define UNLOCKED256 UNLOCKED128,UNLOCKED128
+
+// use a 4k page for locks
+static int locks[256][4] = { UNLOCKED256 };
+
+int *getLock(volatile void *addr)
+{ return locks[qHash(const_cast<void *>(addr)) % 256]; }
+
+static int *align16(int *lock)
+{
+ ulong off = (((ulong) lock) % 16);
+ return off ? (int *)(ulong(lock) + 16 - off) : lock;
+}
+
+extern "C" {
+
+ int q_ldcw(volatile int *addr);
+
+ void q_atomic_lock(int *lock)
+ {
+ // ldcw requires a 16-byte aligned address
+ volatile int *x = align16(lock);
+ while (q_ldcw(x) == 0)
+ ;
+ }
+
+ void q_atomic_unlock(int *lock)
+ { lock[0] = lock[1] = lock[2] = lock[3] = -1; }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/arch/powerpc/arch.pri b/src/corelib/arch/powerpc/arch.pri
new file mode 100644
index 0000000000..1989ac73a7
--- /dev/null
+++ b/src/corelib/arch/powerpc/arch.pri
@@ -0,0 +1,10 @@
+#
+# PowerPC architecture
+#
+!*-g++* {
+ *-64 {
+ SOURCES += $$QT_ARCH_CPP/qatomic64.s
+ } else {
+ SOURCES += $$QT_ARCH_CPP/qatomic32.s
+ }
+}
diff --git a/src/corelib/arch/powerpc/qatomic32.s b/src/corelib/arch/powerpc/qatomic32.s
new file mode 100644
index 0000000000..a446359e25
--- /dev/null
+++ b/src/corelib/arch/powerpc/qatomic32.s
@@ -0,0 +1,525 @@
+############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is part of the QtGui module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 2.1 requirements
+## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+ .machine "ppc"
+ .toc
+ .csect .text[PR]
+
+ .align 2
+ .globl q_atomic_test_and_set_int
+ .globl .q_atomic_test_and_set_int
+ .csect q_atomic_test_and_set_int[DS],3
+q_atomic_test_and_set_int:
+ .long .q_atomic_test_and_set_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int
+ .short 25
+ .byte "q_atomic_test_and_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_int
+ .globl .q_atomic_test_and_set_acquire_int
+ .csect q_atomic_test_and_set_acquire_int[DS],3
+q_atomic_test_and_set_acquire_int:
+ .long .q_atomic_test_and_set_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_acquire_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stwcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int
+ .short 33
+ .byte "q_atomic_test_and_set_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_int
+ .globl .q_atomic_test_and_set_release_int
+ .csect q_atomic_test_and_set_release_int[DS],3
+q_atomic_test_and_set_release_int:
+ .long .q_atomic_test_and_set_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_release_int:
+ eieio
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int
+ .short 33
+ .byte "q_atomic_test_and_set_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_ptr
+ .globl .q_atomic_test_and_set_ptr
+ .csect q_atomic_test_and_set_ptr[DS],3
+q_atomic_test_and_set_ptr:
+ .long .q_atomic_test_and_set_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_ptr:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr
+ .short 25
+ .byte "q_atomic_test_and_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_ptr
+ .globl .q_atomic_test_and_set_acquire_ptr
+ .csect q_atomic_test_and_set_acquire_ptr[DS],3
+q_atomic_test_and_set_acquire_ptr:
+ .long .q_atomic_test_and_set_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_acquire_ptr:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stwcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr
+ .short 25
+ .byte "q_atomic_test_and_set_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_ptr
+ .globl .q_atomic_test_and_set_release_ptr
+ .csect q_atomic_test_and_set_release_ptr[DS],3
+q_atomic_test_and_set_release_ptr:
+ .long .q_atomic_test_and_set_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_release_ptr:
+ eieio
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr
+ .short 33
+ .byte "q_atomic_test_and_set_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_increment
+ .globl .q_atomic_increment
+ .csect q_atomic_increment[DS],3
+q_atomic_increment:
+ .long .q_atomic_increment,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_increment:
+ lwarx 4,0,3
+ addi 4,4,1
+ stwcx. 4,0,3
+ bne- $-12
+ mr 3,4
+ blr
+LT..q_atomic_increment:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_increment-.q_atomic_increment
+ .short 18
+ .byte "q_atomic_increment"
+ .align 2
+
+ .align 2
+ .globl q_atomic_decrement
+ .globl .q_atomic_decrement
+ .csect q_atomic_decrement[DS],3
+q_atomic_decrement:
+ .long .q_atomic_decrement,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_decrement:
+ lwarx 4,0,3
+ subi 4,4,1
+ stwcx. 4,0,3
+ bne- $-12
+ mr 3,4
+ blr
+LT..q_atomic_decrement:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_decrement-.q_atomic_decrement
+ .short 18
+ .byte "q_atomic_decrement"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_int
+ .globl .q_atomic_set_int
+ .csect q_atomic_set_int[DS],3
+q_atomic_set_int:
+ .long .q_atomic_set_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_set_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_int-.q_atomic_set_int
+ .short 16
+ .byte "q_atomic_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_int
+ .globl .q_atomic_fetch_and_store_acquire_int
+ .csect q_atomic_fetch_and_store_acquire_int[DS],3
+q_atomic_fetch_and_store_acquire_int:
+ .long .q_atomic_fetch_and_store_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_acquire_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int
+ .short 16
+ .byte "q_atomic_fetch_and_store_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_int
+ .globl .q_atomic_fetch_and_store_release_int
+ .csect q_atomic_fetch_and_store_release_int[DS],3
+q_atomic_fetch_and_store_release_int:
+ .long .q_atomic_fetch_and_store_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_release_int:
+ eieio
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int
+ .short 16
+ .byte "q_atomic_fetch_and_store_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_ptr
+ .globl .q_atomic_set_ptr
+ .csect q_atomic_set_ptr[DS],3
+q_atomic_set_ptr:
+ .long .q_atomic_set_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_set_ptr:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_ptr-.q_atomic_set_ptr
+ .short 16
+ .byte "q_atomic_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_ptr
+ .globl .q_atomic_fetch_and_store_acquire_ptr
+ .csect q_atomic_fetch_and_store_acquire_ptr[DS],3
+q_atomic_fetch_and_store_acquire_ptr:
+ .long .q_atomic_fetch_and_store_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_acquire_ptr:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr
+ .short 16
+ .byte "q_atomic_fetch_and_store_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_ptr
+ .globl .q_atomic_fetch_and_store_release_ptr
+ .csect q_atomic_fetch_and_store_release_ptr[DS],3
+q_atomic_fetch_and_store_release_ptr:
+ .long .q_atomic_fetch_and_store_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_release_ptr:
+ eieio
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr
+ .short 16
+ .byte "q_atomic_fetch_and_store_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_int
+ .globl .q_atomic_fetch_and_add_int
+ .csect q_atomic_fetch_and_add_int[DS],3
+q_atomic_fetch_and_add_int:
+ .long .q_atomic_fetch_and_add_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_int:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int
+ .short 18
+ .byte "q_atomic_fetch_and_add_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_int
+ .globl .q_atomic_fetch_and_add_acquire_int
+ .csect q_atomic_fetch_and_add_acquire_int[DS],3
+q_atomic_fetch_and_add_acquire_int:
+ .long .q_atomic_fetch_and_add_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_acquire_int:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int
+ .short 18
+ .byte "q_atomic_fetch_and_add_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_int
+ .globl .q_atomic_fetch_and_add_release_int
+ .csect q_atomic_fetch_and_add_release_int[DS],3
+q_atomic_fetch_and_add_release_int:
+ .long .q_atomic_fetch_and_add_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_release_int:
+ eieio
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_ptr
+ .globl .q_atomic_fetch_and_add_ptr
+ .csect q_atomic_fetch_and_add_ptr[DS],3
+q_atomic_fetch_and_add_ptr:
+ .long .q_atomic_fetch_and_add_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_ptr:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr
+ .short 26
+ .byte "q_atomic_fetch_and_add_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_ptr
+ .globl .q_atomic_fetch_and_add_acquire_ptr
+ .csect q_atomic_fetch_and_add_acquire_ptr[DS],3
+q_atomic_fetch_and_add_acquire_ptr:
+ .long .q_atomic_fetch_and_add_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_acquire_ptr:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_ptr
+ .globl .q_atomic_fetch_and_add_release_ptr
+ .csect q_atomic_fetch_and_add_release_ptr[DS],3
+q_atomic_fetch_and_add_release_ptr:
+ .long .q_atomic_fetch_and_add_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_release_ptr:
+ eieio
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_ptr"
+ .align 2
+
+_section_.text:
+ .csect .data[RW],3
+ .long _section_.text
diff --git a/src/corelib/arch/powerpc/qatomic64.s b/src/corelib/arch/powerpc/qatomic64.s
new file mode 100644
index 0000000000..9bf31912a1
--- /dev/null
+++ b/src/corelib/arch/powerpc/qatomic64.s
@@ -0,0 +1,533 @@
+############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is part of the QtGui module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 2.1 requirements
+## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+ .machine "ppc64"
+ .toc
+ .csect .text[PR]
+
+ .align 2
+ .globl q_atomic_test_and_set_int
+ .globl .q_atomic_test_and_set_int
+ .csect q_atomic_test_and_set_int[DS],3
+q_atomic_test_and_set_int:
+ .llong .q_atomic_test_and_set_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ extsw 3,3
+ blr
+LT..q_atomic_test_and_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int
+ .short 25
+ .byte "q_atomic_test_and_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_int
+ .globl .q_atomic_test_and_set_acquire_int
+ .csect q_atomic_test_and_set_acquire_int[DS],3
+q_atomic_test_and_set_acquire_int:
+ .llong .q_atomic_test_and_set_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_acquire_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stwcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ extsw 3,3
+ blr
+LT..q_atomic_test_and_set_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int
+ .short 33
+ .byte "q_atomic_test_and_set_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_int
+ .globl .q_atomic_test_and_set_release_int
+ .csect q_atomic_test_and_set_release_int[DS],3
+q_atomic_test_and_set_release_int:
+ .llong .q_atomic_test_and_set_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_release_int:
+ eieio
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ extsw 3,3
+ blr
+LT..q_atomic_test_and_set_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int
+ .short 33
+ .byte "q_atomic_test_and_set_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_ptr
+ .globl .q_atomic_test_and_set_ptr
+ .csect q_atomic_test_and_set_ptr[DS],3
+q_atomic_test_and_set_ptr:
+ .llong .q_atomic_test_and_set_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_ptr:
+ ldarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stdcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr
+ .short 25
+ .byte "q_atomic_test_and_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_ptr
+ .globl .q_atomic_test_and_set_acquire_ptr
+ .csect q_atomic_test_and_set_acquire_ptr[DS],3
+q_atomic_test_and_set_acquire_ptr:
+ .llong .q_atomic_test_and_set_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_acquire_ptr:
+ ldarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stdcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr
+ .short 33
+ .byte "q_atomic_test_and_set_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_ptr
+ .globl .q_atomic_test_and_set_release_ptr
+ .csect q_atomic_test_and_set_release_ptr[DS],3
+q_atomic_test_and_set_release_ptr:
+ .llong .q_atomic_test_and_set_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_test_and_set_release_ptr:
+ eieio
+ ldarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stdcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr
+ .short 33
+ .byte "q_atomic_test_and_set_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_increment
+ .globl .q_atomic_increment
+ .csect q_atomic_increment[DS],3
+q_atomic_increment:
+ .llong .q_atomic_increment,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_increment:
+ lwarx 4,0,3
+ addi 5,4,1
+ extsw 4,5
+ stwcx. 4,0,3
+ bne- $-16
+ mr 3,4
+ blr
+LT..q_atomic_increment:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_increment-.q_atomic_increment
+ .short 18
+ .byte "q_atomic_increment"
+ .align 2
+
+ .align 2
+ .globl q_atomic_decrement
+ .globl .q_atomic_decrement
+ .csect q_atomic_decrement[DS],3
+q_atomic_decrement:
+ .llong .q_atomic_decrement,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_decrement:
+ lwarx 4,0,3
+ subi 5,4,1
+ extsw 4,5
+ stwcx. 4,0,3
+ bne- $-16
+ mr 3,4
+ blr
+LT..q_atomic_decrement:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_decrement-.q_atomic_decrement
+ .short 18
+ .byte "q_atomic_decrement"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_int
+ .globl .q_atomic_set_int
+ .csect q_atomic_set_int[DS],3
+q_atomic_set_int:
+ .llong .q_atomic_set_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_set_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ extsw 3,5
+ blr
+LT..q_atomic_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_int-.q_atomic_set_int
+ .short 16
+ .byte "q_atomic_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_int
+ .globl .q_atomic_fetch_and_store_acquire_int
+ .csect q_atomic_fetch_and_store_acquire_int[DS],3
+q_atomic_fetch_and_store_acquire_int:
+ .llong .q_atomic_fetch_and_store_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_acquire_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ isync
+ extsw 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int
+ .short 36
+ .byte "q_atomic_fetch_and_store_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_int
+ .globl .q_atomic_fetch_and_store_release_int
+ .csect q_atomic_fetch_and_store_release_int[DS],3
+q_atomic_fetch_and_store_release_int:
+ .llong .q_atomic_fetch_and_store_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_release_int:
+ eieio
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ extsw 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int
+ .short 36
+ .byte "q_atomic_fetch_and_store_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_ptr
+ .globl .q_atomic_set_ptr
+ .csect q_atomic_set_ptr[DS],3
+q_atomic_set_ptr:
+ .llong .q_atomic_set_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_set_ptr:
+ ldarx 5,0,3
+ stdcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_ptr-.q_atomic_set_ptr
+ .short 16
+ .byte "q_atomic_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_ptr
+ .globl .q_atomic_fetch_and_store_acquire_ptr
+ .csect q_atomic_fetch_and_store_acquire_ptr[DS],3
+q_atomic_fetch_and_store_acquire_ptr:
+ .llong .q_atomic_fetch_and_store_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_acquire_ptr:
+ ldarx 5,0,3
+ stdcx. 4,0,3
+ bne- $-8
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr
+ .short 36
+ .byte "q_atomic_fetch_and_store_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_ptr
+ .globl .q_atomic_fetch_and_store_release_ptr
+ .csect q_atomic_fetch_and_store_release_ptr[DS],3
+q_atomic_fetch_and_store_release_ptr:
+ .llong .q_atomic_fetch_and_store_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_store_release_ptr:
+ eieio
+ ldarx 5,0,3
+ stdcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr
+ .short 36
+ .byte "q_atomic_fetch_and_store_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_int
+ .globl .q_atomic_fetch_and_add_int
+ .csect q_atomic_fetch_and_add_int[DS],3
+q_atomic_fetch_and_add_int:
+ .llong .q_atomic_fetch_and_add_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_int:
+ lwarx 5,0,3
+ add 6,4,5
+ extsw 7,6
+ stwcx. 7,0,3
+ bne- $-16
+ extsw 3,5
+ blr
+LT..q_atomic_fetch_and_add_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int
+ .short 26
+ .byte "q_atomic_fetch_and_add_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_int
+ .globl .q_atomic_fetch_and_add_acquire_int
+ .csect q_atomic_fetch_and_add_acquire_int[DS],3
+q_atomic_fetch_and_add_acquire_int:
+ .llong .q_atomic_fetch_and_add_acquire_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_acquire_int:
+ lwarx 5,0,3
+ add 6,4,5
+ extsw 7,6
+ stwcx. 7,0,3
+ bne- $-16
+ isync
+ extsw 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int
+ .short 34
+ .byte "q_atomic_fetch_and_add_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_int
+ .globl .q_atomic_fetch_and_add_release_int
+ .csect q_atomic_fetch_and_add_release_int[DS],3
+q_atomic_fetch_and_add_release_int:
+ .llong .q_atomic_fetch_and_add_release_int,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_release_int:
+ eieio
+ lwarx 5,0,3
+ add 6,4,5
+ extsw 7,6
+ stwcx. 7,0,3
+ bne- $-16
+ extsw 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_ptr
+ .globl .q_atomic_fetch_and_add_ptr
+ .csect q_atomic_fetch_and_add_ptr[DS],3
+q_atomic_fetch_and_add_ptr:
+ .llong .q_atomic_fetch_and_add_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_ptr:
+ ldarx 5,0,3
+ add 6,4,5
+ stdcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr
+ .short 26
+ .byte "q_atomic_fetch_and_add_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_ptr
+ .globl .q_atomic_fetch_and_add_acquire_ptr
+ .csect q_atomic_fetch_and_add_acquire_ptr[DS],3
+q_atomic_fetch_and_add_acquire_ptr:
+ .llong .q_atomic_fetch_and_add_acquire_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_acquire_ptr:
+ ldarx 5,0,3
+ add 6,4,5
+ stdcx. 6,0,3
+ bne- $-12
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_ptr
+ .globl .q_atomic_fetch_and_add_release_ptr
+ .csect q_atomic_fetch_and_add_release_ptr[DS],3
+q_atomic_fetch_and_add_release_ptr:
+ .llong .q_atomic_fetch_and_add_release_ptr,TOC[tc0],0
+ .csect .text[PR]
+.q_atomic_fetch_and_add_release_ptr:
+ eieio
+ ldarx 5,0,3
+ add 6,4,5
+ stdcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_ptr"
+ .align 2
+
+_section_.text:
+ .csect .data[RW],3
+ .llong _section_.text
diff --git a/src/corelib/arch/qatomic_alpha.h b/src/corelib/arch/qatomic_alpha.h
new file mode 100644
index 0000000000..be5d7ec884
--- /dev/null
+++ b/src/corelib/arch/qatomic_alpha.h
@@ -0,0 +1,642 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ALPHA_H
+#define QATOMIC_ALPHA_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#if defined(Q_CC_GNU)
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "addl %0,1,%1\n" /* tmp=old+1; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ :
+ : "memory");
+ return old != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "subl %0,1,%1\n" /* tmp=old-1; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ :
+ : "memory");
+ return old != 1;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int ret;
+ asm volatile("1:\n"
+ "ldl_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */
+ "beq %0,3f\n" /* if (ret==0) goto 3; */
+ "mov %3,%0\n" /* ret=newval; */
+ "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ register int ret;
+ asm volatile("1:\n"
+ "ldl_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */
+ "beq %0,3f\n" /* if (ret==0) goto 3; */
+ "mov %3,%0\n" /* ret=newval; */
+ "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ register int ret;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldl_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */
+ "beq %0,3f\n" /* if (ret==0) goto 3; */
+ "mov %3,%0\n" /* ret=newval; */
+ "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ register int old, tmp;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "addl %0,%3,%1\n"/* tmp=old+value; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ register int old, tmp;
+ asm volatile("1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "addl %0,%3,%1\n"/* tmp=old+value; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ register int old, tmp;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldl_l %0,%2\n" /* old=*ptr; */
+ "addl %0,%3,%1\n"/* tmp=old+value; */
+ "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register void *ret;
+ asm volatile("1:\n"
+ "ldq_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */
+ "beq %0,3f\n" /* if (tmp==0) goto 3; */
+ "mov %3,%0\n" /* tmp=newval; */
+ "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ register void *ret;
+ asm volatile("1:\n"
+ "ldq_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */
+ "beq %0,3f\n" /* if (tmp==0) goto 3; */
+ "mov %3,%0\n" /* tmp=newval; */
+ "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ register void *ret;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldq_l %0,%1\n" /* ret=*ptr; */
+ "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */
+ "beq %0,3f\n" /* if (tmp==0) goto 3; */
+ "mov %3,%0\n" /* tmp=newval; */
+ "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %0,2f\n" /* if (ret==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *old, *tmp;
+ asm volatile("1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ register T *old, *tmp;
+ asm volatile("1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ register T *old, *tmp;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "mov %3,%1\n" /* tmp=newval; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp==0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *old, *tmp;
+ asm volatile("1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "addq %0,%3,%1\n"/* tmp=old+value; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return reinterpret_cast<T *>(old);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ register T *old, *tmp;
+ asm volatile("1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "addq %0,%3,%1\n"/* tmp=old+value; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ "mb\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return reinterpret_cast<T *>(old);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ register T *old, *tmp;
+ asm volatile("mb\n"
+ "1:\n"
+ "ldq_l %0,%2\n" /* old=*ptr; */
+ "addq %0,%3,%1\n"/* tmp=old+value; */
+ "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
+ "beq %1,2f\n" /* if (tmp == 0) goto 2; */
+ "br 3f\n" /* goto 3; */
+ "2: br 1b\n" /* goto 1; */
+ "3:\n"
+ : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
+ : "r" (valueToAdd)
+ : "memory");
+ return reinterpret_cast<T *>(old);
+}
+
+#else // !Q_CC_GNU
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value);
+} // extern "C"
+
+inline bool QBasicAtomicInt::ref()
+{
+ return q_atomic_increment(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return q_atomic_decrement(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return q_atomic_set_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return q_atomic_fetch_and_store_release_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_int(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_acquire_int(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_release_int(&_q_value, valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, newValue));
+}
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, newValue));
+}
+
+#endif // Q_CC_GNU
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_ALPHA_H
diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h
new file mode 100644
index 0000000000..3da833a424
--- /dev/null
+++ b/src/corelib/arch/qatomic_arch.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARCH_H
+#define QATOMIC_ARCH_H
+
+QT_BEGIN_HEADER
+
+#include "QtCore/qglobal.h"
+
+#if defined(QT_ARCH_INTEGRITY)
+# include "QtCore/qatomic_integrity.h"
+#elif defined(QT_ARCH_VXWORKS)
+# include "QtCore/qatomic_vxworks.h"
+#elif defined(QT_ARCH_ALPHA)
+# include "QtCore/qatomic_alpha.h"
+#elif defined(QT_ARCH_ARM)
+# include "QtCore/qatomic_arm.h"
+#elif defined(QT_ARCH_ARMV6)
+# include "QtCore/qatomic_armv6.h"
+#elif defined(QT_ARCH_AVR32)
+# include "QtCore/qatomic_avr32.h"
+#elif defined(QT_ARCH_BFIN)
+# include "QtCore/qatomic_bfin.h"
+#elif defined(QT_ARCH_GENERIC)
+# include "QtCore/qatomic_generic.h"
+#elif defined(QT_ARCH_I386)
+# include "QtCore/qatomic_i386.h"
+#elif defined(QT_ARCH_IA64)
+# include "QtCore/qatomic_ia64.h"
+#elif defined(QT_ARCH_MACOSX)
+# include "QtCore/qatomic_macosx.h"
+#elif defined(QT_ARCH_MIPS)
+# include "QtCore/qatomic_mips.h"
+#elif defined(QT_ARCH_PARISC)
+# include "QtCore/qatomic_parisc.h"
+#elif defined(QT_ARCH_POWERPC)
+# include "QtCore/qatomic_powerpc.h"
+#elif defined(QT_ARCH_S390)
+# include "QtCore/qatomic_s390.h"
+#elif defined(QT_ARCH_SPARC)
+# include "QtCore/qatomic_sparc.h"
+#elif defined(QT_ARCH_WINDOWS)
+# include "QtCore/qatomic_windows.h"
+#elif defined(QT_ARCH_WINDOWSCE)
+# include "QtCore/qatomic_windowsce.h"
+#elif defined(QT_ARCH_X86_64)
+# include "QtCore/qatomic_x86_64.h"
+#elif defined(QT_ARCH_SYMBIAN)
+# include "QtCore/qatomic_symbian.h"
+#elif defined(QT_ARCH_SH)
+# include "QtCore/qatomic_sh.h"
+#elif defined(QT_ARCH_SH4A)
+# include "QtCore/qatomic_sh4a.h"
+#elif defined(QT_ARCH_NACL)
+# include "QtCore/qatomic_generic.h"
+#else
+# error "Qt has not been ported to this architecture"
+#endif
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARCH_H
diff --git a/src/corelib/arch/qatomic_arm.h b/src/corelib/arch/qatomic_arm.h
new file mode 100644
index 0000000000..07d21438d6
--- /dev/null
+++ b/src/corelib/arch/qatomic_arm.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARM_H
+#define QATOMIC_ARM_H
+
+QT_BEGIN_HEADER
+
+#if defined(__ARM_ARCH_7__) \
+ || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) \
+ || defined(__ARM_ARCH_7M__)
+# define QT_ARCH_ARMV7
+QT_BEGIN_INCLUDE_HEADER
+# include "QtCore/qatomic_armv7.h"
+QT_END_INCLUDE_HEADER
+#elif defined(__ARM_ARCH_6__) \
+ || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6K__) \
+ || defined(__ARM_ARCH_6ZK__) \
+ || defined(__ARM_ARCH_6M__) \
+ || (defined(__TARGET_ARCH_ARM) && (__TARGET_ARCH_ARM-0 >= 6))
+# define QT_ARCH_ARMV6
+QT_BEGIN_INCLUDE_HEADER
+# include "QtCore/qatomic_armv6.h"
+QT_END_INCLUDE_HEADER
+#else
+# define QT_ARCH_ARMV5
+QT_BEGIN_INCLUDE_HEADER
+# include "QtCore/qatomic_armv5.h"
+QT_END_INCLUDE_HEADER
+#endif
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARM_H
diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h
new file mode 100644
index 0000000000..ac8fe9670e
--- /dev/null
+++ b/src/corelib/arch/qatomic_armv5.h
@@ -0,0 +1,431 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARMV5_H
+#define QATOMIC_ARMV5_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#ifndef QT_NO_ARM_EABI
+
+// kernel places a restartable cmpxchg implementation at a fixed address
+extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr);
+extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(const void *oldval, const void *newval, volatile void *ptr);
+#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0))
+#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0))
+
+#else
+
+extern Q_CORE_EXPORT char q_atomic_lock;
+Q_CORE_EXPORT void qt_atomic_yield(int *);
+
+#ifdef Q_CC_RVCT
+
+Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval);
+
+#else
+
+inline char q_atomic_swp(volatile char *ptr, char newval)
+{
+ register char ret;
+ asm volatile("swpb %0,%2,[%3]"
+ : "=&r"(ret), "=m" (*ptr)
+ : "r"(newval), "r"(ptr)
+ : "cc", "memory");
+ return ret;
+}
+
+#endif // Q_CC_RVCT
+
+#endif // QT_NO_ARM_EABI
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+#ifndef QT_NO_ARM_EABI
+ register int originalValue;
+ register int newValue;
+ do {
+ originalValue = _q_value;
+ newValue = originalValue + 1;
+ } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
+ return newValue != 0;
+#else
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value++;
+ q_atomic_swp(&q_atomic_lock, 0);
+ return originalValue != -1;
+#endif
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+#ifndef QT_NO_ARM_EABI
+ register int originalValue;
+ register int newValue;
+ do {
+ originalValue = _q_value;
+ newValue = originalValue - 1;
+ } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
+ return newValue != 0;
+#else
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value--;
+ q_atomic_swp(&q_atomic_lock, 0);
+ return originalValue != 1;
+#endif
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+#ifndef QT_NO_ARM_EABI
+ register int originalValue;
+ do {
+ originalValue = _q_value;
+ if (originalValue != expectedValue)
+ return false;
+ } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0);
+ return true;
+#else
+ bool returnValue = false;
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ returnValue = true;
+ }
+ q_atomic_swp(&q_atomic_lock, 0);
+ return returnValue;
+#endif
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+#ifndef Q_CC_RVCT
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ int originalValue;
+ asm volatile("swp %0,%2,[%3]"
+ : "=&r"(originalValue), "=m" (_q_value)
+ : "r"(newValue), "r"(&_q_value)
+ : "cc", "memory");
+ return originalValue;
+}
+
+#endif
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+#ifndef QT_NO_ARM_EABI
+ register int originalValue;
+ register int newValue;
+ do {
+ originalValue = _q_value;
+ newValue = originalValue + valueToAdd;
+ } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
+ return originalValue;
+#else
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value;
+ _q_value += valueToAdd;
+ q_atomic_swp(&q_atomic_lock, 0);
+ return originalValue;
+#endif
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+#ifndef QT_NO_ARM_EABI
+ register T *originalValue;
+ do {
+ originalValue = _q_value;
+ if (originalValue != expectedValue)
+ return false;
+ } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0);
+ return true;
+#else
+ bool returnValue = false;
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ returnValue = true;
+ }
+ q_atomic_swp(&q_atomic_lock, 0);
+ return returnValue;
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+#ifdef Q_CC_RVCT
+
+template <typename T>
+__asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ add r2, pc, #0
+ bx r2
+ arm
+ swp r2,r1,[r0]
+ mov r0, r2
+ bx lr
+ thumb
+}
+
+#else
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ T *originalValue;
+ asm volatile("swp %0,%2,[%3]"
+ : "=&r"(originalValue), "=m" (_q_value)
+ : "r"(newValue), "r"(&_q_value)
+ : "cc", "memory");
+ return originalValue;
+}
+
+#endif // Q_CC_RVCT
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+#ifndef QT_NO_ARM_EABI
+ register T *originalValue;
+ register T *newValue;
+ do {
+ originalValue = _q_value;
+ newValue = originalValue + valueToAdd;
+ } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0);
+ return originalValue;
+#else
+ int count = 0;
+ while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
+ qt_atomic_yield(&count);
+ T *originalValue = (_q_value);
+ _q_value += valueToAdd;
+ q_atomic_swp(&q_atomic_lock, 0);
+ return originalValue;
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARMV5_H
diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h
new file mode 100644
index 0000000000..3bd605853f
--- /dev/null
+++ b/src/corelib/arch/qatomic_armv6.h
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARMV6_H
+#define QATOMIC_ARMV6_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#ifndef Q_CC_RVCT
+
+#ifndef Q_DATA_MEMORY_BARRIER
+# define Q_DATA_MEMORY_BARRIER asm volatile("":::"memory")
+#endif
+#ifndef Q_COMPILER_MEMORY_BARRIER
+# define Q_COMPILER_MEMORY_BARRIER asm volatile("":::"memory")
+#endif
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int newValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[newValue], [%[_q_value]]\n"
+ "add %[newValue], %[newValue], #1\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [newValue] "=&r" (newValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int newValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[newValue], [%[_q_value]]\n"
+ "sub %[newValue], %[newValue], #1\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [newValue] "=&r" (newValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[result], [%[_q_value]]\n"
+ "eors %[result], %[result], %[expectedValue]\n"
+ "strexeq %[result], %[newValue], [%[_q_value]]\n"
+ "teqeq %[result], #1\n"
+ "beq 0b\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return result == 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int originalValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[originalValue], [%[_q_value]]\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [newValue] "r" (newValue),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[originalValue], [%[_q_value]]\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [valueToAdd] "r" (valueToAdd),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register T *result;
+ asm volatile("0:\n"
+ "ldrex %[result], [%[_q_value]]\n"
+ "eors %[result], %[result], %[expectedValue]\n"
+ "strexeq %[result], %[newValue], [%[_q_value]]\n"
+ "teqeq %[result], #1\n"
+ "beq 0b\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *originalValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[originalValue], [%[_q_value]]\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [newValue] "r" (newValue),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ register int result;
+ asm volatile("0:\n"
+ "ldrex %[originalValue], [%[_q_value]]\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ "strex %[result], %[newValue], [%[_q_value]]\n"
+ "teq %[result], #0\n"
+ "bne 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ [result] "=&r" (result),
+ "+m" (_q_value)
+ : [valueToAdd] "r" (valueToAdd * sizeof(T)),
+ [_q_value] "r" (&_q_value)
+ : "cc");
+ return originalValue;
+}
+
+#else
+// This is Q_CC_RVCT
+
+// RVCT inline assembly documentation:
+// http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm
+// RVCT embedded assembly documentation:
+// http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm
+
+#if __TARGET_ARCH_THUMB-0 < 4
+// save our pragma state and switch to ARM mode (unless using Thumb2)
+# pragma push
+# pragma arm
+#endif
+
+#ifndef Q_DATA_MEMORY_BARRIER
+# define Q_DATA_MEMORY_BARRIER __schedule_barrier()
+#endif
+#ifndef Q_COMPILER_MEMORY_BARRIER
+# define Q_COMPILER_MEMORY_BARRIER __schedule_barrier()
+#endif
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int newValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex newValue, [&_q_value]
+ add newValue, newValue, #1
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int newValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex newValue, [&_q_value]
+ sub newValue, newValue, #1
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int result;
+ retry:
+ __asm {
+ ldrex result, [&_q_value]
+ eors result, result, expectedValue
+ strexeq result, newValue, [&_q_value]
+ teqeq result, #1
+ beq retry
+ }
+ return result == 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int originalValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex originalValue, [&_q_value]
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex originalValue, [&_q_value]
+ add newValue, originalValue, valueToAdd
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register T *result;
+ retry:
+ __asm {
+ ldrex result, [&_q_value]
+ eors result, result, expectedValue
+ strexeq result, newValue, [&_q_value]
+ teqeq result, #1
+ beq retry
+ }
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *originalValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex originalValue, [&_q_value]
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ register int result;
+ retry:
+ __asm {
+ ldrex originalValue, [&_q_value]
+ add newValue, originalValue, valueToAdd * sizeof(T)
+ strex result, newValue, [&_q_value]
+ teq result, #0
+ bne retry
+ }
+ return originalValue;
+}
+
+#if __TARGET_ARCH_THUMB-0 < 4
+# pragma pop
+#endif
+
+#endif
+
+// common code
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ bool returnValue = testAndSetRelaxed(expectedValue, newValue);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return testAndSetRelaxed(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ bool returnValue = testAndSetRelaxed(expectedValue, newValue);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ int returnValue = fetchAndStoreRelaxed(newValue);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return fetchAndStoreRelaxed(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ int returnValue = fetchAndStoreRelaxed(newValue);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ int returnValue = fetchAndAddRelaxed(valueToAdd);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return fetchAndAddRelaxed(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ Q_DATA_MEMORY_BARRIER;
+ int returnValue = fetchAndAddRelaxed(valueToAdd);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ bool returnValue = testAndSetRelaxed(expectedValue, newValue);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return testAndSetRelaxed(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ bool returnValue = testAndSetAcquire(expectedValue, newValue);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ T *returnValue = fetchAndStoreRelaxed(newValue);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return fetchAndStoreRelaxed(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ Q_DATA_MEMORY_BARRIER;
+ T *returnValue = fetchAndStoreRelaxed(newValue);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ T *returnValue = fetchAndAddRelaxed(valueToAdd);
+ Q_DATA_MEMORY_BARRIER;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ Q_DATA_MEMORY_BARRIER;
+ return fetchAndAddRelaxed(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ Q_DATA_MEMORY_BARRIER;
+ T *returnValue = fetchAndAddRelaxed(valueToAdd);
+ Q_COMPILER_MEMORY_BARRIER;
+ return returnValue;
+}
+
+#undef Q_DATA_MEMORY_BARRIER
+#undef Q_COMPILER_MEMORY_BARRIER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARMV6_H
diff --git a/src/corelib/arch/qatomic_armv7.h b/src/corelib/arch/qatomic_armv7.h
new file mode 100644
index 0000000000..b35866b32c
--- /dev/null
+++ b/src/corelib/arch/qatomic_armv7.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARMV7_H
+#define QATOMIC_ARMV7_H
+
+QT_BEGIN_HEADER
+
+// use the DMB instruction when compiling for ARMv7, ...
+#ifndef Q_CC_RCVT
+# define Q_DATA_MEMORY_BARRIER asm volatile("dmb\n":::"memory")
+#else
+# define Q_DATA_MEMORY_BARRIER do{__asm { dmb } __schedule_barrier();}while(0)
+#endif
+
+// ... but the implementation is otherwise identical to that for ARMv6
+QT_BEGIN_INCLUDE_HEADER
+#include "QtCore/qatomic_armv6.h"
+QT_END_INCLUDE_HEADER
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARMV7_H
diff --git a/src/corelib/arch/qatomic_avr32.h b/src/corelib/arch/qatomic_avr32.h
new file mode 100644
index 0000000000..a650d73332
--- /dev/null
+++ b/src/corelib/arch/qatomic_avr32.h
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_AVR32_H
+#define QATOMIC_AVR32_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+inline bool QBasicAtomicInt::ref()
+{
+ return __sync_add_and_fetch(&_q_value, 1);
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return __sync_sub_and_fetch(&_q_value, 1);
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return __sync_lock_test_and_set(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return __sync_fetch_and_add(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return __sync_lock_test_and_set(&_q_value, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return __sync_fetch_and_add(&_q_value, valueToAdd * sizeof(T));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_AVR32_H
diff --git a/src/corelib/arch/qatomic_bfin.h b/src/corelib/arch/qatomic_bfin.h
new file mode 100644
index 0000000000..dd53342dfa
--- /dev/null
+++ b/src/corelib/arch/qatomic_bfin.h
@@ -0,0 +1,343 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_BFIN_H
+#define QATOMIC_BFIN_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <asm/fixed_code.h>
+QT_END_INCLUDE_NAMESPACE
+
+inline bool QBasicAtomicInt::ref()
+{
+ int ret;
+ asm volatile("R0 = 1;\n\t"
+ "P0 = %3;\n\t"
+ "CALL (%2);\n\t"
+ "%0 = R0;"
+ : "=da" (ret), "=m" (_q_value)
+ : "a" (ATOMIC_ADD32), "da" (&_q_value), "m" (_q_value)
+ : "R0", "R1", "P0", "RETS", "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int ret;
+ asm volatile("R0 = 1;\n\t"
+ "P0 = %3;\n\t"
+ "CALL (%2);\n\t"
+ "%0 = R0;"
+ : "=da" (ret), "=m" (_q_value)
+ : "a" (ATOMIC_SUB32), "da" (&_q_value), "m" (_q_value)
+ : "R0", "R1", "P0", "RETS", "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ long int readval;
+ asm volatile ("P0 = %2;\n\t"
+ "R1 = %3;\n\t"
+ "R2 = %4;\n\t"
+ "CALL (%5);\n\t"
+ "%0 = R0;\n\t"
+ : "=da" (readval), "=m" (_q_value)
+ : "da" (&_q_value),
+ "da" (expectedValue),
+ "da" (newValue),
+ "a" (ATOMIC_CAS32),
+ "m" (_q_value)
+ : "P0", "R0", "R1", "R2", "RETS", "memory", "cc");
+ return readval == expectedValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ asm volatile("R1 = %2;\n\t"
+ "P0 = %4;\n\t"
+ "CALL (%3);\n\t"
+ "%0 = R0;"
+ : "=da" (newValue), "=m" (_q_value)
+ : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value)
+ : "R0", "R1", "P0", "RETS", "memory");
+ return newValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ int ret;
+ asm volatile("R0 = %[val];\n\t"
+ "P0 = %[qvalp];\n\t"
+ "CALL (%[addr]);\n\t"
+ "%[ret] = R1;"
+ : [ret] "=da" (ret), "=m" (_q_value)
+ : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd)
+ : "R0", "R1", "P0", "RETS", "memory");
+ return ret;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ T *readval;
+ asm volatile ("P0 = %2;\n\t"
+ "R1 = %3;\n\t"
+ "R2 = %4;\n\t"
+ "CALL (%5);\n\t"
+ "%0 = R0;\n\t"
+ : "=da" (readval), "=m" (_q_value)
+ : "da" (&_q_value),
+ "da" (expectedValue),
+ "da" (newValue),
+ "a" (ATOMIC_CAS32),
+ "m" (_q_value)
+ : "P0", "R0", "R1", "R2", "RETS", "memory", "cc");
+ return readval == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ asm volatile("R1 = %2;\n\t"
+ "P0 = %4;\n\t"
+ "CALL (%3);\n\t"
+ "%0 = R0;"
+ : "=da" (newValue), "=m" (_q_value)
+ : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value)
+ : "R0", "R1", "P0", "RETS", "memory");
+ return newValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ T* ret;
+ asm volatile("R0 = %[val];\n\t"
+ "P0 = %[qvalp];\n\t"
+ "CALL (%[addr]);\n\t"
+ "%[ret] = R1;"
+ : [ret] "=da" (ret), "=m" (_q_value)
+ : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd * sizeof(T))
+ : "R0", "R1", "P0", "RETS", "memory");
+ return ret;
+}
+
+
+#endif // Q_OS_LINUX && Q_CC_GNU
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_BFIN_H
diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h
new file mode 100644
index 0000000000..7927d8b557
--- /dev/null
+++ b/src/corelib/arch/qatomic_bootstrap.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_BOOTSTRAP_H
+#define QATOMIC_BOOTSTRAP_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+inline bool QBasicAtomicInt::ref()
+{
+ return ++_q_value != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return --_q_value != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ return true;
+ }
+ return false;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ int returnValue = _q_value;
+ _q_value += valueToAdd;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_BOOTSTRAP_H
diff --git a/src/corelib/arch/qatomic_generic.h b/src/corelib/arch/qatomic_generic.h
new file mode 100644
index 0000000000..d9c864798e
--- /dev/null
+++ b/src/corelib/arch/qatomic_generic.h
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_GENERIC_H
+#define QATOMIC_GENERIC_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetOrdered(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddOrdered(volatile int *, int);
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *, qptrdiff);
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, 1) != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, -1) != 1;
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ union { T * volatile * typed; void * volatile * voidp; } pointer;
+ pointer.typed = &_q_value;
+ return QBasicAtomicPointer_testAndSetOrdered(pointer.voidp, expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ union { T * volatile * typed; void * volatile * voidp; } pointer;
+ union { T *typed; void *voidp; } returnValue;
+ pointer.typed = &_q_value;
+ returnValue.voidp = QBasicAtomicPointer_fetchAndStoreOrdered(pointer.voidp, newValue);
+ return returnValue.typed;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ union { T * volatile *typed; void * volatile *voidp; } pointer;
+ union { T *typed; void *voidp; } returnValue;
+ pointer.typed = &_q_value;
+ returnValue.voidp = QBasicAtomicPointer_fetchAndAddOrdered(pointer.voidp, valueToAdd * sizeof(T));
+ return returnValue.typed;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_GENERIC_H
diff --git a/src/corelib/arch/qatomic_i386.h b/src/corelib/arch/qatomic_i386.h
new file mode 100644
index 0000000000..73095a94f6
--- /dev/null
+++ b/src/corelib/arch/qatomic_i386.h
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_I386_H
+#define QATOMIC_I386_H
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return true; }
+
+#if defined(Q_CC_GNU) || defined(Q_CC_INTEL)
+
+inline bool QBasicAtomicInt::ref()
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "incl %0\n"
+ "setne %1"
+ : "=m" (_q_value), "=qm" (ret)
+ : "m" (_q_value)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "decl %0\n"
+ "setne %1"
+ : "=m" (_q_value), "=qm" (ret)
+ : "m" (_q_value)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "cmpxchgl %3,%2\n"
+ "sete %1\n"
+ : "=a" (newValue), "=qm" (ret), "+m" (_q_value)
+ : "r" (newValue), "0" (expectedValue)
+ : "memory");
+ return ret != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ asm volatile("xchgl %0,%1"
+ : "=r" (newValue), "+m" (_q_value)
+ : "0" (newValue)
+ : "memory");
+ return newValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ asm volatile("lock\n"
+ "xaddl %0,%1"
+ : "=r" (valueToAdd), "+m" (_q_value)
+ : "0" (valueToAdd)
+ : "memory");
+ return valueToAdd;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "cmpxchgl %3,%2\n"
+ "sete %1\n"
+ : "=a" (newValue), "=qm" (ret), "+m" (_q_value)
+ : "r" (newValue), "0" (expectedValue)
+ : "memory");
+ return ret != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ asm volatile("xchgl %0,%1"
+ : "=r" (newValue), "+m" (_q_value)
+ : "0" (newValue)
+ : "memory");
+ return newValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ asm volatile("lock\n"
+ "xaddl %0,%1"
+ : "=r" (valueToAdd), "+m" (_q_value)
+ : "0" (valueToAdd * sizeof(T))
+ : "memory");
+ return reinterpret_cast<T *>(valueToAdd);
+}
+
+#else
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, int value);
+} // extern "C"
+
+inline bool QBasicAtomicInt::ref()
+{
+ return q_atomic_increment(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return q_atomic_decrement(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return q_atomic_set_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_int(&_q_value, valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+#endif
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QATOMIC_I386_H
diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h
new file mode 100644
index 0000000000..42f30266d2
--- /dev/null
+++ b/src/corelib/arch/qatomic_ia64.h
@@ -0,0 +1,813 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_IA64_H
+#define QATOMIC_IA64_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+inline bool _q_ia64_fetchadd_immediate(register int value)
+{
+ return value == 1 || value == -1
+ || value == 4 || value == -4
+ || value == 8 || value == -8
+ || value == 16 || value == -16;
+}
+
+#if defined(Q_CC_INTEL)
+
+// intrinsics provided by the Intel C++ Compiler
+#include <ia64intrin.h>
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return static_cast<int>(_InterlockedExchange(&_q_value, newValue));
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ __memory_barrier();
+ return static_cast<int>(_InterlockedExchange(&_q_value, newValue));
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int expectedValueCopy = expectedValue;
+ return (static_cast<int>(_InterlockedCompareExchange(&_q_value,
+ newValue,
+ expectedValueCopy))
+ == expectedValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ register int expectedValueCopy = expectedValue;
+ return (static_cast<int>(_InterlockedCompareExchange_acq(reinterpret_cast<volatile uint *>(&_q_value),
+ newValue,
+ expectedValueCopy))
+ == expectedValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ register int expectedValueCopy = expectedValue;
+ return (static_cast<int>(_InterlockedCompareExchange_rel(reinterpret_cast<volatile uint *>(&_q_value),
+ newValue,
+ expectedValueCopy))
+ == expectedValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ __memory_barrier();
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ if (__builtin_constant_p(valueToAdd)) {
+ if (valueToAdd == 1)
+ return __fetchadd4_acq((unsigned int *)&_q_value, 1);
+ if (valueToAdd == -1)
+ return __fetchadd4_acq((unsigned int *)&_q_value, -1);
+ }
+ return _InterlockedExchangeAdd(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ if (__builtin_constant_p(valueToAdd)) {
+ if (valueToAdd == 1)
+ return __fetchadd4_rel((unsigned int *)&_q_value, 1);
+ if (valueToAdd == -1)
+ return __fetchadd4_rel((unsigned int *)&_q_value, -1);
+ }
+ __memory_barrier();
+ return _InterlockedExchangeAdd(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ __memory_barrier();
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+inline bool QBasicAtomicInt::ref()
+{
+ return _InterlockedIncrement(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return _InterlockedDecrement(&_q_value) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return (T *)_InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ __memory_barrier();
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register T *expectedValueCopy = expectedValue;
+ return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile*>(&_q_value),
+ newValue,
+ expectedValueCopy)
+ == expectedValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ union {
+ volatile void *x;
+ volatile unsigned long *p;
+ };
+ x = &_q_value;
+ register T *expectedValueCopy = expectedValue;
+ return (_InterlockedCompareExchange64_acq(p, quintptr(newValue), quintptr(expectedValueCopy))
+ == quintptr(expectedValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ union {
+ volatile void *x;
+ volatile unsigned long *p;
+ };
+ x = &_q_value;
+ register T *expectedValueCopy = expectedValue;
+ return (_InterlockedCompareExchange64_rel(p, quintptr(newValue), quintptr(expectedValueCopy))
+ == quintptr(expectedValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ __memory_barrier();
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value,
+ valueToAdd * sizeof(T));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ __memory_barrier();
+ return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value,
+ valueToAdd * sizeof(T));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ __memory_barrier();
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+#else // !Q_CC_INTEL
+
+# if defined(Q_CC_GNU)
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ int ret;
+ asm volatile("xchg4 %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return ret;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ int ret;
+ asm volatile("mf\n"
+ "xchg4 %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return ret;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ int ret;
+ asm volatile("mov ar.ccv=%2\n"
+ ";;\n"
+ "cmpxchg4.acq %0=%1,%3,ar.ccv\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret == expectedValue;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ int ret;
+ asm volatile("mov ar.ccv=%2\n"
+ ";;\n"
+ "cmpxchg4.rel %0=%1,%3,ar.ccv\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret == expectedValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ int ret;
+
+#if (__GNUC__ >= 4)
+ // We implement a fast fetch-and-add when we can
+ if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) {
+ asm volatile("fetchadd4.acq %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "i" (valueToAdd)
+ : "memory");
+ return ret;
+ }
+#endif
+
+ // otherwise, use a loop around test-and-set
+ ret = _q_value;
+ asm volatile("0:\n"
+ " mov r9=%0\n"
+ " mov ar.ccv=%0\n"
+ " add %0=%0, %2\n"
+ " ;;\n"
+ " cmpxchg4.acq %0=%1,%0,ar.ccv\n"
+ " ;;\n"
+ " cmp.ne p6,p0 = %0, r9\n"
+ "(p6) br.dptk 0b\n"
+ "1:\n"
+ : "+r" (ret), "+m" (_q_value)
+ : "r" (valueToAdd)
+ : "r9", "p6", "memory");
+ return ret;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ int ret;
+
+#if (__GNUC__ >= 4)
+ // We implement a fast fetch-and-add when we can
+ if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) {
+ asm volatile("fetchadd4.rel %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "i" (valueToAdd)
+ : "memory");
+ return ret;
+ }
+#endif
+
+ // otherwise, use a loop around test-and-set
+ ret = _q_value;
+ asm volatile("0:\n"
+ " mov r9=%0\n"
+ " mov ar.ccv=%0\n"
+ " add %0=%0, %2\n"
+ " ;;\n"
+ " cmpxchg4.rel %0=%1,%0,ar.ccv\n"
+ " ;;\n"
+ " cmp.ne p6,p0 = %0, r9\n"
+ "(p6) br.dptk 0b\n"
+ "1:\n"
+ : "+r" (ret), "+m" (_q_value)
+ : "r" (valueToAdd)
+ : "r9", "p6", "memory");
+ return ret;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ asm volatile("mf" ::: "memory");
+ return fetchAndAddRelease(valueToAdd);
+}
+
+inline bool QBasicAtomicInt::ref()
+{
+ int ret;
+ asm volatile("fetchadd4.acq %0=%1,1\n"
+ : "=r" (ret), "+m" (_q_value)
+ :
+ : "memory");
+ return ret != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int ret;
+ asm volatile("fetchadd4.rel %0=%1,-1\n"
+ : "=r" (ret), "+m" (_q_value)
+ :
+ : "memory");
+ return ret != 1;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ T *ret;
+ asm volatile("xchg8 %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return ret;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ T *ret;
+ asm volatile("mf\n"
+ "xchg8 %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (newValue)
+ : "memory");
+ return ret;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ T *ret;
+ asm volatile("mov ar.ccv=%2\n"
+ ";;\n"
+ "cmpxchg8.acq %0=%1,%3,ar.ccv\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ T *ret;
+ asm volatile("mov ar.ccv=%2\n"
+ ";;\n"
+ "cmpxchg8.rel %0=%1,%3,ar.ccv\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "r" (expectedValue), "r" (newValue)
+ : "memory");
+ return ret == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ T *ret;
+
+#if (__GNUC__ >= 4)
+ // We implement a fast fetch-and-add when we can
+ if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) {
+ asm volatile("fetchadd8.acq %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "i" (valueToAdd * sizeof(T))
+ : "memory");
+ return ret;
+ }
+#endif
+
+ // otherwise, use a loop around test-and-set
+ ret = _q_value;
+ asm volatile("0:\n"
+ " mov r9=%0\n"
+ " mov ar.ccv=%0\n"
+ " add %0=%0, %2\n"
+ " ;;\n"
+ " cmpxchg8.acq %0=%1,%0,ar.ccv\n"
+ " ;;\n"
+ " cmp.ne p6,p0 = %0, r9\n"
+ "(p6) br.dptk 0b\n"
+ "1:\n"
+ : "+r" (ret), "+m" (_q_value)
+ : "r" (valueToAdd * sizeof(T))
+ : "r9", "p6", "memory");
+ return ret;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ T *ret;
+
+#if (__GNUC__ >= 4)
+ // We implement a fast fetch-and-add when we can
+ if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) {
+ asm volatile("fetchadd8.rel %0=%1,%2\n"
+ : "=r" (ret), "+m" (_q_value)
+ : "i" (valueToAdd * sizeof(T))
+ : "memory");
+ return ret;
+ }
+#endif
+
+ // otherwise, use a loop around test-and-set
+ ret = _q_value;
+ asm volatile("0:\n"
+ " mov r9=%0\n"
+ " mov ar.ccv=%0\n"
+ " add %0=%0, %2\n"
+ " ;;\n"
+ " cmpxchg8.rel %0=%1,%0,ar.ccv\n"
+ " ;;\n"
+ " cmp.ne p6,p0 = %0, r9\n"
+ "(p6) br.dptk 0b\n"
+ "1:\n"
+ : "+r" (ret), "+m" (_q_value)
+ : "r" (valueToAdd * sizeof(T))
+ : "r9", "p6", "memory");
+ return ret;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ asm volatile("mf" ::: "memory");
+ return fetchAndAddRelease(valueToAdd);
+}
+
+#elif defined Q_CC_HPACC
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <ia64/sys/inline.h>
+QT_END_INCLUDE_NAMESPACE
+
+#define FENCE (_Asm_fence)(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue,
+ (_Asm_ldhint)_LDHINT_NONE, FENCE);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ _Asm_mf(FENCE);
+ return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue,
+ (_Asm_ldhint)_LDHINT_NONE, FENCE);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE);
+ int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, (unsigned)newValue, (_Asm_ldhint)_LDHINT_NONE);
+ return ret == expectedValue;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE);
+ int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, newValue, (_Asm_ldhint)_LDHINT_NONE);
+ return ret == expectedValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ if (valueToAdd == 1)
+ return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
+ else if (valueToAdd == -1)
+ return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
+
+ // implement the test-and-set loop
+ register int old, ret;
+ do {
+ old = _q_value;
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE);
+ ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE);
+ } while (ret != old);
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ if (valueToAdd == 1)
+ return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
+ else if (valueToAdd == -1)
+ return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
+
+ // implement the test-and-set loop
+ register int old, ret;
+ do {
+ old = _q_value;
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE);
+ ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE);
+ } while (ret != old);
+ return old;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ _Asm_mf(FENCE);
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+inline bool QBasicAtomicInt::ref()
+{
+ return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != 1;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+#ifdef __LP64__
+ return (T *)_Asm_xchg((_Asm_sz)_SZ_D, &_q_value, (quint64)newValue,
+ (_Asm_ldhint)_LDHINT_NONE, FENCE);
+#else
+ return (T *)_Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (quint32)newValue,
+ (_Asm_ldhint)_LDHINT_NONE, FENCE);
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ _Asm_mf(FENCE);
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+#ifdef __LP64__
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE);
+ T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ,
+ &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE);
+#else
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE);
+ T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE);
+#endif
+ return ret == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+#ifdef __LP64__
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE);
+ T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL,
+ &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE);
+#else
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE);
+ T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE);
+#endif
+ return ret == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ // implement the test-and-set loop
+ register T *old, *ret;
+ do {
+ old = _q_value;
+#ifdef __LP64__
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE);
+ ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ,
+ &_q_value, (quint64)(old + valueToAdd),
+ (_Asm_ldhint)_LDHINT_NONE);
+#else
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE);
+ ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
+ &_q_value, (quint32)(old + valueToAdd),
+ (_Asm_ldhint)_LDHINT_NONE);
+#endif
+ } while (old != ret);
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ // implement the test-and-set loop
+ register T *old, *ret;
+ do {
+ old = _q_value;
+#ifdef __LP64__
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE);
+ ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL,
+ &_q_value, (quint64)(old + valueToAdd),
+ (_Asm_ldhint)_LDHINT_NONE);
+#else
+ _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE);
+ ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
+ &_q_value, (quint32)(old + valueToAdd),
+ (_Asm_ldhint)_LDHINT_NONE);
+#endif
+ } while (old != ret);
+ return old;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ _Asm_mf(FENCE);
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+#else
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+} // extern "C"
+
+#endif
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+#endif // Q_CC_INTEL
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreRelease(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreRelaxed(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_IA64_H
diff --git a/src/corelib/arch/qatomic_integrity.h b/src/corelib/arch/qatomic_integrity.h
new file mode 100644
index 0000000000..6563903a25
--- /dev/null
+++ b/src/corelib/arch/qatomic_integrity.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_INTEGRITY_H
+#define QATOMIC_INTEGRITY_H
+
+#include <INTEGRITY.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define qt_i2addr(a) reinterpret_cast<Address *>(const_cast<int *>(a))
+#define qt_p2addr(a) reinterpret_cast<Address *>(const_cast<void *>(a))
+#define qt_addr(a) reinterpret_cast<Address>(a)
+
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return true; }
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+ int oldval;
+ AtomicModify(qt_i2addr(&_q_value), qt_i2addr(&oldval), 0, 1);
+ return _q_value != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int oldval;
+ AtomicModify(qt_i2addr(&_q_value), qt_i2addr(&oldval), 0, -1U);
+ return _q_value != 0;
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return TestAndSet(qt_i2addr(&_q_value), expectedValue, newValue) == Success;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ int old_val;
+ do {
+ old_val = _q_value;
+ } while (TestAndSet(qt_i2addr(&_q_value), old_val, newValue) != Success);
+ return old_val;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ int old_val;
+ do {
+ old_val = _q_value;
+ } while (TestAndSet(qt_i2addr(&_q_value), old_val, old_val + valueToAdd) != Success);
+ return old_val;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return TestAndSet((Address*)&_q_value, qt_addr(expectedValue), qt_addr(newValue)) == Success;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ Address old_val;
+ do {
+ old_val = *reinterpret_cast<Address *>(const_cast<T *>(newValue));
+ } while (TestAndSet(reinterpret_cast<Address *>(const_cast<T **>(&_q_value)), old_val, qt_addr(newValue)) != Success);
+ return reinterpret_cast<T *>(old_val);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ AtomicModify(qt_p2addr(&_q_value), qt_addr(_q_value), qt_addr(_q_value) + valueToAdd * sizeof(T));
+ return _q_value;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_INTEGRITY_H
+
diff --git a/src/corelib/arch/qatomic_macosx.h b/src/corelib/arch/qatomic_macosx.h
new file mode 100644
index 0000000000..be4501f4d2
--- /dev/null
+++ b/src/corelib/arch/qatomic_macosx.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_MACOSX_H
+#define QATOMIC_MACOSX_H
+
+QT_BEGIN_HEADER
+
+#if defined(__x86_64__)
+# include <QtCore/qatomic_x86_64.h>
+#elif defined(__i386__)
+# include <QtCore/qatomic_i386.h>
+#else // !__x86_64 && !__i386__
+# include <QtCore/qatomic_powerpc.h>
+#endif // !__x86_64__ && !__i386__
+
+QT_END_HEADER
+
+#endif // QATOMIC_MACOSX_H
diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h
new file mode 100644
index 0000000000..6f2607c524
--- /dev/null
+++ b/src/corelib/arch/qatomic_mips.h
@@ -0,0 +1,892 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_MIPS_H
+#define QATOMIC_MIPS_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#if defined(Q_CC_GNU) && !defined(Q_OS_IRIX)
+
+#if _MIPS_SIM == _ABIO32
+#define SET_MIPS2 ".set mips2\n\t"
+#else
+#define SET_MIPS2
+#endif
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "addiu %[newValue], %[originalValue], %[one]\n"
+ "sc %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [one] "i" (1)
+ : "cc", "memory");
+ return originalValue != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "addiu %[newValue], %[originalValue], %[minusOne]\n"
+ "sc %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [minusOne] "i" (-1)
+ : "cc", "memory");
+ return originalValue != 1;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int result;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ register int result;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ register int result;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ "ll %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int originalValue;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ register int originalValue;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ register int originalValue;
+ register int tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ "sc %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ "sc %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ "sc %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ "ll %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ "sc %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+#if defined(__LP64__)
+# define LLP "lld"
+# define SCP "scd"
+#else
+# define LLP "ll"
+# define SCP "sc"
+#endif
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register T *result;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ register T *result;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ register T *result;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ LLP" %[result], %[_q_value]\n"
+ "xor %[result], %[result], %[expectedValue]\n"
+ "bnez %[result], 0f\n"
+ "nop\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "0:\n"
+ ".set pop\n"
+ : [result] "=&r" (result),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *originalValue;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ register T *originalValue;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ register T *originalValue;
+ register T *tempValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "move %[tempValue], %[newValue]\n"
+ SCP" %[tempValue], %[_q_value]\n"
+ "beqz %[tempValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [tempValue] "=&r" (tempValue),
+ [_q_value] "+m" (_q_value)
+ : [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ SCP" %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ SCP" %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ "sync\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
+ "0:\n"
+ LLP" %[originalValue], %[_q_value]\n"
+ "addu %[newValue], %[originalValue], %[valueToAdd]\n"
+ SCP" %[newValue], %[_q_value]\n"
+ "beqz %[newValue], 0b\n"
+ "nop\n"
+ ".set pop\n"
+ : [originalValue] "=&r" (originalValue),
+ [_q_value] "+m" (_q_value),
+ [newValue] "=&r" (newValue)
+ : [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+#else // !Q_CC_GNU
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr, void *expected, void *newval);
+} // extern "C"
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int expected;
+ for (;;) {
+ expected = _q_value;
+ if (q_atomic_test_and_set_int(&_q_value, expected, expected + 1))
+ break;
+ }
+ return expected != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int expected;
+ for (;;) {
+ expected = _q_value;
+ if (q_atomic_test_and_set_int(&_q_value, expected, expected - 1))
+ break;
+ }
+ return expected != 1;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetRelaxed(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetAcquire(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetRelease(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetOrdered(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetRelaxed(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetAcquire(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetRelease(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ int returnValue;
+ for (;;) {
+ returnValue = _q_value;
+ if (testAndSetOrdered(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetRelaxed(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetAcquire(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetRelease(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetOrdered(returnValue, newValue))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetRelaxed(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE
+T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetAcquire(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetRelease(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ T *returnValue;
+ for (;;) {
+ returnValue = (_q_value);
+ if (testAndSetOrdered(returnValue, returnValue + valueToAdd))
+ break;
+ }
+ return returnValue;
+}
+
+#endif // Q_CC_GNU
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_MIPS_H
diff --git a/src/corelib/arch/qatomic_parisc.h b/src/corelib/arch/qatomic_parisc.h
new file mode 100644
index 0000000000..eeff9266ee
--- /dev/null
+++ b/src/corelib/arch/qatomic_parisc.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_PARISC_H
+#define QATOMIC_PARISC_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+extern "C" {
+ Q_CORE_EXPORT void q_atomic_lock(int *lock);
+ Q_CORE_EXPORT void q_atomic_unlock(int *lock);
+}
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+ q_atomic_lock(_q_lock);
+ bool ret = (++_q_value != 0);
+ q_atomic_unlock(_q_lock);
+ return ret;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ q_atomic_lock(_q_lock);
+ bool ret = (--_q_value != 0);
+ q_atomic_unlock(_q_lock);
+ return ret;
+}
+
+// Test-and-set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ q_atomic_lock(_q_lock);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ q_atomic_unlock(_q_lock);
+ return true;
+ }
+ q_atomic_unlock(_q_lock);
+ return false;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch-and-store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ q_atomic_lock(_q_lock);
+ int returnValue = _q_value;
+ _q_value = newValue;
+ q_atomic_unlock(_q_lock);
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch-and-add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ q_atomic_lock(_q_lock);
+ int originalValue = _q_value;
+ _q_value += valueToAdd;
+ q_atomic_unlock(_q_lock);
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ q_atomic_lock(_q_lock);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ q_atomic_unlock(_q_lock);
+ return true;
+ }
+ q_atomic_unlock(_q_lock);
+ return false;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ q_atomic_lock(_q_lock);
+ T *returnValue = (_q_value);
+ _q_value = newValue;
+ q_atomic_unlock(_q_lock);
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ q_atomic_lock(_q_lock);
+ T *returnValue = (_q_value);
+ _q_value += valueToAdd;
+ q_atomic_unlock(_q_lock);
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_PARISC_H
diff --git a/src/corelib/arch/qatomic_powerpc.h b/src/corelib/arch/qatomic_powerpc.h
new file mode 100644
index 0000000000..e261ff7192
--- /dev/null
+++ b/src/corelib/arch/qatomic_powerpc.h
@@ -0,0 +1,648 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_POWERPC_H
+#define QATOMIC_POWERPC_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#if defined(Q_CC_GNU)
+
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) \
+ || (!defined(__64BIT__) && !defined(__powerpc64__) && !defined(__ppc64__))
+# define _Q_VALUE "0, %[_q_value]"
+# define _Q_VALUE_MEMORY_OPERAND "+m" (_q_value)
+# define _Q_VALUE_REGISTER_OPERAND [_q_value] "r" (&_q_value),
+#else
+// On 64-bit with gcc >= 4.2
+# define _Q_VALUE "%y[_q_value]"
+# define _Q_VALUE_MEMORY_OPERAND [_q_value] "+Z" (_q_value)
+# define _Q_VALUE_REGISTER_OPERAND
+#endif
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "addi %[newValue], %[originalValue], %[one]\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&b" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [one] "i" (1)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "addi %[newValue], %[originalValue], %[minusOne]\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&b" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [minusOne] "i" (-1)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("lwarx %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+12\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("lwarx %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+16\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ "isync\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("eieio\n"
+ "lwarx %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+12\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int originalValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ register int originalValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ "isync\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ register int originalValue;
+ asm volatile("eieio\n"
+ "lwarx %[originalValue]," _Q_VALUE "\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ "isync\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ register int originalValue;
+ register int newValue;
+ asm volatile("eieio\n"
+ "lwarx %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ "stwcx. %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd)
+ : "cc", "memory");
+ return originalValue;
+}
+
+#if defined(__64BIT__) || defined(__powerpc64__) || defined(__ppc64__)
+# define LPARX "ldarx"
+# define STPCX "stdcx."
+#else
+# define LPARX "lwarx"
+# define STPCX "stwcx."
+#endif
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register void *result;
+ asm volatile(LPARX" %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+12\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ register void *result;
+ asm volatile(LPARX" %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+16\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ "isync\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ register void *result;
+ asm volatile("eieio\n"
+ LPARX" %[result]," _Q_VALUE "\n"
+ "xor. %[result], %[result], %[expectedValue]\n"
+ "bne $+12\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-16\n"
+ : [result] "=&r" (result),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *originalValue;
+ asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ register T *originalValue;
+ asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ "isync\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ register T *originalValue;
+ asm volatile("eieio\n"
+ LPARX" %[originalValue]," _Q_VALUE "\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-8\n"
+ : [originalValue] "=&r" (originalValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [newValue] "r" (newValue)
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ "isync\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ register T *newValue;
+ asm volatile("eieio\n"
+ LPARX" %[originalValue]," _Q_VALUE "\n"
+ "add %[newValue], %[originalValue], %[valueToAdd]\n"
+ STPCX" %[newValue]," _Q_VALUE "\n"
+ "bne- $-12\n"
+ : [originalValue] "=&r" (originalValue),
+ [newValue] "=&r" (newValue),
+ _Q_VALUE_MEMORY_OPERAND
+ : _Q_VALUE_REGISTER_OPERAND
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "cc", "memory");
+ return originalValue;
+}
+
+#undef LPARX
+#undef STPCX
+#undef _Q_VALUE
+#undef _Q_VALUE_MEMORY_OPERAND
+#undef _Q_VALUE_REGISTER_OPERAND
+
+#else
+
+extern "C" {
+ int q_atomic_test_and_set_int(volatile int *ptr, int expectedValue, int newValue);
+ int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expectedValue, int newValue);
+ int q_atomic_test_and_set_release_int(volatile int *ptr, int expectedValue, int newValue);
+ int q_atomic_test_and_set_ptr(volatile void *ptr, void *expectedValue, void *newValue);
+ int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, void *expectedValue, void *newValue);
+ int q_atomic_test_and_set_release_ptr(volatile void *ptr, void *expectedValue, void *newValue);
+ int q_atomic_increment(volatile int *);
+ int q_atomic_decrement(volatile int *);
+ int q_atomic_set_int(volatile int *, int);
+ int q_atomic_fetch_and_store_acquire_int(volatile int *ptr, int newValue);
+ int q_atomic_fetch_and_store_release_int(volatile int *ptr, int newValue);
+ void *q_atomic_set_ptr(volatile void *, void *);
+ int q_atomic_fetch_and_store_acquire_ptr(volatile void *ptr, void *newValue);
+ int q_atomic_fetch_and_store_release_ptr(volatile void *ptr, void *newValue);
+ int q_atomic_fetch_and_add_int(volatile int *ptr, int valueToAdd);
+ int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int valueToAdd);
+ int q_atomic_fetch_and_add_release_int(volatile int *ptr, int valueToAdd);
+ void *q_atomic_fetch_and_add_ptr(volatile void *ptr, qptrdiff valueToAdd);
+ void *q_atomic_fetch_and_add_acquire_ptr(volatile void *ptr, qptrdiff valueToAdd);
+ void *q_atomic_fetch_and_add_release_ptr(volatile void *ptr, qptrdiff valueToAdd);
+} // extern "C"
+
+
+inline bool QBasicAtomicInt::ref()
+{
+ return q_atomic_increment(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return q_atomic_decrement(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return q_atomic_set_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return q_atomic_fetch_and_store_release_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_int(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_acquire_int(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return q_atomic_fetch_and_add_release_int(&_q_value, valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+#endif
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_POWERPC_H
diff --git a/src/corelib/arch/qatomic_s390.h b/src/corelib/arch/qatomic_s390.h
new file mode 100644
index 0000000000..552ebe43fe
--- /dev/null
+++ b/src/corelib/arch/qatomic_s390.h
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_S390_H
+#define QATOMIC_S390_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+#ifdef __GNUC__
+#define __GNU_EXTENSION __extension__
+#else
+#define __GNU_EXTENSION
+#endif
+
+#define __CS_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \
+ volatile int old_val, new_val; \
+ __asm__ __volatile__(pre \
+ " l %0,0(%3)\n" \
+ "0: lr %1,%0\n" \
+ op_string " %1,%4\n" \
+ " cs %0,%1,0(%3)\n" \
+ " jl 0b\n" \
+ post \
+ : "=&d" (old_val), "=&d" (new_val), \
+ "=m" (*ptr) \
+ : "a" (ptr), "d" (op_val), \
+ "m" (*ptr) \
+ : "cc", "memory" ); \
+ new_val; \
+})
+
+#define __CS_OLD_LOOP(ptr, op_val, op_string, pre, post ) __GNU_EXTENSION ({ \
+ volatile int old_val, new_val; \
+ __asm__ __volatile__(pre \
+ " l %0,0(%3)\n" \
+ "0: lr %1,%0\n" \
+ op_string " %1,%4\n" \
+ " cs %0,%1,0(%3)\n" \
+ " jl 0b\n" \
+ post \
+ : "=&d" (old_val), "=&d" (new_val), \
+ "=m" (*ptr) \
+ : "a" (ptr), "d" (op_val), \
+ "m" (*ptr) \
+ : "cc", "memory" ); \
+ old_val; \
+})
+
+#ifdef __s390x__
+#define __CSG_OLD_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \
+ long old_val, new_val; \
+ __asm__ __volatile__(pre \
+ " lg %0,0(%3)\n" \
+ "0: lgr %1,%0\n" \
+ op_string " %1,%4\n" \
+ " csg %0,%1,0(%3)\n" \
+ " jl 0b\n" \
+ post \
+ : "=&d" (old_val), "=&d" (new_val), \
+ "=m" (*ptr) \
+ : "a" (ptr), "d" (op_val), \
+ "m" (*ptr) \
+ : "cc", "memory" ); \
+ old_val; \
+})
+#endif
+
+inline bool QBasicAtomicInt::ref()
+{
+ return __CS_LOOP(&_q_value, 1, "ar", "", "") != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return __CS_LOOP(&_q_value, 1, "sr", "", "") != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ int retval;
+ __asm__ __volatile__(
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+ return retval == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ int retval;
+ __asm__ __volatile__(
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:\n"
+ " bcr 15,0\n"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+ return retval == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ int retval;
+ __asm__ __volatile__(
+ " bcr 15,0\n"
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+ return retval == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", "");
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", "bcr 15,0\n");
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return __CS_OLD_LOOP(&_q_value, newValue, "lr", "bcr 15,0\n", "");
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return __CS_OLD_LOOP(&_q_value, valueToAdd, "ar", "", "bcr 15,0\n");
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ int retval;
+
+#ifndef __s390x__
+ __asm__ __volatile__(
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#else
+ __asm__ __volatile__(
+ " lgr %0,%3\n"
+ " csg %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#endif
+
+ return retval == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ int retval;
+
+#ifndef __s390x__
+ __asm__ __volatile__(
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:\n"
+ " bcr 15,0\n"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#else
+ __asm__ __volatile__(
+ " lgr %0,%3\n"
+ " csg %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:\n"
+ " bcr 15,0\n"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#endif
+
+ return retval == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ int retval;
+
+#ifndef __s390x__
+ __asm__ __volatile__(
+ " bcr 15,0\n"
+ " lr %0,%3\n"
+ " cs %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#else
+ __asm__ __volatile__(
+ " bcr 15,0\n"
+ " lgr %0,%3\n"
+ " csg %0,%4,0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval), "=m" (_q_value)
+ : "a" (&_q_value), "d" (expectedValue) , "d" (newValue),
+ "m" (_q_value) : "cc", "memory" );
+#endif
+
+ return retval == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+#ifndef __s390x__
+ return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "", "");
+#else
+ return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "", "");
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+#ifndef __s390x__
+ return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "", "bcr 15,0 \n");
+#else
+ return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "", "bcr 15,0 \n");
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+#ifndef __s390x__
+ return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "bcr 15,0 \n", "");
+#else
+ return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "bcr 15,0\n", "");
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+#undef __GNU_EXTENSION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_S390_H
diff --git a/src/corelib/arch/qatomic_sh.h b/src/corelib/arch/qatomic_sh.h
new file mode 100644
index 0000000000..0150ca4443
--- /dev/null
+++ b/src/corelib/arch/qatomic_sh.h
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_SH_H
+#define QATOMIC_SH_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+extern Q_CORE_EXPORT volatile char qt_atomic_lock;
+Q_CORE_EXPORT void qt_atomic_yield(int *count);
+
+inline int qt_atomic_tasb(volatile char *ptr)
+{
+ register int ret;
+ asm volatile("tas.b @%2\n"
+ "movt %0"
+ : "=&r"(ret), "=m"(*ptr)
+ : "r"(ptr)
+ : "cc", "memory");
+ return ret;
+}
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value++;
+ qt_atomic_lock = 0;
+ return originalValue != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value--;
+ qt_atomic_lock = 0;
+ return originalValue != 1;
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ bool returnValue = false;
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ returnValue = true;
+ }
+ qt_atomic_lock = 0;
+ return returnValue;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value;
+ _q_value = newValue;
+ qt_atomic_lock = 0;
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ int originalValue = _q_value;
+ _q_value += valueToAdd;
+ qt_atomic_lock = 0;
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ bool returnValue = false;
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ returnValue = true;
+ }
+ qt_atomic_lock = 0;
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ T *originalValue = _q_value;
+ _q_value = newValue;
+ qt_atomic_lock = 0;
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ int count = 0;
+ while (qt_atomic_tasb(&qt_atomic_lock) == 0)
+ qt_atomic_yield(&count);
+ T *originalValue = (_q_value);
+ _q_value += valueToAdd;
+ qt_atomic_lock = 0;
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_SH_H
diff --git a/src/corelib/arch/qatomic_sh4a.h b/src/corelib/arch/qatomic_sh4a.h
new file mode 100644
index 0000000000..88fd4d451d
--- /dev/null
+++ b/src/corelib/arch/qatomic_sh4a.h
@@ -0,0 +1,537 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_SH4A_H
+#define QATOMIC_SH4A_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_CC_GNU)
+# error "SH-4A support has not been added for this compiler"
+#else
+
+inline bool QBasicAtomicInt::ref()
+{
+ register int newValue asm("r0");
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], %[newValue]\n"
+ "add #1,%[newValue]\n"
+ "movco.l %[newValue], @%[_q_value]\n"
+ "bf 0b\n"
+ : [newValue] "=&r" (newValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ register int newValue asm("r0");
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], %[newValue]\n"
+ "add #-1,%[newValue]\n"
+ "movco.l %[newValue], @%[_q_value]\n"
+ "bf 0b\n"
+ : [newValue] "=&r" (newValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value)
+ : "cc", "memory");
+ return newValue != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ register int result;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ register int originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ register int originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ register int originalValue;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ register int originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ register int originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ register int originalValue;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ register T *result;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ register T *result;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ register T *result;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "xor %[expectedValue], r0\n"
+ "cmp/eq #0, r0\n"
+ "bf/s 0f\n"
+ "mov r0, %[result]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "0:\n"
+ : [result] "=&r" (result),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [expectedValue] "r" (expectedValue),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return result == 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return testAndSetAcquire(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ register T *originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ register T *originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ register T *originalValue;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "mov %[newValue], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [newValue] "r" (newValue)
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return fetchAndStoreAcquire(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ asm volatile("0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ "synco\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ register T *originalValue;
+ asm volatile("synco\n"
+ "0:\n"
+ "movli.l @%[_q_value], r0\n"
+ "mov r0, %[originalValue]\n"
+ "add %[valueToAdd], r0\n"
+ "movco.l r0, @%[_q_value]\n"
+ "bf 0b\n"
+ : [originalValue] "=&r" (originalValue),
+ "+m" (_q_value)
+ : [_q_value] "r" (&_q_value),
+ [valueToAdd] "r" (valueToAdd * sizeof(T))
+ : "r0", "cc", "memory");
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return fetchAndAddAcquire(valueToAdd);
+}
+
+#endif // Q_CC_GNU
+
+#endif // QATOMIC_SH4A_H
diff --git a/src/corelib/arch/qatomic_sparc.h b/src/corelib/arch/qatomic_sparc.h
new file mode 100644
index 0000000000..a89a5f3fe5
--- /dev/null
+++ b/src/corelib/arch/qatomic_sparc.h
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_SPARC_H
+#define QATOMIC_SPARC_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#if defined(_LP64)
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr);
+
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr,
+ int expected,
+ int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr,
+ int expected,
+ int newval);
+
+ Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT int q_atomic_fetch_and_store_acquire_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT int q_atomic_fetch_and_store_release_int(volatile int *ptr, int newval);
+
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value);
+
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr,
+ void *expected,
+ void *newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr,
+ void *expected,
+ void *newval);
+
+ Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_store_acquire_ptr(volatile void *ptr, void *newval);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_store_release_ptr(volatile void *ptr, void *newval);
+
+ Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, int value);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_add_acquire_ptr(volatile void *ptr, int value);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_add_release_ptr(volatile void *ptr, int value);
+}
+
+inline bool QBasicAtomicInt::ref()
+{
+ return fetchAndAddRelaxed(1) != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return fetchAndAddRelaxed(-1) != 1;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return q_atomic_set_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return q_atomic_fetch_and_store_release_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int newValue)
+{
+ return q_atomic_fetch_and_add_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int newValue)
+{
+ return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int newValue)
+{
+ return q_atomic_fetch_and_add_release_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int newValue)
+{
+ return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE
+T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+#else
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_lock_int(volatile int *addr);
+ Q_CORE_EXPORT int q_atomic_lock_ptr(volatile void *addr);
+ Q_CORE_EXPORT void q_atomic_unlock(volatile void *addr, int value);
+ Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
+} // extern "C"
+
+inline bool QBasicAtomicInt::ref()
+{
+ const int val = q_atomic_lock_int(&_q_value);
+ q_atomic_unlock(&_q_value, val + 1);
+ return val != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ const int val = q_atomic_lock_int(&_q_value);
+ q_atomic_unlock(&_q_value, val - 1);
+ return val != 1;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ int val = q_atomic_lock_int(&_q_value);
+ if (val == expectedValue) {
+ q_atomic_unlock(&_q_value, newValue);
+ return true;
+ }
+ q_atomic_unlock(&_q_value, val);
+ return false;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return q_atomic_set_int(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ const int originalValue = q_atomic_lock_int(&_q_value);
+ q_atomic_unlock(&_q_value, originalValue + valueToAdd);
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ T *val = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value));
+ if (val == expectedValue) {
+ q_atomic_unlock(&_q_value, reinterpret_cast<int>(newValue));
+ return true;
+ }
+ q_atomic_unlock(&_q_value, reinterpret_cast<int>(val));
+ return false;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ T *originalValue = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value));
+ q_atomic_unlock(&_q_value, int(originalValue + valueToAdd));
+ return originalValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+#endif // _LP64
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_SPARC_H
diff --git a/src/corelib/arch/qatomic_symbian.h b/src/corelib/arch/qatomic_symbian.h
new file mode 100644
index 0000000000..c4cd301218
--- /dev/null
+++ b/src/corelib/arch/qatomic_symbian.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_SYMBIAN_H
+#define QATOMIC_SYMBIAN_H
+
+#include <QtCore/qglobal.h>
+#include <e32std.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isTestAndSetNative();
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return QBasicAtomicPointer_isTestAndSetNative(); }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndStoreNative();
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return QBasicAtomicPointer_isFetchAndStoreNative(); }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndAddNative();
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return QBasicAtomicPointer_isFetchAndAddNative(); }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetOrdered(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddOrdered(volatile int *, int);
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetRelaxed(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *, int);
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetAcquire(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddAcquire(volatile int *, int);
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetRelease(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreRelease(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddRelease(volatile int *, int);
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *, qptrdiff);
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *, qptrdiff);
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *, qptrdiff);
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetRelease(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *, qptrdiff);
+
+// Reference counting
+
+//LockedInc and LockedDec are machine coded for ARMv6 (and future proof)
+inline bool QBasicAtomicInt::ref()
+{
+ int original = User::LockedInc((TInt&)_q_value);
+ return original != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int original = User::LockedDec((TInt&)_q_value);
+ return original != 1;
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetRelaxed(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetAcquire(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetRelease(&_q_value, expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreRelaxed(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreAcquire(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreRelease(&_q_value, newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddRelaxed(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddAcquire(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddRelease(&_q_value, valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return QBasicAtomicPointer_testAndSetOrdered(reinterpret_cast<void * volatile *>(&_q_value),
+ expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return QBasicAtomicPointer_testAndSetRelaxed(reinterpret_cast<void * volatile *>(&_q_value),
+ expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return QBasicAtomicPointer_testAndSetAcquire(reinterpret_cast<void * volatile *>(&_q_value),
+ expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return QBasicAtomicPointer_testAndSetRelease(reinterpret_cast<void * volatile *>(&_q_value),
+ expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndStoreOrdered(
+ reinterpret_cast<void * volatile *>(&_q_value)
+ , newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndStoreRelaxed(
+ reinterpret_cast<void * volatile *>(&_q_value)
+ , newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndStoreAcquire(
+ reinterpret_cast<void * volatile *>(&_q_value)
+ , newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndStoreRelease(
+ reinterpret_cast<void * volatile *>(&_q_value)
+ , newValue));
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndAddOrdered(
+ reinterpret_cast<void * volatile *>(&_q_value),
+ valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndAddRelaxed(
+ reinterpret_cast<void * volatile *>(&_q_value),
+ valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndAddAcquire(
+ reinterpret_cast<void * volatile *>(&_q_value),
+ valueToAdd * sizeof(T)));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return static_cast<T*>(QBasicAtomicPointer_fetchAndAddRelease(
+ reinterpret_cast<void * volatile *>(&_q_value),
+ valueToAdd * sizeof(T)));
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_SYMBIAN_H
diff --git a/src/corelib/arch/qatomic_vxworks.h b/src/corelib/arch/qatomic_vxworks.h
new file mode 100644
index 0000000000..9386d19ece
--- /dev/null
+++ b/src/corelib/arch/qatomic_vxworks.h
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_VXWORKS_H
+#define QATOMIC_VXWORKS_H
+
+QT_BEGIN_HEADER
+
+#if defined(__ppc)
+# include <QtCore/qatomic_powerpc.h>
+#else // generic implementation with taskLock()
+
+#if 0
+// we don't want to include the system header here for two function prototypes,
+// because it pulls in a _lot_ of stuff that pollutes the global namespace
+# include <vxWorksCommon.h>
+# include <taskLib.h>
+#else
+extern "C" int taskLock();
+extern "C" int taskUnlock();
+#endif
+
+
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+// Reference counting
+
+inline bool QBasicAtomicInt::ref()
+{
+ taskLock();
+ bool ret = (++_q_value != 0);
+ taskUnlock();
+ return ret;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ taskLock();
+ bool ret = (--_q_value != 0);
+ taskUnlock();
+ return ret;
+}
+
+// Test-and-set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ taskLock();
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ taskUnlock();
+ return true;
+ }
+ taskUnlock();
+ return false;
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch-and-store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ taskLock();
+ int returnValue = _q_value;
+ _q_value = newValue;
+ taskUnlock();
+ return returnValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch-and-add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ taskLock();
+ int originalValue = _q_value;
+ _q_value += valueToAdd;
+ taskUnlock();
+ return originalValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ taskLock();
+ if (_q_value == expectedValue) {
+ _q_value = newValue;
+ taskUnlock();
+ return true;
+ }
+ taskUnlock();
+ return false;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ taskLock();
+ T *returnValue = (_q_value);
+ _q_value = newValue;
+ taskUnlock();
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ taskLock();
+ T *returnValue = (_q_value);
+ _q_value += valueToAdd;
+ taskUnlock();
+ return returnValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+#endif // generic implementation with taskLock()
+
+QT_END_HEADER
+
+#endif // QATOMIC_VXWORKS_H
diff --git a/src/corelib/arch/qatomic_windows.h b/src/corelib/arch/qatomic_windows.h
new file mode 100644
index 0000000000..538c00cff1
--- /dev/null
+++ b/src/corelib/arch/qatomic_windows.h
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_WINDOWS_H
+#define QATOMIC_WINDOWS_H
+
+#ifndef Q_CC_MSVC
+
+// Mingw and other GCC platforms get inline assembly
+
+# ifdef __i386__
+# include "QtCore/qatomic_i386.h"
+# else
+# include "QtCore/qatomic_x86_64.h"
+# endif
+
+#else // Q_CC_MSVC
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef Q_OS_WINCE
+
+// use compiler intrinsics for all atomic functions
+# define QT_INTERLOCKED_PREFIX _
+# define QT_INTERLOCKED_PROTOTYPE __cdecl
+# define QT_INTERLOCKED_DECLARE_PROTOTYPES
+# define QT_INTERLOCKED_INTRINSIC
+
+#else // Q_OS_WINCE
+
+# if _WIN32_WCE < 0x600 && defined(_X86_)
+// For X86 Windows CE, include winbase.h to catch inline functions which
+// override the regular definitions inside of coredll.dll.
+// Though one could use the original version of Increment/Decrement, others are
+// not exported at all.
+# include <winbase.h>
+
+// It's safer to remove the volatile and let the compiler add it as needed.
+# define QT_INTERLOCKED_NO_VOLATILE
+
+# else // _WIN32_WCE >= 0x600 || !_X86_
+
+# define QT_INTERLOCKED_PROTOTYPE __cdecl
+# define QT_INTERLOCKED_DECLARE_PROTOTYPES
+
+# if _WIN32_WCE >= 0x600
+# if defined(_X86_)
+# define QT_INTERLOCKED_PREFIX _
+# define QT_INTERLOCKED_INTRINSIC
+# endif
+# else
+# define QT_INTERLOCKED_NO_VOLATILE
+# endif
+
+# endif // _WIN32_WCE >= 0x600 || !_X86_
+
+#endif // Q_OS_WINCE
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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)
+
+#ifdef QT_INTERLOCKED_NO_VOLATILE
+# define QT_INTERLOCKED_VOLATILE
+# define QT_INTERLOCKED_REMOVE_VOLATILE(a) qt_interlocked_remove_volatile(a)
+#else
+# define QT_INTERLOCKED_VOLATILE volatile
+# define QT_INTERLOCKED_REMOVE_VOLATILE(a) a
+#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(Q_OS_WINCE) && !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
+
+}
+
+#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(Q_OS_WINCE) && !defined(_M_IX86)
+# pragma intrinsic (_InterlockedCompareExchangePointer)
+# pragma intrinsic (_InterlockedExchangePointer)
+# pragma intrinsic (_InterlockedExchangeAdd64)
+# endif
+
+#endif // QT_INTERLOCKED_INTRINSIC
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interlocked* replacement macros
+
+#define QT_INTERLOCKED_INCREMENT(value) \
+ QT_INTERLOCKED_FUNCTION( Increment )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ) )
+
+#define QT_INTERLOCKED_DECREMENT(value) \
+ QT_INTERLOCKED_FUNCTION( Decrement )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ) )
+
+#define QT_INTERLOCKED_COMPARE_EXCHANGE(value, newValue, expectedValue) \
+ QT_INTERLOCKED_FUNCTION( CompareExchange )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \
+ newValue, \
+ expectedValue )
+
+#define QT_INTERLOCKED_EXCHANGE(value, newValue) \
+ QT_INTERLOCKED_FUNCTION( Exchange )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \
+ newValue )
+
+#define QT_INTERLOCKED_EXCHANGE_ADD(value, valueToAdd) \
+ QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \
+ valueToAdd )
+
+#if defined(Q_OS_WINCE) || defined(__i386__) || defined(_M_IX86)
+
+# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
+ reinterpret_cast<void *>( \
+ QT_INTERLOCKED_FUNCTION( CompareExchange )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \
+ (long)( newValue ), \
+ (long)( expectedValue ) ))
+
+# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
+ QT_INTERLOCKED_FUNCTION( Exchange )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \
+ (quintptr)( newValue ) )
+
+# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
+ QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \
+ valueToAdd )
+
+#else // !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86)
+
+# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
+ QT_INTERLOCKED_FUNCTION( CompareExchangePointer )( \
+ reinterpret_cast<void * QT_INTERLOCKED_VOLATILE *>( QT_INTERLOCKED_REMOVE_VOLATILE( value ) ), \
+ newValue, \
+ expectedValue )
+
+# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
+ QT_INTERLOCKED_FUNCTION( ExchangePointer )( \
+ reinterpret_cast<void * QT_INTERLOCKED_VOLATILE *>( QT_INTERLOCKED_REMOVE_VOLATILE( value ) ), \
+ newValue )
+
+# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
+ QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )( \
+ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \
+ valueToAdd )
+
+#endif // !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86)
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return true; }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef QT_INTERLOCKED_NO_VOLATILE
+template <class T>
+Q_INLINE_TEMPLATE T *qt_interlocked_remove_volatile(T volatile *t)
+{
+ return const_cast<T *>(t);
+}
+#endif // !QT_INTERLOCKED_NO_VOLATILE
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline bool QBasicAtomicInt::ref()
+{
+ return QT_INTERLOCKED_INCREMENT(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return QT_INTERLOCKED_DECREMENT(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return QT_INTERLOCKED_COMPARE_EXCHANGE(&_q_value, newValue, expectedValue)
+ == expectedValue;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return QT_INTERLOCKED_EXCHANGE(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue)
+ == expectedValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T* newValue)
+{
+ return reinterpret_cast<T *>(
+ QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(
+ QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Cleanup
+
+#undef QT_INTERLOCKED_CONCAT_I
+#undef QT_INTERLOCKED_CONCAT
+#undef QT_INTERLOCKED_FUNCTION
+#undef QT_INTERLOCKED_PREFIX
+
+#undef QT_INTERLOCKED_NO_VOLATILE
+#undef QT_INTERLOCKED_VOLATILE
+#undef QT_INTERLOCKED_REMOVE_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
+
+QT_END_HEADER
+
+#endif // Q_CC_MSVC
+
+#endif // QATOMIC_WINDOWS_H
diff --git a/src/corelib/arch/qatomic_windowsce.h b/src/corelib/arch/qatomic_windowsce.h
new file mode 100644
index 0000000000..25696f9626
--- /dev/null
+++ b/src/corelib/arch/qatomic_windowsce.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOWSCE_QATOMIC_H
+#define WINDOWSCE_QATOMIC_H
+
+#include <QtCore/qglobal.h>
+QT_BEGIN_HEADER
+
+#if defined(QT_ARCH_WINDOWSCE)
+#include "QtCore/qatomic_windows.h"
+#endif
+
+QT_END_HEADER
+
+#endif // QATOMIC_ARCH_H
+
+
diff --git a/src/corelib/arch/qatomic_x86_64.h b/src/corelib/arch/qatomic_x86_64.h
new file mode 100644
index 0000000000..9303f191ce
--- /dev/null
+++ b/src/corelib/arch/qatomic_x86_64.h
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_X86_64_H
+#define QATOMIC_X86_64_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return true; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return true; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return true; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return true; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return true; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return true; }
+
+#if defined(Q_CC_GNU) || defined(Q_CC_INTEL)
+
+inline bool QBasicAtomicInt::ref()
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "incl %0\n"
+ "setne %1"
+ : "=m" (_q_value), "=qm" (ret)
+ : "m" (_q_value)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "decl %0\n"
+ "setne %1"
+ : "=m" (_q_value), "=qm" (ret)
+ : "m" (_q_value)
+ : "memory");
+ return ret != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "cmpxchgl %3,%2\n"
+ "sete %1\n"
+ : "=a" (newValue), "=qm" (ret), "+m" (_q_value)
+ : "r" (newValue), "0" (expectedValue)
+ : "memory");
+ return ret != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ asm volatile("xchgl %0,%1"
+ : "=r" (newValue), "+m" (_q_value)
+ : "0" (newValue)
+ : "memory");
+ return newValue;
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ asm volatile("lock\n"
+ "xaddl %0,%1"
+ : "=r" (valueToAdd), "+m" (_q_value)
+ : "0" (valueToAdd)
+ : "memory");
+ return valueToAdd;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ unsigned char ret;
+ asm volatile("lock\n"
+ "cmpxchgq %3,%2\n"
+ "sete %1\n"
+ : "=a" (newValue), "=qm" (ret), "+m" (_q_value)
+ : "r" (newValue), "0" (expectedValue)
+ : "memory");
+ return ret != 0;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ asm volatile("xchgq %0,%1"
+ : "=r" (newValue), "+m" (_q_value)
+ : "0" (newValue)
+ : "memory");
+ return newValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ asm volatile("lock\n"
+ "xaddq %0,%1"
+ : "=r" (valueToAdd), "+m" (_q_value)
+ : "0" (valueToAdd * sizeof(T))
+ : "memory");
+ return reinterpret_cast<T *>(valueToAdd);
+}
+
+#else // !Q_CC_INTEL && !Q_CC_GNU
+
+extern "C" {
+ Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
+ Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
+ Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr);
+ Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
+ Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
+ Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value);
+ Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, qptrdiff value);
+} // extern "C"
+
+inline bool QBasicAtomicInt::ref()
+{
+ return q_atomic_increment(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ return q_atomic_decrement(&_q_value) != 0;
+}
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expected, int newval)
+{
+ return q_atomic_test_and_set_int(&_q_value, expected, newval) != 0;
+}
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newval)
+{
+ return q_atomic_set_int(&_q_value, newval);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int aValue)
+{
+ return q_atomic_fetch_and_add_int(&_q_value, aValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T)));
+}
+
+#endif // Q_CC_GNU || Q_CC_INTEL
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QATOMIC_X86_64_H
diff --git a/src/corelib/arch/s390/arch.pri b/src/corelib/arch/s390/arch.pri
new file mode 100644
index 0000000000..45cc57824b
--- /dev/null
+++ b/src/corelib/arch/s390/arch.pri
@@ -0,0 +1,3 @@
+#
+# S390 architecture
+#
diff --git a/src/corelib/arch/sh/arch.pri b/src/corelib/arch/sh/arch.pri
new file mode 100644
index 0000000000..67fbb16c10
--- /dev/null
+++ b/src/corelib/arch/sh/arch.pri
@@ -0,0 +1,4 @@
+#
+# SH (Renesas SuperH) architecture
+#
+SOURCES += $$QT_ARCH_CPP/qatomic_sh.cpp
diff --git a/src/corelib/arch/sh/qatomic_sh.cpp b/src/corelib/arch/sh/qatomic_sh.cpp
new file mode 100644
index 0000000000..a27702010a
--- /dev/null
+++ b/src/corelib/arch/sh/qatomic_sh.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+# include <sched.h>
+#endif
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+Q_CORE_EXPORT volatile char qt_atomic_lock = 0;
+
+Q_CORE_EXPORT void qt_atomic_yield(int *count)
+{
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ if((*count)++ < 50) {
+ sched_yield();
+ } else
+#endif
+ {
+ struct timespec tm;
+ tm.tv_sec = 0;
+ tm.tv_nsec = 2000001;
+ nanosleep(&tm, NULL);
+ *count = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/arch/sh4a/arch.pri b/src/corelib/arch/sh4a/arch.pri
new file mode 100644
index 0000000000..19d5e040a9
--- /dev/null
+++ b/src/corelib/arch/sh4a/arch.pri
@@ -0,0 +1,3 @@
+#
+# SH-4A (Renesas SuperH) architecture
+#
diff --git a/src/corelib/arch/sparc/arch.pri b/src/corelib/arch/sparc/arch.pri
new file mode 100644
index 0000000000..9bb3a888e8
--- /dev/null
+++ b/src/corelib/arch/sparc/arch.pri
@@ -0,0 +1,10 @@
+#
+# SPARC architecture
+#
+*-64* {
+ SOURCES += $$QT_ARCH_CPP/qatomic64.s
+}
+else {
+ SOURCES += $$QT_ARCH_CPP/qatomic32.s \
+ $$QT_ARCH_CPP/qatomic_sparc.cpp
+}
diff --git a/src/corelib/arch/sparc/qatomic32.s b/src/corelib/arch/sparc/qatomic32.s
new file mode 100644
index 0000000000..a242add4bc
--- /dev/null
+++ b/src/corelib/arch/sparc/qatomic32.s
@@ -0,0 +1,103 @@
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!
+!! Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+!! All rights reserved.
+!! Contact: Nokia Corporation (qt-info@nokia.com)
+!!
+!! This file is part of the QtGui module of the Qt Toolkit.
+!!
+!! $QT_BEGIN_LICENSE:LGPL$
+!! No Commercial Usage
+!! This file contains pre-release code and may not be distributed.
+!! You may use this file in accordance with the terms and conditions
+!! contained in the Technology Preview License Agreement accompanying
+!! this package.
+!!
+!! GNU Lesser General Public License Usage
+!! Alternatively, this file may be used under the terms of the GNU Lesser
+!! General Public License version 2.1 as published by the Free Software
+!! Foundation and appearing in the file LICENSE.LGPL included in the
+!! packaging of this file. Please review the following information to
+!! ensure the GNU Lesser General Public License version 2.1 requirements
+!! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+!!
+!! In addition, as a special exception, Nokia gives you certain additional
+!! rights. These rights are described in the Nokia Qt LGPL Exception
+!! version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+!!
+!! If you have questions regarding the use of this file, please contact
+!! Nokia at qt-info@nokia.com.
+!!
+!!
+!!
+!!
+!!
+!!
+!!
+!!
+!! $QT_END_LICENSE$
+!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ .section ".text"
+
+ .align 4
+ .type q_atomic_trylock_int,#function
+ .global q_atomic_trylock_int
+q_atomic_trylock_int:
+ sethi %hi(-2147483648),%o2
+ swap [%o0],%o2
+ retl
+ mov %o2,%o0
+ .size q_atomic_trylock_int,.-q_atomic_trylock_int
+
+
+
+
+ .align 4
+ .type q_atomic_trylock_ptr,#function
+ .global q_atomic_trylock_ptr
+q_atomic_trylock_ptr:
+ mov -1, %o2
+ swap [%o0], %o2
+ retl
+ mov %o2, %o0
+ .size q_atomic_trylock_ptr,.-q_atomic_trylock_ptr
+
+
+
+
+ .align 4
+ .type q_atomic_unlock,#function
+ .global q_atomic_unlock
+q_atomic_unlock:
+ stbar
+ retl
+ st %o1,[%o0]
+ .size q_atomic_unlock,.-q_atomic_unlock
+
+
+
+
+ .align 4
+ .type q_atomic_set_int,#function
+ .global q_atomic_set_int
+q_atomic_set_int:
+ swap [%o0],%o1
+ stbar
+ retl
+ mov %o1,%o0
+ .size q_atomic_set_int,.-q_atomic_set_int
+
+
+
+
+ .align 4
+ .type q_atomic_set_ptr,#function
+ .global q_atomic_set_ptr
+q_atomic_set_ptr:
+ swap [%o0],%o1
+ stbar
+ retl
+ mov %o1,%o0
+ .size q_atomic_set_ptr,.-q_atomic_set_ptr
+
diff --git a/src/corelib/arch/sparc/qatomic64.s b/src/corelib/arch/sparc/qatomic64.s
new file mode 100644
index 0000000000..f826311da4
--- /dev/null
+++ b/src/corelib/arch/sparc/qatomic64.s
@@ -0,0 +1,327 @@
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!
+!! Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+!! All rights reserved.
+!! Contact: Nokia Corporation (qt-info@nokia.com)
+!!
+!! This file is part of the QtGui module of the Qt Toolkit.
+!!
+!! $QT_BEGIN_LICENSE:LGPL$
+!! No Commercial Usage
+!! This file contains pre-release code and may not be distributed.
+!! You may use this file in accordance with the terms and conditions
+!! contained in the Technology Preview License Agreement accompanying
+!! this package.
+!!
+!! GNU Lesser General Public License Usage
+!! Alternatively, this file may be used under the terms of the GNU Lesser
+!! General Public License version 2.1 as published by the Free Software
+!! Foundation and appearing in the file LICENSE.LGPL included in the
+!! packaging of this file. Please review the following information to
+!! ensure the GNU Lesser General Public License version 2.1 requirements
+!! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+!!
+!! In addition, as a special exception, Nokia gives you certain additional
+!! rights. These rights are described in the Nokia Qt LGPL Exception
+!! version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+!!
+!! If you have questions regarding the use of this file, please contact
+!! Nokia at qt-info@nokia.com.
+!!
+!!
+!!
+!!
+!!
+!!
+!!
+!!
+!! $QT_END_LICENSE$
+!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ .section ".text"
+
+ .align 4
+ .type q_atomic_test_and_set_int,#function
+ .global q_atomic_test_and_set_int
+q_atomic_test_and_set_int:
+ cas [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_int,.-q_atomic_test_and_set_int
+
+ .align 4
+ .type q_atomic_test_and_set_acquire_int,#function
+ .global q_atomic_test_and_set_acquire_int
+q_atomic_test_and_set_acquire_int:
+ cas [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ membar #LoadLoad | #LoadStore
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_acquire_int,.-q_atomic_test_and_set_acquire_int
+
+ .align 4
+ .type q_atomic_test_and_set_release_int,#function
+ .global q_atomic_test_and_set_release_int
+q_atomic_test_and_set_release_int:
+ membar #LoadStore | #StoreStore
+ cas [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_release_int,.-q_atomic_test_and_set_release_int
+
+ .align 4
+ .type q_atomic_test_and_set_ptr,#function
+ .global q_atomic_test_and_set_ptr
+q_atomic_test_and_set_ptr:
+ casx [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_ptr,.-q_atomic_test_and_set_ptr
+
+ .align 4
+ .type q_atomic_increment,#function
+ .global q_atomic_increment
+q_atomic_increment:
+q_atomic_increment_retry:
+ ld [%o0],%o3
+ add %o3,1,%o4
+ cas [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_increment_retry
+ nop
+ cmp %o4,-1
+ clr %o0
+ retl
+ movne %icc,1,%o0
+ .size q_atomic_increment,.-q_atomic_increment
+
+ .align 4
+ .type q_atomic_decrement,#function
+ .global q_atomic_decrement
+q_atomic_decrement:
+q_atomic_decrement_retry:
+ ld [%o0],%o3
+ add %o3,-1,%o4
+ cas [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_decrement_retry
+ nop
+ cmp %o4,1
+ clr %o0
+ retl
+ movne %icc,1,%o0
+ .size q_atomic_decrement,.-q_atomic_decrement
+
+ .align 4
+ .type q_atomic_set_int,#function
+ .global q_atomic_set_int
+q_atomic_set_int:
+q_atomic_set_int_retry:
+ ld [%o0],%o2
+ cas [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_set_int_retry
+ nop
+ retl
+ mov %o1,%o0
+ .size q_atomic_set_int,.-q_atomic_set_int
+
+ .align 4
+ .type q_atomic_set_ptr,#function
+ .global q_atomic_set_ptr
+q_atomic_set_ptr:
+q_atomic_set_ptr_retry:
+ ldx [%o0],%o2
+ casx [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_set_ptr_retry
+ nop
+ retl
+ mov %o1,%o0
+ .size q_atomic_set_ptr,.-q_atomic_set_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_add_int,#function
+ .global q_atomic_fetch_and_add_int
+q_atomic_fetch_and_add_int:
+q_atomic_fetch_and_add_int_retry:
+ ld [%o0],%o3
+ add %o3,%o1,%o4
+ cas [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_int_retry
+ nop
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int
+
+ .align 4
+ .type q_atomic_fetch_and_add_acquire_int,#function
+ .global q_atomic_fetch_and_add_acquire_int
+q_atomic_fetch_and_add_acquire_int:
+q_atomic_fetch_and_add_acquire_int_retry:
+ ld [%o0],%o3
+ add %o3,%o1,%o4
+ cas [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_acquire_int_retry
+ nop
+ membar #LoadLoad | #LoadStore
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_acquire_int,.-q_atomic_fetch_and_add_acquire_int
+
+ .align 4
+ .type q_atomic_fetch_and_add_release_int,#function
+ .global q_atomic_fetch_and_add_release_int
+q_atomic_fetch_and_add_release_int:
+q_atomic_fetch_and_add_release_int_retry:
+ membar #LoadStore | #StoreStore
+ ld [%o0],%o3
+ add %o3,%o1,%o4
+ cas [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_release_int_retry
+ nop
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_release_int,.-q_atomic_fetch_and_add_release_int
+
+ .align 4
+ .type q_atomic_fetch_and_store_acquire_int,#function
+ .global q_atomic_fetch_and_store_acquire_int
+q_atomic_fetch_and_store_acquire_int:
+q_atomic_fetch_and_store_acquire_int_retry:
+ ld [%o0],%o2
+ cas [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_fetch_and_store_acquire_int_retry
+ nop
+ membar #LoadLoad | #LoadStore
+ retl
+ mov %o1,%o0
+ .size q_atomic_fetch_and_store_acquire_int,.-q_atomic_fetch_and_store_acquire_int
+
+ .align 4
+ .type q_atomic_fetch_and_store_release_int,#function
+ .global q_atomic_fetch_and_store_release_int
+q_atomic_fetch_and_store_release_int:
+q_atomic_fetch_and_store_release_int_retry:
+ membar #LoadStore | #StoreStore
+ ld [%o0],%o2
+ cas [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_fetch_and_store_release_int_retry
+ nop
+ retl
+ mov %o1,%o0
+ .size q_atomic_fetch_and_store_release_int,.-q_atomic_fetch_and_store_release_int
+
+ .align 4
+ .type q_atomic_test_and_set_acquire_ptr,#function
+ .global q_atomic_test_and_set_acquire_ptr
+q_atomic_test_and_set_acquire_ptr:
+ casx [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ membar #LoadLoad | #LoadStore
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_acquire_ptr,.-q_atomic_test_and_set_acquire_ptr
+
+ .align 4
+ .type q_atomic_test_and_set_release_ptr,#function
+ .global q_atomic_test_and_set_release_ptr
+q_atomic_test_and_set_release_ptr:
+ membar #LoadStore | #StoreStore
+ casx [%o0],%o1,%o2
+ cmp %o1,%o2
+ clr %o0
+ retl
+ move %icc,1,%o0
+ .size q_atomic_test_and_set_release_ptr,.-q_atomic_test_and_set_release_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_store_acquire_ptr,#function
+ .global q_atomic_fetch_and_store_acquire_ptr
+q_atomic_fetch_and_store_acquire_ptr:
+q_atomic_fetch_and_store_acquire_ptr_retry:
+ ldx [%o0],%o2
+ casx [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_fetch_and_store_acquire_ptr_retry
+ nop
+ membar #LoadLoad | #LoadStore
+ retl
+ mov %o1,%o0
+ .size q_atomic_fetch_and_store_acquire_ptr,.-q_atomic_fetch_and_store_acquire_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_store_release_ptr,#function
+ .global q_atomic_fetch_and_store_release_ptr
+q_atomic_fetch_and_store_release_ptr:
+q_atomic_fetch_and_store_release_ptr_retry:
+ membar #LoadStore | #StoreStore
+ ldx [%o0],%o2
+ casx [%o0],%o2,%o1
+ cmp %o2,%o1
+ bne q_atomic_fetch_and_store_release_ptr_retry
+ nop
+ retl
+ mov %o1,%o0
+ .size q_atomic_fetch_and_store_release_ptr,.-q_atomic_fetch_and_store_release_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_add_ptr,#function
+ .global q_atomic_fetch_and_add_ptr
+q_atomic_fetch_and_add_ptr:
+q_atomic_fetch_and_add_ptr_retry:
+ ldx [%o0],%o3
+ add %o3,%o1,%o4
+ casx [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_ptr_retry
+ nop
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_add_acquire_ptr,#function
+ .global q_atomic_fetch_and_add_acquire_ptr
+q_atomic_fetch_and_add_acquire_ptr:
+q_atomic_fetch_and_add_acquire_ptr_retry:
+ ldx [%o0],%o3
+ add %o3,%o1,%o4
+ casx [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_acquire_ptr_retry
+ nop
+ membar #LoadLoad | #LoadStore
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_acquire_ptr,.-q_atomic_fetch_and_add_acquire_ptr
+
+ .align 4
+ .type q_atomic_fetch_and_add_release_ptr,#function
+ .global q_atomic_fetch_and_add_release_ptr
+q_atomic_fetch_and_add_release_ptr:
+q_atomic_fetch_and_add_release_ptr_retry:
+ membar #LoadStore | #StoreStore
+ ldx [%o0],%o3
+ add %o3,%o1,%o4
+ casx [%o0],%o3,%o4
+ cmp %o3,%o4
+ bne q_atomic_fetch_and_add_release_ptr_retry
+ nop
+ retl
+ mov %o3,%o0
+ .size q_atomic_fetch_and_add_release_ptr,.-q_atomic_fetch_and_add_release_ptr
diff --git a/src/corelib/arch/sparc/qatomic_sparc.cpp b/src/corelib/arch/sparc/qatomic_sparc.cpp
new file mode 100644
index 0000000000..ec398e03b6
--- /dev/null
+++ b/src/corelib/arch/sparc/qatomic_sparc.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qatomic.h>
+
+#include <limits.h>
+#include <sched.h>
+
+extern "C" {
+
+int q_atomic_trylock_int(volatile int *addr);
+int q_atomic_trylock_ptr(volatile void *addr);
+
+Q_CORE_EXPORT int q_atomic_lock_int(volatile int *addr)
+{
+ int returnValue = q_atomic_trylock_int(addr);
+
+ if (returnValue == INT_MIN) {
+ do {
+ // spin until we think we can succeed
+ do {
+ sched_yield();
+ returnValue = *addr;
+ } while (returnValue == INT_MIN);
+
+ // try again
+ returnValue = q_atomic_trylock_int(addr);
+ } while (returnValue == INT_MIN);
+ }
+
+ return returnValue;
+}
+
+Q_CORE_EXPORT int q_atomic_lock_ptr(volatile void *addr)
+{
+ int returnValue = q_atomic_trylock_ptr(addr);
+
+ if (returnValue == -1) {
+ do {
+ // spin until we think we can succeed
+ do {
+ sched_yield();
+ returnValue = *reinterpret_cast<volatile int *>(addr);
+ } while (returnValue == -1);
+
+ // try again
+ returnValue = q_atomic_trylock_ptr(addr);
+ } while (returnValue == -1);
+ }
+
+ return returnValue;
+}
+
+} // extern "C"
diff --git a/src/corelib/arch/symbian/arch.pri b/src/corelib/arch/symbian/arch.pri
new file mode 100644
index 0000000000..2e2a9b6aed
--- /dev/null
+++ b/src/corelib/arch/symbian/arch.pri
@@ -0,0 +1,18 @@
+#
+# Symbian architecture
+#
+SOURCES += $$QT_ARCH_CPP/qatomic_symbian.cpp \
+ $$QT_ARCH_CPP/qatomic_generic_armv6.cpp \
+ $$QT_ARCH_CPP/heap_hybrid.cpp \
+ $$QT_ARCH_CPP/debugfunction.cpp \
+ $$QT_ARCH_CPP/qt_heapsetup_symbian.cpp
+
+HEADERS += $$QT_ARCH_CPP/dla_p.h \
+ $$QT_ARCH_CPP/heap_hybrid_p.h \
+ $$QT_ARCH_CPP/common_p.h \
+ $$QT_ARCH_CPP/page_alloc_p.h \
+ $$QT_ARCH_CPP/slab_p.h \
+ $$QT_ARCH_CPP/qt_hybridHeap_symbian_p.h
+
+exists($${EPOCROOT}epoc32/include/platform/u32std.h):DEFINES += QT_SYMBIAN_HAVE_U32STD_H
+exists($${EPOCROOT}epoc32/include/platform/e32btrace.h):DEFINES += QT_SYMBIAN_HAVE_E32BTRACE_H
diff --git a/src/corelib/arch/symbian/common_p.h b/src/corelib/arch/symbian/common_p.h
new file mode 100644
index 0000000000..852646c250
--- /dev/null
+++ b/src/corelib/arch/symbian/common_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __E32_COMMON_H__
+#define __E32_COMMON_H__
+
+#ifdef __KERNEL_MODE__
+#include <e32cmn.h>
+#include <e32panic.h>
+#include "u32std.h"
+#else
+#include <e32std.h>
+#include <e32base.h>
+#include <e32math.h>
+#include <e32svr.h>
+#include <e32ver.h>
+#include <e32hal.h>
+#include <e32panic.h>
+// backport of Symbian^4 allocator to Symbian^3 SDK does not contain u32exec.h
+//#include <u32exec.h>
+#endif
+
+GLREF_C void Panic(TCdtPanic aPanic);
+GLDEF_C void PanicBadArrayIndex();
+GLREF_C TInt __DoConvertNum(TUint, TRadix, TUint, TUint8*&);
+GLREF_C TInt __DoConvertNum(Uint64, TRadix, TUint, TUint8*&);
+
+#ifdef __KERNEL_MODE__
+GLREF_C void KernHeapFault(TCdtPanic aPanic);
+GLREF_C void KHeapCheckThreadState();
+TInt StringLength(const TUint16* aPtr);
+TInt StringLength(const TUint8* aPtr);
+
+#define STD_CLASS Kern
+#define STRING_LENGTH(s) StringLength(s)
+#define STRING_LENGTH_16(s) StringLength(s)
+#define PANIC_CURRENT_THREAD(c,r) Kern::PanicCurrentThread(c, r)
+#define __KERNEL_CHECK_RADIX(r) __ASSERT_ALWAYS(((r)==EDecimal)||((r)==EHex),Panic(EInvalidRadix))
+#define APPEND_BUF_SIZE 10
+#define APPEND_BUF_SIZE_64 20
+#define HEAP_PANIC(r) Kern::Printf("HEAP CORRUPTED %s %d", __FILE__, __LINE__), RHeapK::Fault(r)
+#define GET_PAGE_SIZE(x) x = M::PageSizeInBytes()
+#define DIVISION_BY_ZERO() FAULT()
+
+#ifdef _DEBUG
+#define __CHECK_THREAD_STATE RHeapK::CheckThreadState()
+#else
+#define __CHECK_THREAD_STATE
+#endif
+
+#else
+
+#define STD_CLASS User
+#define STRING_LENGTH(s) User::StringLength(s)
+#define STRING_LENGTH_16(s) User::StringLength(s)
+#define PANIC_CURRENT_THREAD(c,r) User::Panic(c, r)
+#define MEM_COMPARE_16 Mem::Compare
+#define __KERNEL_CHECK_RADIX(r)
+#define APPEND_BUF_SIZE 32
+#define APPEND_BUF_SIZE_64 64
+#define HEAP_PANIC(r) RDebug::Printf("HEAP CORRUPTED %s %d", __FILE__, __LINE__), Panic(r)
+#define GET_PAGE_SIZE(x) UserHal::PageSizeInBytes(x)
+#define DIVISION_BY_ZERO() User::RaiseException(EExcIntegerDivideByZero)
+#define __CHECK_THREAD_STATE
+
+#endif // __KERNEL_MODE__
+
+#endif
diff --git a/src/corelib/arch/symbian/debugfunction.cpp b/src/corelib/arch/symbian/debugfunction.cpp
new file mode 100644
index 0000000000..445f1063a8
--- /dev/null
+++ b/src/corelib/arch/symbian/debugfunction.cpp
@@ -0,0 +1,1143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt_hybridheap_symbian_p.h"
+
+#ifdef QT_USE_NEW_SYMBIAN_ALLOCATOR
+
+#define GM (&iGlobalMallocState)
+#define __HEAP_CORRUPTED_TRACE(t,p,l) BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)t, (TUint32)p, (TUint32)l);
+#define __HEAP_CORRUPTED_TEST(c,x, p,l) if (!c) { if (iFlags & (EMonitorMemory+ETraceAllocs) ) __HEAP_CORRUPTED_TRACE(this,p,l) HEAP_PANIC(x); }
+#define __HEAP_CORRUPTED_TEST_STATIC(c,t,x,p,l) if (!c) { if (t && (t->iFlags & (EMonitorMemory+ETraceAllocs) )) __HEAP_CORRUPTED_TRACE(t,p,l) HEAP_PANIC(x); }
+
+TInt RHybridHeap::DebugFunction(TInt aFunc, TAny* a1, TAny* a2)
+{
+ TInt r = KErrNone;
+ switch(aFunc)
+ {
+
+ case RAllocator::ECount:
+ struct HeapInfo info;
+ Lock();
+ GetInfo(&info, NULL);
+ *(unsigned*)a1 = info.iFreeN;
+ r = info.iAllocN;
+ Unlock();
+ break;
+
+ case RAllocator::EMarkStart:
+ __DEBUG_ONLY(DoMarkStart());
+ break;
+
+ case RAllocator::EMarkEnd:
+ __DEBUG_ONLY( r = DoMarkEnd((TInt)a1) );
+ break;
+
+ case RAllocator::ECheck:
+ r = DoCheckHeap((SCheckInfo*)a1);
+ break;
+
+ case RAllocator::ESetFail:
+ __DEBUG_ONLY(DoSetAllocFail((TAllocFail)(TInt)a1, (TInt)a2));
+ break;
+
+ case RHybridHeap::EGetFail:
+ __DEBUG_ONLY(r = iFailType);
+ break;
+
+ case RHybridHeap::ESetBurstFail:
+#if _DEBUG
+ {
+ SRAllocatorBurstFail* fail = (SRAllocatorBurstFail*) a2;
+ DoSetAllocFail((TAllocFail)(TInt)a1, fail->iRate, fail->iBurst);
+ }
+#endif
+ break;
+
+ case RHybridHeap::ECheckFailure:
+ // iRand will be incremented for each EFailNext, EBurstFailNext,
+ // EDeterministic and EBurstDeterministic failure.
+ r = iRand;
+ break;
+
+ case RAllocator::ECopyDebugInfo:
+ {
+ TInt nestingLevel = ((SDebugCell*)a1)[-1].nestingLevel;
+ ((SDebugCell*)a2)[-1].nestingLevel = nestingLevel;
+ break;
+ }
+
+ case RHybridHeap::EGetSize:
+ {
+ r = iChunkSize - sizeof(RHybridHeap);
+ break;
+ }
+
+ case RHybridHeap::EGetMaxLength:
+ {
+ r = iMaxLength;
+ break;
+ }
+
+ case RHybridHeap::EGetBase:
+ {
+ *(TAny**)a1 = iBase;
+ break;
+ }
+
+ case RHybridHeap::EAlignInteger:
+ {
+ r = _ALIGN_UP((TInt)a1, iAlign);
+ break;
+ }
+
+ case RHybridHeap::EAlignAddr:
+ {
+ *(TAny**)a2 = (TAny*)_ALIGN_UP((TLinAddr)a1, iAlign);
+ break;
+ }
+
+ case RHybridHeap::EWalk:
+ struct HeapInfo hinfo;
+ SWalkInfo winfo;
+ Lock();
+ winfo.iFunction = (TWalkFunc)a1;
+ winfo.iParam = a2;
+ winfo.iHeap = (RHybridHeap*)this;
+ GetInfo(&hinfo, &winfo);
+ Unlock();
+ break;
+
+#ifndef __KERNEL_MODE__
+
+ case RHybridHeap::EHybridHeap:
+ {
+ if ( !a1 )
+ return KErrGeneral;
+ STestCommand* cmd = (STestCommand*)a1;
+ switch ( cmd->iCommand )
+ {
+ case EGetConfig:
+ cmd->iConfig.iSlabBits = iSlabConfigBits;
+ cmd->iConfig.iDelayedSlabThreshold = iPageThreshold;
+ cmd->iConfig.iPagePower = iPageThreshold;
+ break;
+
+ case ESetConfig:
+ //
+ // New configuration data for slab and page allocator.
+ // Reset heap to get data into use
+ //
+#if USE_HYBRID_HEAP
+ iSlabConfigBits = cmd->iConfig.iSlabBits & 0x3fff;
+ iSlabInitThreshold = cmd->iConfig.iDelayedSlabThreshold;
+ iPageThreshold = (cmd->iConfig.iPagePower & 0x1f);
+ Reset();
+#endif
+ break;
+
+ case EHeapMetaData:
+ cmd->iData = this;
+ break;
+
+ case ETestData:
+ iTestData = cmd->iData;
+ break;
+
+ default:
+ return KErrNotSupported;
+
+ }
+
+ break;
+ }
+#endif // __KERNEL_MODE
+
+ default:
+ return KErrNotSupported;
+
+ }
+ return r;
+}
+
+void RHybridHeap::Walk(SWalkInfo* aInfo, TAny* aBfr, TInt aLth, TCellType aBfrType, TAllocatorType aAllocatorType)
+{
+ //
+ // This function is always called from RHybridHeap::GetInfo.
+ // Actual walk function is called if SWalkInfo pointer is defined
+ //
+ //
+ if ( aInfo )
+ {
+#ifdef __KERNEL_MODE__
+ (void)aAllocatorType;
+#if defined(_DEBUG)
+ if ( aBfrType == EGoodAllocatedCell )
+ aInfo->iFunction(aInfo->iParam, aBfrType, ((TUint8*)aBfr+EDebugHdrSize), (aLth-EDebugHdrSize) );
+ else
+ aInfo->iFunction(aInfo->iParam, aBfrType, aBfr, aLth );
+#else
+ aInfo->iFunction(aInfo->iParam, aBfrType, aBfr, aLth );
+#endif
+
+#else // __KERNEL_MODE__
+
+ if ( aAllocatorType & (EFullSlab + EPartialFullSlab + EEmptySlab + ESlabSpare) )
+ {
+ if ( aInfo->iHeap )
+ {
+ TUint32 dummy;
+ TInt npages;
+ aInfo->iHeap->DoCheckSlab((slab*)aBfr, aAllocatorType);
+ __HEAP_CORRUPTED_TEST_STATIC(aInfo->iHeap->CheckBitmap(Floor(aBfr, PAGESIZE), PAGESIZE, dummy, npages),
+ aInfo->iHeap, ETHeapBadCellAddress, aBfr, aLth);
+ }
+ if ( aAllocatorType & EPartialFullSlab )
+ WalkPartialFullSlab(aInfo, (slab*)aBfr, aBfrType, aLth);
+ else if ( aAllocatorType & EFullSlab )
+ WalkFullSlab(aInfo, (slab*)aBfr, aBfrType, aLth);
+ }
+#if defined(_DEBUG)
+ else if ( aBfrType == EGoodAllocatedCell )
+ aInfo->iFunction(aInfo->iParam, aBfrType, ((TUint8*)aBfr+EDebugHdrSize), (aLth-EDebugHdrSize) );
+ else
+ aInfo->iFunction(aInfo->iParam, aBfrType, aBfr, aLth );
+#else
+ else
+ aInfo->iFunction(aInfo->iParam, aBfrType, aBfr, aLth );
+#endif
+
+#endif // __KERNEL_MODE
+ }
+}
+
+#ifndef __KERNEL_MODE__
+void RHybridHeap::WalkPartialFullSlab(SWalkInfo* aInfo, slab* aSlab, TCellType /*aBfrType*/, TInt /*aLth*/)
+{
+ if ( aInfo )
+ {
+ //
+ // Build bitmap of free buffers in the partial full slab
+ //
+ TUint32 bitmap[4];
+ __HEAP_CORRUPTED_TEST_STATIC( (aInfo->iHeap != NULL), aInfo->iHeap, ETHeapBadCellAddress, 0, aSlab);
+ aInfo->iHeap->BuildPartialSlabBitmap(bitmap, aSlab);
+ //
+ // Find used (allocated) buffers from iPartial full slab
+ //
+ TUint32 h = aSlab->iHeader;
+ TUint32 size = SlabHeaderSize(h);
+ TUint32 count = KMaxSlabPayload / size; // Total buffer count in slab
+ TUint32 i = 0;
+ TUint32 ix = 0;
+ TUint32 bit = 1;
+
+ while ( i < count )
+ {
+
+ if ( bitmap[ix] & bit )
+ {
+ aInfo->iFunction(aInfo->iParam, EGoodFreeCell, &aSlab->iPayload[i*size], size );
+ }
+ else
+ {
+#if defined(_DEBUG)
+ aInfo->iFunction(aInfo->iParam, EGoodAllocatedCell, (&aSlab->iPayload[i*size]+EDebugHdrSize), (size-EDebugHdrSize) );
+#else
+ aInfo->iFunction(aInfo->iParam, EGoodAllocatedCell, &aSlab->iPayload[i*size], size );
+#endif
+ }
+ bit <<= 1;
+ if ( bit == 0 )
+ {
+ bit = 1;
+ ix ++;
+ }
+
+ i ++;
+ }
+ }
+
+}
+
+void RHybridHeap::WalkFullSlab(SWalkInfo* aInfo, slab* aSlab, TCellType aBfrType, TInt /*aLth*/)
+{
+ if ( aInfo )
+ {
+ TUint32 h = aSlab->iHeader;
+ TUint32 size = SlabHeaderSize(h);
+ TUint32 count = (SlabHeaderUsedm4(h) + 4) / size;
+ TUint32 i = 0;
+ while ( i < count )
+ {
+#if defined(_DEBUG)
+ if ( aBfrType == EGoodAllocatedCell )
+ aInfo->iFunction(aInfo->iParam, aBfrType, (&aSlab->iPayload[i*size]+EDebugHdrSize), (size-EDebugHdrSize) );
+ else
+ aInfo->iFunction(aInfo->iParam, aBfrType, &aSlab->iPayload[i*size], size );
+#else
+ aInfo->iFunction(aInfo->iParam, aBfrType, &aSlab->iPayload[i*size], size );
+#endif
+ i ++;
+ }
+ }
+}
+
+void RHybridHeap::BuildPartialSlabBitmap(TUint32* aBitmap, slab* aSlab, TAny* aBfr)
+{
+ //
+ // Build a bitmap of free buffers in a partial full slab
+ //
+ TInt i;
+ TUint32 bit = 0;
+ TUint32 index;
+ TUint32 h = aSlab->iHeader;
+ TUint32 used = SlabHeaderUsedm4(h)+4;
+ TUint32 size = SlabHeaderSize(h);
+ TInt count = (KMaxSlabPayload / size);
+ TInt free_count = count - (used / size); // Total free buffer count in slab
+ aBitmap[0] = 0, aBitmap[1] = 0, aBitmap[2] = 0, aBitmap[3] = 0;
+ TUint32 offs = (h & 0xff) << 2;
+
+ //
+ // Process first buffer in partial slab free buffer chain
+ //
+ while ( offs )
+ {
+ unsigned char* p = (unsigned char*)Offset(aSlab, offs);
+ __HEAP_CORRUPTED_TEST( (sizeof(slabhdr) <= offs), ETHeapBadCellAddress, p, aSlab);
+ offs -= sizeof(slabhdr);
+ __HEAP_CORRUPTED_TEST( (offs % size == 0), ETHeapBadCellAddress, p, aSlab);
+ index = (offs / size); // Bit index in bitmap
+ i = 0;
+ while ( i < 4 )
+ {
+ if ( index < 32 )
+ {
+ bit = (1 << index);
+ break;
+ }
+ index -= 32;
+ i ++;
+ }
+
+ __HEAP_CORRUPTED_TEST( ((aBitmap[i] & bit) == 0), ETHeapBadCellAddress, p, aSlab); // Buffer already in chain
+
+ aBitmap[i] |= bit;
+ free_count --;
+ offs = ((unsigned)*p) << 2; // Next in free chain
+ }
+
+ __HEAP_CORRUPTED_TEST( (free_count >= 0), ETHeapBadCellAddress, aBfr, aSlab); // free buffer count/size mismatch
+ //
+ // Process next rest of the free buffers which are in the
+ // wilderness (at end of the slab)
+ //
+ index = count - 1;
+ i = index / 32;
+ index = index % 32;
+ while ( free_count && (i >= 0))
+ {
+ bit = (1 << index);
+ __HEAP_CORRUPTED_TEST( ((aBitmap[i] & bit) == 0), ETHeapBadCellAddress, aBfr, aSlab); // Buffer already in chain
+ aBitmap[i] |= bit;
+ if ( index )
+ index --;
+ else
+ {
+ index = 31;
+ i --;
+ }
+ free_count --;
+ }
+
+ if ( aBfr ) // Assure that specified buffer does NOT exist in partial slab free buffer chain
+ {
+ offs = LowBits(aBfr, SLABSIZE);
+ __HEAP_CORRUPTED_TEST( (sizeof(slabhdr) <= offs), ETHeapBadCellAddress, aBfr, aSlab);
+ offs -= sizeof(slabhdr);
+ __HEAP_CORRUPTED_TEST( ((offs % size) == 0), ETHeapBadCellAddress, aBfr, aSlab);
+ index = (offs / size); // Bit index in bitmap
+ i = 0;
+ while ( i < 4 )
+ {
+ if ( index < 32 )
+ {
+ bit = (1 << index);
+ break;
+ }
+ index -= 32;
+ i ++;
+ }
+ __HEAP_CORRUPTED_TEST( ((aBitmap[i] & bit) == 0), ETHeapBadCellAddress, aBfr, aSlab); // Buffer already in chain
+ }
+}
+
+#endif // __KERNEL_MODE__
+
+void RHybridHeap::WalkCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen)
+{
+ (void)aCell;
+ SHeapCellInfo& info = *(SHeapCellInfo*)aPtr;
+ switch(aType)
+ {
+ case EGoodAllocatedCell:
+ {
+ ++info.iTotalAlloc;
+ info.iTotalAllocSize += aLen;
+#if defined(_DEBUG)
+ RHybridHeap& h = *info.iHeap;
+ SDebugCell* DbgCell = (SDebugCell*)((TUint8*)aCell-EDebugHdrSize);
+ if ( DbgCell->nestingLevel == h.iNestingLevel )
+ {
+ if (++info.iLevelAlloc==1)
+ info.iStranded = DbgCell;
+#ifdef __KERNEL_MODE__
+ if (KDebugNum(KSERVER) || KDebugNum(KTESTFAST))
+ {
+ Kern::Printf("LEAKED KERNEL HEAP CELL @ %08x : len=%d", aCell, aLen);
+ TLinAddr base = ((TLinAddr)aCell)&~0x0f;
+ TLinAddr end = ((TLinAddr)aCell)+(TLinAddr)aLen;
+ while(base<end)
+ {
+ const TUint32* p = (const TUint32*)base;
+ Kern::Printf("%08x: %08x %08x %08x %08x", p, p[0], p[1], p[2], p[3]);
+ base += 16;
+ }
+ }
+#endif
+ }
+#endif
+ break;
+ }
+ case EGoodFreeCell:
+ ++info.iTotalFree;
+ break;
+ case EBadAllocatedCellSize:
+ HEAP_PANIC(ETHeapBadAllocatedCellSize);
+ case EBadAllocatedCellAddress:
+ HEAP_PANIC(ETHeapBadAllocatedCellAddress);
+ case EBadFreeCellAddress:
+ HEAP_PANIC(ETHeapBadFreeCellAddress);
+ case EBadFreeCellSize:
+ HEAP_PANIC(ETHeapBadFreeCellSize);
+ default:
+ HEAP_PANIC(ETHeapWalkBadCellType);
+ }
+}
+
+
+TInt RHybridHeap::DoCheckHeap(SCheckInfo* aInfo)
+{
+ (void)aInfo;
+ SHeapCellInfo info;
+ memclr(&info, sizeof(info));
+ info.iHeap = this;
+ struct HeapInfo hinfo;
+ SWalkInfo winfo;
+ Lock();
+ DoCheckMallocState(GM); // Check DL heap internal structure
+#ifndef __KERNEL_MODE__
+ TUint32 dummy;
+ TInt npages;
+ __HEAP_CORRUPTED_TEST(CheckBitmap(NULL, 0, dummy, npages), ETHeapBadCellAddress, this, 0); // Check page allocator buffers
+ DoCheckSlabTrees();
+ DoCheckCommittedSize(npages, GM);
+#endif
+ winfo.iFunction = WalkCheckCell;
+ winfo.iParam = &info;
+ winfo.iHeap = (RHybridHeap*)this;
+ GetInfo(&hinfo, &winfo);
+ Unlock();
+
+#if defined(_DEBUG)
+ if (!aInfo)
+ return KErrNone;
+ TInt expected = aInfo->iCount;
+ TInt actual = aInfo->iAll ? info.iTotalAlloc : info.iLevelAlloc;
+ if (actual!=expected && !iTestData)
+ {
+#ifdef __KERNEL_MODE__
+ Kern::Fault("KERN-ALLOC COUNT", (expected<<16)|actual );
+#else
+ User::Panic(_L("ALLOC COUNT"), (expected<<16)|actual );
+#endif
+ }
+#endif
+ return KErrNone;
+}
+
+#ifdef _DEBUG
+void RHybridHeap::DoMarkStart()
+{
+ if (iNestingLevel==0)
+ iAllocCount=0;
+ iNestingLevel++;
+}
+
+TUint32 RHybridHeap::DoMarkEnd(TInt aExpected)
+{
+ if (iNestingLevel==0)
+ return 0;
+ SHeapCellInfo info;
+ SHeapCellInfo* p = iTestData ? (SHeapCellInfo*)iTestData : &info;
+ memclr(p, sizeof(info));
+ p->iHeap = this;
+ struct HeapInfo hinfo;
+ SWalkInfo winfo;
+ Lock();
+ winfo.iFunction = WalkCheckCell;
+ winfo.iParam = p;
+ winfo.iHeap = (RHybridHeap*)this;
+ GetInfo(&hinfo, &winfo);
+ Unlock();
+
+ if (p->iLevelAlloc != aExpected && !iTestData)
+ return (TUint32)(p->iStranded + 1);
+ if (--iNestingLevel == 0)
+ iAllocCount = 0;
+ return 0;
+}
+
+void RHybridHeap::DoSetAllocFail(TAllocFail aType, TInt aRate)
+{// Default to a burst mode of 1, as aType may be a burst type.
+ DoSetAllocFail(aType, aRate, 1);
+}
+
+void ResetAllocCellLevels(TAny* aPtr, RHybridHeap::TCellType aType, TAny* aCell, TInt aLen)
+{
+ (void)aPtr;
+ (void)aLen;
+
+ if (aType == RHybridHeap::EGoodAllocatedCell)
+ {
+ RHybridHeap::SDebugCell* DbgCell = (RHybridHeap::SDebugCell*)((TUint8*)aCell-RHybridHeap::EDebugHdrSize);
+ DbgCell->nestingLevel = 0;
+ }
+}
+
+// Don't change as the ETHeapBadDebugFailParameter check below and the API
+// documentation rely on this being 16 for RHybridHeap.
+LOCAL_D const TInt KBurstFailRateShift = 16;
+LOCAL_D const TInt KBurstFailRateMask = (1 << KBurstFailRateShift) - 1;
+
+void RHybridHeap::DoSetAllocFail(TAllocFail aType, TInt aRate, TUint aBurst)
+{
+ if (aType==EReset)
+ {
+ // reset levels of all allocated cells to 0
+ // this should prevent subsequent tests failing unnecessarily
+ iFailed = EFalse; // Reset for ECheckFailure relies on this.
+ struct HeapInfo hinfo;
+ SWalkInfo winfo;
+ Lock();
+ winfo.iFunction = (TWalkFunc)&ResetAllocCellLevels;
+ winfo.iParam = NULL;
+ winfo.iHeap = (RHybridHeap*)this;
+ GetInfo(&hinfo, &winfo);
+ Unlock();
+ // reset heap allocation mark as well
+ iNestingLevel=0;
+ iAllocCount=0;
+ aType=ENone;
+ }
+
+ switch (aType)
+ {
+ case EBurstRandom:
+ case EBurstTrueRandom:
+ case EBurstDeterministic:
+ case EBurstFailNext:
+ // If the fail type is a burst type then iFailRate is split in 2:
+ // the 16 lsbs are the fail rate and the 16 msbs are the burst length.
+ if (TUint(aRate) > (TUint)KMaxTUint16 || aBurst > KMaxTUint16)
+ HEAP_PANIC(ETHeapBadDebugFailParameter);
+
+ iFailed = EFalse;
+ iFailType = aType;
+ iFailRate = (aRate == 0) ? 1 : aRate;
+ iFailAllocCount = -iFailRate;
+ iFailRate = iFailRate | (aBurst << KBurstFailRateShift);
+ break;
+
+ default:
+ iFailed = EFalse;
+ iFailType = aType;
+ iFailRate = (aRate == 0) ? 1 : aRate; // A rate of <1 is meaningless
+ iFailAllocCount = 0;
+ break;
+ }
+
+ // Set up iRand for either:
+ // - random seed value, or
+ // - a count of the number of failures so far.
+ iRand = 0;
+#ifndef __KERNEL_MODE__
+ switch (iFailType)
+ {
+ case ETrueRandom:
+ case EBurstTrueRandom:
+ {
+ TTime time;
+ time.HomeTime();
+ TInt64 seed = time.Int64();
+ iRand = Math::Rand(seed);
+ break;
+ }
+ case ERandom:
+ case EBurstRandom:
+ {
+ TInt64 seed = 12345;
+ iRand = Math::Rand(seed);
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+}
+
+TBool RHybridHeap::CheckForSimulatedAllocFail()
+//
+// Check to see if the user has requested simulated alloc failure, and if so possibly
+// Return ETrue indicating a failure.
+//
+{
+ // For burst mode failures iFailRate is shared
+ TUint16 rate = (TUint16)(iFailRate & KBurstFailRateMask);
+ TUint16 burst = (TUint16)(iFailRate >> KBurstFailRateShift);
+ TBool r = EFalse;
+ switch (iFailType)
+ {
+#ifndef __KERNEL_MODE__
+ case ERandom:
+ case ETrueRandom:
+ if (++iFailAllocCount>=iFailRate)
+ {
+ iFailAllocCount=0;
+ if (!iFailed) // haven't failed yet after iFailRate allocations so fail now
+ return(ETrue);
+ iFailed=EFalse;
+ }
+ else
+ {
+ if (!iFailed)
+ {
+ TInt64 seed=iRand;
+ iRand=Math::Rand(seed);
+ if (iRand%iFailRate==0)
+ {
+ iFailed=ETrue;
+ return(ETrue);
+ }
+ }
+ }
+ break;
+
+ case EBurstRandom:
+ case EBurstTrueRandom:
+ if (++iFailAllocCount < 0)
+ {
+ // We haven't started failing yet so should we now?
+ TInt64 seed = iRand;
+ iRand = Math::Rand(seed);
+ if (iRand % rate == 0)
+ {// Fail now. Reset iFailAllocCount so we fail burst times
+ iFailAllocCount = 0;
+ r = ETrue;
+ }
+ }
+ else
+ {
+ if (iFailAllocCount < burst)
+ {// Keep failing for burst times
+ r = ETrue;
+ }
+ else
+ {// We've now failed burst times so start again.
+ iFailAllocCount = -(rate - 1);
+ }
+ }
+ break;
+#endif
+ case EDeterministic:
+ if (++iFailAllocCount%iFailRate==0)
+ {
+ r=ETrue;
+ iRand++; // Keep count of how many times we have failed
+ }
+ break;
+
+ case EBurstDeterministic:
+ // This will fail burst number of times, every rate attempts.
+ if (++iFailAllocCount >= 0)
+ {
+ if (iFailAllocCount == burst - 1)
+ {// This is the burst time we have failed so make it the last by
+ // reseting counts so we next fail after rate attempts.
+ iFailAllocCount = -rate;
+ }
+ r = ETrue;
+ iRand++; // Keep count of how many times we have failed
+ }
+ break;
+
+ case EFailNext:
+ if ((++iFailAllocCount%iFailRate)==0)
+ {
+ iFailType=ENone;
+ r=ETrue;
+ iRand++; // Keep count of how many times we have failed
+ }
+ break;
+
+ case EBurstFailNext:
+ if (++iFailAllocCount >= 0)
+ {
+ if (iFailAllocCount == burst - 1)
+ {// This is the burst time we have failed so make it the last.
+ iFailType = ENone;
+ }
+ r = ETrue;
+ iRand++; // Keep count of how many times we have failed
+ }
+ break;
+
+ default:
+ break;
+ }
+ return r;
+}
+
+#endif // DEBUG
+
+//
+// Methods for Doug Lea allocator detailed check
+//
+
+void RHybridHeap::DoCheckAnyChunk(mstate m, mchunkptr p)
+{
+ __HEAP_CORRUPTED_TEST(((IS_ALIGNED(CHUNK2MEM(p))) || (p->iHead == FENCEPOST_HEAD)), ETHeapBadCellAddress, p, 0);
+ (void)m;
+}
+
+/* Check properties of iTop chunk */
+void RHybridHeap::DoCheckTopChunk(mstate m, mchunkptr p)
+{
+ msegmentptr sp = &m->iSeg;
+ size_t sz = CHUNKSIZE(p);
+ __HEAP_CORRUPTED_TEST((sp != 0), ETHeapBadCellAddress, p, 0);
+ __HEAP_CORRUPTED_TEST(((IS_ALIGNED(CHUNK2MEM(p))) || (p->iHead == FENCEPOST_HEAD)), ETHeapBadCellAddress, p,0);
+ __HEAP_CORRUPTED_TEST((sz == m->iTopSize), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((sz > 0), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((sz == ((sp->iBase + sp->iSize) - (TUint8*)p) - TOP_FOOT_SIZE), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((PINUSE(p)), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((!NEXT_PINUSE(p)), ETHeapBadCellAddress,p,0);
+}
+
+/* Check properties of inuse chunks */
+void RHybridHeap::DoCheckInuseChunk(mstate m, mchunkptr p)
+{
+ DoCheckAnyChunk(m, p);
+ __HEAP_CORRUPTED_TEST((CINUSE(p)), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((NEXT_PINUSE(p)), ETHeapBadCellAddress,p,0);
+ /* If not PINUSE and not mmapped, previous chunk has OK offset */
+ __HEAP_CORRUPTED_TEST((PINUSE(p) || NEXT_CHUNK(PREV_CHUNK(p)) == p), ETHeapBadCellAddress,p,0);
+}
+
+/* Check properties of free chunks */
+void RHybridHeap::DoCheckFreeChunk(mstate m, mchunkptr p)
+{
+ size_t sz = p->iHead & ~(PINUSE_BIT|CINUSE_BIT);
+ mchunkptr next = CHUNK_PLUS_OFFSET(p, sz);
+ DoCheckAnyChunk(m, p);
+ __HEAP_CORRUPTED_TEST((!CINUSE(p)), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((!NEXT_PINUSE(p)), ETHeapBadCellAddress,p,0);
+ if (p != m->iDv && p != m->iTop)
+ {
+ if (sz >= MIN_CHUNK_SIZE)
+ {
+ __HEAP_CORRUPTED_TEST(((sz & CHUNK_ALIGN_MASK) == 0), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((IS_ALIGNED(CHUNK2MEM(p))), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((next->iPrevFoot == sz), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((PINUSE(p)), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST( (next == m->iTop || CINUSE(next)), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((p->iFd->iBk == p), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((p->iBk->iFd == p), ETHeapBadCellAddress,p,0);
+ }
+ else /* markers are always of size SIZE_T_SIZE */
+ __HEAP_CORRUPTED_TEST((sz == SIZE_T_SIZE), ETHeapBadCellAddress,p,0);
+ }
+}
+
+/* Check properties of malloced chunks at the point they are malloced */
+void RHybridHeap::DoCheckMallocedChunk(mstate m, void* mem, size_t s)
+{
+ if (mem != 0)
+ {
+ mchunkptr p = MEM2CHUNK(mem);
+ size_t sz = p->iHead & ~(PINUSE_BIT|CINUSE_BIT);
+ DoCheckInuseChunk(m, p);
+ __HEAP_CORRUPTED_TEST(((sz & CHUNK_ALIGN_MASK) == 0), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((sz >= MIN_CHUNK_SIZE), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((sz >= s), ETHeapBadCellAddress,p,0);
+ /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
+ __HEAP_CORRUPTED_TEST((sz < (s + MIN_CHUNK_SIZE)), ETHeapBadCellAddress,p,0);
+ }
+}
+
+/* Check a tree and its subtrees. */
+void RHybridHeap::DoCheckTree(mstate m, tchunkptr t)
+{
+ tchunkptr head = 0;
+ tchunkptr u = t;
+ bindex_t tindex = t->iIndex;
+ size_t tsize = CHUNKSIZE(t);
+ bindex_t idx;
+ DoComputeTreeIndex(tsize, idx);
+ __HEAP_CORRUPTED_TEST((tindex == idx), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((tsize >= MIN_LARGE_SIZE), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((tsize >= MINSIZE_FOR_TREE_INDEX(idx)), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST(((idx == NTREEBINS-1) || (tsize < MINSIZE_FOR_TREE_INDEX((idx+1)))), ETHeapBadCellAddress,u,0);
+
+ do
+ { /* traverse through chain of same-sized nodes */
+ DoCheckAnyChunk(m, ((mchunkptr)u));
+ __HEAP_CORRUPTED_TEST((u->iIndex == tindex), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((CHUNKSIZE(u) == tsize), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((!CINUSE(u)), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((!NEXT_PINUSE(u)), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((u->iFd->iBk == u), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((u->iBk->iFd == u), ETHeapBadCellAddress,u,0);
+ if (u->iParent == 0)
+ {
+ __HEAP_CORRUPTED_TEST((u->iChild[0] == 0), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((u->iChild[1] == 0), ETHeapBadCellAddress,u,0);
+ }
+ else
+ {
+ __HEAP_CORRUPTED_TEST((head == 0), ETHeapBadCellAddress,u,0); /* only one node on chain has iParent */
+ head = u;
+ __HEAP_CORRUPTED_TEST((u->iParent != u), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST( (u->iParent->iChild[0] == u ||
+ u->iParent->iChild[1] == u ||
+ *((tbinptr*)(u->iParent)) == u), ETHeapBadCellAddress,u,0);
+ if (u->iChild[0] != 0)
+ {
+ __HEAP_CORRUPTED_TEST((u->iChild[0]->iParent == u), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((u->iChild[0] != u), ETHeapBadCellAddress,u,0);
+ DoCheckTree(m, u->iChild[0]);
+ }
+ if (u->iChild[1] != 0)
+ {
+ __HEAP_CORRUPTED_TEST((u->iChild[1]->iParent == u), ETHeapBadCellAddress,u,0);
+ __HEAP_CORRUPTED_TEST((u->iChild[1] != u), ETHeapBadCellAddress,u,0);
+ DoCheckTree(m, u->iChild[1]);
+ }
+ if (u->iChild[0] != 0 && u->iChild[1] != 0)
+ {
+ __HEAP_CORRUPTED_TEST((CHUNKSIZE(u->iChild[0]) < CHUNKSIZE(u->iChild[1])), ETHeapBadCellAddress,u,0);
+ }
+ }
+ u = u->iFd;
+ }
+ while (u != t);
+ __HEAP_CORRUPTED_TEST((head != 0), ETHeapBadCellAddress,u,0);
+}
+
+/* Check all the chunks in a treebin. */
+void RHybridHeap::DoCheckTreebin(mstate m, bindex_t i)
+{
+ tbinptr* tb = TREEBIN_AT(m, i);
+ tchunkptr t = *tb;
+ int empty = (m->iTreeMap & (1U << i)) == 0;
+ if (t == 0)
+ __HEAP_CORRUPTED_TEST((empty), ETHeapBadCellAddress,t,0);
+ if (!empty)
+ DoCheckTree(m, t);
+}
+
+/* Check all the chunks in a smallbin. */
+void RHybridHeap::DoCheckSmallbin(mstate m, bindex_t i)
+{
+ sbinptr b = SMALLBIN_AT(m, i);
+ mchunkptr p = b->iBk;
+ unsigned int empty = (m->iSmallMap & (1U << i)) == 0;
+ if (p == b)
+ __HEAP_CORRUPTED_TEST((empty), ETHeapBadCellAddress,p,0);
+ if (!empty)
+ {
+ for (; p != b; p = p->iBk)
+ {
+ size_t size = CHUNKSIZE(p);
+ mchunkptr q;
+ /* each chunk claims to be free */
+ DoCheckFreeChunk(m, p);
+ /* chunk belongs in bin */
+ __HEAP_CORRUPTED_TEST((SMALL_INDEX(size) == i), ETHeapBadCellAddress,p,0);
+ __HEAP_CORRUPTED_TEST((p->iBk == b || CHUNKSIZE(p->iBk) == CHUNKSIZE(p)), ETHeapBadCellAddress,p,0);
+ /* chunk is followed by an inuse chunk */
+ q = NEXT_CHUNK(p);
+ if (q->iHead != FENCEPOST_HEAD)
+ DoCheckInuseChunk(m, q);
+ }
+ }
+}
+
+/* Find x in a bin. Used in other check functions. */
+TInt RHybridHeap::BinFind(mstate m, mchunkptr x)
+{
+ size_t size = CHUNKSIZE(x);
+ if (IS_SMALL(size))
+ {
+ bindex_t sidx = SMALL_INDEX(size);
+ sbinptr b = SMALLBIN_AT(m, sidx);
+ if (SMALLMAP_IS_MARKED(m, sidx))
+ {
+ mchunkptr p = b;
+ do
+ {
+ if (p == x)
+ return 1;
+ }
+ while ((p = p->iFd) != b);
+ }
+ }
+ else
+ {
+ bindex_t tidx;
+ DoComputeTreeIndex(size, tidx);
+ if (TREEMAP_IS_MARKED(m, tidx))
+ {
+ tchunkptr t = *TREEBIN_AT(m, tidx);
+ size_t sizebits = size << LEFTSHIFT_FOR_TREE_INDEX(tidx);
+ while (t != 0 && CHUNKSIZE(t) != size)
+ {
+ t = t->iChild[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
+ sizebits <<= 1;
+ }
+ if (t != 0)
+ {
+ tchunkptr u = t;
+ do
+ {
+ if (u == (tchunkptr)x)
+ return 1;
+ }
+ while ((u = u->iFd) != t);
+ }
+ }
+ }
+ return 0;
+}
+
+/* Traverse each chunk and check it; return total */
+size_t RHybridHeap::TraverseAndCheck(mstate m)
+{
+ size_t sum = 0;
+ msegmentptr s = &m->iSeg;
+ sum += m->iTopSize + TOP_FOOT_SIZE;
+ mchunkptr q = ALIGN_AS_CHUNK(s->iBase);
+ mchunkptr lastq = 0;
+ __HEAP_CORRUPTED_TEST((PINUSE(q)), ETHeapBadCellAddress,q,0);
+ while (q != m->iTop && q->iHead != FENCEPOST_HEAD)
+ {
+ sum += CHUNKSIZE(q);
+ if (CINUSE(q))
+ {
+ __HEAP_CORRUPTED_TEST((!BinFind(m, q)), ETHeapBadCellAddress,q,0);
+ DoCheckInuseChunk(m, q);
+ }
+ else
+ {
+ __HEAP_CORRUPTED_TEST((q == m->iDv || BinFind(m, q)), ETHeapBadCellAddress,q,0);
+ __HEAP_CORRUPTED_TEST((lastq == 0 || CINUSE(lastq)), ETHeapBadCellAddress,q,0); /* Not 2 consecutive free */
+ DoCheckFreeChunk(m, q);
+ }
+ lastq = q;
+ q = NEXT_CHUNK(q);
+ }
+ return sum;
+}
+
+/* Check all properties of malloc_state. */
+void RHybridHeap::DoCheckMallocState(mstate m)
+{
+ bindex_t i;
+// size_t total;
+ /* check bins */
+ for (i = 0; i < NSMALLBINS; ++i)
+ DoCheckSmallbin(m, i);
+ for (i = 0; i < NTREEBINS; ++i)
+ DoCheckTreebin(m, i);
+
+ if (m->iDvSize != 0)
+ { /* check iDv chunk */
+ DoCheckAnyChunk(m, m->iDv);
+ __HEAP_CORRUPTED_TEST((m->iDvSize == CHUNKSIZE(m->iDv)), ETHeapBadCellAddress,m->iDv,0);
+ __HEAP_CORRUPTED_TEST((m->iDvSize >= MIN_CHUNK_SIZE), ETHeapBadCellAddress,m->iDv,0);
+ __HEAP_CORRUPTED_TEST((BinFind(m, m->iDv) == 0), ETHeapBadCellAddress,m->iDv,0);
+ }
+
+ if (m->iTop != 0)
+ { /* check iTop chunk */
+ DoCheckTopChunk(m, m->iTop);
+ __HEAP_CORRUPTED_TEST((m->iTopSize == CHUNKSIZE(m->iTop)), ETHeapBadCellAddress,m->iTop,0);
+ __HEAP_CORRUPTED_TEST((m->iTopSize > 0), ETHeapBadCellAddress,m->iTop,0);
+ __HEAP_CORRUPTED_TEST((BinFind(m, m->iTop) == 0), ETHeapBadCellAddress,m->iTop,0);
+ }
+
+// total =
+ TraverseAndCheck(m);
+}
+
+#ifndef __KERNEL_MODE__
+//
+// Methods for Slab allocator detailed check
+//
+void RHybridHeap::DoCheckSlabTree(slab** aS, TBool aPartialPage)
+{
+ slab* s = *aS;
+ if (!s)
+ return;
+
+ TUint size = SlabHeaderSize(s->iHeader);
+ slab** parent = aS;
+ slab** child2 = &s->iChild2;
+
+ while ( s )
+ {
+ __HEAP_CORRUPTED_TEST((s->iParent == parent), ETHeapBadCellAddress,s,SLABSIZE);
+ __HEAP_CORRUPTED_TEST((!s->iChild1 || s < s->iChild1), ETHeapBadCellAddress,s,SLABSIZE);
+ __HEAP_CORRUPTED_TEST((!s->iChild2 || s < s->iChild2), ETHeapBadCellAddress,s,SLABSIZE);
+
+ if ( aPartialPage )
+ {
+ if ( s->iChild1 )
+ size = SlabHeaderSize(s->iChild1->iHeader);
+ }
+ else
+ {
+ __HEAP_CORRUPTED_TEST((SlabHeaderSize(s->iHeader) == size), ETHeapBadCellAddress,s,SLABSIZE);
+ }
+ parent = &s->iChild1;
+ s = s->iChild1;
+
+ }
+
+ parent = child2;
+ s = *child2;
+
+ while ( s )
+ {
+ __HEAP_CORRUPTED_TEST((s->iParent == parent), ETHeapBadCellAddress,s,SLABSIZE);
+ __HEAP_CORRUPTED_TEST((!s->iChild1 || s < s->iChild1), ETHeapBadCellAddress,s,SLABSIZE);
+ __HEAP_CORRUPTED_TEST((!s->iChild2 || s < s->iChild2), ETHeapBadCellAddress,s,SLABSIZE);
+
+ if ( aPartialPage )
+ {
+ if ( s->iChild2 )
+ size = SlabHeaderSize(s->iChild2->iHeader);
+ }
+ else
+ {
+ __HEAP_CORRUPTED_TEST((SlabHeaderSize(s->iHeader) == size), ETHeapBadCellAddress,s,SLABSIZE);
+ }
+ parent = &s->iChild2;
+ s = s->iChild2;
+
+ }
+
+}
+
+void RHybridHeap::DoCheckSlabTrees()
+{
+ for (TInt i = 0; i < (MAXSLABSIZE>>2); ++i)
+ DoCheckSlabTree(&iSlabAlloc[i].iPartial, EFalse);
+ DoCheckSlabTree(&iPartialPage, ETrue);
+}
+
+void RHybridHeap::DoCheckSlab(slab* aSlab, TAllocatorType aSlabType, TAny* aBfr)
+{
+ if ( (aSlabType == ESlabSpare) || (aSlabType == EEmptySlab) )
+ return;
+
+ unsigned h = aSlab->iHeader;
+ __HEAP_CORRUPTED_TEST((ZEROBITS(h)), ETHeapBadCellAddress,aBfr,aSlab);
+ unsigned used = SlabHeaderUsedm4(h)+4;
+ unsigned size = SlabHeaderSize(h);
+ __HEAP_CORRUPTED_TEST( (used < SLABSIZE),ETHeapBadCellAddress, aBfr, aSlab);
+ __HEAP_CORRUPTED_TEST( ((size > 3 ) && (size <= MAXSLABSIZE)), ETHeapBadCellAddress,aBfr,aSlab);
+ unsigned count = 0;
+
+ switch ( aSlabType )
+ {
+ case EFullSlab:
+ count = (KMaxSlabPayload / size );
+ __HEAP_CORRUPTED_TEST((used == count*size), ETHeapBadCellAddress,aBfr,aSlab);
+ __HEAP_CORRUPTED_TEST((HeaderFloating(h)), ETHeapBadCellAddress,aBfr,aSlab);
+ break;
+
+ case EPartialFullSlab:
+ __HEAP_CORRUPTED_TEST(((used % size)==0),ETHeapBadCellAddress,aBfr,aSlab);
+ __HEAP_CORRUPTED_TEST(((SlabHeaderFree(h) == 0) || (((SlabHeaderFree(h)<<2)-sizeof(slabhdr)) % SlabHeaderSize(h) == 0)),
+ ETHeapBadCellAddress,aBfr,aSlab);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+//
+// Check that committed size in heap equals number of pages in bitmap
+// plus size of Doug Lea region
+//
+void RHybridHeap::DoCheckCommittedSize(TInt aNPages, mstate aM)
+{
+ TInt total_committed = (aNPages * iPageSize) + aM->iSeg.iSize + (iBase - (TUint8*)this);
+ __HEAP_CORRUPTED_TEST((total_committed == iChunkSize), ETHeapBadCellAddress,total_committed,iChunkSize);
+}
+
+#endif // __KERNEL_MODE__
+
+#endif /* QT_USE_NEW_SYMBIAN_ALLOCATOR */
diff --git a/src/corelib/arch/symbian/dla_p.h b/src/corelib/arch/symbian/dla_p.h
new file mode 100644
index 0000000000..c2fa99a087
--- /dev/null
+++ b/src/corelib/arch/symbian/dla_p.h
@@ -0,0 +1,969 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __DLA__
+#define __DLA__
+
+#define DEFAULT_TRIM_THRESHOLD ((size_t)4U * (size_t)1024U)
+
+#define MSPACES 0
+#define HAVE_MORECORE 1
+#define MORECORE_CONTIGUOUS 1
+#define HAVE_MMAP 0
+#define HAVE_MREMAP 0
+#define DEFAULT_GRANULARITY (4096U)
+#define FOOTERS 0
+#define USE_LOCKS 0
+#define INSECURE 1
+#define NO_MALLINFO 0
+
+#define LACKS_SYS_TYPES_H
+#ifndef LACKS_SYS_TYPES_H
+#include <sys/types.h> /* For size_t */
+#else
+#ifndef _SIZE_T_DECLARED
+typedef unsigned int size_t;
+#define _SIZE_T_DECLARED
+#endif
+#endif /* LACKS_SYS_TYPES_H */
+
+/* The maximum possible size_t value has all bits set */
+#define MAX_SIZE_T (~(size_t)0)
+
+#ifndef ONLY_MSPACES
+ #define ONLY_MSPACES 0
+#endif /* ONLY_MSPACES */
+
+#ifndef MSPACES
+ #if ONLY_MSPACES
+ #define MSPACES 1
+ #else /* ONLY_MSPACES */
+ #define MSPACES 0
+ #endif /* ONLY_MSPACES */
+#endif /* MSPACES */
+
+//#ifndef MALLOC_ALIGNMENT
+// #define MALLOC_ALIGNMENT ((size_t)8U)
+//#endif /* MALLOC_ALIGNMENT */
+
+#ifndef FOOTERS
+ #define FOOTERS 0
+#endif /* FOOTERS */
+
+#ifndef ABORT
+// #define ABORT abort()
+// #define ABORT User::Invariant()// redefined so euser isn't dependant on oe
+ #define ABORT HEAP_PANIC(ETHeapBadCellAddress)
+#endif /* ABORT */
+
+#ifndef PROCEED_ON_ERROR
+ #define PROCEED_ON_ERROR 0
+#endif /* PROCEED_ON_ERROR */
+
+#ifndef USE_LOCKS
+ #define USE_LOCKS 0
+#endif /* USE_LOCKS */
+
+#ifndef INSECURE
+ #define INSECURE 0
+#endif /* INSECURE */
+
+#ifndef HAVE_MMAP
+ #define HAVE_MMAP 1
+#endif /* HAVE_MMAP */
+
+#ifndef MMAP_CLEARS
+ #define MMAP_CLEARS 1
+#endif /* MMAP_CLEARS */
+
+#ifndef HAVE_MREMAP
+ #ifdef linux
+ #define HAVE_MREMAP 1
+ #else /* linux */
+ #define HAVE_MREMAP 0
+ #endif /* linux */
+#endif /* HAVE_MREMAP */
+
+#ifndef MALLOC_FAILURE_ACTION
+ //#define MALLOC_FAILURE_ACTION errno = ENOMEM;
+ #define MALLOC_FAILURE_ACTION ;
+#endif /* MALLOC_FAILURE_ACTION */
+
+#ifndef HAVE_MORECORE
+ #if ONLY_MSPACES
+ #define HAVE_MORECORE 1 /*AMOD: has changed */
+ #else /* ONLY_MSPACES */
+ #define HAVE_MORECORE 1
+ #endif /* ONLY_MSPACES */
+#endif /* HAVE_MORECORE */
+
+#if !HAVE_MORECORE
+ #define MORECORE_CONTIGUOUS 0
+#else /* !HAVE_MORECORE */
+ #ifndef MORECORE
+ #define MORECORE DLAdjust
+ #endif /* MORECORE */
+ #ifndef MORECORE_CONTIGUOUS
+ #define MORECORE_CONTIGUOUS 0
+ #endif /* MORECORE_CONTIGUOUS */
+#endif /* !HAVE_MORECORE */
+
+#ifndef DEFAULT_GRANULARITY
+ #if MORECORE_CONTIGUOUS
+ #define DEFAULT_GRANULARITY 4096 /* 0 means to compute in init_mparams */
+ #else /* MORECORE_CONTIGUOUS */
+ #define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
+ #endif /* MORECORE_CONTIGUOUS */
+#endif /* DEFAULT_GRANULARITY */
+
+#ifndef DEFAULT_TRIM_THRESHOLD
+ #ifndef MORECORE_CANNOT_TRIM
+ #define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
+ #else /* MORECORE_CANNOT_TRIM */
+ #define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
+ #endif /* MORECORE_CANNOT_TRIM */
+#endif /* DEFAULT_TRIM_THRESHOLD */
+
+#ifndef DEFAULT_MMAP_THRESHOLD
+ #if HAVE_MMAP
+ #define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
+ #else /* HAVE_MMAP */
+ #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
+ #endif /* HAVE_MMAP */
+#endif /* DEFAULT_MMAP_THRESHOLD */
+
+#ifndef USE_BUILTIN_FFS
+ #define USE_BUILTIN_FFS 0
+#endif /* USE_BUILTIN_FFS */
+
+#ifndef USE_DEV_RANDOM
+ #define USE_DEV_RANDOM 0
+#endif /* USE_DEV_RANDOM */
+
+#ifndef NO_MALLINFO
+ #define NO_MALLINFO 0
+#endif /* NO_MALLINFO */
+#ifndef MALLINFO_FIELD_TYPE
+ #define MALLINFO_FIELD_TYPE size_t
+#endif /* MALLINFO_FIELD_TYPE */
+
+/*
+ mallopt tuning options. SVID/XPG defines four standard parameter
+ numbers for mallopt, normally defined in malloc.h. None of these
+ are used in this malloc, so setting them has no effect. But this
+ malloc does support the following options.
+*/
+
+#define M_TRIM_THRESHOLD (-1)
+#define M_GRANULARITY (-2)
+#define M_MMAP_THRESHOLD (-3)
+
+#if !NO_MALLINFO
+/*
+ This version of malloc supports the standard SVID/XPG mallinfo
+ routine that returns a struct containing usage properties and
+ statistics. It should work on any system that has a
+ /usr/include/malloc.h defining struct mallinfo. The main
+ declaration needed is the mallinfo struct that is returned (by-copy)
+ by mallinfo(). The malloinfo struct contains a bunch of fields that
+ are not even meaningful in this version of malloc. These fields are
+ are instead filled by mallinfo() with other numbers that might be of
+ interest.
+
+ HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
+ /usr/include/malloc.h file that includes a declaration of struct
+ mallinfo. If so, it is included; else a compliant version is
+ declared below. These must be precisely the same for mallinfo() to
+ work. The original SVID version of this struct, defined on most
+ systems with mallinfo, declares all fields as ints. But some others
+ define as unsigned long. If your system defines the fields using a
+ type of different width than listed here, you MUST #include your
+ system version and #define HAVE_USR_INCLUDE_MALLOC_H.
+*/
+
+/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
+#ifdef HAVE_USR_INCLUDE_MALLOC_H
+#include "/usr/include/malloc.h"
+#else /* HAVE_USR_INCLUDE_MALLOC_H */
+
+struct mallinfo {
+ MALLINFO_FIELD_TYPE iArena; /* non-mmapped space allocated from system */
+ MALLINFO_FIELD_TYPE iOrdblks; /* number of free chunks */
+ MALLINFO_FIELD_TYPE iSmblks; /* always 0 */
+ MALLINFO_FIELD_TYPE iHblks; /* always 0 */
+ MALLINFO_FIELD_TYPE iHblkhd; /* space in mmapped regions */
+ MALLINFO_FIELD_TYPE iUsmblks; /* maximum total allocated space */
+ MALLINFO_FIELD_TYPE iFsmblks; /* always 0 */
+ MALLINFO_FIELD_TYPE iUordblks; /* total allocated space */
+ MALLINFO_FIELD_TYPE iFordblks; /* total free space */
+ MALLINFO_FIELD_TYPE iKeepcost; /* releasable (via malloc_trim) space */
+ MALLINFO_FIELD_TYPE iCellCount;/* Number of chunks allocated*/
+};
+
+#endif /* HAVE_USR_INCLUDE_MALLOC_H */
+#endif /* NO_MALLINFO */
+
+#if MSPACES
+ typedef void* mspace;
+#endif /* MSPACES */
+
+#if 0
+
+#include <stdio.h>/* for printing in malloc_stats */
+
+#ifndef LACKS_ERRNO_H
+ #include <errno.h> /* for MALLOC_FAILURE_ACTION */
+#endif /* LACKS_ERRNO_H */
+
+#if FOOTERS
+ #include <time.h> /* for iMagic initialization */
+#endif /* FOOTERS */
+
+#ifndef LACKS_STDLIB_H
+ #include <stdlib.h> /* for abort() */
+#endif /* LACKS_STDLIB_H */
+
+#if !defined(ASSERT)
+#define ASSERT(x) __ASSERT_DEBUG(x, HEAP_PANIC(ETHeapBadCellAddress))
+#endif
+
+#ifndef LACKS_STRING_H
+ #include <string.h> /* for memset etc */
+#endif /* LACKS_STRING_H */
+
+#if USE_BUILTIN_FFS
+ #ifndef LACKS_STRINGS_H
+ #include <strings.h> /* for ffs */
+ #endif /* LACKS_STRINGS_H */
+#endif /* USE_BUILTIN_FFS */
+
+#if HAVE_MMAP
+ #ifndef LACKS_SYS_MMAN_H
+ #include <sys/mman.h> /* for mmap */
+ #endif /* LACKS_SYS_MMAN_H */
+ #ifndef LACKS_FCNTL_H
+ #include <fcntl.h>
+ #endif /* LACKS_FCNTL_H */
+#endif /* HAVE_MMAP */
+
+#if HAVE_MORECORE
+ #ifndef LACKS_UNISTD_H
+ #include <unistd.h> /* for sbrk */
+ extern void* sbrk(size_t);
+ #else /* LACKS_UNISTD_H */
+ #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
+ extern void* sbrk(ptrdiff_t);
+ /*Amod sbrk is not defined in WIN32 need to check in symbian*/
+ #endif /* FreeBSD etc */
+ #endif /* LACKS_UNISTD_H */
+#endif /* HAVE_MORECORE */
+
+#endif
+
+/*AMOD: For MALLOC_GETPAGESIZE*/
+#if 0 // replaced with GET_PAGE_SIZE() defined in heap.cpp
+#ifndef WIN32
+ #ifndef MALLOC_GETPAGESIZE
+ #ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
+ #ifndef _SC_PAGE_SIZE
+ #define _SC_PAGE_SIZE _SC_PAGESIZE
+ #endif
+ #endif
+ #ifdef _SC_PAGE_SIZE
+ #define MALLOC_GETPAGESIZE sysconf(_SC_PAGE_SIZE)
+ #else
+ #if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+ extern size_t getpagesize();
+ #define MALLOC_GETPAGESIZE getpagesize()
+ #else
+ #ifdef WIN32 /* use supplied emulation of getpagesize */
+ #define MALLOC_GETPAGESIZE getpagesize()
+ #else
+ #ifndef LACKS_SYS_PARAM_H
+ #include <sys/param.h>
+ #endif
+ #ifdef EXEC_PAGESIZE
+ #define MALLOC_GETPAGESIZE EXEC_PAGESIZE
+ #else
+ #ifdef NBPG
+ #ifndef CLSIZE
+ #define MALLOC_GETPAGESIZE NBPG
+ #else
+ #define MALLOC_GETPAGESIZE (NBPG * CLSIZE)
+ #endif
+ #else
+ #ifdef NBPC
+ #define MALLOC_GETPAGESIZE NBPC
+ #else
+ #ifdef PAGESIZE
+ #define MALLOC_GETPAGESIZE PAGESIZE
+ #else /* just guess */
+ #define MALLOC_GETPAGESIZE ((size_t)4096U)
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+#endif
+/*AMOD: For MALLOC_GETPAGESIZE*/
+
+/* ------------------- size_t and alignment properties -------------------- */
+
+/* The byte and bit size of a size_t */
+#define SIZE_T_SIZE (sizeof(size_t))
+#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
+
+/* Some constants coerced to size_t */
+/* Annoying but necessary to avoid errors on some plaftorms */
+#define SIZE_T_ZERO ((size_t)0)
+#define SIZE_T_ONE ((size_t)1)
+#define SIZE_T_TWO ((size_t)2)
+#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
+#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
+#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
+#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
+
+/* The bit mask value corresponding to MALLOC_ALIGNMENT */
+#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
+
+/* True if address a has acceptable alignment */
+//#define IS_ALIGNED(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
+#define IS_ALIGNED(A) (((unsigned int)((A)) & (CHUNK_ALIGN_MASK)) == 0)
+
+/* the number of bytes to offset an address to align it */
+#define ALIGN_OFFSET(A)\
+ ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
+ ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
+
+/* -------------------------- MMAP preliminaries ------------------------- */
+
+/*
+ If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
+ checks to fail so compiler optimizer can delete code rather than
+ using so many "#if"s.
+*/
+
+
+/* MORECORE and MMAP must return MFAIL on failure */
+#define MFAIL ((void*)(MAX_SIZE_T))
+#define CMFAIL ((TUint8*)(MFAIL)) /* defined for convenience */
+
+#if !HAVE_MMAP
+ #define IS_MMAPPED_BIT (SIZE_T_ZERO)
+ #define USE_MMAP_BIT (SIZE_T_ZERO)
+ #define CALL_MMAP(s) MFAIL
+ #define CALL_MUNMAP(a, s) (-1)
+ #define DIRECT_MMAP(s) MFAIL
+#else /* !HAVE_MMAP */
+ #define IS_MMAPPED_BIT (SIZE_T_ONE)
+ #define USE_MMAP_BIT (SIZE_T_ONE)
+ #ifndef WIN32
+ #define CALL_MUNMAP(a, s) DLUMMAP((a),(s)) /*munmap((a), (s))*/
+ #define MMAP_PROT (PROT_READ|PROT_WRITE)
+ #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+ #define MAP_ANONYMOUS MAP_ANON
+ #endif /* MAP_ANON */
+ #ifdef MAP_ANONYMOUS
+ #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
+ #define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, (int)MMAP_FLAGS, -1, 0)
+ #else /* MAP_ANONYMOUS */
+ /*
+ Nearly all versions of mmap support MAP_ANONYMOUS, so the following
+ is unlikely to be needed, but is supplied just in case.
+ */
+ #define MMAP_FLAGS (MAP_PRIVATE)
+ //static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
+ #define CALL_MMAP(s) DLMMAP(s)
+ /*#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
+ (dev_zero_fd = open("/dev/zero", O_RDWR), \
+ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
+ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
+ */
+ #define CALL_REMAP(a, s, d) DLREMAP((a),(s),(d))
+ #endif /* MAP_ANONYMOUS */
+ #define DIRECT_MMAP(s) CALL_MMAP(s)
+ #else /* WIN32 */
+ #define CALL_MMAP(s) win32mmap(s)
+ #define CALL_MUNMAP(a, s) win32munmap((a), (s))
+ #define DIRECT_MMAP(s) win32direct_mmap(s)
+ #endif /* WIN32 */
+#endif /* HAVE_MMAP */
+
+#if HAVE_MMAP && HAVE_MREMAP
+ #define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
+#else /* HAVE_MMAP && HAVE_MREMAP */
+ #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
+#endif /* HAVE_MMAP && HAVE_MREMAP */
+
+#if HAVE_MORECORE
+ #define CALL_MORECORE(S) SetBrk(S)
+#else /* HAVE_MORECORE */
+ #define CALL_MORECORE(S) MFAIL
+#endif /* HAVE_MORECORE */
+
+/* mstate bit set if continguous morecore disabled or failed */
+#define USE_NONCONTIGUOUS_BIT (4U)
+
+/* segment bit set in create_mspace_with_base */
+#define EXTERN_BIT (8U)
+
+
+#if USE_LOCKS
+/*
+ When locks are defined, there are up to two global locks:
+ * If HAVE_MORECORE, iMorecoreMutex protects sequences of calls to
+ MORECORE. In many cases sys_alloc requires two calls, that should
+ not be interleaved with calls by other threads. This does not
+ protect against direct calls to MORECORE by other threads not
+ using this lock, so there is still code to cope the best we can on
+ interference.
+ * iMagicInitMutex ensures that mparams.iMagic and other
+ unique mparams values are initialized only once.
+*/
+ #ifndef WIN32
+ /* By default use posix locks */
+ #include <pthread.h>
+ #define MLOCK_T pthread_mutex_t
+ #define INITIAL_LOCK(l) pthread_mutex_init(l, NULL)
+ #define ACQUIRE_LOCK(l) pthread_mutex_lock(l)
+ #define RELEASE_LOCK(l) pthread_mutex_unlock(l)
+
+ #if HAVE_MORECORE
+ //static MLOCK_T iMorecoreMutex = PTHREAD_MUTEX_INITIALIZER;
+ #endif /* HAVE_MORECORE */
+ //static MLOCK_T iMagicInitMutex = PTHREAD_MUTEX_INITIALIZER;
+ #else /* WIN32 */
+ #define MLOCK_T long
+ #define INITIAL_LOCK(l) *(l)=0
+ #define ACQUIRE_LOCK(l) win32_acquire_lock(l)
+ #define RELEASE_LOCK(l) win32_release_lock(l)
+ #if HAVE_MORECORE
+ static MLOCK_T iMorecoreMutex;
+ #endif /* HAVE_MORECORE */
+ static MLOCK_T iMagicInitMutex;
+ #endif /* WIN32 */
+ #define USE_LOCK_BIT (2U)
+#else /* USE_LOCKS */
+ #define USE_LOCK_BIT (0U)
+ #define INITIAL_LOCK(l)
+#endif /* USE_LOCKS */
+
+#if USE_LOCKS && HAVE_MORECORE
+ #define ACQUIRE_MORECORE_LOCK(M) ACQUIRE_LOCK((M->iMorecoreMutex)/*&iMorecoreMutex*/);
+ #define RELEASE_MORECORE_LOCK(M) RELEASE_LOCK((M->iMorecoreMutex)/*&iMorecoreMutex*/);
+#else /* USE_LOCKS && HAVE_MORECORE */
+ #define ACQUIRE_MORECORE_LOCK(M)
+ #define RELEASE_MORECORE_LOCK(M)
+#endif /* USE_LOCKS && HAVE_MORECORE */
+
+#if USE_LOCKS
+ /*Currently not suporting this*/
+ #define ACQUIRE_MAGIC_INIT_LOCK(M) ACQUIRE_LOCK(((M)->iMagicInitMutex));
+ //AMOD: changed #define ACQUIRE_MAGIC_INIT_LOCK()
+ //#define RELEASE_MAGIC_INIT_LOCK()
+ #define RELEASE_MAGIC_INIT_LOCK(M) RELEASE_LOCK(((M)->iMagicInitMutex));
+#else /* USE_LOCKS */
+ #define ACQUIRE_MAGIC_INIT_LOCK(M)
+ #define RELEASE_MAGIC_INIT_LOCK(M)
+#endif /* USE_LOCKS */
+
+/*CHUNK representation*/
+struct malloc_chunk {
+ size_t iPrevFoot; /* Size of previous chunk (if free). */
+ size_t iHead; /* Size and inuse bits. */
+ struct malloc_chunk* iFd; /* double links -- used only if free. */
+ struct malloc_chunk* iBk;
+};
+
+typedef struct malloc_chunk mchunk;
+typedef struct malloc_chunk* mchunkptr;
+typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
+typedef unsigned int bindex_t; /* Described below */
+typedef unsigned int binmap_t; /* Described below */
+typedef unsigned int flag_t; /* The type of various bit flag sets */
+
+
+/* ------------------- Chunks sizes and alignments ----------------------- */
+#define MCHUNK_SIZE (sizeof(mchunk))
+
+//#if FOOTERS
+// #define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
+//#else /* FOOTERS */
+// #define CHUNK_OVERHEAD (SIZE_T_SIZE)
+//#endif /* FOOTERS */
+
+/* MMapped chunks need a second word of overhead ... */
+#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
+/* ... and additional padding for fake next-chunk at foot */
+#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
+
+/* The smallest size we can malloc is an aligned minimal chunk */
+#define MIN_CHUNK_SIZE ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
+/* conversion from malloc headers to user pointers, and back */
+#define CHUNK2MEM(p) ((void*)((TUint8*)(p) + TWO_SIZE_T_SIZES))
+#define MEM2CHUNK(mem) ((mchunkptr)((TUint8*)(mem) - TWO_SIZE_T_SIZES))
+/* chunk associated with aligned address A */
+#define ALIGN_AS_CHUNK(A) (mchunkptr)((A) + ALIGN_OFFSET(CHUNK2MEM(A)))
+
+/* Bounds on request (not chunk) sizes. */
+#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
+#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
+
+/* pad request bytes into a usable size */
+#define PAD_REQUEST(req) (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
+/* pad request, checking for minimum (but not maximum) */
+#define REQUEST2SIZE(req) (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : PAD_REQUEST(req))
+
+/* ------------------ Operations on iHead and foot fields ----------------- */
+
+/*
+ The iHead field of a chunk is or'ed with PINUSE_BIT when previous
+ adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
+ use. If the chunk was obtained with mmap, the iPrevFoot field has
+ IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
+ mmapped region to the base of the chunk.
+*/
+#define PINUSE_BIT (SIZE_T_ONE)
+#define CINUSE_BIT (SIZE_T_TWO)
+#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
+
+/* Head value for fenceposts */
+#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
+
+/* extraction of fields from iHead words */
+#define CINUSE(p) ((p)->iHead & CINUSE_BIT)
+#define PINUSE(p) ((p)->iHead & PINUSE_BIT)
+#define CHUNKSIZE(p) ((p)->iHead & ~(INUSE_BITS))
+
+#define CLEAR_PINUSE(p) ((p)->iHead &= ~PINUSE_BIT)
+#define CLEAR_CINUSE(p) ((p)->iHead &= ~CINUSE_BIT)
+
+/* Treat space at ptr +/- offset as a chunk */
+#define CHUNK_PLUS_OFFSET(p, s) ((mchunkptr)(((TUint8*)(p)) + (s)))
+#define CHUNK_MINUS_OFFSET(p, s) ((mchunkptr)(((TUint8*)(p)) - (s)))
+
+/* Ptr to next or previous physical malloc_chunk. */
+#define NEXT_CHUNK(p) ((mchunkptr)( ((TUint8*)(p)) + ((p)->iHead & ~INUSE_BITS)))
+#define PREV_CHUNK(p) ((mchunkptr)( ((TUint8*)(p)) - ((p)->iPrevFoot) ))
+
+/* extract next chunk's PINUSE bit */
+#define NEXT_PINUSE(p) ((NEXT_CHUNK(p)->iHead) & PINUSE_BIT)
+
+/* Get/set size at footer */
+#define GET_FOOT(p, s) (((mchunkptr)((TUint8*)(p) + (s)))->iPrevFoot)
+#define SET_FOOT(p, s) (((mchunkptr)((TUint8*)(p) + (s)))->iPrevFoot = (s))
+
+/* Set size, PINUSE bit, and foot */
+#define SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, s) ((p)->iHead = (s|PINUSE_BIT), SET_FOOT(p, s))
+
+/* Set size, PINUSE bit, foot, and clear next PINUSE */
+#define SET_FREE_WITH_PINUSE(p, s, n) (CLEAR_PINUSE(n), SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, s))
+
+#define IS_MMAPPED(p) (!((p)->iHead & PINUSE_BIT) && ((p)->iPrevFoot & IS_MMAPPED_BIT))
+
+/* Get the internal overhead associated with chunk p */
+#define OVERHEAD_FOR(p) (IS_MMAPPED(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
+
+/* Return true if malloced space is not necessarily cleared */
+#if MMAP_CLEARS
+ #define CALLOC_MUST_CLEAR(p) (!IS_MMAPPED(p))
+#else /* MMAP_CLEARS */
+ #define CALLOC_MUST_CLEAR(p) (1)
+#endif /* MMAP_CLEARS */
+
+/* ---------------------- Overlaid data structures ----------------------- */
+struct malloc_tree_chunk {
+ /* The first four fields must be compatible with malloc_chunk */
+ size_t iPrevFoot;
+ size_t iHead;
+ struct malloc_tree_chunk* iFd;
+ struct malloc_tree_chunk* iBk;
+
+ struct malloc_tree_chunk* iChild[2];
+ struct malloc_tree_chunk* iParent;
+ bindex_t iIndex;
+};
+
+typedef struct malloc_tree_chunk tchunk;
+typedef struct malloc_tree_chunk* tchunkptr;
+typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
+
+/* A little helper macro for trees */
+#define LEFTMOST_CHILD(t) ((t)->iChild[0] != 0? (t)->iChild[0] : (t)->iChild[1])
+/*Segment structur*/
+//struct malloc_segment {
+// TUint8* iBase; /* base address */
+// size_t iSize; /* allocated size */
+//};
+
+#define IS_MMAPPED_SEGMENT(S) ((S)->iSflags & IS_MMAPPED_BIT)
+#define IS_EXTERN_SEGMENT(S) ((S)->iSflags & EXTERN_BIT)
+
+typedef struct malloc_segment msegment;
+typedef struct malloc_segment* msegmentptr;
+
+/*Malloc State data structur*/
+
+//#define NSMALLBINS (32U)
+//#define NTREEBINS (32U)
+#define SMALLBIN_SHIFT (3U)
+#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
+#define TREEBIN_SHIFT (8U)
+#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
+#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
+#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
+
+/*struct malloc_state {
+ binmap_t iSmallMap;
+ binmap_t iTreeMap;
+ size_t iDvSize;
+ size_t iTopSize;
+ mchunkptr iDv;
+ mchunkptr iTop;
+ size_t iTrimCheck;
+ mchunkptr iSmallBins[(NSMALLBINS+1)*2];
+ tbinptr iTreeBins[NTREEBINS];
+ msegment iSeg;
+ };*/
+/*
+struct malloc_state {
+ binmap_t iSmallMap;
+ binmap_t iTreeMap;
+ size_t iDvSize;
+ size_t iTopSize;
+ TUint8* iLeastAddr;
+ mchunkptr iDv;
+ mchunkptr iTop;
+ size_t iTrimCheck;
+ size_t iMagic;
+ mchunkptr iSmallBins[(NSMALLBINS+1)*2];
+ tbinptr iTreeBins[NTREEBINS];
+ size_t iFootprint;
+ size_t iMaxFootprint;
+ flag_t iMflags;
+#if USE_LOCKS
+ MLOCK_T iMutex;
+ MLOCK_T iMagicInitMutex;
+ MLOCK_T iMorecoreMutex;
+#endif
+ msegment iSeg;
+};
+*/
+typedef struct malloc_state* mstate;
+
+/* ------------- Global malloc_state and malloc_params ------------------- */
+
+/*
+ malloc_params holds global properties, including those that can be
+ dynamically set using mallopt. There is a single instance, mparams,
+ initialized in init_mparams.
+*/
+
+struct malloc_params {
+ size_t iMagic;
+ size_t iPageSize;
+ size_t iGranularity;
+ size_t iMmapThreshold;
+ size_t iTrimThreshold;
+ flag_t iDefaultMflags;
+#if USE_LOCKS
+ MLOCK_T iMagicInitMutex;
+#endif /* USE_LOCKS */
+};
+
+/* The global malloc_state used for all non-"mspace" calls */
+/*AMOD: Need to check this as this will be the member of the class*/
+
+//static struct malloc_state _gm_;
+//#define GM (&_gm_)
+
+//#define IS_GLOBAL(M) ((M) == &_gm_)
+/*AMOD: has changed*/
+#define IS_GLOBAL(M) ((M) == GM)
+#define IS_INITIALIZED(M) ((M)->iTop != 0)
+
+/* -------------------------- system alloc setup ------------------------- */
+
+/* Operations on iMflags */
+
+#define USE_LOCK(M) ((M)->iMflags & USE_LOCK_BIT)
+#define ENABLE_LOCK(M) ((M)->iMflags |= USE_LOCK_BIT)
+#define DISABLE_LOCK(M) ((M)->iMflags &= ~USE_LOCK_BIT)
+
+#define USE_MMAP(M) ((M)->iMflags & USE_MMAP_BIT)
+#define ENABLE_MMAP(M) ((M)->iMflags |= USE_MMAP_BIT)
+#define DISABLE_MMAP(M) ((M)->iMflags &= ~USE_MMAP_BIT)
+
+#define USE_NONCONTIGUOUS(M) ((M)->iMflags & USE_NONCONTIGUOUS_BIT)
+#define DISABLE_CONTIGUOUS(M) ((M)->iMflags |= USE_NONCONTIGUOUS_BIT)
+
+#define SET_LOCK(M,L) ((M)->iMflags = (L)? ((M)->iMflags | USE_LOCK_BIT) : ((M)->iMflags & ~USE_LOCK_BIT))
+
+/* page-align a size */
+#define PAGE_ALIGN(S) (((S) + (mparams.iPageSize)) & ~(mparams.iPageSize - SIZE_T_ONE))
+
+/* iGranularity-align a size */
+#define GRANULARITY_ALIGN(S) (((S) + (mparams.iGranularity)) & ~(mparams.iGranularity - SIZE_T_ONE))
+
+#define IS_PAGE_ALIGNED(S) (((size_t)(S) & (mparams.iPageSize - SIZE_T_ONE)) == 0)
+#define IS_GRANULARITY_ALIGNED(S) (((size_t)(S) & (mparams.iGranularity - SIZE_T_ONE)) == 0)
+
+/* True if segment S holds address A */
+#define SEGMENT_HOLDS(S, A) ((TUint8*)(A) >= S->iBase && (TUint8*)(A) < S->iBase + S->iSize)
+
+#ifndef MORECORE_CANNOT_TRIM
+ #define SHOULD_TRIM(M,s) ((s) > (M)->iTrimCheck)
+#else /* MORECORE_CANNOT_TRIM */
+ #define SHOULD_TRIM(M,s) (0)
+#endif /* MORECORE_CANNOT_TRIM */
+
+/*
+ TOP_FOOT_SIZE is padding at the end of a segment, including space
+ that may be needed to place segment records and fenceposts when new
+ noncontiguous segments are added.
+*/
+#define TOP_FOOT_SIZE (ALIGN_OFFSET(CHUNK2MEM(0))+PAD_REQUEST(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
+
+#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
+/* ------------------------------- Hooks -------------------------------- */
+
+/*
+ PREACTION should be defined to return 0 on success, and nonzero on
+ failure. If you are not using locking, you can redefine these to do
+ anything you like.
+*/
+
+#if USE_LOCKS
+ /* Ensure locks are initialized */
+ #define GLOBALLY_INITIALIZE() (mparams.iPageSize == 0 && init_mparams())
+ #define PREACTION(M) (USE_LOCK((M))?(ACQUIRE_LOCK((M)->iMutex),0):0) /*Action to take like lock before alloc*/
+ #define POSTACTION(M) { if (USE_LOCK(M)) RELEASE_LOCK((M)->iMutex); }
+
+#else /* USE_LOCKS */
+ #ifndef PREACTION
+ #define PREACTION(M) (0)
+ #endif /* PREACTION */
+ #ifndef POSTACTION
+ #define POSTACTION(M)
+ #endif /* POSTACTION */
+#endif /* USE_LOCKS */
+
+/*
+ CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
+ USAGE_ERROR_ACTION is triggered on detected bad frees and
+ reallocs. The argument p is an address that might have triggered the
+ fault. It is ignored by the two predefined actions, but might be
+ useful in custom actions that try to help diagnose errors.
+*/
+
+#if PROCEED_ON_ERROR
+ /* A count of the number of corruption errors causing resets */
+ int malloc_corruption_error_count;
+ /* default corruption action */
+ static void ResetOnError(mstate m);
+ #define CORRUPTION_ERROR_ACTION(m) ResetOnError(m)
+ #define USAGE_ERROR_ACTION(m, p)
+#else /* PROCEED_ON_ERROR */
+ #ifndef CORRUPTION_ERROR_ACTION
+ #define CORRUPTION_ERROR_ACTION(m) ABORT
+ #endif /* CORRUPTION_ERROR_ACTION */
+ #ifndef USAGE_ERROR_ACTION
+ #define USAGE_ERROR_ACTION(m,p) ABORT
+ #endif /* USAGE_ERROR_ACTION */
+#endif /* PROCEED_ON_ERROR */
+
+
+#ifdef _DEBUG
+ #define CHECK_FREE_CHUNK(M,P) DoCheckFreeChunk(M,P)
+ #define CHECK_INUSE_CHUNK(M,P) DoCheckInuseChunk(M,P)
+ #define CHECK_TOP_CHUNK(M,P) DoCheckTopChunk(M,P)
+ #define CHECK_MALLOCED_CHUNK(M,P,N) DoCheckMallocedChunk(M,P,N)
+ #define CHECK_MMAPPED_CHUNK(M,P) DoCheckMmappedChunk(M,P)
+ #define CHECK_MALLOC_STATE(M) DoCheckMallocState(M)
+#else /* DEBUG */
+ #define CHECK_FREE_CHUNK(M,P)
+ #define CHECK_INUSE_CHUNK(M,P)
+ #define CHECK_MALLOCED_CHUNK(M,P,N)
+ #define CHECK_MMAPPED_CHUNK(M,P)
+ #define CHECK_MALLOC_STATE(M)
+ #define CHECK_TOP_CHUNK(M,P)
+#endif /* DEBUG */
+
+/* ---------------------------- Indexing Bins ---------------------------- */
+
+#define IS_SMALL(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
+#define SMALL_INDEX(s) ((s) >> SMALLBIN_SHIFT)
+#define SMALL_INDEX2SIZE(i) ((i) << SMALLBIN_SHIFT)
+#define MIN_SMALL_INDEX (SMALL_INDEX(MIN_CHUNK_SIZE))
+
+/* addressing by index. See above about smallbin repositioning */
+#define SMALLBIN_AT(M, i) ((sbinptr)((TUint8*)&((M)->iSmallBins[(i)<<1])))
+#define TREEBIN_AT(M,i) (&((M)->iTreeBins[i]))
+
+
+/* Bit representing maximum resolved size in a treebin at i */
+#define BIT_FOR_TREE_INDEX(i) (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
+
+/* Shift placing maximum resolved bit in a treebin at i as sign bit */
+#define LEFTSHIFT_FOR_TREE_INDEX(i) ((i == NTREEBINS-1)? 0 : ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
+
+/* The size of the smallest chunk held in bin with index i */
+#define MINSIZE_FOR_TREE_INDEX(i) ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
+
+
+/* ------------------------ Operations on bin maps ----------------------- */
+/* bit corresponding to given index */
+#define IDX2BIT(i) ((binmap_t)(1) << (i))
+/* Mark/Clear bits with given index */
+#define MARK_SMALLMAP(M,i) ((M)->iSmallMap |= IDX2BIT(i))
+#define CLEAR_SMALLMAP(M,i) ((M)->iSmallMap &= ~IDX2BIT(i))
+#define SMALLMAP_IS_MARKED(M,i) ((M)->iSmallMap & IDX2BIT(i))
+#define MARK_TREEMAP(M,i) ((M)->iTreeMap |= IDX2BIT(i))
+#define CLEAR_TREEMAP(M,i) ((M)->iTreeMap &= ~IDX2BIT(i))
+#define TREEMAP_IS_MARKED(M,i) ((M)->iTreeMap & IDX2BIT(i))
+
+ /* isolate the least set bit of a bitmap */
+#define LEAST_BIT(x) ((x) & -(x))
+
+/* mask with all bits to left of least bit of x on */
+#define LEFT_BITS(x) ((x<<1) | -(x<<1))
+
+/* mask with all bits to left of or equal to least bit of x on */
+#define SAME_OR_LEFT_BITS(x) ((x) | -(x))
+
+#if !INSECURE
+ /* Check if address a is at least as high as any from MORECORE or MMAP */
+ #define OK_ADDRESS(M, a) ((TUint8*)(a) >= (M)->iLeastAddr)
+ /* Check if address of next chunk n is higher than base chunk p */
+ #define OK_NEXT(p, n) ((TUint8*)(p) < (TUint8*)(n))
+ /* Check if p has its CINUSE bit on */
+ #define OK_CINUSE(p) CINUSE(p)
+ /* Check if p has its PINUSE bit on */
+ #define OK_PINUSE(p) PINUSE(p)
+#else /* !INSECURE */
+ #define OK_ADDRESS(M, a) (1)
+ #define OK_NEXT(b, n) (1)
+ #define OK_CINUSE(p) (1)
+ #define OK_PINUSE(p) (1)
+#endif /* !INSECURE */
+
+#if (FOOTERS && !INSECURE)
+ /* Check if (alleged) mstate m has expected iMagic field */
+ #define OK_MAGIC(M) ((M)->iMagic == mparams.iMagic)
+#else /* (FOOTERS && !INSECURE) */
+ #define OK_MAGIC(M) (1)
+#endif /* (FOOTERS && !INSECURE) */
+
+/* In gcc, use __builtin_expect to minimize impact of checks */
+#if !INSECURE
+ #if defined(__GNUC__) && __GNUC__ >= 3
+ #define RTCHECK(e) __builtin_expect(e, 1)
+ #else /* GNUC */
+ #define RTCHECK(e) (e)
+ #endif /* GNUC */
+
+#else /* !INSECURE */
+ #define RTCHECK(e) (1)
+#endif /* !INSECURE */
+/* macros to set up inuse chunks with or without footers */
+#if !FOOTERS
+ #define MARK_INUSE_FOOT(M,p,s)
+ /* Set CINUSE bit and PINUSE bit of next chunk */
+ #define SET_INUSE(M,p,s) ((p)->iHead = (((p)->iHead & PINUSE_BIT)|s|CINUSE_BIT),((mchunkptr)(((TUint8*)(p)) + (s)))->iHead |= PINUSE_BIT)
+ /* Set CINUSE and PINUSE of this chunk and PINUSE of next chunk */
+ #define SET_INUSE_AND_PINUSE(M,p,s) ((p)->iHead = (s|PINUSE_BIT|CINUSE_BIT),((mchunkptr)(((TUint8*)(p)) + (s)))->iHead |= PINUSE_BIT)
+ /* Set size, CINUSE and PINUSE bit of this chunk */
+ #define SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(M, p, s) ((p)->iHead = (s|PINUSE_BIT|CINUSE_BIT))
+#else /* FOOTERS */
+ /* Set foot of inuse chunk to be xor of mstate and seed */
+ #define MARK_INUSE_FOOT(M,p,s) (((mchunkptr)((TUint8*)(p) + (s)))->iPrevFoot = ((size_t)(M) ^ mparams.iMagic))
+ #define GET_MSTATE_FOR(p) ((mstate)(((mchunkptr)((TUint8*)(p)+(CHUNKSIZE(p))))->iPrevFoot ^ mparams.iMagic))
+ #define SET_INUSE(M,p,s)\
+ ((p)->iHead = (((p)->iHead & PINUSE_BIT)|s|CINUSE_BIT),\
+ (((mchunkptr)(((TUint8*)(p)) + (s)))->iHead |= PINUSE_BIT), \
+ MARK_INUSE_FOOT(M,p,s))
+ #define SET_INUSE_AND_PINUSE(M,p,s)\
+ ((p)->iHead = (s|PINUSE_BIT|CINUSE_BIT),\
+ (((mchunkptr)(((TUint8*)(p)) + (s)))->iHead |= PINUSE_BIT),\
+ MARK_INUSE_FOOT(M,p,s))
+ #define SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(M, p, s)\
+ ((p)->iHead = (s|PINUSE_BIT|CINUSE_BIT),\
+ MARK_INUSE_FOOT(M, p, s))
+#endif /* !FOOTERS */
+
+
+#if ONLY_MSPACES
+#define INTERNAL_MALLOC(m, b) mspace_malloc(m, b)
+#define INTERNAL_FREE(m, mem) mspace_free(m,mem);
+#else /* ONLY_MSPACES */
+ #if MSPACES
+ #define INTERNAL_MALLOC(m, b) (m == GM)? dlmalloc(b) : mspace_malloc(m, b)
+ #define INTERNAL_FREE(m, mem) if (m == GM) dlfree(mem); else mspace_free(m,mem);
+ #else /* MSPACES */
+ #define INTERNAL_MALLOC(m, b) dlmalloc(b)
+ #define INTERNAL_FREE(m, mem) dlfree(mem)
+ #endif /* MSPACES */
+#endif /* ONLY_MSPACES */
+
+ #ifndef NDEBUG
+ #define CHECKING 1
+ #endif
+// #define HYSTERESIS 4
+ #define HYSTERESIS 1
+ #define HYSTERESIS_BYTES (2*PAGESIZE)
+ #define HYSTERESIS_GROW (HYSTERESIS*PAGESIZE)
+
+ #if CHECKING
+ #define CHECK(x) x
+ #else
+ #undef ASSERT
+ #define ASSERT(x) (void)0
+ #define CHECK(x) (void)0
+ #endif
+
+#endif/*__DLA__*/
diff --git a/src/corelib/arch/symbian/heap_hybrid.cpp b/src/corelib/arch/symbian/heap_hybrid.cpp
new file mode 100644
index 0000000000..6e2ef21e93
--- /dev/null
+++ b/src/corelib/arch/symbian/heap_hybrid.cpp
@@ -0,0 +1,3346 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt_hybridheap_symbian_p.h"
+
+#ifdef QT_USE_NEW_SYMBIAN_ALLOCATOR
+
+// if non zero this causes the iSlabs to be configured only when the chunk size exceeds this level
+#define DELAYED_SLAB_THRESHOLD (64*1024) // 64KB seems about right based on trace data
+#define SLAB_CONFIG 0x3fff // Use all slab sizes 4,8..56 bytes. This is more efficient for large heaps as Qt tends to have
+
+#ifdef _DEBUG
+#define __SIMULATE_ALLOC_FAIL(s) if (CheckForSimulatedAllocFail()) {s}
+#define __ALLOC_DEBUG_HEADER(s) (s += EDebugHdrSize)
+#define __SET_DEBUG_DATA(p,n,c) (((SDebugCell*)(p))->nestingLevel = (n), ((SDebugCell*)(p))->allocCount = (c))
+#define __GET_USER_DATA_BFR(p) ((p!=0) ? (TUint8*)(p) + EDebugHdrSize : NULL)
+#define __GET_DEBUG_DATA_BFR(p) ((p!=0) ? (TUint8*)(p) - EDebugHdrSize : NULL)
+#define __ZAP_CELL(p) memset( (TUint8*)p, 0xde, (AllocLen(__GET_USER_DATA_BFR(p))+EDebugHdrSize))
+#define __DEBUG_SAVE(p) TInt dbgNestLevel = ((SDebugCell*)p)->nestingLevel
+#define __DEBUG_RESTORE(p) if (p) {((SDebugCell*)p)->nestingLevel = dbgNestLevel;}
+#define __DEBUG_HDR_SIZE EDebugHdrSize
+#define __REMOVE_DBG_HDR(n) (n*EDebugHdrSize)
+#define __GET_AVAIL_BLOCK_SIZE(s) ( (s<EDebugHdrSize) ? 0 : s-EDebugHdrSize )
+#define __UPDATE_ALLOC_COUNT(o,n,c) if (o!=n && n) {((SDebugCell*)n)->allocCount = (c);}
+#define __INIT_COUNTERS(i) iCellCount=i,iTotalAllocSize=i
+#define __INCREMENT_COUNTERS(p) iCellCount++, iTotalAllocSize += AllocLen(p)
+#define __DECREMENT_COUNTERS(p) iCellCount--, iTotalAllocSize -= AllocLen(p)
+#define __UPDATE_TOTAL_ALLOC(p,s) iTotalAllocSize += (AllocLen(__GET_USER_DATA_BFR(p)) - s)
+
+#else
+#define __SIMULATE_ALLOC_FAIL(s)
+#define __ALLOC_DEBUG_HEADER(s)
+#define __SET_DEBUG_DATA(p,n,c)
+#define __GET_USER_DATA_BFR(p) (p)
+#define __GET_DEBUG_DATA_BFR(p) (p)
+#define __ZAP_CELL(p)
+#define __DEBUG_SAVE(p)
+#define __DEBUG_RESTORE(p)
+#define __DEBUG_HDR_SIZE 0
+#define __REMOVE_DBG_HDR(n) 0
+#define __GET_AVAIL_BLOCK_SIZE(s) (s)
+#define __UPDATE_ALLOC_COUNT(o,n,c)
+#define __INIT_COUNTERS(i) iCellCount=i,iTotalAllocSize=i
+#define __INCREMENT_COUNTERS(p)
+#define __DECREMENT_COUNTERS(p)
+#define __UPDATE_TOTAL_ALLOC(p,s)
+
+#endif
+
+
+#define MEMORY_MONITORED (iFlags & EMonitorMemory)
+#define GM (&iGlobalMallocState)
+#define IS_FIXED_HEAP (iFlags & EFixedSize)
+#define __INIT_COUNTERS(i) iCellCount=i,iTotalAllocSize=i
+#define __POWER_OF_2(x) (!((x)&((x)-1)))
+
+#define __DL_BFR_CHECK(M,P) \
+ if ( MEMORY_MONITORED ) \
+ if ( !IS_ALIGNED(P) || ((TUint8*)(P)<M->iSeg.iBase) || ((TUint8*)(P)>(M->iSeg.iBase+M->iSeg.iSize))) \
+ BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)0), HEAP_PANIC(ETHeapBadCellAddress); \
+ else DoCheckInuseChunk(M, MEM2CHUNK(P))
+
+#ifndef __KERNEL_MODE__
+
+#define __SLAB_BFR_CHECK(S,P,B) \
+ if ( MEMORY_MONITORED ) \
+ if ( ((TUint32)P & 0x3) || ((TUint8*)P<iMemBase) || ((TUint8*)(P)>(TUint8*)this)) \
+ BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)S), HEAP_PANIC(ETHeapBadCellAddress); \
+ else DoCheckSlab(S, EPartialFullSlab, P), BuildPartialSlabBitmap(B,S,P)
+#define __PAGE_BFR_CHECK(P) \
+ if ( MEMORY_MONITORED ) \
+ if ( ((TUint32)P & ((1 << iPageSize)-1)) || ((TUint8*)P<iMemBase) || ((TUint8*)(P)>(TUint8*)this)) \
+ BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)0), HEAP_PANIC(ETHeapBadCellAddress)
+
+#endif
+
+#ifdef _MSC_VER
+// This is required while we are still using VC6 to compile, so as to avoid warnings that cannot be fixed
+// without having to edit the original Doug Lea source. The 4146 warnings are due to the original code having
+// a liking for negating unsigned numbers and the 4127 warnings are due to the original code using the RTCHECK
+// macro with values that are always defined as 1. It is better to turn these warnings off than to introduce
+// diffs between the original Doug Lea implementation and our adaptation of it
+#pragma warning( disable : 4146 ) /* unary minus operator applied to unsigned type, result still unsigned */
+#pragma warning( disable : 4127 ) /* conditional expression is constant */
+#endif // _MSC_VER
+
+
+/**
+@SYMPatchable
+@publishedPartner
+@released
+
+Defines the minimum cell size of a heap.
+
+The constant can be changed at ROM build time using patchdata OBY keyword.
+
+@deprecated Patching this constant no longer has any effect.
+*/
+#ifdef __X86GCC__ // For X86GCC we don't use the proper data import attribute
+#undef IMPORT_D // since the constants are not really imported. GCC doesn't
+#define IMPORT_D // allow imports from self.
+#endif
+IMPORT_D extern const TInt KHeapMinCellSize;
+
+/**
+@SYMPatchable
+@publishedPartner
+@released
+
+This constant defines the ratio that determines the amount of hysteresis between heap growing and heap
+shrinking.
+It is a 32-bit fixed point number where the radix point is defined to be
+between bits 7 and 8 (where the LSB is bit 0) i.e. using standard notation, a Q8 or a fx24.8
+fixed point number. For example, for a ratio of 2.0, set KHeapShrinkHysRatio=0x200.
+
+The heap shrinking hysteresis value is calculated to be:
+@code
+KHeapShrinkHysRatio*(iGrowBy>>8)
+@endcode
+where iGrowBy is a page aligned value set by the argument, aGrowBy, to the RHeap constructor.
+The default hysteresis value is iGrowBy bytes i.e. KHeapShrinkHysRatio=2.0.
+
+Memory usage may be improved by reducing the heap shrinking hysteresis
+by setting 1.0 < KHeapShrinkHysRatio < 2.0. Heap shrinking hysteresis is disabled/removed
+when KHeapShrinkHysRatio <= 1.0.
+
+The constant can be changed at ROM build time using patchdata OBY keyword.
+*/
+IMPORT_D extern const TInt KHeapShrinkHysRatio;
+
+UEXPORT_C TInt RHeap::AllocLen(const TAny* aCell) const
+{
+ const MAllocator* m = this;
+ return m->AllocLen(aCell);
+}
+
+UEXPORT_C TAny* RHeap::Alloc(TInt aSize)
+{
+ const MAllocator* m = this;
+ return ((MAllocator*)m)->Alloc(aSize);
+}
+
+UEXPORT_C void RHeap::Free(TAny* aCell)
+{
+ const MAllocator* m = this;
+ ((MAllocator*)m)->Free(aCell);
+}
+
+UEXPORT_C TAny* RHeap::ReAlloc(TAny* aCell, TInt aSize, TInt aMode)
+{
+ const MAllocator* m = this;
+ return ((MAllocator*)m)->ReAlloc(aCell, aSize, aMode);
+}
+
+UEXPORT_C TInt RHeap::DebugFunction(TInt aFunc, TAny* a1, TAny* a2)
+{
+ const MAllocator* m = this;
+ return ((MAllocator*)m)->DebugFunction(aFunc, a1, a2);
+}
+
+UEXPORT_C TInt RHeap::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
+{
+ const MAllocator* m = this;
+ return ((MAllocator*)m)->Extension_(aExtensionId, a0, a1);
+}
+
+#ifndef __KERNEL_MODE__
+
+EXPORT_C TInt RHeap::AllocSize(TInt& aTotalAllocSize) const
+{
+ const MAllocator* m = this;
+ return m->AllocSize(aTotalAllocSize);
+}
+
+EXPORT_C TInt RHeap::Available(TInt& aBiggestBlock) const
+{
+ const MAllocator* m = this;
+ return m->Available(aBiggestBlock);
+}
+
+EXPORT_C void RHeap::Reset()
+{
+ const MAllocator* m = this;
+ ((MAllocator*)m)->Reset();
+}
+
+EXPORT_C TInt RHeap::Compress()
+{
+ const MAllocator* m = this;
+ return ((MAllocator*)m)->Compress();
+}
+#endif
+
+RHybridHeap::RHybridHeap()
+ {
+ // This initialisation cannot be done in RHeap() for compatibility reasons
+ iMaxLength = iChunkHandle = iNestingLevel = 0;
+ iTop = NULL;
+ iFailType = ENone;
+ iTestData = NULL;
+ }
+
+void RHybridHeap::operator delete(TAny*, TAny*)
+/**
+Called if constructor issued by operator new(TUint aSize, TAny* aBase) throws exception.
+This is dummy as corresponding new operator does not allocate memory.
+*/
+{}
+
+
+#ifndef __KERNEL_MODE__
+void RHybridHeap::Lock() const
+ /**
+ @internalComponent
+*/
+ {((RFastLock&)iLock).Wait();}
+
+
+void RHybridHeap::Unlock() const
+ /**
+ @internalComponent
+*/
+ {((RFastLock&)iLock).Signal();}
+
+
+TInt RHybridHeap::ChunkHandle() const
+ /**
+ @internalComponent
+*/
+{
+ return iChunkHandle;
+}
+
+#else
+//
+// This method is implemented in kheap.cpp
+//
+//void RHybridHeap::Lock() const
+ /**
+ @internalComponent
+*/
+// {;}
+
+
+
+//
+// This method is implemented in kheap.cpp
+//
+//void RHybridHeap::Unlock() const
+ /**
+ @internalComponent
+*/
+// {;}
+
+
+TInt RHybridHeap::ChunkHandle() const
+ /**
+ @internalComponent
+*/
+{
+ return 0;
+}
+#endif
+
+RHybridHeap::RHybridHeap(TInt aChunkHandle, TInt aOffset, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, TInt aAlign, TBool aSingleThread, TBool aDLOnly, TBool aUseAdjust)
+/**
+Constructor for a non fixed heap. Unlike the fixed heap, this heap is quite flexible in terms of its minimum and
+maximum lengths and in that it can use the hybrid allocator if all of its requirements are met.
+*/
+ : iOffset(aOffset), iChunkSize(aMinLength)
+ {
+ __ASSERT_ALWAYS(iOffset>=0, HEAP_PANIC(ETHeapNewBadOffset));
+
+ iChunkHandle = aChunkHandle;
+ iMinLength = aMinLength;
+ iMaxLength = aMaxLength;
+
+ // If the user has explicitly specified 0 as the aGrowBy value, set it to 1 so that it will be rounded up to the nearst page size
+ if (aGrowBy == 0)
+ aGrowBy = 1;
+ GET_PAGE_SIZE(iPageSize);
+ iGrowBy = _ALIGN_UP(aGrowBy, iPageSize);
+
+ Construct(aSingleThread, aDLOnly, aUseAdjust, aAlign);
+ }
+
+RHybridHeap::RHybridHeap(TInt aMaxLength, TInt aAlign, TBool aSingleThread)
+/**
+Constructor for a fixed heap. We have restrictions in that we have fixed minimum and maximum lengths and cannot grow
+and we only use DL allocator.
+*/
+ : iOffset(0), iChunkSize(aMaxLength)
+ {
+ iChunkHandle = NULL;
+ iMinLength = aMaxLength;
+ iMaxLength = aMaxLength;
+ iGrowBy = 0;
+
+ Construct(aSingleThread, ETrue, ETrue, aAlign);
+ }
+
+TAny* RHybridHeap::operator new(TUint aSize, TAny* aBase) __NO_THROW
+{
+ __ASSERT_ALWAYS(aSize>=sizeof(RHybridHeap), HEAP_PANIC(ETHeapNewBadSize));
+ RHybridHeap* h = (RHybridHeap*)aBase;
+ h->iBase = ((TUint8*)aBase) + aSize;
+ return aBase;
+}
+
+void RHybridHeap::Construct(TBool aSingleThread, TBool aDLOnly, TBool aUseAdjust, TInt aAlign)
+{
+ iAlign = aAlign ? aAlign : RHybridHeap::ECellAlignment;
+ __ASSERT_ALWAYS((TUint32)iAlign>=sizeof(TAny*) && __POWER_OF_2(iAlign), HEAP_PANIC(ETHeapNewBadAlignment));
+
+ // This initialisation cannot be done in RHeap() for compatibility reasons
+ iTop = NULL;
+ iFailType = ENone;
+ iNestingLevel = 0;
+ iTestData = NULL;
+
+ iHighWaterMark = iMinLength;
+ iAllocCount = 0;
+ iFlags = aSingleThread ? ESingleThreaded : 0;
+ iGrowBy = _ALIGN_UP(iGrowBy, iPageSize);
+
+ if ( iMinLength == iMaxLength )
+ {
+ iFlags |= EFixedSize;
+ aDLOnly = ETrue;
+ }
+#ifndef __KERNEL_MODE__
+#ifdef DELAYED_SLAB_THRESHOLD
+ iSlabInitThreshold = DELAYED_SLAB_THRESHOLD;
+#else
+ iSlabInitThreshold = 0;
+#endif // DELAYED_SLAB_THRESHOLD
+ iUseAdjust = aUseAdjust;
+ iDLOnly = aDLOnly;
+#else
+ (void)aUseAdjust;
+#endif
+ // Initialise suballocators
+ // if DL only is required then it cannot allocate slab or page memory
+ // so these sub-allocators should be disabled. Otherwise initialise with default values
+ if ( aDLOnly )
+ {
+ Init(0, 0);
+ }
+ else
+ {
+ Init(SLAB_CONFIG, 16);
+ }
+
+#ifdef ENABLE_BTRACE
+
+ TUint32 traceData[4];
+ traceData[0] = iMinLength;
+ traceData[1] = iMaxLength;
+ traceData[2] = iGrowBy;
+ traceData[3] = iAlign;
+ BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 11, traceData, sizeof(traceData));
+#endif
+
+}
+
+#ifndef __KERNEL_MODE__
+TInt RHybridHeap::ConstructLock(TUint32 aMode)
+{
+ TBool duplicateLock = EFalse;
+ TInt r = KErrNone;
+ if (!(iFlags & ESingleThreaded))
+ {
+ duplicateLock = aMode & UserHeap::EChunkHeapSwitchTo;
+ r = iLock.CreateLocal(duplicateLock ? EOwnerThread : EOwnerProcess);
+ if( r != KErrNone)
+ {
+ iChunkHandle = 0;
+ return r;
+ }
+ }
+
+ if ( aMode & UserHeap::EChunkHeapSwitchTo )
+ User::SwitchHeap(this);
+
+ iHandles = &iChunkHandle;
+ if (!(iFlags & ESingleThreaded))
+ {
+ // now change the thread-relative chunk/semaphore handles into process-relative handles
+ iHandleCount = 2;
+ if(duplicateLock)
+ {
+ RHandleBase s = iLock;
+ r = iLock.Duplicate(RThread());
+ s.Close();
+ }
+ if (r==KErrNone && (aMode & UserHeap::EChunkHeapDuplicate))
+ {
+ r = ((RChunk*)&iChunkHandle)->Duplicate(RThread());
+ if (r!=KErrNone)
+ iLock.Close(), iChunkHandle=0;
+ }
+ }
+ else
+ {
+ iHandleCount = 1;
+ if (aMode & UserHeap::EChunkHeapDuplicate)
+ r = ((RChunk*)&iChunkHandle)->Duplicate(RThread(), EOwnerThread);
+ }
+
+ return r;
+}
+#endif
+
+void RHybridHeap::Init(TInt aBitmapSlab, TInt aPagePower)
+{
+ /*Moved code which does initialization */
+ iTop = (TUint8*)this + iMinLength;
+ iBase = Ceiling(iBase, ECellAlignment); // Align iBase address
+
+ __INIT_COUNTERS(0);
+ // memset(&mparams,0,sizeof(mparams));
+
+ InitDlMalloc(iTop - iBase, 0);
+
+#ifndef __KERNEL_MODE__
+ SlabInit();
+ iSlabConfigBits = aBitmapSlab;
+ if ( iChunkSize > iSlabInitThreshold )
+ {
+ iSlabInitThreshold = KMaxTInt32;
+ SlabConfig(aBitmapSlab); // Delayed slab configuration done
+ }
+ if ( aPagePower )
+ {
+ RChunk chunk;
+ chunk.SetHandle(iChunkHandle);
+ iMemBase = chunk.Base(); // Store base address for paged allocator
+ }
+
+ /*10-1K,11-2K,12-4k,13-8K,14-16K,15-32K,16-64K*/
+ PagedInit(aPagePower);
+
+#ifdef ENABLE_BTRACE
+ TUint32 traceData[3];
+ traceData[0] = aBitmapSlab;
+ traceData[1] = aPagePower;
+ traceData[2] = GM->iTrimCheck;
+ BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 0, traceData, sizeof(traceData));
+#endif
+#else
+ (void)aBitmapSlab;
+ (void)aPagePower;
+#endif // __KERNEL_MODE__
+
+}
+
+
+TInt RHybridHeap::AllocLen(const TAny* aCell) const
+{
+ aCell = __GET_DEBUG_DATA_BFR(aCell);
+
+ if (PtrDiff(aCell, this) >= 0)
+ {
+ mchunkptr m = MEM2CHUNK(aCell);
+ return CHUNKSIZE(m) - OVERHEAD_FOR(m) - __DEBUG_HDR_SIZE;
+ }
+#ifndef __KERNEL_MODE__
+ if ( aCell )
+ {
+ if (LowBits(aCell, iPageSize) )
+ return SlabHeaderSize(slab::SlabFor(aCell)->iHeader) - __DEBUG_HDR_SIZE;
+
+ return PagedSize((void*)aCell) - __DEBUG_HDR_SIZE;
+ }
+#endif
+ return 0; // NULL pointer situation, should PANIC !!
+}
+
+#ifdef __KERNEL_MODE__
+TAny* RHybridHeap::Alloc(TInt aSize)
+{
+ __CHECK_THREAD_STATE;
+ __ASSERT_ALWAYS((TUint)aSize<(KMaxTInt/2),HEAP_PANIC(ETHeapBadAllocatedCellSize));
+ __SIMULATE_ALLOC_FAIL(return NULL;)
+ Lock();
+ __ALLOC_DEBUG_HEADER(aSize);
+ TAny* addr = DlMalloc(aSize);
+ if ( addr )
+ {
+// iCellCount++;
+ __SET_DEBUG_DATA(addr, iNestingLevel, ++iAllocCount);
+ addr = __GET_USER_DATA_BFR(addr);
+ __INCREMENT_COUNTERS(addr);
+ memclr(addr, AllocLen(addr));
+ }
+ Unlock();
+#ifdef ENABLE_BTRACE
+ if (iFlags & ETraceAllocs)
+ {
+ if ( addr )
+ {
+ TUint32 traceData[3];
+ traceData[0] = AllocLen(addr);
+ traceData[1] = aSize - __DEBUG_HDR_SIZE;
+ traceData[2] = 0;
+ BTraceContextN(BTrace::EHeap, BTrace::EHeapAlloc, (TUint32)this, (TUint32)addr, traceData, sizeof(traceData));
+ }
+ else
+ BTraceContext8(BTrace::EHeap, BTrace::EHeapAllocFail, (TUint32)this, (TUint32)(aSize - __DEBUG_HDR_SIZE));
+ }
+#endif
+ return addr;
+}
+#else
+
+TAny* RHybridHeap::Alloc(TInt aSize)
+{
+ __ASSERT_ALWAYS((TUint)aSize<(KMaxTInt/2),HEAP_PANIC(ETHeapBadAllocatedCellSize));
+ __SIMULATE_ALLOC_FAIL(return NULL;)
+
+ TAny* addr;
+#ifdef ENABLE_BTRACE
+ TInt aSubAllocator=0;
+#endif
+
+ Lock();
+
+ __ALLOC_DEBUG_HEADER(aSize);
+
+ if (aSize < iSlabThreshold)
+ {
+ TInt ix = iSizeMap[(aSize+3)>>2];
+ HEAP_ASSERT(ix != 0xff);
+ addr = SlabAllocate(iSlabAlloc[ix]);
+ if ( !addr )
+ { // Slab allocation has failed, try to allocate from DL
+ addr = DlMalloc(aSize);
+ }
+#ifdef ENABLE_BTRACE
+ else
+ aSubAllocator=1;
+#endif
+ }else if((aSize >> iPageThreshold)==0)
+ {
+ addr = DlMalloc(aSize);
+ }
+ else
+ {
+ addr = PagedAllocate(aSize);
+ if ( !addr )
+ { // Page allocation has failed, try to allocate from DL
+ addr = DlMalloc(aSize);
+ }
+#ifdef ENABLE_BTRACE
+ else
+ aSubAllocator=2;
+#endif
+ }
+
+ if ( addr )
+ {
+// iCellCount++;
+ __SET_DEBUG_DATA(addr, iNestingLevel, ++iAllocCount);
+ addr = __GET_USER_DATA_BFR(addr);
+ __INCREMENT_COUNTERS(addr);
+ }
+ Unlock();
+
+#ifdef ENABLE_BTRACE
+ if (iFlags & ETraceAllocs)
+ {
+ if ( addr )
+ {
+ TUint32 traceData[3];
+ traceData[0] = AllocLen(addr);
+ traceData[1] = aSize - __DEBUG_HDR_SIZE;
+ traceData[2] = aSubAllocator;
+ BTraceContextN(BTrace::EHeap, BTrace::EHeapAlloc, (TUint32)this, (TUint32)addr, traceData, sizeof(traceData));
+ }
+ else
+ BTraceContext8(BTrace::EHeap, BTrace::EHeapAllocFail, (TUint32)this, (TUint32)(aSize - __DEBUG_HDR_SIZE));
+ }
+#endif
+
+ return addr;
+}
+#endif // __KERNEL_MODE__
+
+#ifndef __KERNEL_MODE__
+TInt RHybridHeap::Compress()
+{
+ if ( IS_FIXED_HEAP )
+ return 0;
+
+ Lock();
+ TInt Reduced = SysTrim(GM, 0);
+ if (iSparePage)
+ {
+ Unmap(iSparePage, iPageSize);
+ iSparePage = 0;
+ Reduced += iPageSize;
+ }
+ Unlock();
+ return Reduced;
+}
+#endif
+
+void RHybridHeap::Free(TAny* aPtr)
+{
+ __CHECK_THREAD_STATE;
+ if ( !aPtr )
+ return;
+#ifdef ENABLE_BTRACE
+ TInt aSubAllocator=0;
+#endif
+ Lock();
+
+ aPtr = __GET_DEBUG_DATA_BFR(aPtr);
+
+#ifndef __KERNEL_MODE__
+ if (PtrDiff(aPtr, this) >= 0)
+ {
+#endif
+ __DL_BFR_CHECK(GM, aPtr);
+ __DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));
+ __ZAP_CELL(aPtr);
+ DlFree( aPtr);
+#ifndef __KERNEL_MODE__
+ }
+
+ else if ( LowBits(aPtr, iPageSize) == 0 )
+ {
+#ifdef ENABLE_BTRACE
+ aSubAllocator = 2;
+#endif
+ __PAGE_BFR_CHECK(aPtr);
+ __DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));
+ PagedFree(aPtr);
+ }
+ else
+ {
+#ifdef ENABLE_BTRACE
+ aSubAllocator = 1;
+#endif
+ TUint32 bm[4];
+ __SLAB_BFR_CHECK(slab::SlabFor(aPtr),aPtr,bm);
+ __DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));
+ __ZAP_CELL(aPtr);
+ SlabFree(aPtr);
+ }
+#endif // __KERNEL_MODE__
+// iCellCount--;
+ Unlock();
+#ifdef ENABLE_BTRACE
+ if (iFlags & ETraceAllocs)
+ {
+ TUint32 traceData;
+ traceData = aSubAllocator;
+ BTraceContextN(BTrace::EHeap, BTrace::EHeapFree, (TUint32)this, (TUint32)__GET_USER_DATA_BFR(aPtr), &traceData, sizeof(traceData));
+ }
+#endif
+}
+
+#ifndef __KERNEL_MODE__
+void RHybridHeap::Reset()
+/**
+Frees all allocated cells on this heap.
+*/
+{
+ Lock();
+ if ( !IS_FIXED_HEAP )
+ {
+ if ( GM->iSeg.iSize > (iMinLength - sizeof(*this)) )
+ Unmap(GM->iSeg.iBase + (iMinLength - sizeof(*this)), (GM->iSeg.iSize - (iMinLength - sizeof(*this))));
+ ResetBitmap();
+ if ( !iDLOnly )
+ Init(iSlabConfigBits, iPageThreshold);
+ else
+ Init(0,0);
+ }
+ else Init(0,0);
+ Unlock();
+}
+#endif
+
+TAny* RHybridHeap::ReAllocImpl(TAny* aPtr, TInt aSize, TInt aMode)
+{
+ // First handle special case of calling reallocate with NULL aPtr
+ if (!aPtr)
+ {
+ if (( aMode & ENeverMove ) == 0 )
+ {
+ aPtr = Alloc(aSize - __DEBUG_HDR_SIZE);
+ aPtr = __GET_DEBUG_DATA_BFR(aPtr);
+ }
+ return aPtr;
+ }
+
+ TInt oldsize = AllocLen(__GET_USER_DATA_BFR(aPtr)) + __DEBUG_HDR_SIZE;
+
+ // Insist on geometric growth when reallocating memory, this reduces copying and fragmentation
+ // generated during arithmetic growth of buffer/array/vector memory
+ // Experiments have shown that 25% is a good threshold for this policy
+ if (aSize <= oldsize)
+ {
+ if (aSize >= oldsize - (oldsize>>2))
+ return aPtr; // don't change if >75% original size
+ }
+ else
+ {
+ __SIMULATE_ALLOC_FAIL(return NULL;)
+ if (aSize < oldsize + (oldsize>>2))
+ {
+ aSize = _ALIGN_UP(oldsize + (oldsize>>2), 4); // grow to at least 125% original size
+ }
+ }
+ __DEBUG_SAVE(aPtr);
+
+ TAny* newp;
+#ifdef __KERNEL_MODE__
+ Lock();
+ __DL_BFR_CHECK(GM, aPtr);
+ newp = DlRealloc(aPtr, aSize, aMode);
+ Unlock();
+ if ( newp )
+ {
+ if ( aSize > oldsize )
+ memclr(((TUint8*)newp) + oldsize, (aSize-oldsize)); // Buffer has grown in place, clear extra
+ __DEBUG_RESTORE(newp);
+ __UPDATE_ALLOC_COUNT(aPtr, newp, ++iAllocCount);
+ __UPDATE_TOTAL_ALLOC(newp, oldsize);
+ }
+#else
+ // Decide how to reallocate based on (a) the current cell location, (b) the mode requested and (c) the new size
+ if ( PtrDiff(aPtr, this) >= 0 )
+ { // current cell in Doug Lea iArena
+ if ( (aMode & ENeverMove)
+ ||
+ (!(aMode & EAllowMoveOnShrink) && (aSize < oldsize))
+ ||
+ ((aSize >= iSlabThreshold) && ((aSize >> iPageThreshold) == 0)) )
+ {
+ Lock();
+ __DL_BFR_CHECK(GM, aPtr);
+ newp = DlRealloc(aPtr, aSize, aMode); // old and new in DL allocator
+ Unlock();
+ __DEBUG_RESTORE(newp);
+ __UPDATE_ALLOC_COUNT(aPtr,newp, ++iAllocCount);
+ __UPDATE_TOTAL_ALLOC(newp, oldsize);
+ return newp;
+ }
+ }
+ else if (LowBits(aPtr, iPageSize) == 0)
+ { // current cell in paged iArena
+ if ( (aMode & ENeverMove)
+ ||
+ (!(aMode & EAllowMoveOnShrink) && (aSize < oldsize))
+ ||
+ ((aSize >> iPageThreshold) != 0) )
+ {
+ Lock();
+ __PAGE_BFR_CHECK(aPtr);
+ newp = PagedReallocate(aPtr, aSize, aMode); // old and new in paged allocator
+ Unlock();
+ __DEBUG_RESTORE(newp);
+ __UPDATE_ALLOC_COUNT(aPtr,newp, ++iAllocCount);
+ __UPDATE_TOTAL_ALLOC(newp, oldsize);
+ return newp;
+ }
+ }
+ else
+ { // current cell in slab iArena
+ TUint32 bm[4];
+ Lock();
+ __SLAB_BFR_CHECK(slab::SlabFor(aPtr), aPtr, bm);
+ Unlock();
+ if ( aSize <= oldsize)
+ return aPtr;
+ if (aMode & ENeverMove)
+ return NULL; // cannot grow in slab iArena
+ // just use alloc/copy/free...
+ }
+
+ // fallback to allocate and copy
+ // shouldn't get here if we cannot move the cell
+ // __ASSERT(mode == emobile || (mode==efixshrink && size>oldsize));
+
+ newp = Alloc(aSize - __DEBUG_HDR_SIZE);
+ newp = __GET_DEBUG_DATA_BFR(newp);
+ if (newp)
+ {
+ memcpy(newp, aPtr, oldsize<aSize ? oldsize : aSize);
+ __DEBUG_RESTORE(newp);
+ Free(__GET_USER_DATA_BFR(aPtr));
+ }
+
+#endif // __KERNEL_MODE__
+ return newp;
+}
+
+
+TAny* RHybridHeap::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode )
+{
+
+ aPtr = __GET_DEBUG_DATA_BFR(aPtr);
+ __ALLOC_DEBUG_HEADER(aSize);
+
+ TAny* retval = ReAllocImpl(aPtr, aSize, aMode);
+
+ retval = __GET_USER_DATA_BFR(retval);
+
+#ifdef ENABLE_BTRACE
+ if (iFlags & ETraceAllocs)
+ {
+ if ( retval )
+ {
+ TUint32 traceData[3];
+ traceData[0] = AllocLen(retval);
+ traceData[1] = aSize - __DEBUG_HDR_SIZE;
+ traceData[2] = (TUint32)aPtr;
+ BTraceContextN(BTrace::EHeap, BTrace::EHeapReAlloc,(TUint32)this, (TUint32)retval, traceData, sizeof(traceData));
+ }
+ else
+ BTraceContext12(BTrace::EHeap, BTrace::EHeapReAllocFail, (TUint32)this, (TUint32)aPtr, (TUint32)(aSize - __DEBUG_HDR_SIZE));
+ }
+#endif
+ return retval;
+}
+
+#ifndef __KERNEL_MODE__
+TInt RHybridHeap::Available(TInt& aBiggestBlock) const
+/**
+Gets the total free space currently available on the heap and the space
+available in the largest free block.
+
+Note that this function exists mainly for compatibility reasons. In a modern
+heap implementation such as that present in Symbian it is not appropriate to
+concern oneself with details such as the amount of free memory available on a
+heap and its largeset free block, because the way that a modern heap implementation
+works is not simple. The amount of available virtual memory != physical memory
+and there are multiple allocation strategies used internally, which makes all
+memory usage figures "fuzzy" at best.
+
+In short, if you want to see if there is enough memory available to allocate a
+block of memory, call Alloc() and if it succeeds then there is enough memory!
+Messing around with functions like this is somewhat pointless with modern heap
+allocators.
+
+@param aBiggestBlock On return, contains the space available in the largest
+ free block on the heap. Due to the internals of modern
+ heap implementations, you can probably still allocate a
+ block larger than this!
+
+@return The total free space currently available on the heap. Again, you can
+ probably still allocate more than this!
+*/
+{
+ struct HeapInfo info;
+ Lock();
+ TInt Biggest = GetInfo(&info);
+ aBiggestBlock = __GET_AVAIL_BLOCK_SIZE(Biggest);
+ Unlock();
+ return __GET_AVAIL_BLOCK_SIZE(info.iFreeBytes);
+
+}
+
+TInt RHybridHeap::AllocSize(TInt& aTotalAllocSize) const
+ /**
+ Gets the number of cells allocated on this heap, and the total space
+ allocated to them.
+
+ @param aTotalAllocSize On return, contains the total space allocated
+ to the cells.
+
+ @return The number of cells allocated on this heap.
+*/
+{
+ struct HeapInfo info;
+ Lock();
+ GetInfo(&info);
+ aTotalAllocSize = info.iAllocBytes - __REMOVE_DBG_HDR(info.iAllocN);
+ Unlock();
+ return info.iAllocN;
+}
+
+#endif
+
+TInt RHybridHeap::Extension_(TUint /* aExtensionId */, TAny*& /* a0 */, TAny* /* a1 */)
+{
+ return KErrNotSupported;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// imported from dla.cpp
+///////////////////////////////////////////////////////////////////////////////
+
+//#include <unistd.h>
+//#define DEBUG_REALLOC
+#ifdef DEBUG_REALLOC
+#include <e32debug.h>
+#endif
+
+inline void RHybridHeap::InitBins(mstate m)
+{
+ /* Establish circular links for iSmallBins */
+ bindex_t i;
+ for (i = 0; i < NSMALLBINS; ++i) {
+ sbinptr bin = SMALLBIN_AT(m,i);
+ bin->iFd = bin->iBk = bin;
+ }
+ }
+/* ---------------------------- malloc support --------------------------- */
+
+/* allocate a large request from the best fitting chunk in a treebin */
+void* RHybridHeap::TmallocLarge(mstate m, size_t nb) {
+ tchunkptr v = 0;
+ size_t rsize = -nb; /* Unsigned negation */
+ tchunkptr t;
+ bindex_t idx;
+ ComputeTreeIndex(nb, idx);
+
+ if ((t = *TREEBIN_AT(m, idx)) != 0)
+ {
+ /* Traverse tree for this bin looking for node with size == nb */
+ size_t sizebits = nb << LEFTSHIFT_FOR_TREE_INDEX(idx);
+ tchunkptr rst = 0; /* The deepest untaken right subtree */
+ for (;;)
+ {
+ tchunkptr rt;
+ size_t trem = CHUNKSIZE(t) - nb;
+ if (trem < rsize)
+ {
+ v = t;
+ if ((rsize = trem) == 0)
+ break;
+ }
+ rt = t->iChild[1];
+ t = t->iChild[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
+ if (rt != 0 && rt != t)
+ rst = rt;
+ if (t == 0)
+ {
+ t = rst; /* set t to least subtree holding sizes > nb */
+ break;
+ }
+ sizebits <<= 1;
+ }
+ }
+ if (t == 0 && v == 0)
+ { /* set t to root of next non-empty treebin */
+ binmap_t leftbits = LEFT_BITS(IDX2BIT(idx)) & m->iTreeMap;
+ if (leftbits != 0)
+ {
+ bindex_t i;
+ binmap_t leastbit = LEAST_BIT(leftbits);
+ ComputeBit2idx(leastbit, i);
+ t = *TREEBIN_AT(m, i);
+ }
+ }
+ while (t != 0)
+ { /* Find smallest of tree or subtree */
+ size_t trem = CHUNKSIZE(t) - nb;
+ if (trem < rsize) {
+ rsize = trem;
+ v = t;
+ }
+ t = LEFTMOST_CHILD(t);
+ }
+ /* If iDv is a better fit, return 0 so malloc will use it */
+ if (v != 0 && rsize < (size_t)(m->iDvSize - nb))
+ {
+ if (RTCHECK(OK_ADDRESS(m, v)))
+ { /* split */
+ mchunkptr r = CHUNK_PLUS_OFFSET(v, nb);
+ HEAP_ASSERT(CHUNKSIZE(v) == rsize + nb);
+ if (RTCHECK(OK_NEXT(v, r)))
+ {
+ UnlinkLargeChunk(m, v);
+ if (rsize < MIN_CHUNK_SIZE)
+ SET_INUSE_AND_PINUSE(m, v, (rsize + nb));
+ else
+ {
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, v, nb);
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
+ InsertChunk(m, r, rsize);
+ }
+ return CHUNK2MEM(v);
+ }
+ }
+ // CORRUPTION_ERROR_ACTION(m);
+ }
+ return 0;
+ }
+
+/* allocate a small request from the best fitting chunk in a treebin */
+void* RHybridHeap::TmallocSmall(mstate m, size_t nb)
+{
+ tchunkptr t, v;
+ size_t rsize;
+ bindex_t i;
+ binmap_t leastbit = LEAST_BIT(m->iTreeMap);
+ ComputeBit2idx(leastbit, i);
+
+ v = t = *TREEBIN_AT(m, i);
+ rsize = CHUNKSIZE(t) - nb;
+
+ while ((t = LEFTMOST_CHILD(t)) != 0)
+ {
+ size_t trem = CHUNKSIZE(t) - nb;
+ if (trem < rsize)
+ {
+ rsize = trem;
+ v = t;
+ }
+ }
+
+ if (RTCHECK(OK_ADDRESS(m, v)))
+ {
+ mchunkptr r = CHUNK_PLUS_OFFSET(v, nb);
+ HEAP_ASSERT(CHUNKSIZE(v) == rsize + nb);
+ if (RTCHECK(OK_NEXT(v, r)))
+ {
+ UnlinkLargeChunk(m, v);
+ if (rsize < MIN_CHUNK_SIZE)
+ SET_INUSE_AND_PINUSE(m, v, (rsize + nb));
+ else
+ {
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, v, nb);
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
+ ReplaceDv(m, r, rsize);
+ }
+ return CHUNK2MEM(v);
+ }
+ }
+ // CORRUPTION_ERROR_ACTION(m);
+ // return 0;
+ }
+
+inline void RHybridHeap::InitTop(mstate m, mchunkptr p, size_t psize)
+{
+ /* Ensure alignment */
+ size_t offset = ALIGN_OFFSET(CHUNK2MEM(p));
+ p = (mchunkptr)((TUint8*)p + offset);
+ psize -= offset;
+ m->iTop = p;
+ m->iTopSize = psize;
+ p->iHead = psize | PINUSE_BIT;
+ /* set size of fake trailing chunk holding overhead space only once */
+ mchunkptr chunkPlusOff = CHUNK_PLUS_OFFSET(p, psize);
+ chunkPlusOff->iHead = TOP_FOOT_SIZE;
+ m->iTrimCheck = KHeapShrinkHysRatio*(iGrowBy>>8);
+}
+
+
+/* Unlink the first chunk from a smallbin */
+inline void RHybridHeap::UnlinkFirstSmallChunk(mstate M,mchunkptr B,mchunkptr P,bindex_t& I)
+{
+ mchunkptr F = P->iFd;
+ HEAP_ASSERT(P != B);
+ HEAP_ASSERT(P != F);
+ HEAP_ASSERT(CHUNKSIZE(P) == SMALL_INDEX2SIZE(I));
+ if (B == F)
+ CLEAR_SMALLMAP(M, I);
+ else if (RTCHECK(OK_ADDRESS(M, F)))
+ {
+ B->iFd = F;
+ F->iBk = B;
+ }
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ }
+}
+/* Link a free chunk into a smallbin */
+inline void RHybridHeap::InsertSmallChunk(mstate M,mchunkptr P, size_t S)
+{
+ bindex_t I = SMALL_INDEX(S);
+ mchunkptr B = SMALLBIN_AT(M, I);
+ mchunkptr F = B;
+ HEAP_ASSERT(S >= MIN_CHUNK_SIZE);
+ if (!SMALLMAP_IS_MARKED(M, I))
+ MARK_SMALLMAP(M, I);
+ else if (RTCHECK(OK_ADDRESS(M, B->iFd)))
+ F = B->iFd;
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ B->iFd = P;
+ F->iBk = P;
+ P->iFd = F;
+ P->iBk = B;
+}
+
+
+inline void RHybridHeap::InsertChunk(mstate M,mchunkptr P,size_t S)
+{
+ if (IS_SMALL(S))
+ InsertSmallChunk(M, P, S);
+ else
+ {
+ tchunkptr TP = (tchunkptr)(P); InsertLargeChunk(M, TP, S);
+ }
+}
+
+inline void RHybridHeap::UnlinkLargeChunk(mstate M,tchunkptr X)
+{
+ tchunkptr XP = X->iParent;
+ tchunkptr R;
+ if (X->iBk != X)
+ {
+ tchunkptr F = X->iFd;
+ R = X->iBk;
+ if (RTCHECK(OK_ADDRESS(M, F)))
+ {
+ F->iBk = R;
+ R->iFd = F;
+ }
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ }
+ else
+ {
+ tchunkptr* RP;
+ if (((R = *(RP = &(X->iChild[1]))) != 0) ||
+ ((R = *(RP = &(X->iChild[0]))) != 0))
+ {
+ tchunkptr* CP;
+ while ((*(CP = &(R->iChild[1])) != 0) ||
+ (*(CP = &(R->iChild[0])) != 0))
+ {
+ R = *(RP = CP);
+ }
+ if (RTCHECK(OK_ADDRESS(M, RP)))
+ *RP = 0;
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ }
+ }
+ if (XP != 0)
+ {
+ tbinptr* H = TREEBIN_AT(M, X->iIndex);
+ if (X == *H)
+ {
+ if ((*H = R) == 0)
+ CLEAR_TREEMAP(M, X->iIndex);
+ }
+ else if (RTCHECK(OK_ADDRESS(M, XP)))
+ {
+ if (XP->iChild[0] == X)
+ XP->iChild[0] = R;
+ else
+ XP->iChild[1] = R;
+ }
+ else
+ CORRUPTION_ERROR_ACTION(M);
+ if (R != 0)
+ {
+ if (RTCHECK(OK_ADDRESS(M, R)))
+ {
+ tchunkptr C0, C1;
+ R->iParent = XP;
+ if ((C0 = X->iChild[0]) != 0)
+ {
+ if (RTCHECK(OK_ADDRESS(M, C0)))
+ {
+ R->iChild[0] = C0;
+ C0->iParent = R;
+ }
+ else
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ if ((C1 = X->iChild[1]) != 0)
+ {
+ if (RTCHECK(OK_ADDRESS(M, C1)))
+ {
+ R->iChild[1] = C1;
+ C1->iParent = R;
+ }
+ else
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ }
+ else
+ CORRUPTION_ERROR_ACTION(M);
+ }
+ }
+}
+
+/* Unlink a chunk from a smallbin */
+inline void RHybridHeap::UnlinkSmallChunk(mstate M, mchunkptr P,size_t S)
+{
+ mchunkptr F = P->iFd;
+ mchunkptr B = P->iBk;
+ bindex_t I = SMALL_INDEX(S);
+ HEAP_ASSERT(P != B);
+ HEAP_ASSERT(P != F);
+ HEAP_ASSERT(CHUNKSIZE(P) == SMALL_INDEX2SIZE(I));
+ if (F == B)
+ CLEAR_SMALLMAP(M, I);
+ else if (RTCHECK((F == SMALLBIN_AT(M,I) || OK_ADDRESS(M, F)) &&
+ (B == SMALLBIN_AT(M,I) || OK_ADDRESS(M, B))))
+ {
+ F->iBk = B;
+ B->iFd = F;
+ }
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ }
+}
+
+inline void RHybridHeap::UnlinkChunk(mstate M, mchunkptr P, size_t S)
+{
+ if (IS_SMALL(S))
+ UnlinkSmallChunk(M, P, S);
+ else
+ {
+ tchunkptr TP = (tchunkptr)(P); UnlinkLargeChunk(M, TP);
+ }
+}
+
+// For DL debug functions
+void RHybridHeap::DoComputeTreeIndex(size_t S, bindex_t& I)
+{
+ ComputeTreeIndex(S, I);
+}
+
+inline void RHybridHeap::ComputeTreeIndex(size_t S, bindex_t& I)
+{
+ size_t X = S >> TREEBIN_SHIFT;
+ if (X == 0)
+ I = 0;
+ else if (X > 0xFFFF)
+ I = NTREEBINS-1;
+ else
+ {
+ unsigned int Y = (unsigned int)X;
+ unsigned int N = ((Y - 0x100) >> 16) & 8;
+ unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;
+ N += K;
+ N += K = (((Y <<= K) - 0x4000) >> 16) & 2;
+ K = 14 - N + ((Y <<= K) >> 15);
+ I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));
+ }
+}
+
+/* ------------------------- Operations on trees ------------------------- */
+
+/* Insert chunk into tree */
+inline void RHybridHeap::InsertLargeChunk(mstate M,tchunkptr X,size_t S)
+{
+ tbinptr* H;
+ bindex_t I;
+ ComputeTreeIndex(S, I);
+ H = TREEBIN_AT(M, I);
+ X->iIndex = I;
+ X->iChild[0] = X->iChild[1] = 0;
+ if (!TREEMAP_IS_MARKED(M, I))
+ {
+ MARK_TREEMAP(M, I);
+ *H = X;
+ X->iParent = (tchunkptr)H;
+ X->iFd = X->iBk = X;
+ }
+ else
+ {
+ tchunkptr T = *H;
+ size_t K = S << LEFTSHIFT_FOR_TREE_INDEX(I);
+ for (;;)
+ {
+ if (CHUNKSIZE(T) != S) {
+ tchunkptr* C = &(T->iChild[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);
+ K <<= 1;
+ if (*C != 0)
+ T = *C;
+ else if (RTCHECK(OK_ADDRESS(M, C)))
+ {
+ *C = X;
+ X->iParent = T;
+ X->iFd = X->iBk = X;
+ break;
+ }
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ break;
+ }
+ }
+ else
+ {
+ tchunkptr F = T->iFd;
+ if (RTCHECK(OK_ADDRESS(M, T) && OK_ADDRESS(M, F)))
+ {
+ T->iFd = F->iBk = X;
+ X->iFd = F;
+ X->iBk = T;
+ X->iParent = 0;
+ break;
+ }
+ else
+ {
+ CORRUPTION_ERROR_ACTION(M);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+Unlink steps:
+
+1. If x is a chained node, unlink it from its same-sized iFd/iBk links
+and choose its iBk node as its replacement.
+2. If x was the last node of its size, but not a leaf node, it must
+be replaced with a leaf node (not merely one with an open left or
+right), to make sure that lefts and rights of descendents
+correspond properly to bit masks. We use the rightmost descendent
+of x. We could use any other leaf, but this is easy to locate and
+tends to counteract removal of leftmosts elsewhere, and so keeps
+paths shorter than minimally guaranteed. This doesn't loop much
+because on average a node in a tree is near the bottom.
+3. If x is the base of a chain (i.e., has iParent links) relink
+x's iParent and children to x's replacement (or null if none).
+*/
+
+/* Replace iDv node, binning the old one */
+/* Used only when iDvSize known to be small */
+inline void RHybridHeap::ReplaceDv(mstate M, mchunkptr P, size_t S)
+{
+ size_t DVS = M->iDvSize;
+ if (DVS != 0)
+ {
+ mchunkptr DV = M->iDv;
+ HEAP_ASSERT(IS_SMALL(DVS));
+ InsertSmallChunk(M, DV, DVS);
+ }
+ M->iDvSize = S;
+ M->iDv = P;
+}
+
+
+inline void RHybridHeap::ComputeBit2idx(binmap_t X,bindex_t& I)
+{
+ unsigned int Y = X - 1;
+ unsigned int K = Y >> (16-4) & 16;
+ unsigned int N = K; Y >>= K;
+ N += K = Y >> (8-3) & 8; Y >>= K;
+ N += K = Y >> (4-2) & 4; Y >>= K;
+ N += K = Y >> (2-1) & 2; Y >>= K;
+ N += K = Y >> (1-0) & 1; Y >>= K;
+ I = (bindex_t)(N + Y);
+}
+
+
+
+int RHybridHeap::SysTrim(mstate m, size_t pad)
+{
+ size_t extra = 0;
+
+ if ( IS_INITIALIZED(m) )
+ {
+ pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
+
+ if (m->iTopSize > pad)
+ {
+ extra = Floor(m->iTopSize - pad, iPageSize);
+ if ( (m->iSeg.iSize - extra) < (iMinLength - sizeof(*this)) )
+ {
+ if ( m->iSeg.iSize > (iMinLength - sizeof(*this)) )
+ extra = Floor(m->iSeg.iSize - (iMinLength - sizeof(*this)), iPageSize); /* do not shrink heap below min length */
+ else extra = 0;
+ }
+
+ if ( extra )
+ {
+ Unmap(m->iSeg.iBase + m->iSeg.iSize - extra, extra);
+
+ m->iSeg.iSize -= extra;
+ InitTop(m, m->iTop, m->iTopSize - extra);
+ CHECK_TOP_CHUNK(m, m->iTop);
+ }
+ }
+
+ }
+
+ return extra;
+}
+
+/* Get memory from system using MORECORE */
+
+void* RHybridHeap::SysAlloc(mstate m, size_t nb)
+{
+ HEAP_ASSERT(m->iTop);
+ /* Subtract out existing available iTop space from MORECORE request. */
+// size_t asize = _ALIGN_UP(nb - m->iTopSize + TOP_FOOT_SIZE + SIZE_T_ONE, iGrowBy);
+ TInt asize = _ALIGN_UP(nb - m->iTopSize + SYS_ALLOC_PADDING, iGrowBy); // From DLA version 2.8.4
+
+ char* br = (char*)Map(m->iSeg.iBase+m->iSeg.iSize, asize);
+ if (!br)
+ return 0;
+ HEAP_ASSERT(br == (char*)m->iSeg.iBase+m->iSeg.iSize);
+
+ /* Merge with an existing segment */
+ m->iSeg.iSize += asize;
+ InitTop(m, m->iTop, m->iTopSize + asize);
+
+ if (nb < m->iTopSize)
+ { /* Allocate from new or extended iTop space */
+ size_t rsize = m->iTopSize -= nb;
+ mchunkptr p = m->iTop;
+ mchunkptr r = m->iTop = CHUNK_PLUS_OFFSET(p, nb);
+ r->iHead = rsize | PINUSE_BIT;
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, p, nb);
+ CHECK_TOP_CHUNK(m, m->iTop);
+ CHECK_MALLOCED_CHUNK(m, CHUNK2MEM(p), nb);
+ return CHUNK2MEM(p);
+ }
+
+ return 0;
+}
+
+
+void RHybridHeap::InitDlMalloc(size_t capacity, int /*locked*/)
+{
+ memset(GM,0,sizeof(malloc_state));
+ // The maximum amount that can be allocated can be calculated as:-
+ // 2^sizeof(size_t) - sizeof(malloc_state) - TOP_FOOT_SIZE - page Size(all accordingly padded)
+ // If the capacity exceeds this, no allocation will be done.
+ GM->iSeg.iBase = iBase;
+ GM->iSeg.iSize = capacity;
+ InitBins(GM);
+ InitTop(GM, (mchunkptr)iBase, capacity - TOP_FOOT_SIZE);
+}
+
+void* RHybridHeap::DlMalloc(size_t bytes)
+{
+ /*
+ Basic algorithm:
+ If a small request (< 256 bytes minus per-chunk overhead):
+ 1. If one exists, use a remainderless chunk in associated smallbin.
+ (Remainderless means that there are too few excess bytes to
+ represent as a chunk.)
+ 2. If it is big enough, use the iDv chunk, which is normally the
+ chunk adjacent to the one used for the most recent small request.
+ 3. If one exists, split the smallest available chunk in a bin,
+ saving remainder in iDv.
+ 4. If it is big enough, use the iTop chunk.
+ 5. If available, get memory from system and use it
+ Otherwise, for a large request:
+ 1. Find the smallest available binned chunk that fits, and use it
+ if it is better fitting than iDv chunk, splitting if necessary.
+ 2. If better fitting than any binned chunk, use the iDv chunk.
+ 3. If it is big enough, use the iTop chunk.
+ 4. If request size >= mmap threshold, try to directly mmap this chunk.
+ 5. If available, get memory from system and use it
+*/
+ void* mem;
+ size_t nb;
+ if (bytes <= MAX_SMALL_REQUEST)
+ {
+ bindex_t idx;
+ binmap_t smallbits;
+ nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : PAD_REQUEST(bytes);
+ idx = SMALL_INDEX(nb);
+ smallbits = GM->iSmallMap >> idx;
+
+ if ((smallbits & 0x3U) != 0)
+ { /* Remainderless fit to a smallbin. */
+ mchunkptr b, p;
+ idx += ~smallbits & 1; /* Uses next bin if idx empty */
+ b = SMALLBIN_AT(GM, idx);
+ p = b->iFd;
+ HEAP_ASSERT(CHUNKSIZE(p) == SMALL_INDEX2SIZE(idx));
+ UnlinkFirstSmallChunk(GM, b, p, idx);
+ SET_INUSE_AND_PINUSE(GM, p, SMALL_INDEX2SIZE(idx));
+ mem = CHUNK2MEM(p);
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+
+ else if (nb > GM->iDvSize)
+ {
+ if (smallbits != 0)
+ { /* Use chunk in next nonempty smallbin */
+ mchunkptr b, p, r;
+ size_t rsize;
+ bindex_t i;
+ binmap_t leftbits = (smallbits << idx) & LEFT_BITS(IDX2BIT(idx));
+ binmap_t leastbit = LEAST_BIT(leftbits);
+ ComputeBit2idx(leastbit, i);
+ b = SMALLBIN_AT(GM, i);
+ p = b->iFd;
+ HEAP_ASSERT(CHUNKSIZE(p) == SMALL_INDEX2SIZE(i));
+ UnlinkFirstSmallChunk(GM, b, p, i);
+ rsize = SMALL_INDEX2SIZE(i) - nb;
+ /* Fit here cannot be remainderless if 4byte sizes */
+ if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
+ SET_INUSE_AND_PINUSE(GM, p, SMALL_INDEX2SIZE(i));
+ else
+ {
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
+ r = CHUNK_PLUS_OFFSET(p, nb);
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
+ ReplaceDv(GM, r, rsize);
+ }
+ mem = CHUNK2MEM(p);
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+
+ else if (GM->iTreeMap != 0 && (mem = TmallocSmall(GM, nb)) != 0)
+ {
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+ }
+ }
+ else if (bytes >= MAX_REQUEST)
+ nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
+ else
+ {
+ nb = PAD_REQUEST(bytes);
+ if (GM->iTreeMap != 0 && (mem = TmallocLarge(GM, nb)) != 0)
+ {
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+ }
+
+ if (nb <= GM->iDvSize)
+ {
+ size_t rsize = GM->iDvSize - nb;
+ mchunkptr p = GM->iDv;
+ if (rsize >= MIN_CHUNK_SIZE)
+ { /* split iDv */
+ mchunkptr r = GM->iDv = CHUNK_PLUS_OFFSET(p, nb);
+ GM->iDvSize = rsize;
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
+ }
+ else
+ { /* exhaust iDv */
+ size_t dvs = GM->iDvSize;
+ GM->iDvSize = 0;
+ GM->iDv = 0;
+ SET_INUSE_AND_PINUSE(GM, p, dvs);
+ }
+ mem = CHUNK2MEM(p);
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+
+ else if (nb < GM->iTopSize)
+ { /* Split iTop */
+ size_t rsize = GM->iTopSize -= nb;
+ mchunkptr p = GM->iTop;
+ mchunkptr r = GM->iTop = CHUNK_PLUS_OFFSET(p, nb);
+ r->iHead = rsize | PINUSE_BIT;
+ SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
+ mem = CHUNK2MEM(p);
+ CHECK_TOP_CHUNK(GM, GM->iTop);
+ CHECK_MALLOCED_CHUNK(GM, mem, nb);
+ return mem;
+ }
+
+ return SysAlloc(GM, nb);
+}
+
+
+void RHybridHeap::DlFree(void* mem)
+{
+ /*
+ Consolidate freed chunks with preceding or succeeding bordering
+ free chunks, if they exist, and then place in a bin. Intermixed
+ with special cases for iTop, iDv, mmapped chunks, and usage errors.
+*/
+ mchunkptr p = MEM2CHUNK(mem);
+ CHECK_INUSE_CHUNK(GM, p);
+ if (RTCHECK(OK_ADDRESS(GM, p) && OK_CINUSE(p)))
+ {
+ size_t psize = CHUNKSIZE(p);
+ mchunkptr next = CHUNK_PLUS_OFFSET(p, psize);
+ if (!PINUSE(p))
+ {
+ size_t prevsize = p->iPrevFoot;
+ mchunkptr prev = CHUNK_MINUS_OFFSET(p, prevsize);
+ psize += prevsize;
+ p = prev;
+ if (RTCHECK(OK_ADDRESS(GM, prev)))
+ { /* consolidate backward */
+ if (p != GM->iDv)
+ {
+ UnlinkChunk(GM, p, prevsize);
+ }
+ else if ((next->iHead & INUSE_BITS) == INUSE_BITS)
+ {
+ GM->iDvSize = psize;
+ SET_FREE_WITH_PINUSE(p, psize, next);
+ return;
+ }
+ }
+ else
+ {
+ USAGE_ERROR_ACTION(GM, p);
+ return;
+ }
+ }
+
+ if (RTCHECK(OK_NEXT(p, next) && OK_PINUSE(next)))
+ {
+ if (!CINUSE(next))
+ { /* consolidate forward */
+ if (next == GM->iTop)
+ {
+ size_t tsize = GM->iTopSize += psize;
+ GM->iTop = p;
+ p->iHead = tsize | PINUSE_BIT;
+ if (p == GM->iDv)
+ {
+ GM->iDv = 0;
+ GM->iDvSize = 0;
+ }
+ if ( !IS_FIXED_HEAP && SHOULD_TRIM(GM, tsize) )
+ SysTrim(GM, 0);
+ return;
+ }
+ else if (next == GM->iDv)
+ {
+ size_t dsize = GM->iDvSize += psize;
+ GM->iDv = p;
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, dsize);
+ return;
+ }
+ else
+ {
+ size_t nsize = CHUNKSIZE(next);
+ psize += nsize;
+ UnlinkChunk(GM, next, nsize);
+ SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, psize);
+ if (p == GM->iDv)
+ {
+ GM->iDvSize = psize;
+ return;
+ }
+ }
+ }
+ else
+ SET_FREE_WITH_PINUSE(p, psize, next);
+ InsertChunk(GM, p, psize);
+ CHECK_FREE_CHUNK(GM, p);
+ return;
+ }
+ }
+}
+
+
+void* RHybridHeap::DlRealloc(void* oldmem, size_t bytes, TInt mode)
+{
+ mchunkptr oldp = MEM2CHUNK(oldmem);
+ size_t oldsize = CHUNKSIZE(oldp);
+ mchunkptr next = CHUNK_PLUS_OFFSET(oldp, oldsize);
+ mchunkptr newp = 0;
+ void* extra = 0;
+
+ /* Try to either shrink or extend into iTop. Else malloc-copy-free */
+
+ if (RTCHECK(OK_ADDRESS(GM, oldp) && OK_CINUSE(oldp) &&
+ OK_NEXT(oldp, next) && OK_PINUSE(next)))
+ {
+ size_t nb = REQUEST2SIZE(bytes);
+ if (oldsize >= nb) { /* already big enough */
+ size_t rsize = oldsize - nb;
+ newp = oldp;
+ if (rsize >= MIN_CHUNK_SIZE)
+ {
+ mchunkptr remainder = CHUNK_PLUS_OFFSET(newp, nb);
+ SET_INUSE(GM, newp, nb);
+// SET_INUSE(GM, remainder, rsize);
+ SET_INUSE_AND_PINUSE(GM, remainder, rsize); // corrected in original DLA version V2.8.4
+ extra = CHUNK2MEM(remainder);
+ }
+ }
+ else if (next == GM->iTop && oldsize + GM->iTopSize > nb)
+ {
+ /* Expand into iTop */
+ size_t newsize = oldsize + GM->iTopSize;
+ size_t newtopsize = newsize - nb;
+ mchunkptr newtop = CHUNK_PLUS_OFFSET(oldp, nb);
+ SET_INUSE(GM, oldp, nb);
+ newtop->iHead = newtopsize |PINUSE_BIT;
+ GM->iTop = newtop;
+ GM->iTopSize = newtopsize;
+ newp = oldp;
+ }
+ }
+ else
+ {
+ USAGE_ERROR_ACTION(GM, oldmem);
+ }
+
+ if (newp != 0)
+ {
+ if (extra != 0)
+ {
+ DlFree(extra);
+ }
+ CHECK_INUSE_CHUNK(GM, newp);
+ return CHUNK2MEM(newp);
+ }
+ else
+ {
+ if ( mode & ENeverMove )
+ return 0; // cannot move
+ void* newmem = DlMalloc(bytes);
+ if (newmem != 0)
+ {
+ size_t oc = oldsize - OVERHEAD_FOR(oldp);
+ memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
+ DlFree(oldmem);
+ }
+ return newmem;
+ }
+ // return 0;
+}
+
+size_t RHybridHeap::DlInfo(struct HeapInfo* i, SWalkInfo* wi) const
+{
+ TInt max = ((GM->iTopSize-1) & ~CHUNK_ALIGN_MASK) - CHUNK_OVERHEAD;
+ if ( max < 0 )
+ max = 0;
+ else ++i->iFreeN; // iTop always free
+ i->iFreeBytes += max;
+
+ Walk(wi, GM->iTop, max, EGoodFreeCell, EDougLeaAllocator); // Introduce DL iTop buffer to the walk function
+
+ for (mchunkptr q = ALIGN_AS_CHUNK(GM->iSeg.iBase); q != GM->iTop; q = NEXT_CHUNK(q))
+ {
+ TInt sz = CHUNKSIZE(q);
+ if (!CINUSE(q))
+ {
+ if ( sz > max )
+ max = sz;
+ i->iFreeBytes += sz;
+ ++i->iFreeN;
+ Walk(wi, CHUNK2MEM(q), sz, EGoodFreeCell, EDougLeaAllocator); // Introduce DL free buffer to the walk function
+ }
+ else
+ {
+ i->iAllocBytes += sz - CHUNK_OVERHEAD;
+ ++i->iAllocN;
+ Walk(wi, CHUNK2MEM(q), (sz- CHUNK_OVERHEAD), EGoodAllocatedCell, EDougLeaAllocator); // Introduce DL allocated buffer to the walk function
+ }
+ }
+ return max; // return largest available chunk size
+}
+
+//
+// get statistics about the state of the allocator
+//
+TInt RHybridHeap::GetInfo(struct HeapInfo* i, SWalkInfo* wi) const
+{
+ memset(i,0,sizeof(HeapInfo));
+ i->iFootprint = iChunkSize;
+ i->iMaxSize = iMaxLength;
+#ifndef __KERNEL_MODE__
+ PagedInfo(i, wi);
+ SlabInfo(i, wi);
+#endif
+ return DlInfo(i,wi);
+}
+
+//
+// Methods to commit/decommit memory pages from chunk
+//
+
+
+void* RHybridHeap::Map(void* p, TInt sz)
+//
+// allocate pages in the chunk
+// if p is NULL, Find an allocate the required number of pages (which must lie in the lower half)
+// otherwise commit the pages specified
+//
+{
+ HEAP_ASSERT(sz > 0);
+
+ if ( iChunkSize + sz > iMaxLength)
+ return 0;
+
+#ifdef __KERNEL_MODE__
+
+ TInt r = ((DChunk*)iChunkHandle)->Adjust(iChunkSize + iOffset + sz);
+ if (r < 0)
+ return 0;
+
+ iChunkSize += sz;
+
+#else
+
+ RChunk chunk;
+ chunk.SetHandle(iChunkHandle);
+ if ( p )
+ {
+ TInt r;
+ if ( iUseAdjust )
+ r = chunk.Adjust(iChunkSize + sz);
+ else
+ {
+ HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
+ HEAP_ASSERT(p == Floor(p, iPageSize));
+ r = chunk.Commit(iOffset + PtrDiff(p, this),sz);
+ }
+ if (r < 0)
+ return 0;
+ }
+ else
+ {
+ TInt r = chunk.Allocate(sz);
+ if (r < 0)
+ return 0;
+ if (r > iOffset)
+ {
+ // can't allow page allocations in DL zone
+ chunk.Decommit(r, sz);
+ return 0;
+ }
+ p = Offset(this, r - iOffset);
+ }
+ iChunkSize += sz;
+
+ if (iChunkSize >= iSlabInitThreshold)
+ { // set up slab system now that heap is large enough
+ SlabConfig(iSlabConfigBits);
+ iSlabInitThreshold = KMaxTInt32;
+ }
+
+#endif // __KERNEL_MODE__
+
+#ifdef ENABLE_BTRACE
+ if(iChunkSize > iHighWaterMark)
+ {
+ iHighWaterMark = Ceiling(iChunkSize,16*iPageSize);
+ TUint32 traceData[6];
+ traceData[0] = iChunkHandle;
+ traceData[1] = iMinLength;
+ traceData[2] = iMaxLength;
+ traceData[3] = sz;
+ traceData[4] = iChunkSize;
+ traceData[5] = iHighWaterMark;
+ BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 33, traceData, sizeof(traceData));
+ }
+#endif
+
+ return p;
+}
+
+void RHybridHeap::Unmap(void* p, TInt sz)
+{
+ HEAP_ASSERT(sz > 0);
+
+#ifdef __KERNEL_MODE__
+
+ (void)p;
+ HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
+#if defined(_DEBUG)
+ TInt r =
+#endif
+ ((DChunk*)iChunkHandle)->Adjust(iChunkSize + iOffset - sz);
+ HEAP_ASSERT(r >= 0);
+
+#else
+
+ RChunk chunk;
+ chunk.SetHandle(iChunkHandle);
+ if ( iUseAdjust )
+ {
+ HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
+#if defined(_DEBUG)
+ TInt r =
+#endif
+ chunk.Adjust(iChunkSize - sz);
+ HEAP_ASSERT(r >= 0);
+ }
+ else
+ {
+ HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
+ HEAP_ASSERT(p == Floor(p, iPageSize));
+#if defined(_DEBUG)
+ TInt r =
+#endif
+ chunk.Decommit(PtrDiff(p, Offset(this,-iOffset)), sz);
+ HEAP_ASSERT(r >= 0);
+ }
+#endif // __KERNEL_MODE__
+
+ iChunkSize -= sz;
+}
+
+
+#ifndef __KERNEL_MODE__
+//
+// Slab allocator code
+//
+
+//inline slab* slab::SlabFor(void* p)
+slab* slab::SlabFor( const void* p)
+{
+ return (slab*)(Floor(p, SLABSIZE));
+}
+
+//
+// Remove slab s from its tree/heap (not necessarily the root), preserving the address order
+// invariant of the heap
+//
+void RHybridHeap::TreeRemove(slab* s)
+{
+ slab** r = s->iParent;
+ slab* c1 = s->iChild1;
+ slab* c2 = s->iChild2;
+ for (;;)
+ {
+ if (!c2)
+ {
+ *r = c1;
+ if (c1)
+ c1->iParent = r;
+ return;
+ }
+ if (!c1)
+ {
+ *r = c2;
+ c2->iParent = r;
+ return;
+ }
+ if (c1 > c2)
+ {
+ slab* c3 = c1;
+ c1 = c2;
+ c2 = c3;
+ }
+ slab* newc2 = c1->iChild2;
+ *r = c1;
+ c1->iParent = r;
+ c1->iChild2 = c2;
+ c2->iParent = &c1->iChild2;
+ s = c1;
+ c1 = s->iChild1;
+ c2 = newc2;
+ r = &s->iChild1;
+ }
+}
+//
+// Insert slab s into the tree/heap rooted at r, preserving the address ordering
+// invariant of the heap
+//
+void RHybridHeap::TreeInsert(slab* s,slab** r)
+{
+ slab* n = *r;
+ for (;;)
+ {
+ if (!n)
+ { // tree empty
+ *r = s;
+ s->iParent = r;
+ s->iChild1 = s->iChild2 = 0;
+ break;
+ }
+ if (s < n)
+ { // insert between iParent and n
+ *r = s;
+ s->iParent = r;
+ s->iChild1 = n;
+ s->iChild2 = 0;
+ n->iParent = &s->iChild1;
+ break;
+ }
+ slab* c1 = n->iChild1;
+ slab* c2 = n->iChild2;
+ if ((c1 - 1) > (c2 - 1))
+ {
+ r = &n->iChild1;
+ n = c1;
+ }
+ else
+ {
+ r = &n->iChild2;
+ n = c2;
+ }
+ }
+}
+
+void* RHybridHeap::AllocNewSlab(slabset& allocator)
+//
+// Acquire and initialise a new slab, returning a cell from the slab
+// The strategy is:
+// 1. Use the lowest address free slab, if available. This is done by using the lowest slab
+// in the page at the root of the iPartialPage heap (which is address ordered). If the
+// is now fully used, remove it from the iPartialPage heap.
+// 2. Allocate a new page for iSlabs if no empty iSlabs are available
+//
+{
+ page* p = page::PageFor(iPartialPage);
+ if (!p)
+ return AllocNewPage(allocator);
+
+ unsigned h = p->iSlabs[0].iHeader;
+ unsigned pagemap = SlabHeaderPagemap(h);
+ HEAP_ASSERT(&p->iSlabs[HIBIT(pagemap)] == iPartialPage);
+
+ unsigned slabix = LOWBIT(pagemap);
+ p->iSlabs[0].iHeader = h &~ (0x100<<slabix);
+ if (!(pagemap &~ (1<<slabix)))
+ {
+ TreeRemove(iPartialPage); // last free slab in page
+ }
+
+ return InitNewSlab(allocator, &p->iSlabs[slabix]);
+}
+
+/**Defination of this functionis not there in proto code***/
+#if 0
+void RHybridHeap::partial_insert(slab* s)
+{
+ // slab has had first cell freed and needs to be linked back into iPartial tree
+ slabset& ss = iSlabAlloc[iSizeMap[s->clz]];
+
+ HEAP_ASSERT(s->used == slabfull);
+ s->used = ss.fulluse - s->clz; // full-1 loading
+ TreeInsert(s,&ss.iPartial);
+ CHECKTREE(&ss.iPartial);
+}
+/**Defination of this functionis not there in proto code***/
+#endif
+
+void* RHybridHeap::AllocNewPage(slabset& allocator)
+//
+// Acquire and initialise a new page, returning a cell from a new slab
+// The iPartialPage tree is empty (otherwise we'd have used a slab from there)
+// The iPartialPage link is put in the highest addressed slab in the page, and the
+// lowest addressed slab is used to fulfill the allocation request
+//
+{
+ page* p = iSparePage;
+ if (p)
+ iSparePage = 0;
+ else
+ {
+ p = static_cast<page*>(Map(0, iPageSize));
+ if (!p)
+ return 0;
+ }
+ HEAP_ASSERT(p == Floor(p, iPageSize));
+ // Store page allocated for slab into paged_bitmap (for RHybridHeap::Reset())
+ if (!PagedSetSize(p, iPageSize))
+ {
+ Unmap(p, iPageSize);
+ return 0;
+ }
+ p->iSlabs[0].iHeader = ((1<<3) + (1<<2) + (1<<1))<<8; // set pagemap
+ p->iSlabs[3].iParent = &iPartialPage;
+ p->iSlabs[3].iChild1 = p->iSlabs[3].iChild2 = 0;
+ iPartialPage = &p->iSlabs[3];
+ return InitNewSlab(allocator,&p->iSlabs[0]);
+}
+
+void RHybridHeap::FreePage(page* p)
+//
+// Release an unused page to the OS
+// A single page is cached for reuse to reduce thrashing
+// the OS allocator.
+//
+{
+ HEAP_ASSERT(Ceiling(p, iPageSize) == p);
+ if (!iSparePage)
+ {
+ iSparePage = p;
+ return;
+ }
+
+ // unmapped slab page must be cleared from paged_bitmap, too
+ PagedZapSize(p, iPageSize); // clear page map
+
+ Unmap(p, iPageSize);
+}
+
+void RHybridHeap::FreeSlab(slab* s)
+//
+// Release an empty slab to the slab manager
+// The strategy is:
+// 1. The page containing the slab is checked to see the state of the other iSlabs in the page by
+// inspecting the pagemap field in the iHeader of the first slab in the page.
+// 2. The pagemap is updated to indicate the new unused slab
+// 3. If this is the only unused slab in the page then the slab iHeader is used to add the page to
+// the iPartialPage tree/heap
+// 4. If all the iSlabs in the page are now unused the page is release back to the OS
+// 5. If this slab has a higher address than the one currently used to track this page in
+// the iPartialPage heap, the linkage is moved to the new unused slab
+//
+{
+ TreeRemove(s);
+ CHECKTREE(s->iParent);
+ HEAP_ASSERT(SlabHeaderUsedm4(s->iHeader) == SlabHeaderSize(s->iHeader)-4);
+
+ page* p = page::PageFor(s);
+ unsigned h = p->iSlabs[0].iHeader;
+ int slabix = s - &p->iSlabs[0];
+ unsigned pagemap = SlabHeaderPagemap(h);
+ p->iSlabs[0].iHeader = h | (0x100<<slabix);
+ if (pagemap == 0)
+ { // page was full before, use this slab as link in empty heap
+ TreeInsert(s, &iPartialPage);
+ }
+ else
+ { // Find the current empty-link slab
+ slab* sl = &p->iSlabs[HIBIT(pagemap)];
+ pagemap ^= (1<<slabix);
+ if (pagemap == 0xf)
+ { // page is now empty so recycle page to os
+ TreeRemove(sl);
+ FreePage(p);
+ return;
+ }
+ // ensure the free list link is in highest address slab in page
+ if (s > sl)
+ { // replace current link with new one. Address-order tree so position stays the same
+ slab** r = sl->iParent;
+ slab* c1 = sl->iChild1;
+ slab* c2 = sl->iChild2;
+ s->iParent = r;
+ s->iChild1 = c1;
+ s->iChild2 = c2;
+ *r = s;
+ if (c1)
+ c1->iParent = &s->iChild1;
+ if (c2)
+ c2->iParent = &s->iChild2;
+ }
+ CHECK(if (s < sl) s=sl);
+ }
+ HEAP_ASSERT(SlabHeaderPagemap(p->iSlabs[0].iHeader) != 0);
+ HEAP_ASSERT(HIBIT(SlabHeaderPagemap(p->iSlabs[0].iHeader)) == unsigned(s - &p->iSlabs[0]));
+}
+
+
+void RHybridHeap::SlabInit()
+{
+ iSlabThreshold=0;
+ iPartialPage = 0;
+ iFullSlab = 0;
+ iSparePage = 0;
+ memset(&iSizeMap[0],0xff,sizeof(iSizeMap));
+ memset(&iSlabAlloc[0],0,sizeof(iSlabAlloc));
+}
+
+void RHybridHeap::SlabConfig(unsigned slabbitmap)
+{
+ HEAP_ASSERT((slabbitmap & ~EOkBits) == 0);
+ HEAP_ASSERT(MAXSLABSIZE <= 60);
+
+ unsigned int ix = 0xff;
+ unsigned int bit = 1<<((MAXSLABSIZE>>2)-1);
+ for (int sz = MAXSLABSIZE; sz >= 0; sz -= 4, bit >>= 1)
+ {
+ if (slabbitmap & bit)
+ {
+ if (ix == 0xff)
+ iSlabThreshold=sz+1;
+ ix = (sz>>2)-1;
+ }
+ iSizeMap[sz>>2] = (TUint8) ix;
+ }
+}
+
+
+void* RHybridHeap::SlabAllocate(slabset& ss)
+//
+// Allocate a cell from the given slabset
+// Strategy:
+// 1. Take the partially full slab at the iTop of the heap (lowest address).
+// 2. If there is no such slab, allocate from a new slab
+// 3. If the slab has a non-empty freelist, pop the cell from the front of the list and update the slab
+// 4. Otherwise, if the slab is not full, return the cell at the end of the currently used region of
+// the slab, updating the slab
+// 5. Otherwise, release the slab from the iPartial tree/heap, marking it as 'floating' and go back to
+// step 1
+//
+{
+ for (;;)
+ {
+ slab *s = ss.iPartial;
+ if (!s)
+ break;
+ unsigned h = s->iHeader;
+ unsigned free = h & 0xff; // extract free cell positioning
+ if (free)
+ {
+ HEAP_ASSERT(((free<<2)-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
+ void* p = Offset(s,free<<2);
+ free = *(unsigned char*)p; // get next pos in free list
+ h += (h&0x3C000)<<6; // update usedm4
+ h &= ~0xff;
+ h |= free; // update freelist
+ s->iHeader = h;
+ HEAP_ASSERT(SlabHeaderFree(h) == 0 || ((SlabHeaderFree(h)<<2)-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
+ HEAP_ASSERT(SlabHeaderUsedm4(h) <= 0x3F8u);
+ HEAP_ASSERT((SlabHeaderUsedm4(h)+4)%SlabHeaderSize(h) == 0);
+ return p;
+ }
+ unsigned h2 = h + ((h&0x3C000)<<6);
+// if (h2 < 0xfc00000)
+ if (h2 < MAXUSEDM4BITS)
+ {
+ HEAP_ASSERT((SlabHeaderUsedm4(h2)+4)%SlabHeaderSize(h2) == 0);
+ s->iHeader = h2;
+ return Offset(s,(h>>18) + sizeof(unsigned) + sizeof(slabhdr));
+ }
+ h |= FLOATING_BIT; // mark the slab as full-floating
+ s->iHeader = h;
+ TreeRemove(s);
+ slab* c = iFullSlab; // add to full list
+ iFullSlab = s;
+ s->iParent = &iFullSlab;
+ s->iChild1 = c;
+ s->iChild2 = 0;
+ if (c)
+ c->iParent = &s->iChild1;
+
+ CHECKTREE(&ss.iPartial);
+ // go back and try the next slab...
+ }
+ // no iPartial iSlabs found, so allocate from a new slab
+ return AllocNewSlab(ss);
+}
+
+void RHybridHeap::SlabFree(void* p)
+//
+// Free a cell from the slab allocator
+// Strategy:
+// 1. Find the containing slab (round down to nearest 1KB boundary)
+// 2. Push the cell into the slab's freelist, and update the slab usage count
+// 3. If this is the last allocated cell, free the slab to the main slab manager
+// 4. If the slab was full-floating then insert the slab in it's respective iPartial tree
+//
+{
+ HEAP_ASSERT(LowBits(p,3)==0);
+ slab* s = slab::SlabFor(p);
+ CHECKSLAB(s,ESlabAllocator,p);
+ CHECKSLABBFR(s,p);
+
+ unsigned pos = LowBits(p, SLABSIZE);
+ unsigned h = s->iHeader;
+ HEAP_ASSERT(SlabHeaderUsedm4(h) != 0x3fC); // slab is empty already
+ HEAP_ASSERT((pos-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
+ *(unsigned char*)p = (unsigned char)h;
+ h &= ~0xFF;
+ h |= (pos>>2);
+ unsigned size = h & 0x3C000;
+ if (int(h) >= 0)
+ {
+ h -= size<<6;
+ if (int(h)>=0)
+ {
+ s->iHeader = h;
+ return;
+ }
+ FreeSlab(s);
+ return;
+ }
+ h -= size<<6;
+ h &= ~FLOATING_BIT;
+ s->iHeader = h;
+ slab** full = s->iParent; // remove from full list
+ slab* c = s->iChild1;
+ *full = c;
+ if (c)
+ c->iParent = full;
+
+ slabset& ss = iSlabAlloc[iSizeMap[size>>14]];
+ TreeInsert(s,&ss.iPartial);
+ CHECKTREE(&ss.iPartial);
+}
+
+void* RHybridHeap::InitNewSlab(slabset& allocator, slab* s)
+//
+// initialise an empty slab for this allocator and return the fist cell
+// pre-condition: the slabset has no iPartial iSlabs for allocation
+//
+{
+ HEAP_ASSERT(allocator.iPartial==0);
+ TInt size = 4 + ((&allocator-&iSlabAlloc[0])<<2); // infer size from slab allocator address
+ unsigned h = s->iHeader & 0xF00; // preserve pagemap only
+ h |= (size<<12); // set size
+ h |= (size-4)<<18; // set usedminus4 to one object minus 4
+ s->iHeader = h;
+ allocator.iPartial = s;
+ s->iParent = &allocator.iPartial;
+ s->iChild1 = s->iChild2 = 0;
+ return Offset(s,sizeof(slabhdr));
+}
+
+const unsigned char slab_bitcount[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
+
+const unsigned char slab_ext_frag[16] =
+{
+ 0,
+ 16 + (1008 % 4),
+ 16 + (1008 % 8),
+ 16 + (1008 % 12),
+ 16 + (1008 % 16),
+ 16 + (1008 % 20),
+ 16 + (1008 % 24),
+ 16 + (1008 % 28),
+ 16 + (1008 % 32),
+ 16 + (1008 % 36),
+ 16 + (1008 % 40),
+ 16 + (1008 % 44),
+ 16 + (1008 % 48),
+ 16 + (1008 % 52),
+ 16 + (1008 % 56),
+ 16 + (1008 % 60)
+};
+
+void RHybridHeap::TreeWalk(slab* const* root, void (*f)(slab*, struct HeapInfo*, SWalkInfo*), struct HeapInfo* i, SWalkInfo* wi)
+{
+ // iterative walk around the tree at root
+
+ slab* s = *root;
+ if (!s)
+ return;
+
+ for (;;)
+ {
+ slab* c;
+ while ((c = s->iChild1) != 0)
+ s = c; // walk down left side to end
+ for (;;)
+ {
+ f(s, i, wi);
+ c = s->iChild2;
+ if (c)
+ { // one step down right side, now try and walk down left
+ s = c;
+ break;
+ }
+ for (;;)
+ { // loop to walk up right side
+ slab** pp = s->iParent;
+ if (pp == root)
+ return;
+ s = slab::SlabFor(pp);
+ if (pp == &s->iChild1)
+ break;
+ }
+ }
+ }
+}
+
+void RHybridHeap::SlabEmptyInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
+{
+ Walk(wi, s, SLABSIZE, EGoodFreeCell, EEmptySlab); // Introduce an empty slab to the walk function
+ int nslab = slab_bitcount[SlabHeaderPagemap(page::PageFor(s)->iSlabs[0].iHeader)];
+ i->iFreeN += nslab;
+ i->iFreeBytes += nslab << SLABSHIFT;
+}
+
+void RHybridHeap::SlabPartialInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
+{
+ Walk(wi, s, SLABSIZE, EGoodAllocatedCell, EPartialFullSlab); // Introduce a full slab to the walk function
+ unsigned h = s->iHeader;
+ unsigned used = SlabHeaderUsedm4(h)+4;
+ unsigned size = SlabHeaderSize(h);
+ unsigned free = 1024 - slab_ext_frag[size>>2] - used;
+ i->iFreeN += (free/size);
+ i->iFreeBytes += free;
+ i->iAllocN += (used/size);
+ i->iAllocBytes += used;
+}
+
+void RHybridHeap::SlabFullInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
+{
+ Walk(wi, s, SLABSIZE, EGoodAllocatedCell, EFullSlab); // Introduce a full slab to the walk function
+ unsigned h = s->iHeader;
+ unsigned used = SlabHeaderUsedm4(h)+4;
+ unsigned size = SlabHeaderSize(h);
+ HEAP_ASSERT(1024 - slab_ext_frag[size>>2] - used == 0);
+ i->iAllocN += (used/size);
+ i->iAllocBytes += used;
+}
+
+void RHybridHeap::SlabInfo(struct HeapInfo* i, SWalkInfo* wi) const
+{
+ if (iSparePage)
+ {
+ i->iFreeBytes += iPageSize;
+ i->iFreeN = 4;
+ Walk(wi, iSparePage, iPageSize, EGoodFreeCell, ESlabSpare); // Introduce Slab spare page to the walk function
+ }
+ TreeWalk(&iFullSlab, &SlabFullInfo, i, wi);
+ for (int ix = 0; ix < (MAXSLABSIZE>>2); ++ix)
+ TreeWalk(&iSlabAlloc[ix].iPartial, &SlabPartialInfo, i, wi);
+ TreeWalk(&iPartialPage, &SlabEmptyInfo, i, wi);
+}
+
+
+//
+// Bitmap class implementation for large page allocator
+//
+inline unsigned char* paged_bitmap::Addr() const {return iBase;}
+inline unsigned paged_bitmap::Size() const {return iNbits;}
+//
+
+void paged_bitmap::Init(unsigned char* p, unsigned size, unsigned bit)
+{
+ iBase = p;
+ iNbits=size;
+ int bytes=Ceiling(size,8)>>3;
+ memset(p,bit?0xff:0,bytes);
+}
+
+inline void paged_bitmap::Set(unsigned ix, unsigned bit)
+{
+ if (bit)
+ iBase[ix>>3] |= (1<<(ix&7));
+ else
+ iBase[ix>>3] &= ~(1<<(ix&7));
+}
+
+inline unsigned paged_bitmap::operator[](unsigned ix) const
+{
+ return 1U&(iBase[ix>>3] >> (ix&7));
+}
+
+void paged_bitmap::Setn(unsigned ix, unsigned len, unsigned bit)
+{
+ int l=len;
+ while (--l>=0)
+ Set(ix++,bit);
+}
+
+void paged_bitmap::Set(unsigned ix, unsigned len, unsigned val)
+{
+ int l=len;
+ while (--l>=0)
+ {
+ Set(ix++,val&1);
+ val>>=1;
+ }
+}
+
+unsigned paged_bitmap::Bits(unsigned ix, unsigned len) const
+{
+ int l=len;
+ unsigned val=0;
+ unsigned bit=0;
+ while (--l>=0)
+ val |= (*this)[ix++]<<bit++;
+ return val;
+}
+
+bool paged_bitmap::Is(unsigned ix, unsigned len, unsigned bit) const
+{
+ unsigned i2 = ix+len;
+ if (i2 > iNbits)
+ return false;
+ for (;;)
+ {
+ if ((*this)[ix] != bit)
+ return false;
+ if (++ix==i2)
+ return true;
+ }
+}
+
+int paged_bitmap::Find(unsigned start, unsigned bit) const
+{
+ if (start<iNbits) do
+ {
+ if ((*this)[start]==bit)
+ return start;
+ } while (++start<iNbits);
+ return -1;
+}
+
+
+//
+// Page allocator code
+//
+void RHybridHeap::PagedInit(TInt aPagePower)
+{
+ if (aPagePower > 0)
+ {
+ if (aPagePower < MINPAGEPOWER)
+ aPagePower = MINPAGEPOWER;
+ }
+ else aPagePower = 31;
+
+ iPageThreshold = aPagePower;
+ /*-------------------------------------------------------------
+ * Initialize page bitmap
+ *-------------------------------------------------------------*/
+ iPageMap.Init((unsigned char*)&iBitMapBuffer, MAXSMALLPAGEBITS, 0);
+}
+
+void* RHybridHeap::PagedAllocate(unsigned size)
+{
+ TInt nbytes = Ceiling(size, iPageSize);
+ void* p = Map(0, nbytes);
+ if (!p)
+ return 0;
+ if (!PagedSetSize(p, nbytes))
+ {
+ Unmap(p, nbytes);
+ return 0;
+ }
+ return p;
+}
+
+void* RHybridHeap::PagedReallocate(void* p, unsigned size, TInt mode)
+{
+
+ HEAP_ASSERT(Ceiling(p, iPageSize) == p);
+ unsigned nbytes = Ceiling(size, iPageSize);
+
+ unsigned osize = PagedSize(p);
+ if ( nbytes == 0 ) // Special case to handle shrinking below min page threshold
+ nbytes = Min((1 << MINPAGEPOWER), osize);
+
+ if (osize == nbytes)
+ return p;
+
+ if (nbytes < osize)
+ { // shrink in place, unmap final pages and rewrite the pagemap
+ Unmap(Offset(p, nbytes), osize-nbytes);
+ // zap old code and then write new code (will not fail)
+ PagedZapSize(p, osize);
+
+ TBool check = PagedSetSize(p, nbytes);
+ __ASSERT_ALWAYS(check, HEAP_PANIC(ETHeapBadCellAddress));
+
+ return p;
+ }
+
+ // nbytes > osize
+ // try and extend current region first
+
+ void* newp = Map(Offset(p, osize), nbytes-osize);
+ if (newp)
+ { // In place growth. Possibility that pagemap may have to grow AND then fails
+ if (!PagedSetSize(p, nbytes))
+ { // must release extra mapping
+ Unmap(Offset(p, osize), nbytes-osize);
+ return 0;
+ }
+ // if successful, the new length code will have overwritten the old one (it is at least as long)
+ return p;
+ }
+
+ // fallback to allocate/copy/free
+ if (mode & ENeverMove)
+ return 0; // not allowed to move cell
+
+ newp = PagedAllocate(nbytes);
+ if (!newp)
+ return 0;
+ memcpy(newp, p, osize);
+ PagedFree(p);
+ return newp;
+}
+
+void RHybridHeap::PagedFree(void* p)
+{
+ HEAP_ASSERT(Ceiling(p, iPageSize) == p);
+
+
+ unsigned size = PagedSize(p);
+
+ PagedZapSize(p, size); // clear page map
+ Unmap(p, size);
+}
+
+void RHybridHeap::PagedInfo(struct HeapInfo* i, SWalkInfo* wi) const
+{
+ for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
+ {
+ int npage = PagedDecode(ix);
+ // Introduce paged buffer to the walk function
+ TAny* bfr = Bitmap2addr(ix);
+ int len = npage << PAGESHIFT;
+ if ( len > iPageSize )
+ { // If buffer is not larger than one page it must be a slab page mapped into bitmap
+ i->iAllocBytes += len;
+ ++i->iAllocN;
+ Walk(wi, bfr, len, EGoodAllocatedCell, EPageAllocator);
+ }
+ ix += (npage<<1);
+ }
+}
+
+void RHybridHeap::ResetBitmap()
+/*---------------------------------------------------------
+ * Go through paged_bitmap and unmap all buffers to system
+ * This method is called from RHybridHeap::Reset() to unmap all page
+ * allocated - and slab pages which are stored in bitmap, too
+ *---------------------------------------------------------*/
+{
+ unsigned iNbits = iPageMap.Size();
+ if ( iNbits )
+ {
+ for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
+ {
+ int npage = PagedDecode(ix);
+ void* p = Bitmap2addr(ix);
+ unsigned size = PagedSize(p);
+ PagedZapSize(p, size); // clear page map
+ Unmap(p, size);
+ ix += (npage<<1);
+ }
+ if ( (TInt)iNbits > MAXSMALLPAGEBITS )
+ {
+ // unmap page reserved for enlarged bitmap
+ Unmap(iPageMap.Addr(), (iNbits >> 3) );
+ }
+ }
+}
+
+TBool RHybridHeap::CheckBitmap(void* aBfr, TInt aSize, TUint32& aDummy, TInt& aNPages)
+/*---------------------------------------------------------
+ * If aBfr = NULL
+ * Go through paged_bitmap and unmap all buffers to system
+ * and assure that by reading the first word of each page of aBfr
+ * that aBfr is still accessible
+ * else
+ * Assure that specified buffer is mapped with correct length in
+ * page map
+ *---------------------------------------------------------*/
+{
+ TBool ret;
+ if ( aBfr )
+ {
+ __ASSERT_ALWAYS((Ceiling(aBfr, iPageSize) == aBfr), HEAP_PANIC(ETHeapBadCellAddress));
+ ret = ( aSize == (TInt)PagedSize(aBfr));
+ }
+ else
+ {
+ ret = ETrue;
+ unsigned iNbits = iPageMap.Size();
+ if ( iNbits )
+ {
+ TInt npage;
+ aNPages = 0;
+ for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
+ {
+ npage = PagedDecode(ix);
+ aNPages += npage;
+ void* p = Bitmap2addr(ix);
+ __ASSERT_ALWAYS((Ceiling(p, iPageSize) == p), HEAP_PANIC(ETHeapBadCellAddress));
+ unsigned s = PagedSize(p);
+ __ASSERT_ALWAYS((Ceiling(s, iPageSize) == s), HEAP_PANIC(ETHeapBadCellAddress));
+ while ( s )
+ {
+ aDummy += *(TUint32*)((TUint8*)p + (s-iPageSize));
+ s -= iPageSize;
+ }
+ ix += (npage<<1);
+ }
+ if ( (TInt)iNbits > MAXSMALLPAGEBITS )
+ {
+ // add enlarged bitmap page(s) to total page count
+ npage = (iNbits >> 3);
+ __ASSERT_ALWAYS((Ceiling(npage, iPageSize) == npage), HEAP_PANIC(ETHeapBadCellAddress));
+ aNPages += (npage / iPageSize);
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+// The paged allocations are tracked in a bitmap which has 2 bits per page
+// this allows us to store allocations as small as 4KB
+// The presence and size of an allocation is encoded as follows:
+// let N = number of pages in the allocation, then
+// 10 : N = 1 // 4KB
+// 110n : N = 2 + n // 8-12KB
+// 1110nnnn : N = nnnn // 16-60KB
+// 1111n[18] : N = n[18] // 64KB-1GB
+
+const struct etab { unsigned char offset, len, codelen, code;} encode_table[] =
+{
+ {1,2,2,0x1},
+ {2,4,3,0x3},
+ {0,8,4,0x7},
+ {0,22,4,0xf}
+};
+
+// Return code length for specified allocation Size(assumed to be aligned to pages)
+inline unsigned paged_codelen(unsigned size, unsigned pagesz)
+{
+ HEAP_ASSERT(size == Ceiling(size, pagesz));
+
+ if (size == pagesz)
+ return 2;
+ else if (size < 4*pagesz)
+ return 4;
+ else if (size < 16*pagesz)
+ return 8;
+ else
+ return 22;
+}
+
+inline const etab& paged_coding(unsigned npage)
+{
+ if (npage < 4)
+ return encode_table[npage>>1];
+ else if (npage < 16)
+ return encode_table[2];
+ else
+ return encode_table[3];
+}
+
+bool RHybridHeap::PagedEncode(unsigned pos, unsigned npage)
+{
+ const etab& e = paged_coding(npage);
+ if (pos + e.len > iPageMap.Size())
+ {
+ // need to grow the page bitmap to fit the cell length into the map
+ // if we outgrow original bitmap buffer in RHybridHeap metadata, then just get enough pages to cover the full space:
+ // * initial 68 byte bitmap mapped (68*8*4kB):2 = 1,1MB
+ // * 4KB can Map(4096*8*4kB):2 = 64MB
+ unsigned maxsize = Ceiling(iMaxLength, iPageSize);
+ unsigned mapbits = maxsize >> (PAGESHIFT-1);
+ maxsize = Ceiling(mapbits>>3, iPageSize);
+ void* newb = Map(0, maxsize);
+ if (!newb)
+ return false;
+
+ unsigned char* oldb = iPageMap.Addr();
+ iPageMap.Init((unsigned char*)newb, (maxsize<<3), 0);
+ memcpy(newb, oldb, Ceiling(MAXSMALLPAGEBITS,8)>>3);
+ }
+ // encode the allocation block size into the bitmap, starting at the bit for the start page
+ unsigned bits = e.code;
+ bits |= (npage - e.offset) << e.codelen;
+ iPageMap.Set(pos, e.len, bits);
+ return true;
+}
+
+unsigned RHybridHeap::PagedDecode(unsigned pos) const
+{
+ __ASSERT_ALWAYS(pos + 2 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
+
+ unsigned bits = iPageMap.Bits(pos,2);
+ __ASSERT_ALWAYS(bits & 1, HEAP_PANIC(ETHeapBadCellAddress));
+ bits >>= 1;
+ if (bits == 0)
+ return 1;
+ __ASSERT_ALWAYS(pos + 4 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
+ bits = iPageMap.Bits(pos+2,2);
+ if ((bits & 1) == 0)
+ return 2 + (bits>>1);
+ else if ((bits>>1) == 0)
+ {
+ __ASSERT_ALWAYS(pos + 8 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
+ return iPageMap.Bits(pos+4, 4);
+ }
+ else
+ {
+ __ASSERT_ALWAYS(pos + 22 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
+ return iPageMap.Bits(pos+4, 18);
+ }
+}
+
+inline void RHybridHeap::PagedZapSize(void* p, unsigned size)
+{iPageMap.Setn(PtrDiff(p, iMemBase) >> (PAGESHIFT-1), paged_codelen(size, iPageSize) ,0);}
+
+inline unsigned RHybridHeap::PagedSize(void* p) const
+ { return PagedDecode(PtrDiff(p, iMemBase) >> (PAGESHIFT-1)) << PAGESHIFT; }
+
+inline bool RHybridHeap::PagedSetSize(void* p, unsigned size)
+{ return PagedEncode(PtrDiff(p, iMemBase) >> (PAGESHIFT-1), size >> PAGESHIFT); }
+
+inline void* RHybridHeap::Bitmap2addr(unsigned pos) const
+ { return iMemBase + (1 << (PAGESHIFT-1))*pos; }
+
+
+#ifndef QT_SYMBIAN4_ALLOCATOR_UNWANTED_CODE
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+/**
+Constructor where minimum and maximum length of the heap can be defined.
+It defaults the chunk heap to be created to have use a new local chunk,
+to have a grow by value of KMinHeapGrowBy, to be unaligned, not to be
+single threaded and not to have any mode flags set.
+
+@param aMinLength The minimum length of the heap to be created.
+@param aMaxLength The maximum length to which the heap to be created can grow.
+ If the supplied value is less than a page size, then it
+ is discarded and the page size is used instead.
+*/
+EXPORT_C TChunkHeapCreateInfo::TChunkHeapCreateInfo(TInt aMinLength, TInt aMaxLength) :
+ iVersionNumber(EVersion0), iMinLength(aMinLength), iMaxLength(aMaxLength),
+iAlign(0), iGrowBy(1), iSingleThread(EFalse),
+iOffset(0), iPaging(EUnspecified), iMode(0), iName(NULL)
+{
+}
+
+
+/**
+Sets the chunk heap to create a new chunk with the specified name.
+
+This overriddes any previous call to TChunkHeapCreateInfo::SetNewChunkHeap() or
+TChunkHeapCreateInfo::SetExistingChunkHeap() for this TChunkHeapCreateInfo object.
+
+@param aName The name to be given to the chunk heap to be created
+If NULL, the function constructs a local chunk to host the heap.
+If not NULL, a pointer to a descriptor containing the name to be
+assigned to the global chunk hosting the heap.
+*/
+EXPORT_C void TChunkHeapCreateInfo::SetCreateChunk(const TDesC* aName)
+{
+ iName = (TDesC*)aName;
+ iChunk.SetHandle(KNullHandle);
+}
+
+
+/**
+Sets the chunk heap to be created to use the chunk specified.
+
+This overriddes any previous call to TChunkHeapCreateInfo::SetNewChunkHeap() or
+TChunkHeapCreateInfo::SetExistingChunkHeap() for this TChunkHeapCreateInfo object.
+
+@param aChunk A handle to the chunk to use for the heap.
+*/
+EXPORT_C void TChunkHeapCreateInfo::SetUseChunk(const RChunk aChunk)
+{
+ iName = NULL;
+ iChunk = aChunk;
+}
+
+EXPORT_C RHeap* UserHeap::FixedHeap(TAny* aBase, TInt aMaxLength, TInt aAlign, TBool aSingleThread)
+/**
+Creates a fixed length heap at a specified location.
+
+On successful return from this function, the heap is ready to use. This assumes that
+the memory pointed to by aBase is mapped and able to be used. You must ensure that you
+pass in a large enough value for aMaxLength. Passing in a value that is too small to
+hold the metadata for the heap (~1 KB) will result in the size being rounded up and the
+heap thereby running over the end of the memory assigned to it. But then if you were to
+pass in such as small value then you would not be able to do any allocations from the
+heap anyway. Moral of the story: Use a sensible value for aMaxLength!
+
+@param aBase A pointer to the location where the heap is to be constructed.
+@param aMaxLength The maximum length in bytes to which the heap can grow. If the
+ supplied value is too small to hold the heap's metadata, it
+ will be increased.
+@param aAlign From Symbian^4 onwards, this value is ignored but EABI 8
+ byte alignment is guaranteed for all allocations 8 bytes or
+ more in size. 4 byte allocations will be aligned to a 4
+ byte boundary. Best to pass in zero.
+@param aSingleThread EFalse if the heap is to be accessed from multiple threads.
+ This will cause internal locks to be created, guaranteeing
+ thread safety.
+
+@return A pointer to the new heap, or NULL if the heap could not be created.
+
+@panic USER 56 if aMaxLength is negative.
+*/
+{
+ __ASSERT_ALWAYS( aMaxLength>=0, ::Panic(ETHeapMaxLengthNegative));
+ if ( aMaxLength < (TInt)sizeof(RHybridHeap) )
+ aMaxLength = sizeof(RHybridHeap);
+
+ RHybridHeap* h = new(aBase) RHybridHeap(aMaxLength, aAlign, aSingleThread);
+
+ if (!aSingleThread)
+ {
+ TInt r = h->iLock.CreateLocal();
+ if (r!=KErrNone)
+ return NULL; // No need to delete the RHybridHeap instance as the new above is only a placement new
+ h->iHandles = (TInt*)&h->iLock;
+ h->iHandleCount = 1;
+ }
+ return h;
+}
+
+/**
+Creates a chunk heap of the type specified by the parameter aCreateInfo.
+
+@param aCreateInfo A reference to a TChunkHeapCreateInfo object specifying the
+type of chunk heap to create.
+
+@return A pointer to the new heap or NULL if the heap could not be created.
+
+@panic USER 41 if the heap's specified minimum length is greater than the specified maximum length.
+@panic USER 55 if the heap's specified minimum length is negative.
+@panic USER 172 if the heap's specified alignment is not a power of 2 or is less than the size of a TAny*.
+*/
+EXPORT_C RHeap* UserHeap::ChunkHeap(const TChunkHeapCreateInfo& aCreateInfo)
+{
+ // aCreateInfo must have been configured to use a new chunk or an exiting chunk.
+ __ASSERT_ALWAYS(!(aCreateInfo.iMode & (TUint32)~EChunkHeapMask), ::Panic(EHeapCreateInvalidMode));
+ RHeap* h = NULL;
+
+ if (aCreateInfo.iChunk.Handle() == KNullHandle)
+ {
+ // A new chunk is to be created for this heap.
+
+ __ASSERT_ALWAYS(aCreateInfo.iMinLength >= 0, ::Panic(ETHeapMinLengthNegative));
+ __ASSERT_ALWAYS(aCreateInfo.iMaxLength >= aCreateInfo.iMinLength, ::Panic(ETHeapCreateMaxLessThanMin));
+
+ TInt maxLength = aCreateInfo.iMaxLength;
+ TInt page_size;
+ GET_PAGE_SIZE(page_size);
+
+ if (maxLength < page_size)
+ maxLength = page_size;
+
+ TChunkCreateInfo chunkInfo;
+#if USE_HYBRID_HEAP
+ if ( aCreateInfo.iOffset )
+ chunkInfo.SetNormal(0, maxLength); // Create DL only heap
+ else
+ {
+ maxLength = 2*maxLength;
+ chunkInfo.SetDisconnected(0, 0, maxLength); // Create hybrid heap
+ }
+#else
+ chunkInfo.SetNormal(0, maxLength); // Create DL only heap
+#endif
+ chunkInfo.SetOwner((aCreateInfo.iSingleThread)? EOwnerThread : EOwnerProcess);
+ if (aCreateInfo.iName)
+ chunkInfo.SetGlobal(*aCreateInfo.iName);
+ // Set the paging attributes of the chunk.
+ if (aCreateInfo.iPaging == TChunkHeapCreateInfo::EPaged)
+ chunkInfo.SetPaging(TChunkCreateInfo::EPaged);
+ if (aCreateInfo.iPaging == TChunkHeapCreateInfo::EUnpaged)
+ chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged);
+ // Create the chunk.
+ RChunk chunk;
+ if (chunk.Create(chunkInfo) != KErrNone)
+ return NULL;
+ // Create the heap using the new chunk.
+ TUint mode = aCreateInfo.iMode | EChunkHeapDuplicate; // Must duplicate the handle.
+ h = OffsetChunkHeap(chunk, aCreateInfo.iMinLength, aCreateInfo.iOffset,
+ aCreateInfo.iGrowBy, maxLength, aCreateInfo.iAlign,
+ aCreateInfo.iSingleThread, mode);
+ chunk.Close();
+ }
+ else
+ {
+ h = OffsetChunkHeap(aCreateInfo.iChunk, aCreateInfo.iMinLength, aCreateInfo.iOffset,
+ aCreateInfo.iGrowBy, aCreateInfo.iMaxLength, aCreateInfo.iAlign,
+ aCreateInfo.iSingleThread, aCreateInfo.iMode);
+ }
+ return h;
+}
+
+
+
+EXPORT_C RHeap* UserHeap::ChunkHeap(const TDesC* aName, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, TInt aAlign, TBool aSingleThread)
+/**
+Creates a heap in a local or global chunk.
+
+The chunk hosting the heap can be local or global.
+
+A local chunk is one which is private to the process creating it and is not
+intended for access by other user processes. A global chunk is one which is
+visible to all processes.
+
+The hosting chunk is local, if the pointer aName is NULL, otherwise the
+hosting chunk is global and the descriptor *aName is assumed to contain
+the name to be assigned to it.
+
+Ownership of the host chunk is vested in the current process.
+
+A minimum and a maximum size for the heap can be specified. On successful
+return from this function, the size of the heap is at least aMinLength.
+If subsequent requests for allocation of memory from the heap cannot be
+satisfied by compressing the heap, the size of the heap is extended in
+increments of aGrowBy until the request can be satisfied. Attempts to extend
+the heap causes the size of the host chunk to be adjusted.
+
+Note that the size of the heap cannot be adjusted by more than aMaxLength.
+
+@param aName If NULL, the function constructs a local chunk to host
+ the heap. If not NULL, a pointer to a descriptor containing
+ the name to be assigned to the global chunk hosting the heap.
+@param aMinLength The minimum length of the heap in bytes. This will be
+ rounded up to the nearest page size by the allocator.
+@param aMaxLength The maximum length in bytes to which the heap can grow. This
+ will be rounded up to the nearest page size by the allocator.
+@param aGrowBy The number of bytes by which the heap will grow when more
+ memory is required. This will be rounded up to the nearest
+ page size by the allocator. If a value is not explicitly
+ specified, the page size is taken by default.
+@param aAlign From Symbian^4 onwards, this value is ignored but EABI 8
+ byte alignment is guaranteed for all allocations 8 bytes or
+ more in size. 4 byte allocations will be aligned to a 4
+ byte boundary. Best to pass in zero.
+@param aSingleThread EFalse if the heap is to be accessed from multiple threads.
+ This will cause internal locks to be created, guaranteeing
+ thread safety.
+
+@return A pointer to the new heap or NULL if the heap could not be created.
+
+@panic USER 41 if aMaxLength is < aMinLength.
+@panic USER 55 if aMinLength is negative.
+@panic USER 56 if aMaxLength is negative.
+*/
+ {
+ TInt page_size;
+ GET_PAGE_SIZE(page_size);
+ TInt minLength = _ALIGN_UP(aMinLength, page_size);
+ TInt maxLength = Max(aMaxLength, minLength);
+
+ TChunkHeapCreateInfo createInfo(minLength, maxLength);
+ createInfo.SetCreateChunk(aName);
+ createInfo.SetGrowBy(aGrowBy);
+ createInfo.SetAlignment(aAlign);
+ createInfo.SetSingleThread(aSingleThread);
+
+ return ChunkHeap(createInfo);
+ }
+#endif // QT_SYMBIAN4_ALLOCATOR_UNWANTED_CODE
+
+EXPORT_C RHeap* UserHeap::ChunkHeap(RChunk aChunk, TInt aMinLength, TInt aGrowBy, TInt aMaxLength, TInt aAlign, TBool aSingleThread, TUint32 aMode)
+/**
+Creates a heap in an existing chunk.
+
+This function is intended to be used to create a heap in a user writable code
+chunk as created by a call to RChunk::CreateLocalCode(). This type of heap can
+be used to hold code fragments from a JIT compiler.
+
+@param aChunk The chunk that will host the heap.
+@param aMinLength The minimum length of the heap in bytes. This will be
+ rounded up to the nearest page size by the allocator.
+@param aGrowBy The number of bytes by which the heap will grow when more
+ memory is required. This will be rounded up to the nearest
+ page size by the allocator. If a value is not explicitly
+ specified, the page size is taken by default.
+@param aMaxLength The maximum length in bytes to which the heap can grow. This
+ will be rounded up to the nearest page size by the allocator.
+ If 0 is passed in, the maximum lengt of the chunk is used.
+@param aAlign From Symbian^4 onwards, this value is ignored but EABI 8
+ byte alignment is guaranteed for all allocations 8 bytes or
+ more in size. 4 byte allocations will be aligned to a 4
+ byte boundary. Best to pass in zero.
+@param aSingleThread EFalse if the heap is to be accessed from multiple threads.
+ This will cause internal locks to be created, guaranteeing
+ thread safety.
+@param aMode Flags controlling the heap creation. See RAllocator::TFlags.
+
+@return A pointer to the new heap or NULL if the heap could not be created.
+
+@see UserHeap::OffsetChunkHeap()
+*/
+ {
+ return OffsetChunkHeap(aChunk, aMinLength, 0, aGrowBy, aMaxLength, aAlign, aSingleThread, aMode);
+ }
+
+EXPORT_C RHeap* UserHeap::OffsetChunkHeap(RChunk aChunk, TInt aMinLength, TInt aOffset, TInt aGrowBy, TInt aMaxLength, TInt aAlign, TBool aSingleThread, TUint32 aMode)
+/**
+Creates a heap in an existing chunk, offset from the beginning of the chunk.
+
+This function is intended to be used to create a heap using a chunk which has
+some of its memory already used, at the start of that that chunk. The maximum
+length to which the heap can grow is the maximum size of the chunk, minus the
+data at the start of the chunk.
+
+The offset at which to create the heap is passed in as the aOffset parameter.
+Legacy heap implementations always respected the aOffset value, however more
+modern heap implementations are more sophisticated and cannot necessarily respect
+this value. Therefore, if possible, you should always use an aOffset of 0 unless
+you have a very explicit requirement for using a non zero value. Using a non zero
+value will result in a less efficient heap algorithm being used in order to respect
+the offset.
+
+Another issue to consider when using this function is the type of the chunk passed
+in. In order for the most efficient heap algorithms to be used, the chunk passed
+in should always be a disconnected chunk. Passing in a non disconnected chunk will
+again result in a less efficient heap algorithm being used.
+
+Finally, another requirement for the most efficient heap algorithms to be used is
+for the heap to be able to expand. Therefore, unless you have a specific reason to
+do so, always specify aMaxLength > aMinLength.
+
+So, if possible, use aOffset == zero, aMaxLength > aMinLength and a disconnected
+chunk for best results!
+
+@param aChunk The chunk that will host the heap.
+@param aMinLength The minimum length of the heap in bytes. This will be
+ rounded up to the nearest page size by the allocator.
+@param aOffset The offset in bytes from the start of the chunk at which to
+ create the heap. If used (and it shouldn't really be!)
+ then it will be rounded up to a multiple of 8, to respect
+ EABI 8 byte alignment requirements.
+@param aGrowBy The number of bytes by which the heap will grow when more
+ memory is required. This will be rounded up to the nearest
+ page size by the allocator. If a value is not explicitly
+ specified, the page size is taken by default.
+@param aMaxLength The maximum length in bytes to which the heap can grow. This
+ will be rounded up to the nearest page size by the allocator.
+ If 0 is passed in, the maximum length of the chunk is used.
+@param aAlign From Symbian^4 onwards, this value is ignored but EABI 8
+ byte alignment is guaranteed for all allocations 8 bytes or
+ more in size. 4 byte allocations will be aligned to a 4
+ byte boundary. Best to pass in zero.
+@param aSingleThread EFalse if the heap is to be accessed from multiple threads.
+ This will cause internal locks to be created, guaranteeing
+ thread safety.
+@param aMode Flags controlling the heap creation. See RAllocator::TFlags.
+
+@return A pointer to the new heap or NULL if the heap could not be created.
+
+@panic USER 41 if aMaxLength is < aMinLength.
+@panic USER 55 if aMinLength is negative.
+@panic USER 56 if aMaxLength is negative.
+@panic USER 168 if aOffset is negative.
+*/
+ {
+ TBool dlOnly = EFalse;
+ TInt pageSize;
+ GET_PAGE_SIZE(pageSize);
+ TInt align = RHybridHeap::ECellAlignment; // Always use EABI 8 byte alignment
+
+ __ASSERT_ALWAYS(aMinLength>=0, ::Panic(ETHeapMinLengthNegative));
+ __ASSERT_ALWAYS(aMaxLength>=0, ::Panic(ETHeapMaxLengthNegative));
+
+ if ( aMaxLength > 0 )
+ __ASSERT_ALWAYS(aMaxLength>=aMinLength, ::Panic(ETHeapCreateMaxLessThanMin));
+
+ // Stick to EABI alignment for the start offset, if any
+ aOffset = _ALIGN_UP(aOffset, align);
+
+ // Using an aOffset > 0 means that we can't use the hybrid allocator and have to revert to Doug Lea only
+ if (aOffset > 0)
+ dlOnly = ETrue;
+
+ // Ensure that the minimum length is enough to hold the RHybridHeap object itself
+ TInt minCell = _ALIGN_UP(Max((TInt)RHybridHeap::EAllocCellSize, (TInt)RHybridHeap::EFreeCellSize), align);
+ TInt hybridHeapSize = (sizeof(RHybridHeap) + minCell);
+ if (aMinLength < hybridHeapSize)
+ aMinLength = hybridHeapSize;
+
+ // Round the minimum length up to a multiple of the page size, taking into account that the
+ // offset takes up a part of the chunk's memory
+ aMinLength = _ALIGN_UP((aMinLength + aOffset), pageSize);
+
+ // If aMaxLength is 0 then use the entire chunk
+ TInt chunkSize = aChunk.MaxSize();
+ if (aMaxLength == 0)
+ {
+ aMaxLength = chunkSize;
+ }
+ // Otherwise round the maximum length up to a multiple of the page size, taking into account that
+ // the offset takes up a part of the chunk's memory. We also clip the maximum length to the chunk
+ // size, so the user may get a little less than requested if the chunk size is not large enough
+ else
+ {
+ aMaxLength = _ALIGN_UP((aMaxLength + aOffset), pageSize);
+ if (aMaxLength > chunkSize)
+ aMaxLength = chunkSize;
+ }
+
+ // If the rounded up values don't make sense then a crazy aMinLength or aOffset must have been passed
+ // in, so fail the heap creation
+ if (aMinLength > aMaxLength)
+ return NULL;
+
+ // Adding the offset into the minimum and maximum length was only necessary for ensuring a good fit of
+ // the heap into the chunk. Re-adjust them now back to non offset relative sizes
+ aMinLength -= aOffset;
+ aMaxLength -= aOffset;
+
+ // If we are still creating the hybrid allocator (call parameter
+ // aOffset is 0 and aMaxLength > aMinLength), we must reduce heap
+ // aMaxLength size to the value aMaxLength/2 and set the aOffset to point in the middle of chunk.
+ TInt offset = aOffset;
+ TInt maxLength = aMaxLength;
+ if (!dlOnly && (aMaxLength > aMinLength))
+ maxLength = offset = _ALIGN_UP(aMaxLength >> 1, pageSize);
+
+ // Try to use commit to map aMinLength physical memory for the heap, taking into account the offset. If
+ // the operation fails, suppose that the chunk is not a disconnected heap and try to map physical memory
+ // with adjust. In this case, we also can't use the hybrid allocator and have to revert to Doug Lea only
+ TBool useAdjust = EFalse;
+ TInt r = aChunk.Commit(offset, aMinLength);
+ if (r == KErrGeneral)
+ {
+ dlOnly = useAdjust = ETrue;
+ r = aChunk.Adjust(aMinLength);
+ if (r != KErrNone)
+ return NULL;
+ }
+ else if (r == KErrNone)
+ {
+ // We have a disconnected chunk reset aOffset and aMaxlength
+ aOffset = offset;
+ aMaxLength = maxLength;
+ }
+
+ else
+ return NULL;
+
+ // Parameters have been mostly verified and we know whether to use the hybrid allocator or Doug Lea only. The
+ // constructor for the hybrid heap will automatically drop back to Doug Lea if it determines that aMinLength
+ // == aMaxLength, so no need to worry about that requirement here. The user specified alignment is not used but
+ // is passed in so that it can be sanity checked in case the user is doing something totally crazy with it
+ RHybridHeap* h = new (aChunk.Base() + aOffset) RHybridHeap(aChunk.Handle(), aOffset, aMinLength, aMaxLength,
+ aGrowBy, aAlign, aSingleThread, dlOnly, useAdjust);
+
+ if (h->ConstructLock(aMode) != KErrNone)
+ return NULL;
+
+ // Return the heap address
+ return h;
+ }
+
+#define UserTestDebugMaskBit(bit) (TBool)(UserSvr::DebugMask(bit>>5) & (1<<(bit&31)))
+
+_LIT(KLitDollarHeap,"$HEAP");
+EXPORT_C TInt UserHeap::CreateThreadHeap(SStdEpocThreadCreateInfo& aInfo, RHeap*& aHeap, TInt aAlign, TBool aSingleThread)
+/**
+@internalComponent
+*/
+//
+// Create a user-side heap
+//
+{
+ TInt page_size;
+ GET_PAGE_SIZE(page_size);
+ TInt minLength = _ALIGN_UP(aInfo.iHeapInitialSize, page_size);
+ TInt maxLength = Max(aInfo.iHeapMaxSize, minLength);
+#ifdef ENABLE_BTRACE
+ if (UserTestDebugMaskBit(96)) // 96 == KUSERHEAPTRACE in nk_trace.h
+ aInfo.iFlags |= ETraceHeapAllocs;
+#endif // ENABLE_BTRACE
+ // Create the thread's heap chunk.
+ RChunk c;
+#ifndef NO_NAMED_LOCAL_CHUNKS
+ TChunkCreateInfo createInfo;
+
+ createInfo.SetThreadHeap(0, maxLength, KLitDollarHeap()); // Initialise with no memory committed.
+#if USE_HYBRID_HEAP
+ //
+ // Create disconnected chunk for hybrid heap with double max length value
+ //
+ maxLength = 2*maxLength;
+ createInfo.SetDisconnected(0, 0, maxLength);
+#endif
+#ifdef SYMBIAN_WRITABLE_DATA_PAGING
+ // Set the paging policy of the heap chunk based on the thread's paging policy.
+ TUint pagingflags = aInfo.iFlags & EThreadCreateFlagPagingMask;
+ switch (pagingflags)
+ {
+ case EThreadCreateFlagPaged:
+ createInfo.SetPaging(TChunkCreateInfo::EPaged);
+ break;
+ case EThreadCreateFlagUnpaged:
+ createInfo.SetPaging(TChunkCreateInfo::EUnpaged);
+ break;
+ case EThreadCreateFlagPagingUnspec:
+ // Leave the chunk paging policy unspecified so the process's
+ // paging policy is used.
+ break;
+ }
+#endif // SYMBIAN_WRITABLE_DATA_PAGING
+
+ TInt r = c.Create(createInfo);
+#else
+ TInt r = c.CreateDisconnectedLocal(0, 0, maxLength * 2);
+#endif
+ if (r!=KErrNone)
+ return r;
+
+ aHeap = ChunkHeap(c, minLength, page_size, maxLength, aAlign, aSingleThread, EChunkHeapSwitchTo|EChunkHeapDuplicate);
+ c.Close();
+
+ if ( !aHeap )
+ return KErrNoMemory;
+
+#ifdef ENABLE_BTRACE
+ if (aInfo.iFlags & ETraceHeapAllocs)
+ {
+ aHeap->iFlags |= RHeap::ETraceAllocs;
+ BTraceContext8(BTrace::EHeap, BTrace::EHeapCreate,(TUint32)aHeap, RHybridHeap::EAllocCellSize);
+ TInt chunkId = ((RHandleBase&)((RHybridHeap*)aHeap)->iChunkHandle).BTraceId();
+ BTraceContext8(BTrace::EHeap, BTrace::EHeapChunkCreate, (TUint32)aHeap, chunkId);
+ }
+ if (aInfo.iFlags & EMonitorHeapMemory)
+ aHeap->iFlags |= RHeap::EMonitorMemory;
+#endif // ENABLE_BTRACE
+
+ return KErrNone;
+}
+
+#endif // __KERNEL_MODE__
+
+#endif /* QT_USE_NEW_SYMBIAN_ALLOCATOR */
diff --git a/src/corelib/arch/symbian/heap_hybrid_p.h b/src/corelib/arch/symbian/heap_hybrid_p.h
new file mode 100644
index 0000000000..1767fc1344
--- /dev/null
+++ b/src/corelib/arch/symbian/heap_hybrid_p.h
@@ -0,0 +1,406 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __HEAP_HYBRID_H__
+#define __HEAP_HYBRID_H__
+
+#include <e32cmn.h>
+
+#ifdef __WINS__
+#define USE_HYBRID_HEAP 0
+#else
+#define USE_HYBRID_HEAP 1
+#endif
+
+// This stuff is all temporary in order to prevent having to include dla.h from heap_hybrid.h, which causes
+// problems due to its definition of size_t (and possibly other types). This is unfortunate but we cannot
+// pollute the namespace with these types or it will cause problems with Open C and other POSIX compatibility
+// efforts in Symbian
+
+#define NSMALLBINS (32U)
+#define NTREEBINS (32U)
+
+#ifndef MALLOC_ALIGNMENT
+ #define MALLOC_ALIGNMENT ((TUint)8U)
+#endif /* MALLOC_ALIGNMENT */
+
+#define CHUNK_OVERHEAD (sizeof(TUint))
+
+typedef unsigned int bindex_t;
+typedef unsigned int binmap_t;
+typedef struct malloc_chunk* mchunkptr;
+typedef struct malloc_segment msegment;
+typedef struct malloc_state* mstate;
+typedef struct malloc_tree_chunk* tbinptr;
+typedef struct malloc_tree_chunk* tchunkptr;
+
+struct malloc_segment {
+ TUint8* iBase; /* base address */
+ TUint iSize; /* allocated size */
+};
+
+struct malloc_state {
+ binmap_t iSmallMap;
+ binmap_t iTreeMap;
+ TUint iDvSize;
+ TUint iTopSize;
+ mchunkptr iDv;
+ mchunkptr iTop;
+ TUint iTrimCheck;
+ mchunkptr iSmallBins[(NSMALLBINS+1)*2];
+ tbinptr iTreeBins[NTREEBINS];
+ msegment iSeg;
+ };
+
+class RHybridHeap : public RHeap
+ {
+
+public:
+ // declarations copied from Symbian^4 RAllocator and RHeap
+ typedef void (*TWalkFunc)(TAny*, RHeap::TCellType, TAny*, TInt);
+ enum TFlags {ESingleThreaded=1, EFixedSize=2, ETraceAllocs=4, EMonitorMemory=8,};
+ enum TAllocDebugOp
+ {
+ ECount, EMarkStart, EMarkEnd, ECheck, ESetFail, ECopyDebugInfo, ESetBurstFail, EGetFail,
+ EGetSize=48, EGetMaxLength, EGetBase, EAlignInteger, EAlignAddr
+ };
+ enum TDebugOp { EWalk = 128, EHybridHeap };
+ enum THybridAllocFail
+ {
+ ERandom, ETrueRandom, EDeterministic, EHybridNone, EFailNext, EReset, EBurstRandom,
+ EBurstTrueRandom, EBurstDeterministic, EBurstFailNext, ECheckFailure,
+ };
+ enum { EDebugHdrSize = sizeof(SDebugCell) };
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+ struct SRAllocatorBurstFail {TInt iBurst; TInt iRate; TInt iUnused[2];};
+#endif
+
+ struct HeapInfo
+ {
+ unsigned iFootprint;
+ unsigned iMaxSize;
+ unsigned iAllocBytes;
+ unsigned iAllocN;
+ unsigned iFreeBytes;
+ unsigned iFreeN;
+ };
+
+ struct SHeapCellInfo { RHybridHeap* iHeap; TInt iTotalAlloc; TInt iTotalAllocSize; TInt iTotalFree; TInt iLevelAlloc; SDebugCell* iStranded; };
+
+
+ /**
+ @internalComponent
+ */
+ enum TAllocatorType
+ {ESlabAllocator, EDougLeaAllocator, EPageAllocator, EFullSlab=0x80, EPartialFullSlab=0x40, EEmptySlab=0x20, ESlabSpare=0x10, ESlabMask=0xf0};
+
+
+ /**
+ @internalComponent
+ */
+ struct SWalkInfo {
+ /**
+ Walk function address shall be called
+ */
+ TWalkFunc iFunction;
+
+ /**
+ The first parameter for callback function
+ */
+ TAny* iParam;
+ /**
+ Pointer to RHybridHeap object
+ */
+ RHybridHeap* iHeap;
+ };
+
+ /**
+ @internalComponent
+ */
+ struct SConfig {
+ /**
+ Required slab configuration ( bit 0=4, bit 1=8 ..
+ bit 13 = 56)
+ */
+ TUint32 iSlabBits;
+ /**
+ Delayed slab threshold in bytes (0 = no threshold)
+ */
+ TInt iDelayedSlabThreshold;
+ /**
+ 2^n is smallest size allocated in paged allocator (14-31 = 16 Kb --> )
+ */
+ TInt iPagePower;
+
+ };
+
+ /**
+ @internalComponent
+
+ This structure is used by test code for configuring the allocators and obtaining information
+ from them in order to ensure they are behaving as required. This is internal test specific
+ code and is liable to be changed without warning at any time. You should under no circumstances
+ be using it!
+ */
+ struct STestCommand
+ {
+ TInt iCommand; // The test related command to be executed
+
+ union
+ {
+ SConfig iConfig; // Configuration used by test code only
+ TAny* iData; // Extra supporting data for the test command
+ };
+ };
+
+ /**
+ @internalComponent
+
+ Commands used by test code for configuring the allocators and obtaining information them them
+ */
+ enum TTestCommand { EGetConfig, ESetConfig, EHeapMetaData, ETestData };
+
+ virtual TAny* Alloc(TInt aSize);
+ virtual void Free(TAny* aPtr);
+ virtual TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
+ virtual TInt AllocLen(const TAny* aCell) const;
+#ifndef __KERNEL_MODE__
+ virtual TInt Compress();
+ virtual void Reset();
+ virtual TInt AllocSize(TInt& aTotalAllocSize) const;
+ virtual TInt Available(TInt& aBiggestBlock) const;
+#endif
+ virtual TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL);
+protected:
+ virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
+
+public:
+ TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW;
+ void operator delete(TAny*, TAny*);
+
+private:
+ TInt DoCountAllocFree(TInt& aFree);
+ TInt DoCheckHeap(SCheckInfo* aInfo);
+ void DoMarkStart();
+ TUint32 DoMarkEnd(TInt aExpected);
+ void DoSetAllocFail(TAllocFail aType, TInt aRate);
+ TBool CheckForSimulatedAllocFail();
+ void DoSetAllocFail(TAllocFail aType, TInt aRate, TUint aBurst);
+
+ void Lock() const;
+ void Unlock() const;
+ TInt ChunkHandle() const;
+
+ RHybridHeap(TInt aChunkHandle, TInt aOffset, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, TInt aAlign, TBool aSingleThread, TBool aDlOnly, TBool aUseAdjust);
+ RHybridHeap(TInt aMaxLength, TInt aAlign=0, TBool aSingleThread=ETrue);
+ RHybridHeap();
+
+ void Init(TInt aBitmapSlab, TInt aPagePower);
+ inline void InitBins(mstate m);
+ inline void InitTop(mstate m, mchunkptr p, TUint psize);
+ void* SysAlloc(mstate m, TUint nb);
+ int SysTrim(mstate m, TUint pad);
+ void* TmallocLarge(mstate m, TUint nb);
+ void* TmallocSmall(mstate m, TUint nb);
+ /*MACROS converted functions*/
+ static inline void UnlinkFirstSmallChunk(mstate M,mchunkptr B,mchunkptr P,bindex_t& I);
+ static inline void InsertSmallChunk(mstate M,mchunkptr P, TUint S);
+ static inline void InsertChunk(mstate M,mchunkptr P,TUint S);
+ static inline void UnlinkLargeChunk(mstate M,tchunkptr X);
+ static inline void UnlinkSmallChunk(mstate M, mchunkptr P,TUint S);
+ static inline void UnlinkChunk(mstate M, mchunkptr P, TUint S);
+ static inline void ComputeTreeIndex(TUint S, bindex_t& I);
+ static inline void InsertLargeChunk(mstate M,tchunkptr X,TUint S);
+ static inline void ReplaceDv(mstate M, mchunkptr P, TUint S);
+ static inline void ComputeBit2idx(binmap_t X,bindex_t& I);
+
+ void DoComputeTreeIndex(TUint S, bindex_t& I);
+ void DoCheckAnyChunk(mstate m, mchunkptr p);
+ void DoCheckTopChunk(mstate m, mchunkptr p);
+ void DoCheckInuseChunk(mstate m, mchunkptr p);
+ void DoCheckFreeChunk(mstate m, mchunkptr p);
+ void DoCheckMallocedChunk(mstate m, void* mem, TUint s);
+ void DoCheckTree(mstate m, tchunkptr t);
+ void DoCheckTreebin(mstate m, bindex_t i);
+ void DoCheckSmallbin(mstate m, bindex_t i);
+ TInt BinFind(mstate m, mchunkptr x);
+ TUint TraverseAndCheck(mstate m);
+ void DoCheckMallocState(mstate m);
+
+ TInt GetInfo(struct HeapInfo* i, SWalkInfo* wi=NULL) const;
+ void InitDlMalloc(TUint capacity, int locked);
+ void* DlMalloc(TUint);
+ void DlFree(void*);
+ void* DlRealloc(void*, TUint, TInt);
+ TUint DlInfo(struct HeapInfo* i, SWalkInfo* wi) const;
+ void DoCheckCommittedSize(TInt aNPages, mstate aM);
+
+ TAny* ReAllocImpl(TAny* aPtr, TInt aSize, TInt aMode);
+ void Construct(TBool aSingleThread, TBool aDLOnly, TBool aUseAdjust, TInt aAlign);
+#ifndef __KERNEL_MODE__
+ TInt ConstructLock(TUint32 aMode);
+#endif
+ static void Walk(SWalkInfo* aInfo, TAny* aBfr, TInt aLth, TCellType aBfrType, TAllocatorType aAlloctorType);
+ static void WalkCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
+ void* Map(void* p, TInt sz);
+ void Unmap(void* p,TInt sz);
+
+private:
+ TInt iMinLength;
+ TInt iOffset; // offset of RHeap object from chunk base
+ TInt iGrowBy;
+ TInt iMinCell;
+ TInt iPageSize;
+
+ // Temporarily commented out and exported from RHeap to prevent source breaks from req417-52840.
+ // This will be moved with another REQ after submission and subsequent fixing of bad code
+ //TInt iNestingLevel;
+ TInt iAllocCount;
+ // Temporarily commented out. See comment above regarding req417-52840 source breaks
+ //TAllocFail iFailType;
+ TInt iFailRate;
+ TBool iFailed;
+ TInt iFailAllocCount;
+ TInt iRand;
+ // Temporarily commented out. See comment above regarding req417-52840 source breaks
+ //TAny* iTestData;
+
+ TInt iChunkSize;
+ TInt iHighWaterMark;
+ TBool iUseAdjust;
+ TBool iDLOnly;
+
+ malloc_state iGlobalMallocState;
+
+#ifdef __KERNEL_MODE__
+
+ friend class RHeapK;
+
+#else
+
+ friend class UserHeap;
+ friend class HybridHeap;
+ friend class TestHybridHeap;
+
+private:
+
+ static void TreeRemove(slab* s);
+ static void TreeInsert(slab* s,slab** r);
+
+ enum {EOkBits = (1<<(MAXSLABSIZE>>2))-1};
+
+ void SlabInit();
+ void SlabConfig(unsigned slabbitmap);
+ void* SlabAllocate(slabset& allocator);
+ void SlabFree(void* p);
+ void* AllocNewSlab(slabset& allocator);
+ void* AllocNewPage(slabset& allocator);
+ void* InitNewSlab(slabset& allocator, slab* s);
+ void FreeSlab(slab* s);
+ void FreePage(page* p);
+ void SlabInfo(struct HeapInfo* i, SWalkInfo* wi) const;
+ static void SlabFullInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi);
+ static void SlabPartialInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi);
+ static void SlabEmptyInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi);
+ static void TreeWalk(slab* const* root, void (*f)(slab*, struct HeapInfo*, SWalkInfo*), struct HeapInfo* i, SWalkInfo* wi);
+
+ static void WalkPartialFullSlab(SWalkInfo* aInfo, slab* aSlab, TCellType aBfrType, TInt aLth);
+ static void WalkFullSlab(SWalkInfo* aInfo, slab* aSlab, TCellType aBfrType, TInt aLth);
+ void DoCheckSlab(slab* aSlab, TAllocatorType aSlabType, TAny* aBfr=NULL);
+ void DoCheckSlabTrees();
+ void DoCheckSlabTree(slab** aS, TBool aPartialPage);
+ void BuildPartialSlabBitmap(TUint32* aBitmap, slab* aSlab, TAny* aBfr=NULL);
+
+ static inline unsigned SlabHeaderFree(unsigned h)
+ {return (h&0x000000ff);}
+ static inline unsigned SlabHeaderPagemap(unsigned h)
+ {return (h&0x00000f00)>>8;}
+ static inline unsigned SlabHeaderSize(unsigned h)
+ {return (h&0x0003f000)>>12;}
+ static inline unsigned SlabHeaderUsedm4(unsigned h)
+ {return (h&0x0ffc0000)>>18;}
+ /***paged allocator code***/
+ void PagedInit(TInt aPagePower);
+ void* PagedAllocate(unsigned size);
+ void PagedFree(void* p);
+ void* PagedReallocate(void* p, unsigned size, TInt mode);
+
+ bool PagedEncode(unsigned pos, unsigned npage);
+ unsigned PagedDecode(unsigned pos) const;
+ inline unsigned PagedSize(void* p) const;
+ inline bool PagedSetSize(void* p, unsigned size);
+ inline void PagedZapSize(void* p, unsigned size);
+ inline void* Bitmap2addr(unsigned pos) const;
+ void PagedInfo(struct HeapInfo* i, SWalkInfo* wi) const;
+ void ResetBitmap();
+ TBool CheckBitmap(void* aBfr, TInt aSize, TUint32& aDummy, TInt& aNPages);
+
+private:
+ paged_bitmap iPageMap; // bitmap representing page allocator's pages
+ TUint8* iMemBase; // bottom of paged/slab memory (chunk base)
+ TUint8 iBitMapBuffer[MAXSMALLPAGEBITS>>3]; // buffer for initial page bitmap
+ TInt iSlabThreshold; // allocations < than this are done by the slab allocator
+ TInt iPageThreshold; // 2^n is smallest cell size allocated in paged allocator
+ TInt iSlabInitThreshold; // slab allocator will be used after chunk reaches this size
+ TUint32 iSlabConfigBits; // set of bits that specify which slab sizes to use
+ slab* iPartialPage; // partial-use page tree
+ slab* iFullSlab; // full slabs list (so we can find them when walking)
+ page* iSparePage; // cached, to avoid kernel exec calls for unmapping/remapping
+ TUint8 iSizeMap[(MAXSLABSIZE>>2)+1]; // index of slabset indexes based on size class
+ slabset iSlabAlloc[MAXSLABSIZE>>2]; // array of pointers to slabsets
+
+#endif // __KERNEL_MODE__
+};
+
+#define HEAP_ASSERT(x) __ASSERT_DEBUG(x, HEAP_PANIC(ETHeapBadCellAddress))
+
+template <class T> inline T Floor(const T addr, unsigned aln)
+{return T((unsigned(addr))&~(aln-1));}
+template <class T> inline T Ceiling(T addr, unsigned aln)
+{return T((unsigned(addr)+(aln-1))&~(aln-1));}
+template <class T> inline unsigned LowBits(T addr, unsigned aln)
+{return unsigned(addr)&(aln-1);}
+template <class T1, class T2> inline int PtrDiff(const T1* a1, const T2* a2)
+{return reinterpret_cast<const unsigned char*>(a1) - reinterpret_cast<const unsigned char*>(a2);}
+template <class T> inline T Offset(T addr, unsigned ofs)
+{return T(unsigned(addr)+ofs);}
+
+#endif //__HEAP_HYBRID_H__
diff --git a/src/corelib/arch/symbian/page_alloc_p.h b/src/corelib/arch/symbian/page_alloc_p.h
new file mode 100644
index 0000000000..f92bd332ff
--- /dev/null
+++ b/src/corelib/arch/symbian/page_alloc_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __KERNEL_MODE__
+
+const int MAXSMALLPAGEBITS = 68<<3;
+#define MINPAGEPOWER PAGESHIFT+2
+
+struct paged_bitmap
+{
+ public:
+ inline paged_bitmap() : iBase(0), iNbits(0) {}
+ void Init(unsigned char* p, unsigned size, unsigned bit);
+//
+ inline unsigned char* Addr() const;
+ inline unsigned Size() const;
+//
+ inline void Set(unsigned ix, unsigned bit);
+ inline unsigned operator[](unsigned ix) const;
+ bool Is(unsigned ix, unsigned len, unsigned bit) const;
+ void Set(unsigned ix, unsigned len, unsigned val);
+ void Setn(unsigned ix, unsigned len, unsigned bit);
+ unsigned Bits(unsigned ix, unsigned len) const; // little endian
+ int Find(unsigned start, unsigned bit) const;
+ private:
+ unsigned char* iBase;
+ unsigned iNbits;
+};
+
+#endif // __KERNEL_MODE__
diff --git a/src/corelib/arch/symbian/qatomic_generic_armv6.cpp b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp
new file mode 100644
index 0000000000..f9ce6fd154
--- /dev/null
+++ b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+** This file implements the generic atomics interface using ARMv6 assembly
+** instructions. It is more efficient than the inline versions when Qt is
+** built for the THUMB instruction set, as the required instructions are
+** only available in ARM state.
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_HAVE_ARMV6
+#ifndef SYMBIAN_E32_ATOMIC_API
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#ifdef Q_CC_RVCT
+#pragma push
+#pragma arm
+Q_CORE_EXPORT asm
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+retry_testAndSetOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ EORS r3,r3,r1 //if (r3 == expectedValue) {
+ STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error
+ TEQEQ r3,#1 //if error
+ BEQ retry_testAndSetOrdered //then goto retry }
+ RSBS r0,r3,#1 //return (r3 == 0)
+ MOVCC r0,#0
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ CODE32
+//R0 = _q_value
+//R1 = newValue
+retry_fetchAndStoreOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ STREX r2,r1,[r0] //*_q_value = newValue, r2 = error
+ TEQ r2,#0 //if error
+ BNE retry_fetchAndStoreOrdered //then goto retry
+ MOV r0,r3 //return r3
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = valueToAdd
+ STMDB sp!,{r12,lr}
+retry_fetchAndAddOrdered
+ LDREX r2,[r0] //r2 = *_q_value
+ ADD r3,r2,r1 //r3 = r2 + r1
+ STREX r12,r3,[r0] //*_q_value = r3, r12 = error
+ TEQ r12,#0 //if error
+ BNE retry_fetchAndAddOrdered //then retry
+ MOV r0,r2 //return r2
+ LDMIA sp!,{r12,pc}
+}
+
+Q_CORE_EXPORT asm
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+retryPointer_testAndSetOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ EORS r3,r3,r1 //if (r3 == expectedValue) {
+ STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error
+ TEQEQ r3,#1 //if error
+ BEQ retryPointer_testAndSetOrdered //then goto retry }
+ RSBS r0,r3,#1 //return (r3 == 0)
+ MOVCC r0,#0
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = newValue
+retryPointer_fetchAndStoreOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ STREX r2,r1,[r0] //*_q_value = newValue, r2 = error
+ TEQ r2,#0 //if error
+ BNE retryPointer_fetchAndStoreOrdered //then goto retry
+ MOV r0,r3 //return r3
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ CODE32
+ //fall through
+}
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = valueToAdd
+ STMDB sp!,{r12,lr}
+retryPointer_fetchAndAddOrdered
+ LDREX r2,[r0] //r2 = *_q_value
+ ADD r3,r2,r1 //r3 = r2 + r1
+ STREX r12,r3,[r0] //*_q_value = r3, r12 = error
+ TEQ r12,#0 //if error
+ BNE retryPointer_fetchAndAddOrdered //then retry
+ MOV r0,r2 //return r2
+ LDMIA sp!,{r12,pc}
+}
+
+#pragma pop
+#elif defined (Q_CC_GCCE)
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+ asm("retry_testAndSetOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) {
+ asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error
+ asm(" TEQEQ r3,#1"); //if error
+ asm(" BEQ retry_testAndSetOrdered"); //then goto retry }
+ asm(" RSBS r0,r3,#1"); //return (r3 == 0)
+ asm(" MOVCC r0,#0");
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+//R0 = _q_value
+//R1 = newValue
+ asm("retry_fetchAndStoreOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error
+ asm(" TEQ r2,#0"); //if error
+ asm(" BNE retry_fetchAndStoreOrdered"); //then goto retry
+ asm(" MOV r0,r3"); //return r3
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ //R0 = _q_value
+ //R1 = valueToAdd
+ asm(" STMDB sp!,{r12,lr}");
+ asm("retry_fetchAndAddOrdered:");
+ asm(" LDREX r2,[r0]"); //r2 = *_q_value
+ asm(" ADD r3,r2,r1 "); //r3 = r2 + r1
+ asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error
+ asm(" TEQ r12,#0"); //if error
+ asm(" BNE retry_fetchAndAddOrdered"); //then retry
+ asm(" MOV r0,r2"); //return r2
+ asm(" LDMIA sp!,{r12,pc}");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+ asm("retryPointer_testAndSetOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) {
+ asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error
+ asm(" TEQEQ r3,#1"); //if error
+ asm(" BEQ retryPointer_testAndSetOrdered"); //then goto retry }
+ asm(" RSBS r0,r3,#1"); //return (r3 == 0)
+ asm(" MOVCC r0,#0");
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ //R0 = _q_value
+ //R1 = newValue
+ asm("retryPointer_fetchAndStoreOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error
+ asm(" TEQ r2,#0"); //if error
+ asm(" BNE retryPointer_fetchAndStoreOrdered"); //then goto retry
+ asm(" MOV r0,r3"); //return r3
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ //fall through
+}
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ //R0 = _q_value
+ //R1 = valueToAdd
+ asm(" STMDB sp!,{r12,lr}");
+ asm("retryPointer_fetchAndAddOrdered:");
+ asm(" LDREX r2,[r0]"); //r2 = *_q_value
+ asm(" ADD r3,r2,r1"); //r3 = r2 + r1
+ asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error
+ asm(" TEQ r12,#0"); //if error
+ asm(" BNE retryPointer_fetchAndAddOrdered"); //then retry
+ asm(" MOV r0,r2"); //return r2
+ asm(" LDMIA sp!,{r12,pc}");
+}
+#else
+#error unknown arm compiler
+#endif
+QT_END_NAMESPACE
+#endif
+#endif
diff --git a/src/corelib/arch/symbian/qatomic_symbian.cpp b/src/corelib/arch/symbian/qatomic_symbian.cpp
new file mode 100644
index 0000000000..9b997e1a70
--- /dev/null
+++ b/src/corelib/arch/symbian/qatomic_symbian.cpp
@@ -0,0 +1,527 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+
+#ifdef SYMBIAN_E32_ATOMIC_API
+#include <e32atomics.h>
+#endif
+
+#include <e32debug.h>
+
+QT_BEGIN_NAMESPACE
+
+// Heap and handle info printer.
+// This way we can report on heap cells and handles that are really not owned by anything which still exists.
+// This information can be used to detect whether memory leaks are happening, particularly if these numbers grow as the app is used more.
+// This code is placed here as it happens to make it the very last static to be destroyed in a Qt app. The
+// reason assumed is that this file appears before any other file declaring static data in the generated
+// Symbian MMP file. This particular file was chosen as it is the earliest symbian specific file.
+struct QSymbianPrintExitInfo
+{
+ QSymbianPrintExitInfo()
+ {
+ RThread().HandleCount(initProcessHandleCount, initThreadHandleCount);
+ initCells = User::CountAllocCells();
+ }
+ ~QSymbianPrintExitInfo()
+ {
+ RProcess myProc;
+ TFullName fullName = myProc.FileName();
+ TInt cells = User::CountAllocCells();
+ TInt processHandleCount=0;
+ TInt threadHandleCount=0;
+ RThread().HandleCount(processHandleCount, threadHandleCount);
+ RDebug::Print(_L("%S exiting with %d allocated cells, %d handles"),
+ &fullName,
+ cells - initCells,
+ (processHandleCount + threadHandleCount) - (initProcessHandleCount + initThreadHandleCount));
+ }
+ TInt initCells;
+ TInt initProcessHandleCount;
+ TInt initThreadHandleCount;
+} symbian_printExitInfo;
+
+Q_CORE_EXPORT bool QBasicAtomicInt::isReferenceCountingNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicInt::isTestAndSetNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndStoreNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndAddNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isTestAndSetNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndStoreNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndAddNative()
+{
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
+ return true;
+#else
+ return false;
+#endif
+}
+
+#ifdef SYMBIAN_E32_ATOMIC_API
+//Symbian's API is SMP-safe when using SMP kernel, and cheap when using uniprocessor kernel
+
+//generate compiler error if casting assumptions are wrong (symbian64?)
+__ASSERT_COMPILE(sizeof(int) == sizeof(TUint32));
+__ASSERT_COMPILE(sizeof(void *) == sizeof(TUint32));
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_ord32(_q_value,
+ reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_rlx32(_q_value,
+ reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_acq32(_q_value,
+ reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_rel32(_q_value,
+ reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ return static_cast<int>(__e32_atomic_swp_ord32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+ return static_cast<int>(__e32_atomic_swp_rlx32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+ return static_cast<int>(__e32_atomic_swp_acq32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+ return static_cast<int>(__e32_atomic_swp_rel32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ return static_cast<int>(__e32_atomic_add_ord32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+ return static_cast<int>(__e32_atomic_add_rlx32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+ return static_cast<int>(__e32_atomic_add_acq32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+ return static_cast<int>(__e32_atomic_add_rel32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_ord_ptr(_q_value,
+ &expectedValue,
+ newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_rlx_ptr(_q_value,
+ &expectedValue,
+ newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_acq_ptr(_q_value,
+ &expectedValue,
+ newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return static_cast<bool>(__e32_atomic_cas_rel_ptr(_q_value,
+ &expectedValue,
+ newValue));
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ return __e32_atomic_swp_ord_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+ return __e32_atomic_swp_rlx_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+ return __e32_atomic_swp_acq_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+ return __e32_atomic_swp_rel_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return __e32_atomic_add_ord_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return __e32_atomic_add_rlx_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return __e32_atomic_add_acq_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return __e32_atomic_add_rel_ptr(_q_value, valueToAdd);
+}
+
+#else
+//Symbian kernels 9.4 and earlier don't expose a suitable API
+
+//For ARMv6, the generic atomics are machine coded
+#ifndef QT_HAVE_ARMV6
+
+class QCriticalSection
+{
+public:
+ QCriticalSection() { fastlock.CreateLocal(); }
+ ~QCriticalSection() { fastlock.Close(); }
+ void lock() { fastlock.Wait(); }
+ void unlock() { fastlock.Signal(); }
+
+private:
+ RFastLock fastlock;
+};
+
+QCriticalSection qAtomicCriticalSection;
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value += valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+ return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+ return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+ return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+#endif // QT_HAVE_ARMV6
+#endif // SYMBIAN_E32_ATOMIC_API
+
+QT_END_NAMESPACE
diff --git a/src/corelib/arch/symbian/qt_heapsetup_symbian.cpp b/src/corelib/arch/symbian/qt_heapsetup_symbian.cpp
new file mode 100644
index 0000000000..27ed4bcd10
--- /dev/null
+++ b/src/corelib/arch/symbian/qt_heapsetup_symbian.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt_hybridheap_symbian_p.h"
+
+#ifdef QT_USE_NEW_SYMBIAN_ALLOCATOR
+
+extern const TInt KHeapShrinkHysRatio = 0x800;
+
+/*
+ * \internal
+ * Called from the qtmain.lib application wrapper.
+ * Create a new heap as requested, but use the new allocator
+ */
+Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
+{
+ TInt r = KErrNone;
+ if (!aInfo.iAllocator && aInfo.iHeapInitialSize>0)
+ {
+ // new heap required
+ RHeap* pH = NULL;
+ r = UserHeap::CreateThreadHeap(aInfo, pH);
+ }
+ else if (aInfo.iAllocator)
+ {
+ // sharing a heap
+ RAllocator* pA = aInfo.iAllocator;
+ pA->Open();
+ User::SwitchAllocator(pA);
+ }
+ return r;
+}
+
+#ifndef NO_NAMED_LOCAL_CHUNKS
+void TChunkCreateInfo::SetThreadHeap(TInt aInitialSize, TInt aMaxSize, const TDesC& aName)
+{
+ iType = TChunkCreate::ENormal | TChunkCreate::EData;
+ iMaxSize = aMaxSize;
+ iInitialBottom = 0;
+ iInitialTop = aInitialSize;
+ iAttributes |= TChunkCreate::ELocalNamed;
+ iName = &aName;
+ iOwnerType = EOwnerThread;
+}
+#endif // NO_NAMED_LOCAL_CHUNKS
+
+void Panic(TCdtPanic reason)
+{
+ _LIT(KCat, "QtHybridHeap");
+ User::Panic(KCat, reason);
+}
+
+#else /* QT_USE_NEW_SYMBIAN_ALLOCATOR */
+
+#include <e32std.h>
+
+/*
+ * \internal
+ * Called from the qtmain.lib application wrapper.
+ * Create a new heap as requested, using the default system allocator
+ */
+Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
+{
+ return UserHeap::SetupThreadHeap(aNotFirst, aInfo);
+}
+
+#endif /* QT_USE_NEW_SYMBIAN_ALLOCATOR */
diff --git a/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h b/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h
new file mode 100644
index 0000000000..d1ce7056f4
--- /dev/null
+++ b/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_HYBRIDHEAP_SYMBIAN_H
+#define QT_HYBRIDHEAP_SYMBIAN_H
+
+#include <qglobal.h>
+#include <e32cmn.h>
+
+#if !defined(__SYMBIAN_KERNEL_HYBRID_HEAP__) && !defined(__WINS__)
+//Enable the (backported) new allocator. When it is available in OS,
+//this flag should be disabled for that OS version onward
+#define QT_USE_NEW_SYMBIAN_ALLOCATOR
+#endif
+
+#ifdef QT_USE_NEW_SYMBIAN_ALLOCATOR
+
+#ifdef Q_CC_RVCT
+#pragma push
+#pragma arm
+#pragma Otime
+#pragma O2
+#endif
+
+#include "common_p.h"
+#ifdef QT_SYMBIAN_HAVE_U32STD_H
+#include <u32std.h>
+#endif
+#ifdef QT_SYMBIAN_HAVE_E32BTRACE_H
+#include <e32btrace.h>
+// enables btrace code compiling into
+#define ENABLE_BTRACE
+#endif
+#ifdef __KERNEL_MODE__
+#include <kernel/kern_priv.h>
+#endif
+#include "dla_p.h"
+#ifndef __KERNEL_MODE__
+#include "slab_p.h"
+#include "page_alloc_p.h"
+#endif
+#include "heap_hybrid_p.h"
+
+// disabling Symbian import/export macros to prevent heap_hybrid.cpp, copied from Symbian^4, from exporting symbols in arm builds
+// this minimises the code changes to heap_hybrid.cpp to ease future integration
+#undef UEXPORT_C
+#define UEXPORT_C
+#undef EXPORT_C
+#define EXPORT_C
+#undef IMPORT_D
+#define IMPORT_D
+
+// disabling code ported from Symbian^4 that we don't want/can't have in earlier platforms
+#define QT_SYMBIAN4_ALLOCATOR_UNWANTED_CODE
+
+#if defined(SYMBIAN_VERSION_9_1) || defined(SYMBIAN_VERSION_9_2) || defined(SYMBIAN_VERSION_9_3) || defined(SYMBIAN_VERSION_9_4) || defined(SYMBIAN_VERSION_SYMBIAN2)
+#define NO_NAMED_LOCAL_CHUNKS
+#endif
+
+// disabling the BTrace components of heap checking macros
+#ifndef ENABLE_BTRACE
+inline int noBTrace() {return 0;}
+#define BTraceContext12(a,b,c,d,e) noBTrace()
+#endif
+
+// declare ETHeapBadDebugFailParameter, where missing
+#define ETHeapBadDebugFailParameter ((TCdtPanic)213)
+
+#ifndef QT_SYMBIAN_HAVE_U32STD_H
+struct SThreadCreateInfo
+ {
+ TAny* iHandle;
+ TInt iType;
+ TThreadFunction iFunction;
+ TAny* iPtr;
+ TAny* iSupervisorStack;
+ TInt iSupervisorStackSize;
+ TAny* iUserStack;
+ TInt iUserStackSize;
+ TInt iInitialThreadPriority;
+ TPtrC iName;
+ TInt iTotalSize; // Size including any extras (must be a multiple of 8 bytes)
+ };
+
+struct SStdEpocThreadCreateInfo : public SThreadCreateInfo
+ {
+ RAllocator* iAllocator;
+ TInt iHeapInitialSize;
+ TInt iHeapMaxSize;
+ TInt iPadding; // Make structure size a multiple of 8 bytes
+ };
+
+class TChunkCreate
+ {
+public:
+ // Attributes for chunk creation that are used by both euser and the kernel
+ // by classes TChunkCreateInfo and SChunkCreateInfo, respectively.
+ enum TChunkCreateAtt
+ {
+ ENormal = 0x00000000,
+ EDoubleEnded = 0x00000001,
+ EDisconnected = 0x00000002,
+ ECache = 0x00000003,
+ EMappingMask = 0x0000000f,
+ ELocal = 0x00000000,
+ EGlobal = 0x00000010,
+ EData = 0x00000000,
+ ECode = 0x00000020,
+ EMemoryNotOwned = 0x00000040,
+
+ // Force local chunk to be named. Only required for thread heap
+ // chunks, all other local chunks should be nameless.
+ ELocalNamed = 0x000000080,
+
+ // Make global chunk read only to all processes but the controlling owner
+ EReadOnly = 0x000000100,
+
+ // Paging attributes for chunks.
+ EPagingUnspec = 0x00000000,
+ EPaged = 0x80000000,
+ EUnpaged = 0x40000000,
+ EPagingMask = EPaged | EUnpaged,
+
+ EChunkCreateAttMask = EMappingMask | EGlobal | ECode |
+ ELocalNamed | EReadOnly | EPagingMask,
+ };
+public:
+ TUint iAtt;
+ TBool iForceFixed;
+ TInt iInitialBottom;
+ TInt iInitialTop;
+ TInt iMaxSize;
+ TUint8 iClearByte;
+ };
+
+#endif // QT_SYMBIAN_HAVE_U32STD_H
+
+#endif /* QT_USE_NEW_SYMBIAN_ALLOCATOR */
+
+#endif /* QT_HYBRIDHEAP_SYMBIAN_H */
diff --git a/src/corelib/arch/symbian/slab_p.h b/src/corelib/arch/symbian/slab_p.h
new file mode 100644
index 0000000000..2451bbf151
--- /dev/null
+++ b/src/corelib/arch/symbian/slab_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __KERNEL_MODE__
+
+class slab;
+class slabhdr;
+#define MAXSLABSIZE 56
+#define PAGESHIFT 12
+#define PAGESIZE (1<<PAGESHIFT)
+#define SLABSHIFT 10
+#define SLABSIZE (1 << SLABSHIFT)
+#define CELLALIGN 8
+
+
+const unsigned slabfull = 0;
+const TInt slabsperpage = (int)(PAGESIZE/SLABSIZE);
+#define HIBIT(bits) (((unsigned)bits & 0xc) ? 2 + ((unsigned)bits>>3) : ((unsigned) bits>>1))
+
+#define LOWBIT(bits) (((unsigned) bits&3) ? 1 - ((unsigned)bits&1) : 3 - (((unsigned)bits>>2)&1))
+
+#define ZEROBITS(header) (((unsigned)header & 0x70000000) ? 0 : 1)
+
+class slabhdr
+{
+ public:
+ unsigned iHeader;
+ // made up of
+ // bits | 31 | 30..28 | 27..18 | 17..12 | 11..8 | 7..0 |
+ // +----------+--------+--------+--------+---------+----------+
+ // field | floating | zero | used-4 | size | pagemap | free pos |
+ //
+ slab** iParent; // reference to iParent's pointer to this slab in tree
+ slab* iChild1; // 1st iChild in tree
+ slab* iChild2; // 2nd iChild in tree
+};
+
+const TInt KMaxSlabPayload = SLABSIZE - sizeof(slabhdr);
+#define MAXUSEDM4BITS 0x0fc00000
+#define FLOATING_BIT 0x80000000
+
+inline unsigned HeaderFloating(unsigned h)
+{return (h&0x80000000);}
+const unsigned maxuse = (SLABSIZE - sizeof(slabhdr))>>2;
+const unsigned firstpos = sizeof(slabhdr)>>2;
+
+#ifdef _DEBUG
+#define CHECKTREE(x) DoCheckSlabTree(x,EFalse)
+#define CHECKSLAB(s,t,p) DoCheckSlab(s,t,p)
+#define CHECKSLABBFR(s,p) {TUint32 b[4]; BuildPartialSlabBitmap(b,s,p);}
+#else
+#define CHECKTREE(x) (void)0
+#define CHECKSLAB(s,t,p) (void)0
+#define CHECKSLABBFR(s,p) (void)0
+#endif
+
+class slabset
+{
+ public:
+ slab* iPartial;
+};
+
+class slab : public slabhdr
+{
+ public:
+ void Init(unsigned clz);
+ //static slab* SlabFor( void* p);
+ static slab* SlabFor(const void* p) ;
+ unsigned char iPayload[SLABSIZE-sizeof(slabhdr)];
+};
+
+class page
+{
+ public:
+ inline static page* PageFor(slab* s);
+ //slab iSlabs;
+ slab iSlabs[slabsperpage];
+};
+
+
+inline page* page::PageFor(slab* s)
+{
+ return reinterpret_cast<page*>((unsigned(s))&~(PAGESIZE-1));
+}
+
+
+#endif // __KERNEL_MODE__
diff --git a/src/corelib/arch/vxworks/arch.pri b/src/corelib/arch/vxworks/arch.pri
new file mode 100644
index 0000000000..a7686186b0
--- /dev/null
+++ b/src/corelib/arch/vxworks/arch.pri
@@ -0,0 +1,6 @@
+#
+# VxWorks generic
+#
+*-ppc-* {
+ SOURCES += qatomic_ppc.s
+}
diff --git a/src/corelib/arch/vxworks/qatomic_ppc.s b/src/corelib/arch/vxworks/qatomic_ppc.s
new file mode 100644
index 0000000000..03971e89e8
--- /dev/null
+++ b/src/corelib/arch/vxworks/qatomic_ppc.s
@@ -0,0 +1,415 @@
+
+ .align 2
+ .globl q_atomic_test_and_set_int
+ .globl .q_atomic_test_and_set_int
+q_atomic_test_and_set_int:
+.q_atomic_test_and_set_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int
+ .short 25
+ .byte "q_atomic_test_and_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_int
+ .globl .q_atomic_test_and_set_acquire_int
+q_atomic_test_and_set_acquire_int:
+.q_atomic_test_and_set_acquire_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stwcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int
+ .short 33
+ .byte "q_atomic_test_and_set_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_int
+ .globl .q_atomic_test_and_set_release_int
+q_atomic_test_and_set_release_int:
+.q_atomic_test_and_set_release_int:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int
+ .short 33
+ .byte "q_atomic_test_and_set_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_ptr
+ .globl .q_atomic_test_and_set_ptr
+q_atomic_test_and_set_ptr:
+.q_atomic_test_and_set_ptr:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr
+ .short 25
+ .byte "q_atomic_test_and_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_acquire_ptr
+ .globl .q_atomic_test_and_set_acquire_ptr
+q_atomic_test_and_set_acquire_ptr:
+.q_atomic_test_and_set_acquire_ptr:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+16
+ stwcx. 5,0,3
+ bne- $-16
+ isync
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr
+ .short 25
+ .byte "q_atomic_test_and_set_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_test_and_set_release_ptr
+ .globl .q_atomic_test_and_set_release_ptr
+q_atomic_test_and_set_release_ptr:
+.q_atomic_test_and_set_release_ptr:
+ lwarx 6,0,3
+ xor. 6,6,4
+ bne $+12
+ stwcx. 5,0,3
+ bne- $-16
+ subfic 3,6,0
+ adde 3,3,6
+ blr
+LT..q_atomic_test_and_set_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,3,0
+ .long 0
+ .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr
+ .short 33
+ .byte "q_atomic_test_and_set_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_increment
+ .globl .q_atomic_increment
+q_atomic_increment:
+.q_atomic_increment:
+ lwarx 4,0,3
+ addi 4,4,1
+ stwcx. 4,0,3
+ bne- $-12
+ mr 3,4
+ blr
+LT..q_atomic_increment:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_increment-.q_atomic_increment
+ .short 18
+ .byte "q_atomic_increment"
+ .align 2
+
+ .align 2
+ .globl q_atomic_decrement
+ .globl .q_atomic_decrement
+q_atomic_decrement:
+.q_atomic_decrement:
+ lwarx 4,0,3
+ subi 4,4,1
+ stwcx. 4,0,3
+ bne- $-12
+ mr 3,4
+ blr
+LT..q_atomic_decrement:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_decrement-.q_atomic_decrement
+ .short 18
+ .byte "q_atomic_decrement"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_int
+ .globl .q_atomic_set_int
+q_atomic_set_int:
+.q_atomic_set_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_set_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_int-.q_atomic_set_int
+ .short 16
+ .byte "q_atomic_set_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_int
+ .globl .q_atomic_fetch_and_store_acquire_int
+q_atomic_fetch_and_store_acquire_int:
+.q_atomic_fetch_and_store_acquire_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int
+ .short 16
+ .byte "q_atomic_fetch_and_store_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_int
+ .globl .q_atomic_fetch_and_store_release_int
+q_atomic_fetch_and_store_release_int:
+.q_atomic_fetch_and_store_release_int:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int
+ .short 16
+ .byte "q_atomic_fetch_and_store_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_set_ptr
+ .globl .q_atomic_set_ptr
+q_atomic_set_ptr:
+.q_atomic_set_ptr:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_set_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_set_ptr-.q_atomic_set_ptr
+ .short 16
+ .byte "q_atomic_set_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_acquire_ptr
+ .globl .q_atomic_fetch_and_store_acquire_ptr
+q_atomic_fetch_and_store_acquire_ptr:
+.q_atomic_fetch_and_store_acquire_ptr:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr
+ .short 16
+ .byte "q_atomic_fetch_and_store_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_store_release_ptr
+ .globl .q_atomic_fetch_and_store_release_ptr
+q_atomic_fetch_and_store_release_ptr:
+.q_atomic_fetch_and_store_release_ptr:
+ lwarx 5,0,3
+ stwcx. 4,0,3
+ bne- $-8
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_store_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,2,0
+ .long 0
+ .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr
+ .short 16
+ .byte "q_atomic_fetch_and_store_release_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_int
+ .globl .q_atomic_fetch_and_add_int
+q_atomic_fetch_and_add_int:
+.q_atomic_fetch_and_add_int:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int
+ .short 18
+ .byte "q_atomic_fetch_and_add_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_int
+ .globl .q_atomic_fetch_and_add_acquire_int
+q_atomic_fetch_and_add_acquire_int:
+.q_atomic_fetch_and_add_acquire_int:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int
+ .short 18
+ .byte "q_atomic_fetch_and_add_acquire_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_int
+ .globl .q_atomic_fetch_and_add_release_int
+q_atomic_fetch_and_add_release_int:
+.q_atomic_fetch_and_add_release_int:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_int:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_int"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_ptr
+ .globl .q_atomic_fetch_and_add_ptr
+q_atomic_fetch_and_add_ptr:
+.q_atomic_fetch_and_add_ptr:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr
+ .short 26
+ .byte "q_atomic_fetch_and_add_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_acquire_ptr
+ .globl .q_atomic_fetch_and_add_acquire_ptr
+q_atomic_fetch_and_add_acquire_ptr:
+.q_atomic_fetch_and_add_acquire_ptr:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ isync
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_acquire_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_acquire_ptr"
+ .align 2
+
+ .align 2
+ .globl q_atomic_fetch_and_add_release_ptr
+ .globl .q_atomic_fetch_and_add_release_ptr
+q_atomic_fetch_and_add_release_ptr:
+.q_atomic_fetch_and_add_release_ptr:
+ lwarx 5,0,3
+ add 6,4,5
+ stwcx. 6,0,3
+ bne- $-12
+ mr 3,5
+ blr
+LT..q_atomic_fetch_and_add_release_ptr:
+ .long 0
+ .byte 0,9,32,64,0,0,1,0
+ .long 0
+ .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr
+ .short 34
+ .byte "q_atomic_fetch_and_add_release_ptr"
+ .align 2
+
+_section_.text:
+ .long _section_.text
diff --git a/src/corelib/arch/windows/arch.pri b/src/corelib/arch/windows/arch.pri
new file mode 100644
index 0000000000..d42374b98f
--- /dev/null
+++ b/src/corelib/arch/windows/arch.pri
@@ -0,0 +1,3 @@
+#
+# Windows architecture
+#
diff --git a/src/corelib/arch/x86_64/arch.pri b/src/corelib/arch/x86_64/arch.pri
new file mode 100644
index 0000000000..4145b7b133
--- /dev/null
+++ b/src/corelib/arch/x86_64/arch.pri
@@ -0,0 +1,4 @@
+#
+# AMD64 architecture
+#
+solaris-cc*:SOURCES += $$QT_ARCH_CPP/qatomic_sun.s
diff --git a/src/corelib/arch/x86_64/qatomic_sun.s b/src/corelib/arch/x86_64/qatomic_sun.s
new file mode 100644
index 0000000000..37969e61cb
--- /dev/null
+++ b/src/corelib/arch/x86_64/qatomic_sun.s
@@ -0,0 +1,91 @@
+ .code64
+
+ .globl q_atomic_increment
+ .type q_atomic_increment,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_increment:
+ lock
+ incl (%rdi)
+ setne %al
+ ret
+ .size q_atomic_increment,.-q_atomic_increment
+
+ .globl q_atomic_decrement
+ .type q_atomic_decrement,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_decrement:
+ lock
+ decl (%rdi)
+ setne %al
+ ret
+ .size q_atomic_decrement,.-q_atomic_decrement
+
+ .globl q_atomic_test_and_set_int
+ .type q_atomic_test_and_set_int, @function
+ .section .text, "ax"
+ .align 16
+q_atomic_test_and_set_int:
+ movl %esi,%eax
+ lock
+ cmpxchgl %edx,(%rdi)
+ movl $0,%eax
+ sete %al
+ ret
+ .size q_atomic_test_and_set_int, . - q_atomic_test_and_set_int
+
+ .globl q_atomic_set_int
+ .type q_atomic_set_int,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_set_int:
+ xchgl %esi,(%rdi)
+ movl %esi,%eax
+ ret
+ .size q_atomic_set_int,.-q_atomic_set_int
+
+ .globl q_atomic_fetch_and_add_int
+ .type q_atomic_fetch_and_add_int,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_fetch_and_add_int:
+ lock
+ xaddl %esi,(%rdi)
+ movl %esi, %eax
+ ret
+ .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int
+
+ .globl q_atomic_test_and_set_ptr
+ .type q_atomic_test_and_set_ptr, @function
+ .section .text, "ax"
+ .align 16
+q_atomic_test_and_set_ptr:
+ movq %rsi,%rax
+ lock
+ cmpxchgq %rdx,(%rdi)
+ movq $0, %rax
+ sete %al
+ ret
+ .size q_atomic_test_and_set_ptr, . - q_atomic_test_and_set_ptr
+
+ .globl q_atomic_set_ptr
+ .type q_atomic_set_ptr,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_set_ptr:
+ xchgq %rsi,(%rdi)
+ movq %rsi,%rax
+ ret
+ .size q_atomic_set_ptr,.-q_atomic_set_ptr
+
+ .globl q_atomic_fetch_and_add_ptr
+ .type q_atomic_fetch_and_add_ptr,@function
+ .section .text, "ax"
+ .align 16
+q_atomic_fetch_and_add_ptr:
+ lock
+ xaddq %rsi,(%rdi)
+ movq %rsi,%rax
+ ret
+ .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr
diff --git a/src/corelib/codecs/codecs.pri b/src/corelib/codecs/codecs.pri
new file mode 100644
index 0000000000..46d7dd46da
--- /dev/null
+++ b/src/corelib/codecs/codecs.pri
@@ -0,0 +1,59 @@
+# Qt core library codecs module
+
+HEADERS += \
+ codecs/qisciicodec_p.h \
+ codecs/qlatincodec_p.h \
+ codecs/qsimplecodec_p.h \
+ codecs/qtextcodec_p.h \
+ codecs/qtextcodec.h \
+ codecs/qtsciicodec_p.h \
+ codecs/qutfcodec_p.h \
+ codecs/qtextcodecplugin.h
+
+SOURCES += \
+ codecs/qisciicodec.cpp \
+ codecs/qlatincodec.cpp \
+ codecs/qsimplecodec.cpp \
+ codecs/qtextcodec.cpp \
+ codecs/qtsciicodec.cpp \
+ codecs/qutfcodec.cpp \
+ codecs/qtextcodecplugin.cpp
+
+unix {
+ SOURCES += codecs/qfontlaocodec.cpp
+
+ contains(QT_CONFIG,iconv) {
+ HEADERS += codecs/qiconvcodec_p.h
+ SOURCES += codecs/qiconvcodec.cpp
+ } else:contains(QT_CONFIG,gnu-libiconv) {
+ HEADERS += codecs/qiconvcodec_p.h
+ SOURCES += codecs/qiconvcodec.cpp
+
+ DEFINES += GNU_LIBICONV
+ !mac:LIBS_PRIVATE *= -liconv
+ } else:contains(QT_CONFIG,sun-libiconv) {
+ HEADERS += codecs/qiconvcodec_p.h
+ SOURCES += codecs/qiconvcodec.cpp
+ DEFINES += GNU_LIBICONV
+ } else:!symbian {
+ # no iconv, so we put all plugins in the library
+ HEADERS += \
+ ../plugins/codecs/cn/qgb18030codec.h \
+ ../plugins/codecs/jp/qeucjpcodec.h \
+ ../plugins/codecs/jp/qjiscodec.h \
+ ../plugins/codecs/jp/qsjiscodec.h \
+ ../plugins/codecs/kr/qeuckrcodec.h \
+ ../plugins/codecs/tw/qbig5codec.h \
+ ../plugins/codecs/jp/qfontjpcodec.h
+ SOURCES += \
+ ../plugins/codecs/cn/qgb18030codec.cpp \
+ ../plugins/codecs/jp/qjpunicode.cpp \
+ ../plugins/codecs/jp/qeucjpcodec.cpp \
+ ../plugins/codecs/jp/qjiscodec.cpp \
+ ../plugins/codecs/jp/qsjiscodec.cpp \
+ ../plugins/codecs/kr/qeuckrcodec.cpp \
+ ../plugins/codecs/tw/qbig5codec.cpp \
+ ../plugins/codecs/jp/qfontjpcodec.cpp
+ }
+}
+symbian:LIBS += -lcharconv
diff --git a/src/corelib/codecs/codecs.qdoc b/src/corelib/codecs/codecs.qdoc
new file mode 100644
index 0000000000..c88f073f28
--- /dev/null
+++ b/src/corelib/codecs/codecs.qdoc
@@ -0,0 +1,532 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group codecs
+ \title Codecs
+ \ingroup groups
+ \brief Codec support in Qt.
+
+ These codecs provide facilities for conversion between Unicode and
+ specific text encodings.
+
+ \generatelist{related}
+*/
+
+/*!
+ \page codec-big5.html
+ \title Big5 Text Codec
+ \ingroup codecs
+
+ The Big5 codec provides conversion to and from the Big5 encoding.
+ The code was originally contributed by Ming-Che Chuang
+ \<mingche@cobra.ee.ntu.edu.tw\> for the Big-5+ encoding, and was
+ included in Qt with the author's permission, and the grateful
+ thanks of the Qt team. (Note: Ming-Che's code is QPL'd, as
+ per an mail to qt-info@nokia.com.)
+
+ However, since Big-5+ was never formally approved, and was never
+ used by anyone, the Taiwan Free Software community and the Li18nux
+ Big5 Standard Subgroup agree that the de-facto standard Big5-ETen
+ (zh_TW.Big5 or zh_TW.TW-Big5) be used instead.
+
+ The Big5 is currently implemented as a pure subset of the
+ Big5-HKSCS codec, so more fine-tuning is needed to make it
+ identical to the standard Big5 mapping as determined by
+ Li18nux-Big5. See \l{http://www.autrijus.org/xml/} for the draft
+ Big5 (2002) standard.
+
+ James Su \<suzhe@turbolinux.com.cn\> \<suzhe@gnuchina.org\>
+ generated the Big5-HKSCS-to-Unicode tables with a very
+ space-efficient algorithm. He generously donated his code to glibc
+ in May 2002. Subsequently, James has kindly allowed Anthony Fok
+ \<anthony@thizlinux.com\> \<foka@debian.org\> to adapt the code
+ for Qt.
+
+ \legalese
+ Copyright (C) 2000 Ming-Che Chuang \BR
+ Copyright (C) 2002 James Su, Turbolinux Inc. \BR
+ Copyright (C) 2002 Anthony Fok, ThizLinux Laboratory Ltd.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-big5hkscs.html
+ \title Big5-HKSCS Text Codec
+ \ingroup codecs
+
+ The Big5-HKSCS codec provides conversion to and from the
+ Big5-HKSCS encoding.
+
+ The codec grew out of the QBig5Codec originally contributed by
+ Ming-Che Chuang \<mingche@cobra.ee.ntu.edu.tw\>. James Su
+ \<suzhe@turbolinux.com.cn\> \<suzhe@gnuchina.org\> and Anthony Fok
+ \<anthony@thizlinux.com\> \<foka@debian.org\> implemented HKSCS-1999
+ QBig5hkscsCodec for Qt-2.3.x, but it was too late in Qt development
+ schedule to be officially included in the Qt-2.3.x series.
+
+ Wu Yi \<wuyi@hancom.com\> ported the HKSCS-1999 QBig5hkscsCodec to
+ Qt-3.0.1 in March 2002.
+
+ With the advent of the new HKSCS-2001 standard, James Su
+ \<suzhe@turbolinux.com.cn\> \<suzhe@gnuchina.org\> generated the
+ Big5-HKSCS<->Unicode tables with a very space-efficient algorithm.
+ He generously donated his code to glibc in May 2002. Subsequently,
+ James has generously allowed Anthony Fok to adapt the code for
+ Qt-3.0.5.
+
+ Currently, the Big5-HKSCS tables are generated from the following
+ sources, and with the Euro character added:
+ \list 1
+ \o \l{http://www.microsoft.com/typography/unicode/950.txt}
+ \o \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5-iso.txt}
+ \o \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5cmp.txt}
+ \endlist
+
+ There may be more fine-tuning to the QBig5hkscsCodec to maximize its
+ compatibility with the standard Big5 (2002) mapping as determined by
+ Li18nux Big5 Standard Subgroup. See \l{http://www.autrijus.org/xml/}
+ for the various Big5 CharMapML tables.
+
+ \legalese
+ Copyright (C) 2000 Ming-Che Chuang \BR
+ Copyright (C) 2001, 2002 James Su, Turbolinux Inc. \BR
+ Copyright (C) 2002 WU Yi, HancomLinux Inc. \BR
+ Copyright (C) 2001, 2002 Anthony Fok, ThizLinux Laboratory Ltd.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-eucjp.html
+ \title EUC-JP Text Codec
+ \ingroup codecs
+
+ The EUC-JP codec provides conversion to and from EUC-JP, the main
+ legacy encoding for Unix machines in Japan.
+
+ The environment variable \c UNICODEMAP_JP can be used to
+ fine-tune the JIS, Shift-JIS, and EUC-JP codecs. The \l{ISO
+ 2022-JP (JIS) Text Codec} documentation describes how to use this
+ variable.
+
+ Most of the code here was written by Serika Kurusugawa,
+ a.k.a. Junji Takagi, and is included in Qt with the author's
+ permission and the grateful thanks of the Qt team. Here is
+ the copyright statement for that code:
+
+ \legalese
+
+ Copyright (C) 1999 Serika Kurusugawa. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS".
+ 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-euckr.html
+ \title EUC-KR Text Codec
+ \ingroup codecs
+
+ The EUC-KR codec provides conversion to and from EUC-KR, KR, the
+ main legacy encoding for Unix machines in Korea.
+
+ It was largely written by Mizi Research Inc. Here is the
+ copyright statement for the code as it was at the point of
+ contribution. The subsequent modifications are covered by
+ the usual copyright for Qt.
+
+ \legalese
+
+ Copyright (C) 1999-2000 Mizi Research 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:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-gbk.html
+ \title GBK Text Codec
+ \ingroup codecs
+
+ The GBK codec provides conversion to and from the Chinese
+ GB18030/GBK/GB2312 encoding.
+
+ GBK, formally the Chinese Internal Code Specification, is a commonly
+ used extension of GB 2312-80. Microsoft Windows uses it under the
+ name codepage 936.
+
+ GBK has been superseded by the new Chinese national standard
+ GB 18030-2000, which added a 4-byte encoding while remaining
+ compatible with GB2312 and GBK. The new GB 18030-2000 may be described
+ as a special encoding of Unicode 3.x and ISO-10646-1.
+
+ Special thanks to charset gurus Markus Scherer (IBM),
+ Dirk Meyer (Adobe Systems) and Ken Lunde (Adobe Systems) for publishing
+ an excellent GB 18030-2000 summary and specification on the Internet.
+ Some must-read documents are:
+
+ \list
+ \o \l{ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/pdf/GB18030_Summary.pdf}
+ \o \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/source/gb18030/gb18030.html}
+ \o \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/data/xml/gb-18030-2000.xml}
+ \endlist
+
+ The GBK codec was contributed to Qt by
+ Justin Yu \<justiny@turbolinux.com.cn\> and
+ Sean Chen \<seanc@turbolinux.com.cn\>. They may also be reached at
+ Yu Mingjian \<yumj@sun.ihep.ac.cn\>, \<yumingjian@china.com\>
+ Chen Xiangyang \<chenxy@sun.ihep.ac.cn\>
+
+ The GB18030 codec Qt functions were contributed to Qt by
+ James Su \<suzhe@gnuchina.org\>, \<suzhe@turbolinux.com.cn\>
+ who pioneered much of GB18030 development on GNU/Linux systems.
+
+ The GB18030 codec was contributed to Qt by
+ Anthony Fok \<anthony@thizlinux.com\>, \<foka@debian.org\>
+ using a Perl script to generate C++ tables from gb-18030-2000.xml
+ while merging contributions from James Su, Justin Yu and Sean Chen.
+ A copy of the source Perl script is available at
+ \l{http://people.debian.org/~foka/gb18030/gen-qgb18030codec.pl}
+
+ The copyright notice for their code follows:
+
+ \legalese
+ Copyright (C) 2000 TurboLinux, Inc. Written by Justin Yu and Sean Chen. \BR
+ Copyright (C) 2001, 2002 Turbolinux, Inc. Written by James Su. \BR
+ Copyright (C) 2001, 2002 ThizLinux Laboratory Ltd. Written by Anthony Fok.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codecs-jis.html
+ \title ISO 2022-JP (JIS) Text Codec
+ \ingroup codecs
+
+ The JIS codec provides conversion to and from ISO 2022-JP.
+
+ The environment variable \c UNICODEMAP_JP can be used to
+ fine-tune the JIS, Shift-JIS, and EUC-JP codecs. The mapping
+ names are as for the Japanese XML working group's \link
+ http://www.y-adagio.com/public/standards/tr_xml_jpf/toc.htm XML
+ Japanese Profile\endlink, because it names and explains all the
+ widely used mappings. Here are brief descriptions, written by
+ Serika Kurusugawa:
+
+ \list
+
+ \o "unicode-0.9" or "unicode-0201" for Unicode style. This assumes
+ JISX0201 for 0x00-0x7f. (0.9 is a table version of jisx02xx mapping
+ used for Unicode 1.1.)
+
+ \o "unicode-ascii" This assumes US-ASCII for 0x00-0x7f; some
+ chars (JISX0208 0x2140 and JISX0212 0x2237) are different from
+ Unicode 1.1 to avoid conflict.
+
+ \o "open-19970715-0201" ("open-0201" for convenience) or
+ "jisx0221-1995" for JISX0221-JISX0201 style. JIS X 0221 is JIS
+ version of Unicode, but a few chars (0x5c, 0x7e, 0x2140, 0x216f,
+ 0x2131) are different from Unicode 1.1. This is used when 0x5c is
+ treated as YEN SIGN.
+
+ \o "open-19970715-ascii" ("open-ascii" for convenience) for
+ JISX0221-ASCII style. This is used when 0x5c is treated as REVERSE
+ SOLIDUS.
+
+ \o "open-19970715-ms" ("open-ms" for convenience) or "cp932" for
+ Microsoft Windows style. Windows Code Page 932. Some chars (0x2140,
+ 0x2141, 0x2142, 0x215d, 0x2171, 0x2172) are different from Unicode
+ 1.1.
+
+ \o "jdk1.1.7" for Sun's JDK style. Same as Unicode 1.1, except that
+ JIS 0x2140 is mapped to UFF3C. Either ASCII or JISX0201 can be used
+ for 0x00-0x7f.
+
+ \endlist
+
+ In addition, the extensions "nec-vdc", "ibm-vdc" and "udc" are
+ supported.
+
+ For example, if you want to use Unicode style conversion but with
+ NEC's extension, set \c UNICODEMAP_JP to \c {unicode-0.9,
+ nec-vdc}. (You will probably need to quote that in a shell
+ command.)
+
+ Most of the code here was written by Serika Kurusugawa,
+ a.k.a. Junji Takagi, and is included in Qt with the author's
+ permission and the grateful thanks of the Qt team. Here is
+ the copyright statement for that code:
+
+ \legalese
+
+ Copyright (C) 1999 Serika Kurusugawa. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS".
+ 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-sjis.html
+ \title Shift-JIS Text Codec
+ \ingroup codecs
+
+ The Shift-JIS codec provides conversion to and from Shift-JIS, an
+ encoding of JIS X 0201 Latin, JIS X 0201 Kana and JIS X 0208.
+
+ The environment variable \c UNICODEMAP_JP can be used to
+ fine-tune the codec. The \l{ISO 2022-JP (JIS) Text Codec}
+ documentation describes how to use this variable.
+
+ Most of the code here was written by Serika Kurusugawa, a.k.a.
+ Junji Takagi, and is included in Qt with the author's permission
+ and the grateful thanks of the Qt team. Here is the
+ copyright statement for the code as it was at the point of
+ contribution. The subsequent modifications are covered by
+ the usual copyright for Qt.
+
+ \legalese
+
+ Copyright (C) 1999 Serika Kurusugawa. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS".
+ 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 REGENTS 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.
+ \endlegalese
+*/
+
+/*!
+ \page codec-tscii.html
+ \title TSCII Text Codec
+ \ingroup codecs
+
+ The TSCII codec provides conversion to and from the Tamil TSCII
+ encoding.
+
+ TSCII, formally the Tamil Standard Code Information Interchange
+ specification, is a commonly used charset for Tamils. The
+ official page for the standard is at
+ \link http://www.tamil.net/tscii/ http://www.tamil.net/tscii/\endlink
+
+ This codec uses the mapping table found at
+ \link http://www.geocities.com/Athens/5180/tsciiset.html
+ http://www.geocities.com/Athens/5180/tsciiset.html\endlink.
+ Tamil uses composed Unicode which might cause some
+ problems if you are using Unicode fonts instead of TSCII fonts.
+
+ Most of the code was written by Hans Petter Bieker and is
+ included in Qt with the author's permission and the grateful
+ thanks of the Qt team. Here is the copyright statement for
+ the code as it was at the point of contribution. The
+ subsequent modifications are covered by the usual copyright for
+ Qt:
+
+ \legalese
+
+ Copyright (c) 2000 Hans Petter Bieker. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ \list 1
+ \o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ \o 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.
+ \endlist
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ \endlegalese
+*/
diff --git a/src/corelib/codecs/qfontlaocodec.cpp b/src/corelib/codecs/qfontlaocodec.cpp
new file mode 100644
index 0000000000..981492c54a
--- /dev/null
+++ b/src/corelib/codecs/qfontlaocodec.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfontlaocodec_p.h"
+#include "qlist.h"
+
+#ifndef QT_NO_CODECS
+#ifndef QT_NO_BIG_CODECS
+
+QT_BEGIN_NAMESPACE
+
+static unsigned char const unicode_to_mulelao[256] =
+ {
+ // U+0E80
+ 0x00, 0xa1, 0xa2, 0x00, 0xa4, 0x00, 0x00, 0xa7,
+ 0xa8, 0x00, 0xaa, 0x00, 0x00, 0xad, 0x00, 0x00,
+ // U+0E90
+ 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0x00, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ // U+0EA0
+ 0x00, 0xc1, 0xc2, 0xc3, 0x00, 0xc5, 0x00, 0xc7,
+ 0x00, 0x00, 0xca, 0xcb, 0x00, 0xcd, 0xce, 0xcf,
+ // U+0EB0
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0x00, 0xdb, 0xdc, 0xdd, 0x00, 0x00,
+ // U+0EC0
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x00, 0xe6, 0x00,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0x00, 0x00,
+ // U+0ED0
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00,
+ // U+0EE0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // U+0EF0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+
+QFontLaoCodec::~QFontLaoCodec()
+{
+}
+
+QByteArray QFontLaoCodec::name() const
+{
+ return "mulelao-1";
+}
+
+int QFontLaoCodec::mibEnum() const
+{
+ return -4242;
+}
+
+QString QFontLaoCodec::convertToUnicode(const char *, int, ConverterState *) const
+{
+ return QString();
+}
+
+QByteArray QFontLaoCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *) const
+{
+ QByteArray rstring(len, Qt::Uninitialized);
+ uchar *rdata = (uchar *) rstring.data();
+ const QChar *sdata = uc;
+ int i = 0;
+ for (; i < len; ++i, ++sdata, ++rdata) {
+ if (sdata->unicode() < 0x80) {
+ *rdata = (uchar) sdata->unicode();
+ } else if (sdata->unicode() >= 0x0e80 && sdata->unicode() <= 0x0eff) {
+ uchar lao = unicode_to_mulelao[sdata->unicode() - 0x0e80];
+ if (lao)
+ *rdata = lao;
+ else
+ *rdata = 0;
+ } else {
+ *rdata = 0;
+ }
+ }
+ return rstring;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BIG_CODECS
+#endif // QT_NO_CODECS
diff --git a/src/corelib/codecs/qfontlaocodec_p.h b/src/corelib/codecs/qfontlaocodec_p.h
new file mode 100644
index 0000000000..7d0c957f27
--- /dev/null
+++ b/src/corelib/codecs/qfontlaocodec_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTLAOCODEC_P_H
+#define QFONTLAOCODEC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qfontencodings_x11.cpp and qfont_x11.cpp. This header file may
+// change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_CODECS
+
+class Q_CORE_EXPORT QFontLaoCodec : public QTextCodec
+{
+public:
+ ~QFontLaoCodec();
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+};
+
+#endif // QT_NO_CODECS
+
+QT_END_NAMESPACE
+
+#endif // QFONTLAOCODEC_P_H
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp
new file mode 100644
index 0000000000..053b3d2834
--- /dev/null
+++ b/src/corelib/codecs/qiconvcodec.cpp
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiconvcodec_p.h"
+#include "qtextcodec_p.h"
+#include <qlibrary.h>
+#include <qdebug.h>
+#include <qthreadstorage.h>
+
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+// unistd.h is needed for the _XOPEN_UNIX macro
+#include <unistd.h>
+#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
+# include <langinfo.h>
+#endif
+
+#if defined(Q_OS_HPUX)
+# define NO_BOM
+# define UTF16 "ucs2"
+#elif defined(Q_OS_AIX)
+# define NO_BOM
+# define UTF16 "UCS-2"
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
+# define NO_BOM
+# if Q_BYTE_ORDER == Q_BIG_ENDIAN
+# define UTF16 "UTF-16BE"
+# else
+# define UTF16 "UTF-16LE"
+# endif
+#else
+# define UTF16 "UTF-16"
+#endif
+
+#if defined(Q_OS_MAC)
+#ifndef GNU_LIBICONV
+#define GNU_LIBICONV
+#endif
+typedef iconv_t (*Ptr_iconv_open) (const char*, const char*);
+typedef size_t (*Ptr_iconv) (iconv_t, const char **, size_t *, char **, size_t *);
+typedef int (*Ptr_iconv_close) (iconv_t);
+
+static Ptr_iconv_open ptr_iconv_open = 0;
+static Ptr_iconv ptr_iconv = 0;
+static Ptr_iconv_close ptr_iconv_close = 0;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_locale_initialized;
+
+QIconvCodec::QIconvCodec()
+ : utf16Codec(0)
+{
+ utf16Codec = QTextCodec::codecForMib(1015);
+ Q_ASSERT_X(utf16Codec != 0,
+ "QIconvCodec::convertToUnicode",
+ "internal error, UTF-16 codec not found");
+ if (!utf16Codec) {
+ fprintf(stderr, "QIconvCodec::convertToUnicode: internal error, UTF-16 codec not found\n");
+ utf16Codec = reinterpret_cast<QTextCodec *>(~0);
+ }
+#if defined(Q_OS_MAC)
+ if (ptr_iconv_open == 0) {
+ QLibrary libiconv(QLatin1String("/usr/lib/libiconv"));
+ libiconv.setLoadHints(QLibrary::ExportExternalSymbolsHint);
+
+ ptr_iconv_open = reinterpret_cast<Ptr_iconv_open>(libiconv.resolve("libiconv_open"));
+ if (!ptr_iconv_open)
+ ptr_iconv_open = reinterpret_cast<Ptr_iconv_open>(libiconv.resolve("iconv_open"));
+ ptr_iconv = reinterpret_cast<Ptr_iconv>(libiconv.resolve("libiconv"));
+ if (!ptr_iconv)
+ ptr_iconv = reinterpret_cast<Ptr_iconv>(libiconv.resolve("iconv"));
+ ptr_iconv_close = reinterpret_cast<Ptr_iconv_close>(libiconv.resolve("libiconv_close"));
+ if (!ptr_iconv_close)
+ ptr_iconv_close = reinterpret_cast<Ptr_iconv_close>(libiconv.resolve("iconv_close"));
+
+ Q_ASSERT_X(ptr_iconv_open && ptr_iconv && ptr_iconv_close,
+ "QIconvCodec::QIconvCodec()",
+ "internal error, could not resolve the iconv functions");
+
+# undef iconv_open
+# define iconv_open ptr_iconv_open
+# undef iconv
+# define iconv ptr_iconv
+# undef iconv_close
+# define iconv_close ptr_iconv_close
+ }
+#endif
+}
+
+QIconvCodec::~QIconvCodec()
+{
+}
+
+QIconvCodec::IconvState::IconvState(iconv_t x)
+ : buffer(array), bufferLen(sizeof array), cd(x)
+{
+}
+
+QIconvCodec::IconvState::~IconvState()
+{
+ if (cd != reinterpret_cast<iconv_t>(-1))
+ iconv_close(cd);
+ if (buffer != array)
+ delete[] buffer;
+}
+
+void QIconvCodec::IconvState::saveChars(const char *c, int count)
+{
+ if (count > bufferLen) {
+ if (buffer != array)
+ delete[] buffer;
+ buffer = new char[bufferLen = count];
+ }
+
+ memcpy(buffer, c, count);
+}
+
+static void qIconvCodecStateFree(QTextCodec::ConverterState *state)
+{
+ delete reinterpret_cast<QIconvCodec::IconvState *>(state->d);
+}
+
+Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, toUnicodeState)
+
+QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState *convState) const
+{
+ if (utf16Codec == reinterpret_cast<QTextCodec *>(~0))
+ return QString::fromLatin1(chars, len);
+
+ int invalidCount = 0;
+ int remainingCount = 0;
+ char *remainingBuffer = 0;
+ IconvState *temporaryState = 0;
+ IconvState **pstate;
+
+ if (convState) {
+ // stateful conversion
+ pstate = reinterpret_cast<IconvState **>(&convState->d);
+ if (convState->d) {
+ // restore state
+ remainingCount = convState->remainingChars;
+ remainingBuffer = (*pstate)->buffer;
+ } else {
+ // first time
+ convState->flags |= FreeFunction;
+ QTextCodecUnalignedPointer::encode(convState->state_data, qIconvCodecStateFree);
+ }
+ } else {
+ QThreadStorage<QIconvCodec::IconvState *> *ts = toUnicodeState();
+ if (!qt_locale_initialized || !ts) {
+ // we're running after the Q_GLOBAL_STATIC has been deleted
+ // or before the QCoreApplication initialization
+ // bad programmer, no cookie for you
+ pstate = &temporaryState;
+ } else {
+ // stateless conversion -- use thread-local data
+ pstate = &toUnicodeState()->localData();
+ }
+ }
+
+ if (!*pstate) {
+ // first time, create the state
+ iconv_t cd = QIconvCodec::createIconv_t(UTF16, 0);
+ if (cd == reinterpret_cast<iconv_t>(-1)) {
+ static int reported = 0;
+ if (!reported++) {
+ fprintf(stderr,
+ "QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed\n");
+ }
+ return QString::fromLatin1(chars, len);
+ }
+
+ *pstate = new IconvState(cd);
+ }
+
+ IconvState *state = *pstate;
+ size_t inBytesLeft = len;
+ // best case assumption, each byte is converted into one UTF-16 character, plus 2 bytes for the BOM
+#ifdef GNU_LIBICONV
+ // GNU doesn't disagree with POSIX :/
+ const char *inBytes = chars;
+#else
+ char *inBytes = const_cast<char *>(chars);
+#endif
+
+ QByteArray in;
+ if (remainingCount) {
+ // we have to prepend the remaining bytes from the previous conversion
+ inBytesLeft += remainingCount;
+ in.resize(inBytesLeft);
+ inBytes = in.data();
+
+ memcpy(in.data(), remainingBuffer, remainingCount);
+ memcpy(in.data() + remainingCount, chars, len);
+
+ remainingCount = 0;
+ }
+
+ size_t outBytesLeft = len * 2 + 2;
+ QByteArray ba(outBytesLeft, Qt::Uninitialized);
+ char *outBytes = ba.data();
+ do {
+ size_t ret = iconv(state->cd, &inBytes, &inBytesLeft, &outBytes, &outBytesLeft);
+ if (ret == (size_t) -1) {
+ if (errno == E2BIG) {
+ int offset = ba.size() - outBytesLeft;
+ ba.resize(ba.size() * 2);
+ outBytes = ba.data() + offset;
+ outBytesLeft = ba.size() - offset;
+
+ continue;
+ }
+
+ if (errno == EILSEQ) {
+ // conversion stopped because of an invalid character in the sequence
+ ++invalidCount;
+ } else if (errno == EINVAL && convState) {
+ // conversion stopped because the remaining inBytesLeft make up
+ // an incomplete multi-byte sequence; save them for later
+ state->saveChars(inBytes, inBytesLeft);
+ remainingCount = inBytesLeft;
+ break;
+ }
+
+ if (errno == EILSEQ || errno == EINVAL) {
+ // skip the next character
+ ++inBytes;
+ --inBytesLeft;
+ continue;
+ }
+
+ // some other error
+ // note, cannot use qWarning() since we are implementing the codecForLocale :)
+ perror("QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv failed");
+
+ if (!convState) {
+ // reset state
+ iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
+ }
+
+ delete temporaryState;
+ return QString::fromLatin1(chars, len);
+ }
+ } while (inBytesLeft != 0);
+
+ QString s = utf16Codec->toUnicode(ba.constData(), ba.size() - outBytesLeft);
+
+ if (convState) {
+ convState->invalidChars = invalidCount;
+ convState->remainingChars = remainingCount;
+ } else {
+ // reset state
+ iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
+ }
+
+ delete temporaryState;
+ return s;
+}
+
+Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, fromUnicodeState)
+
+static bool setByteOrder(iconv_t cd)
+{
+#if !defined(NO_BOM)
+ // give iconv() a BOM
+ char buf[4];
+ ushort bom[] = { QChar::ByteOrderMark };
+
+ char *outBytes = buf;
+ char *inBytes = reinterpret_cast<char *>(bom);
+ size_t outBytesLeft = sizeof buf;
+ size_t inBytesLeft = sizeof bom;
+
+#if defined(GNU_LIBICONV)
+ const char **inBytesPtr = const_cast<const char **>(&inBytes);
+#else
+ char **inBytesPtr = &inBytes;
+#endif
+
+ if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) {
+ return false;
+ }
+#endif // NO_BOM
+
+ return true;
+}
+
+QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *convState) const
+{
+ char *inBytes;
+ char *outBytes;
+ size_t inBytesLeft;
+
+#if defined(GNU_LIBICONV)
+ const char **inBytesPtr = const_cast<const char **>(&inBytes);
+#else
+ char **inBytesPtr = &inBytes;
+#endif
+
+ IconvState *temporaryState = 0;
+ QThreadStorage<QIconvCodec::IconvState *> *ts = fromUnicodeState();
+ IconvState *&state = (qt_locale_initialized && ts) ? ts->localData() : temporaryState;
+ if (!state) {
+ iconv_t cd = QIconvCodec::createIconv_t(0, UTF16);
+ if (cd != reinterpret_cast<iconv_t>(-1)) {
+ if (!setByteOrder(cd)) {
+ perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed for BOM");
+
+ iconv_close(cd);
+ cd = reinterpret_cast<iconv_t>(-1);
+
+ return QString(uc, len).toLatin1();
+ }
+ }
+ state = new IconvState(cd);
+ }
+ if (state->cd == reinterpret_cast<iconv_t>(-1)) {
+ static int reported = 0;
+ if (!reported++) {
+ fprintf(stderr,
+ "QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed\n");
+ }
+ delete temporaryState;
+ return QString(uc, len).toLatin1();
+ }
+
+ size_t outBytesLeft = len;
+ QByteArray ba(outBytesLeft, Qt::Uninitialized);
+ outBytes = ba.data();
+
+ // now feed iconv() the real data
+ inBytes = const_cast<char *>(reinterpret_cast<const char *>(uc));
+ inBytesLeft = len * sizeof(QChar);
+
+ QByteArray in;
+ if (convState && convState->remainingChars) {
+ // we have one surrogate char to be prepended
+ in.resize(sizeof(QChar) + len);
+ inBytes = in.data();
+
+ QChar remaining = convState->state_data[0];
+ memcpy(in.data(), &remaining, sizeof(QChar));
+ memcpy(in.data() + sizeof(QChar), uc, inBytesLeft);
+
+ inBytesLeft += sizeof(QChar);
+ convState->remainingChars = 0;
+ }
+
+ int invalidCount = 0;
+ while (inBytesLeft != 0) {
+ if (iconv(state->cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) {
+ if (errno == EINVAL && convState) {
+ // buffer ends in a surrogate
+ Q_ASSERT(inBytesLeft == 2);
+ convState->remainingChars = 1;
+ convState->state_data[0] = uc[len - 1].unicode();
+ break;
+ }
+
+ switch (errno) {
+ case EILSEQ:
+ ++invalidCount;
+ // fall through
+ case EINVAL:
+ {
+ inBytes += sizeof(QChar);
+ inBytesLeft -= sizeof(QChar);
+ break;
+ }
+ case E2BIG:
+ {
+ int offset = ba.size() - outBytesLeft;
+ ba.resize(ba.size() * 2);
+ outBytes = ba.data() + offset;
+ outBytesLeft = ba.size() - offset;
+ break;
+ }
+ default:
+ {
+ // note, cannot use qWarning() since we are implementing the codecForLocale :)
+ perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed");
+
+ // reset to initial state
+ iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
+
+ delete temporaryState;
+ return QString(uc, len).toLatin1();
+ }
+ }
+ }
+ }
+
+ // reset to initial state
+ iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
+ setByteOrder(state->cd);
+
+ ba.resize(ba.size() - outBytesLeft);
+
+ if (convState)
+ convState->invalidChars = invalidCount;
+
+ delete temporaryState;
+ return ba;
+}
+
+QByteArray QIconvCodec::name() const
+{
+ return "System";
+}
+
+int QIconvCodec::mibEnum() const
+{
+ return 0;
+}
+
+iconv_t QIconvCodec::createIconv_t(const char *to, const char *from)
+{
+ Q_ASSERT((to == 0 && from != 0) || (to != 0 && from == 0));
+
+ iconv_t cd = (iconv_t) -1;
+#if defined(__GLIBC__) || defined(GNU_LIBICONV)
+ // both GLIBC and libgnuiconv will use the locale's encoding if from or to is an empty string
+ static const char empty_codeset[] = "";
+ const char *codeset = empty_codeset;
+ cd = iconv_open(to ? to : codeset, from ? from : codeset);
+#else
+ char *codeset = 0;
+#endif
+
+#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
+ if (cd == (iconv_t) -1) {
+ codeset = nl_langinfo(CODESET);
+ if (codeset)
+ cd = iconv_open(to ? to : codeset, from ? from : codeset);
+ }
+#endif
+
+ if (cd == (iconv_t) -1) {
+ // Very poorly defined and followed standards causes lots of
+ // code to try to get all the cases... This logic is
+ // duplicated in QTextCodec, so if you change it here, change
+ // it there too.
+
+ // Try to determine locale codeset from locale name assigned to
+ // LC_CTYPE category.
+
+ // First part is getting that locale name. First try setlocale() which
+ // definitely knows it, but since we cannot fully trust it, get ready
+ // to fall back to environment variables.
+ char * ctype = qstrdup(setlocale(LC_CTYPE, 0));
+
+ // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
+ // environment variables.
+ char * lang = qstrdup(qgetenv("LC_ALL").constData());
+ if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) {
+ if (lang) delete [] lang;
+ lang = qstrdup(qgetenv("LC_CTYPE").constData());
+ }
+ if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) {
+ if (lang) delete [] lang;
+ lang = qstrdup(qgetenv("LANG").constData());
+ }
+
+ // Now try these in order:
+ // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15)
+ // 2. CODESET from lang if it contains a .CODESET part
+ // 3. ctype (maybe the locale is named "ISO-8859-1" or something)
+ // 4. locale (ditto)
+ // 5. check for "@euro"
+
+ // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15)
+ codeset = ctype ? strchr(ctype, '.') : 0;
+ if (codeset && *codeset == '.') {
+ ++codeset;
+ cd = iconv_open(to ? to : codeset, from ? from : codeset);
+ }
+
+ // 2. CODESET from lang if it contains a .CODESET part
+ codeset = lang ? strchr(lang, '.') : 0;
+ if (cd == (iconv_t) -1 && codeset && *codeset == '.') {
+ ++codeset;
+ cd = iconv_open(to ? to : codeset, from ? from : codeset);
+ }
+
+ // 3. ctype (maybe the locale is named "ISO-8859-1" or something)
+ if (cd == (iconv_t) -1 && ctype && *ctype != 0 && strcmp (ctype, "C") != 0)
+ cd = iconv_open(to ? to : ctype, from ? from : ctype);
+
+
+ // 4. locale (ditto)
+ if (cd == (iconv_t) -1 && lang && *lang != 0)
+ cd = iconv_open(to ? to : lang, from ? from : lang);
+
+ // 5. "@euro"
+ if ((cd == (iconv_t) -1 && ctype && strstr(ctype, "@euro")) || (lang && strstr(lang, "@euro")))
+ cd = iconv_open(to ? to : "ISO8859-15", from ? from : "ISO8859-15");
+
+ delete [] ctype;
+ delete [] lang;
+ }
+
+ return cd;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/codecs/qiconvcodec_p.h b/src/corelib/codecs/qiconvcodec_p.h
new file mode 100644
index 0000000000..131347ca1b
--- /dev/null
+++ b/src/corelib/codecs/qiconvcodec_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICONVCODEC_P_H
+#define QICONVCODEC_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtextcodec.h"
+
+#if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
+
+#ifdef Q_OS_MAC
+typedef void * iconv_t;
+#else
+#include <iconv.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QIconvCodec: public QTextCodec
+{
+private:
+ mutable QTextCodec *utf16Codec;
+
+public:
+ QIconvCodec();
+ ~QIconvCodec();
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+ static iconv_t createIconv_t(const char *to, const char *from);
+
+ class IconvState
+ {
+ public:
+ IconvState(iconv_t x);
+ ~IconvState();
+ char *buffer;
+ int bufferLen;
+ iconv_t cd;
+
+ char array[8];
+
+ void saveChars(const char *c, int count);
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_UNIX && !QT_NO_ICONV && !QT_BOOTSTRAPPED
+
+#endif // QICONVCODEC_P_H
diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp
new file mode 100644
index 0000000000..f7b450b4e4
--- /dev/null
+++ b/src/corelib/codecs/qisciicodec.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qisciicodec_p.h"
+#include "qlist.h"
+
+#ifndef QT_NO_CODECS
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QIsciiCodec
+ \brief The QIsciiCodec class provides conversion to and from the ISCII encoding.
+
+ \internal
+*/
+
+
+struct Codecs {
+ const char name[10];
+ ushort base;
+};
+
+static const Codecs codecs [] = {
+ { "Iscii-Dev", 0x900 },
+ { "Iscii-Bng", 0x980 },
+ { "Iscii-Pnj", 0xa00 },
+ { "Iscii-Gjr", 0xa80 },
+ { "Iscii-Ori", 0xb00 },
+ { "Iscii-Tml", 0xb80 },
+ { "Iscii-Tlg", 0xc00 },
+ { "Iscii-Knd", 0xc80 },
+ { "Iscii-Mlm", 0xd00 }
+};
+
+QIsciiCodec::~QIsciiCodec()
+{
+}
+
+QByteArray QIsciiCodec::name() const
+{
+ return codecs[idx].name;
+}
+
+int QIsciiCodec::mibEnum() const
+{
+ /* There is no MIBEnum for Iscii */
+ return -3000-idx;
+}
+
+static const uchar inv = 0xFF;
+
+/* iscii range from 0xa0 - 0xff */
+static const uchar iscii_to_uni_table[0x60] = {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0e,
+ 0x0f, 0x20, 0x0d, 0x12,
+
+ 0x13, 0x14, 0x11, 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, 0x5f, 0x30,
+
+ 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38,
+ 0x39, inv, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43,
+
+ 0x46, 0x47, 0x48, 0x45,
+ 0x4a, 0x4b, 0x4c, 0x49,
+ 0x4d, 0x3c, 0x64, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c,
+ 0x6d, 0x6e, 0x6f, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+static const uchar uni_to_iscii_table[0x80] = {
+ 0x00, 0xa1, 0xa2, 0xa3,
+ 0x00, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xaa,
+ 0x00, 0xae, 0xab, 0xac,
+
+ 0xad, 0xb2, 0xaf, 0xb0,
+ 0xb1, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0xb7, 0xb8, 0xb9,
+ 0xba, 0xbb, 0xbc, 0xbd,
+
+ 0xbe, 0xbf, 0xc0, 0xc1,
+ 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0xcb, 0xcc, 0xcd,
+
+ 0xcf, 0xd0, 0xd1, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0x00, 0x00,
+ 0xe9, 0x00, 0xda, 0xdb,
+
+ 0xdc, 0xdd, 0xde, 0xdf,
+ 0x00, 0xe3, 0xe0, 0xe1,
+ 0xe2, 0xe7, 0xe4, 0xe5,
+ 0xe6, 0xe8, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x04, // decomposable into the uc codes listed here + nukta
+ 0x05, 0x06, 0x07, 0xce,
+
+ 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x08, 0xf1, 0xf2,
+ 0xf3, 0xf4, 0xf5, 0xf6,
+ 0xf7, 0xf8, 0xf9, 0xfa,
+
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+static const uchar uni_to_iscii_pairs[] = {
+ 0x00, 0x00,
+ 0x15, 0x3c, // 0x958
+ 0x16, 0x3c, // 0x959
+ 0x17, 0x3c, // 0x95a
+ 0x1c, 0x3c, // 0x95b
+ 0x21, 0x3c, // 0x95c
+ 0x22, 0x3c, // 0x95d
+ 0x2b, 0x3c, // 0x95e
+ 0x64, 0x64 // 0x965
+};
+
+
+QByteArray QIsciiCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
+{
+ char replacement = '?';
+ bool halant = false;
+ if (state) {
+ if (state->flags & ConvertInvalidToNull)
+ replacement = 0;
+ halant = state->state_data[0];
+ }
+ int invalid = 0;
+
+ QByteArray result(2 * len, Qt::Uninitialized); //worst case
+
+ uchar *ch = reinterpret_cast<uchar *>(result.data());
+
+ const int base = codecs[idx].base;
+
+ for (int i =0; i < len; ++i) {
+ const ushort codePoint = uc[i].unicode();
+
+ /* The low 7 bits of ISCII is plain ASCII. However, we go all the
+ * way up to 0xA0 such that we can roundtrip with convertToUnicode()'s
+ * behavior. */
+ if(codePoint < 0xA0) {
+ *ch++ = static_cast<uchar>(codePoint);
+ continue;
+ }
+
+ const int pos = codePoint - base;
+ if (pos > 0 && pos < 0x80) {
+ uchar iscii = uni_to_iscii_table[pos];
+ if (iscii > 0x80) {
+ *ch++ = iscii;
+ } else if (iscii) {
+ const uchar *pair = uni_to_iscii_pairs + 2*iscii;
+ *ch++ = *pair++;
+ *ch++ = *pair++;
+ } else {
+ *ch++ = replacement;
+ ++invalid;
+ }
+ } else {
+ if (uc[i].unicode() == 0x200c) { // ZWNJ
+ if (halant)
+ // Consonant Halant ZWNJ -> Consonant Halant Halant
+ *ch++ = 0xe8;
+ } else if (uc[i].unicode() == 0x200d) { // ZWJ
+ if (halant)
+ // Consonant Halant ZWJ -> Consonant Halant Nukta
+ *ch++ = 0xe9;
+ } else {
+ *ch++ = replacement;
+ ++invalid;
+ }
+ }
+ halant = (pos == 0x4d);
+ }
+ result.truncate(ch - (uchar *)result.data());
+
+ if (state) {
+ state->invalidChars += invalid;
+ state->state_data[0] = halant;
+ }
+ return result;
+}
+
+QString QIsciiCodec::convertToUnicode(const char* chars, int len, ConverterState *state) const
+{
+ bool halant = false;
+ if (state) {
+ halant = state->state_data[0];
+ }
+
+ QString result(len, Qt::Uninitialized);
+ QChar *uc = result.data();
+
+ const int base = codecs[idx].base;
+
+ for (int i = 0; i < len; ++i) {
+ ushort ch = (uchar) chars[i];
+ if (ch < 0xa0)
+ *uc++ = ch;
+ else {
+ ushort c = iscii_to_uni_table[ch - 0xa0];
+ if (halant && (c == inv || c == 0xe9)) {
+ // Consonant Halant inv -> Consonant Halant ZWJ
+ // Consonant Halant Nukta -> Consonant Halant ZWJ
+ *uc++ = QChar(0x200d);
+ } else if (halant && c == 0xe8) {
+ // Consonant Halant Halant -> Consonant Halant ZWNJ
+ *uc++ = QChar(0x200c);
+ } else {
+ *uc++ = QChar(c+base);
+ }
+ }
+ halant = ((uchar)chars[i] == 0xe8);
+ }
+ result.resize(uc - result.unicode());
+
+ if (state) {
+ state->state_data[0] = halant;
+ }
+ return result;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CODECS
diff --git a/src/corelib/codecs/qisciicodec_p.h b/src/corelib/codecs/qisciicodec_p.h
new file mode 100644
index 0000000000..024670c527
--- /dev/null
+++ b/src/corelib/codecs/qisciicodec_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QISCIICODEC_P_H
+#define QISCIICODEC_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/qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_CODECS
+
+class QIsciiCodec : public QTextCodec {
+public:
+ explicit QIsciiCodec(int i) : idx(i) {}
+ ~QIsciiCodec();
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+private:
+ int idx;
+};
+
+#endif // QT_NO_CODECS
+
+QT_END_NAMESPACE
+
+#endif // QISCIICODEC_P_H
diff --git a/src/corelib/codecs/qlatincodec.cpp b/src/corelib/codecs/qlatincodec.cpp
new file mode 100644
index 0000000000..20e59533a2
--- /dev/null
+++ b/src/corelib/codecs/qlatincodec.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlatincodec_p.h"
+#include "qlist.h"
+
+#ifndef QT_NO_TEXTCODEC
+
+QT_BEGIN_NAMESPACE
+
+QLatin1Codec::~QLatin1Codec()
+{
+}
+
+QString QLatin1Codec::convertToUnicode(const char *chars, int len, ConverterState *) const
+{
+ if (chars == 0)
+ return QString();
+
+ return QString::fromLatin1(chars, len);
+}
+
+
+QByteArray QLatin1Codec::convertFromUnicode(const QChar *ch, int len, ConverterState *state) const
+{
+ const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
+ QByteArray r(len, Qt::Uninitialized);
+ char *d = r.data();
+ int invalid = 0;
+ for (int i = 0; i < len; ++i) {
+ if (ch[i] > 0xff) {
+ d[i] = replacement;
+ ++invalid;
+ } else {
+ d[i] = (char)ch[i].cell();
+ }
+ }
+ if (state) {
+ state->invalidChars += invalid;
+ }
+ return r;
+}
+
+QByteArray QLatin1Codec::name() const
+{
+ return "ISO-8859-1";
+}
+
+QList<QByteArray> QLatin1Codec::aliases() const
+{
+ QList<QByteArray> list;
+ list << "latin1"
+ << "CP819"
+ << "IBM819"
+ << "iso-ir-100"
+ << "csISOLatin1";
+ return list;
+}
+
+
+int QLatin1Codec::mibEnum() const
+{
+ return 4;
+}
+
+
+QLatin15Codec::~QLatin15Codec()
+{
+}
+
+QString QLatin15Codec::convertToUnicode(const char* chars, int len, ConverterState *) const
+{
+ if (chars == 0)
+ return QString();
+
+ QString str = QString::fromLatin1(chars, len);
+ QChar *uc = str.data();
+ while(len--) {
+ switch(uc->unicode()) {
+ case 0xa4:
+ *uc = 0x20ac;
+ break;
+ case 0xa6:
+ *uc = 0x0160;
+ break;
+ case 0xa8:
+ *uc = 0x0161;
+ break;
+ case 0xb4:
+ *uc = 0x017d;
+ break;
+ case 0xb8:
+ *uc = 0x017e;
+ break;
+ case 0xbc:
+ *uc = 0x0152;
+ break;
+ case 0xbd:
+ *uc = 0x0153;
+ break;
+ case 0xbe:
+ *uc = 0x0178;
+ break;
+ default:
+ break;
+ }
+ uc++;
+ }
+ return str;
+}
+
+QByteArray QLatin15Codec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
+{
+ const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
+ QByteArray r(length, Qt::Uninitialized);
+ char *d = r.data();
+ int invalid = 0;
+ for (int i = 0; i < length; ++i) {
+ uchar c;
+ ushort uc = in[i].unicode();
+ if (uc < 0x0100) {
+ if (uc > 0xa3) {
+ switch(uc) {
+ case 0xa4:
+ case 0xa6:
+ case 0xa8:
+ case 0xb4:
+ case 0xb8:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ c = replacement;
+ ++invalid;
+ break;
+ default:
+ c = (unsigned char) uc;
+ break;
+ }
+ } else {
+ c = (unsigned char) uc;
+ }
+ } else {
+ if (uc == 0x20ac)
+ c = 0xa4;
+ else if ((uc & 0xff00) == 0x0100) {
+ switch(uc) {
+ case 0x0160:
+ c = 0xa6;
+ break;
+ case 0x0161:
+ c = 0xa8;
+ break;
+ case 0x017d:
+ c = 0xb4;
+ break;
+ case 0x017e:
+ c = 0xb8;
+ break;
+ case 0x0152:
+ c = 0xbc;
+ break;
+ case 0x0153:
+ c = 0xbd;
+ break;
+ case 0x0178:
+ c = 0xbe;
+ break;
+ default:
+ c = replacement;
+ ++invalid;
+ }
+ } else {
+ c = replacement;
+ ++invalid;
+ }
+ }
+ d[i] = (char)c;
+ }
+ if (state) {
+ state->remainingChars = 0;
+ state->invalidChars += invalid;
+ }
+ return r;
+}
+
+
+QByteArray QLatin15Codec::name() const
+{
+ return "ISO-8859-15";
+}
+
+QList<QByteArray> QLatin15Codec::aliases() const
+{
+ QList<QByteArray> list;
+ list << "latin9";
+ return list;
+}
+
+int QLatin15Codec::mibEnum() const
+{
+ return 111;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TEXTCODEC
diff --git a/src/corelib/codecs/qlatincodec_p.h b/src/corelib/codecs/qlatincodec_p.h
new file mode 100644
index 0000000000..fffc1fa983
--- /dev/null
+++ b/src/corelib/codecs/qlatincodec_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLATINCODEC_P_H
+#define QLATINCODEC_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/qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_TEXTCODEC
+
+class QLatin1Codec : public QTextCodec
+{
+public:
+ ~QLatin1Codec();
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+
+
+class QLatin15Codec: public QTextCodec
+{
+public:
+ ~QLatin15Codec();
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+#endif // QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
+
+#endif // QLATINCODEC_P_H
diff --git a/src/corelib/codecs/qsimplecodec.cpp b/src/corelib/codecs/qsimplecodec.cpp
new file mode 100644
index 0000000000..abbbc8d650
--- /dev/null
+++ b/src/corelib/codecs/qsimplecodec.cpp
@@ -0,0 +1,735 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecodec_p.h"
+#include "qlist.h"
+
+#ifndef QT_NO_TEXTCODEC
+
+QT_BEGIN_NAMESPACE
+
+#define LAST_MIB 2004
+
+static const struct {
+ const char *mime;
+ const char *aliases[7];
+ int mib;
+ quint16 values[128];
+} unicodevalues[QSimpleTextCodec::numSimpleCodecs] = {
+#ifndef Q_OS_SYMBIAN
+ // from RFC 1489, ftp://ftp.isi.edu/in-notes/rfc1489.txt
+ { "KOI8-R", { "csKOI8R", 0 }, 2084,
+ { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
+ 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
+ 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248,
+ 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
+ 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
+ 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
+ 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
+ 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
+ 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
+ 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
+ 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
+ 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
+ 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
+ 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
+ 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
+ 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } },
+ // /**/ - The BULLET OPERATOR is confused. Some people think
+ // it should be 0x2022 (BULLET).
+
+ // from RFC 2319, ftp://ftp.isi.edu/in-notes/rfc2319.txt
+ { "KOI8-U", { "KOI8-RU", 0 }, 2088,
+ { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
+ 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
+ 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
+ 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
+ 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457,
+ 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E,
+ 0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407,
+ 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9,
+ 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
+ 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
+ 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
+ 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
+ 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
+ 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
+ 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
+ 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } },
+
+ // next bits generated from tables on the Unicode 2.0 CD. we can
+ // use these tables since this is part of the transition to using
+ // unicode everywhere in qt.
+
+ // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo 0x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; for a in 8859-* ; do (awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ; cat /tmp/digits) | sort | uniq -w4 | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done
+
+ // then I inserted the files manually.
+ { "ISO-8859-2", {"latin2", "iso-ir-101", "csISOLatin2", 0 }, 5,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
+ 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
+ 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
+ 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+ 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+ 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} },
+ { "ISO-8859-3", { "latin3", "iso-ir-109", "csISOLatin3", 0 }, 6,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7,
+ 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B,
+ 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
+ 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
+ 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
+ 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9} },
+ { "ISO-8859-4", { "latin4", "iso-ir-110", "csISOLatin4", 0 }, 7,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
+ 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
+ 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
+ 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
+ 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
+ 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9} },
+ { "ISO-8859-5", { "cyrillic", "iso-ir-144", "csISOLatinCyrillic", 0 }, 8,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F} },
+ { "ISO-8859-6", { "ISO-8859-6-I", "ECMA-114", "ASMO-708", "arabic", "iso-ir-127", "csISOLatinArabic", 0 }, 82,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F,
+ 0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
+ 0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} },
+ { "ISO-8859-7", { "ECMA-118", "greek", "iso-ir-126", "csISOLatinGreek", 0 }, 10,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7,
+ 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+ 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} },
+ { "ISO-8859-8", { "ISO 8859-8-I", "iso-ir-138", "hebrew", "csISOLatinHebrew", 0 }, 85,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x203E,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} },
+ { "ISO-8859-9", { "iso-ir-148", "latin5", "csISOLatin5", 0 }, 12,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} },
+ { "ISO-8859-10", { "iso-ir-157", "latin6", "ISO-8859-10:1992", "csISOLatin6", 0 }, 13,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
+ 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
+ 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
+ 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138} },
+ { "ISO-8859-13", { 0 }, 109,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
+ 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
+ 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+ 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+ 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+ 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+ 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019} },
+ { "ISO-8859-14", { "iso-ir-199", "latin8", "iso-celtic", 0 }, 110,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
+ 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
+ 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
+ 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF} },
+#endif
+ { "ISO-8859-16", { "iso-ir-226", "latin10", 0 }, 112,
+ { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
+ 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
+ 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
+ 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
+ 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
+ 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF} },
+
+ // next bits generated again from tables on the Unicode 3.0 CD.
+
+ // $ for a in CP* ; do (awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a) | sort | sed -e 's/#UNDEF.*$/0xFFFD/' | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done
+#ifndef Q_OS_SYMBIAN
+ { "IBM850", { "CP850", "csPC850Multilingual", 0 }, 2009,
+ { 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+ 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+ 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+ 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
+ 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+ 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+ 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
+ 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+ 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+ 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
+ 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
+ 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
+ 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
+ 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+ 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0} },
+ { "IBM874", { "CP874", 0 }, -874, //### what is the mib?
+ { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
+ 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+ 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
+ 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+ 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+ 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+ 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+ 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
+ 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+ 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+ 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+ 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} },
+#endif //Q_OS_SYMBIAN
+ { "IBM866", { "CP866", "csIBM866", 0 }, 2086,
+ { 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+ 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+ 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+ 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
+ 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0} },
+
+#ifndef Q_OS_SYMBIAN
+ { "windows-1250", { "CP1250", 0 }, 2250,
+ { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
+ 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
+ 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+ 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+ 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} },
+ { "windows-1251", { "CP1251", 0 }, 2251,
+ { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
+ 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
+ 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
+ 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
+ 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
+ 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F} },
+ { "windows-1252", { "CP1252", 0 }, 2252,
+ { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} },
+ { "windows-1253", {"CP1253", 0 }, 2253,
+ { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
+ 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+ 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} },
+ { "windows-1254", { "CP1254", 0 }, 2254,
+ { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} },
+ { "windows-1255", { "CP1255", 0 }, 2255,
+ { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+ 0x05B8, 0x05B9, 0xFFFD, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
+ 0x05F4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD} },
+ { "windows-1256", { "CP1256", 0 }, 2256,
+ { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
+ 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
+ 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
+ 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
+ 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643,
+ 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
+ 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
+ 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2} },
+ { "windows-1257", { "CP1257", 0 }, 2257,
+ { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0x00A8, 0x02C7, 0x00B8,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0x00AF, 0x02DB, 0xFFFD,
+ 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0xFFFD, 0x00A6, 0x00A7,
+ 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+ 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+ 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+ 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+ 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9} },
+ { "windows-1258", { "CP1258", 0 }, 2258,
+ { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0xFFFD, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0xFFFD, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF} },
+
+#endif
+ { "Apple Roman", { "macintosh", "MacRoman", 0 }, -168,
+ { 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1,
+ 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
+ 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3,
+ 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
+ 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF,
+ 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
+ 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211,
+ 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8,
+ 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB,
+ 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA,
+ 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02,
+ 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1,
+ 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
+ 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC,
+ 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7} },
+
+ // This one is based on the charmap file
+ // /usr/share/i18n/charmaps/SAMI-WS2.gz, which is manually adapted
+ // to this format by Boerre Gaup <boerre@subdimension.com>
+ { "WINSAMI2", { "WS2", 0 }, -165,
+ { 0x20AC, 0xFFFD, 0x010C, 0x0192, 0x010D, 0x01B7, 0x0292, 0x01EE,
+ 0x01EF, 0x0110, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x0111, 0x01E6, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178,
+ 0x00A0, 0x01E7, 0x01E4, 0x00A3, 0x00A4, 0x01E5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x021E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x021F,
+ 0x00B0, 0x00B1, 0x01E8, 0x01E9, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x014A, 0x014B, 0x0166, 0x00BB, 0x0167, 0x00BD, 0x017D, 0x017E,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} },
+
+#ifndef Q_OS_SYMBIAN
+ // this one is generated from the charmap file located in /usr/share/i18n/charmaps
+ // on most Linux distributions. The thai character set tis620 is byte by byte equivalent
+ // to iso8859-11, so we name it 8859-11 here, but recognise the name tis620 too.
+
+ // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; (cut -c25- < TIS-620 ; cat /tmp/digits) | awk '/^x[89ABCDEF]/{ print $1, $2 }' | sed -e 's/<U/0x/' -e 's/>//' | sort | uniq -w4 | cut -c5- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/tis-620
+ { "TIS-620", { "ISO 8859-11", 0 }, 2259, // Thai character set mib enum taken from tis620 (which is byte by byte equivalent)
+ { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
+ 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+ 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
+ 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+ 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+ 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+ 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+ 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
+ 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+ 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+ 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+ 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } },
+
+#endif
+ /*
+ Name: hp-roman8 [HP-PCL5,RFC1345,KXS2]
+ MIBenum: 2004
+ Source: LaserJet IIP Printer User's Manual,
+ HP part no 33471-90901, Hewlet-Packard, June 1989.
+ Alias: roman8
+ Alias: r8
+ Alias: csHPRoman8
+ */
+ { "roman8", { "hp-roman8", "csHPRoman8", 0 }, 2004,
+ { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+ 0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF,
+ 0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4,
+ 0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1,
+ 0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2,
+ 0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA,
+ 0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC,
+ 0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6,
+ 0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4,
+ 0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3,
+ 0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF,
+ 0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC,
+ 0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD } }
+
+ // if you add more chacater sets at the end, change LAST_MIB above
+};
+
+QSimpleTextCodec::QSimpleTextCodec(int i) : forwardIndex(i), reverseMap(0)
+{
+}
+
+
+QSimpleTextCodec::~QSimpleTextCodec()
+{
+ delete reverseMap;
+}
+
+static QByteArray *buildReverseMap(int forwardIndex)
+{
+ QByteArray *map = new QByteArray();
+ int m = 0;
+ int i = 0;
+ while(i < 128) {
+ if (unicodevalues[forwardIndex].values[i] > m &&
+ unicodevalues[forwardIndex].values[i] < 0xfffd)
+ m = unicodevalues[forwardIndex].values[i];
+ i++;
+ }
+ m++;
+ map->resize(m);
+ for(i = 0; i < 128 && i < m; i++)
+ (*map)[i] = (char)i;
+ for(;i < m; i++)
+ (*map)[i] = 0;
+ for(i=128; i<256; i++) {
+ int u = unicodevalues[forwardIndex].values[i-128];
+ if (u < m)
+ (*map)[u] = (char)(unsigned char)(i);
+ }
+ return map;
+}
+
+QString QSimpleTextCodec::convertToUnicode(const char* chars, int len, ConverterState *) const
+{
+ if (len <= 0 || chars == 0)
+ return QString();
+
+ const unsigned char * c = (const unsigned char *)chars;
+
+ QString r(len, Qt::Uninitialized);
+ QChar* uc = r.data();
+
+ for (int i = 0; i < len; i++) {
+ if (c[i] > 127)
+ uc[i] = unicodevalues[forwardIndex].values[c[i]-128];
+ else
+ uc[i] = QLatin1Char(c[i]);
+ }
+ return r;
+}
+
+QByteArray QSimpleTextCodec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
+{
+ const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
+ int invalid = 0;
+
+ if (!reverseMap){
+ QByteArray *tmp = buildReverseMap(this->forwardIndex);
+ if (!reverseMap.testAndSetOrdered(0, tmp))
+ delete tmp;
+ }
+
+ QByteArray r(length, Qt::Uninitialized);
+ int i = length;
+ int u;
+ const QChar* ucp = in;
+ unsigned char* rp = (unsigned char *)r.data();
+ const unsigned char* rmp = (const unsigned char *)reverseMap->constData();
+ int rmsize = (int) reverseMap->size();
+ while(i--)
+ {
+ u = ucp->unicode();
+ if (u < 128) {
+ *rp = (char)u;
+ } else {
+ *rp = ((u < rmsize) ? (*(rmp+u)) : 0);
+ if (*rp == 0) {
+ *rp = replacement;
+ ++invalid;
+ }
+ }
+ rp++;
+ ucp++;
+ }
+
+ if (state) {
+ state->invalidChars += invalid;
+ }
+ return r;
+}
+
+QByteArray QSimpleTextCodec::name() const
+{
+ return unicodevalues[forwardIndex].mime;
+}
+
+QList<QByteArray> QSimpleTextCodec::aliases() const
+{
+ QList<QByteArray> list;
+ const char * const*a = unicodevalues[forwardIndex].aliases;
+ while (*a) {
+ list << *a;
+ ++a;
+ }
+ return list;
+}
+
+int QSimpleTextCodec::mibEnum() const
+{
+ return unicodevalues[forwardIndex].mib;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TEXTCODEC
diff --git a/src/corelib/codecs/qsimplecodec_p.h b/src/corelib/codecs/qsimplecodec_p.h
new file mode 100644
index 0000000000..ea771a68b7
--- /dev/null
+++ b/src/corelib/codecs/qsimplecodec_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECODEC_P_H
+#define QSIMPLECODEC_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/qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_TEXTCODEC
+
+template <typename T> class QAtomicPointer;
+
+class QSimpleTextCodec: public QTextCodec
+{
+public:
+#ifdef Q_OS_SYMBIAN
+ enum { numSimpleCodecs = 5 };
+#else
+ enum { numSimpleCodecs = 30 };
+#endif
+ explicit QSimpleTextCodec(int);
+ ~QSimpleTextCodec();
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+
+private:
+ int forwardIndex;
+ mutable QAtomicPointer<QByteArray> reverseMap;
+};
+
+#endif // QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
+
+#endif // QSIMPLECODEC_P_H
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
new file mode 100644
index 0000000000..3c3d39ed99
--- /dev/null
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -0,0 +1,1878 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qtextcodec.h"
+#include "qtextcodec_p.h"
+
+#ifndef QT_NO_TEXTCODEC
+
+#include "qlist.h"
+#include "qfile.h"
+#ifndef QT_NO_LIBRARY
+# include "qcoreapplication.h"
+# include "qtextcodecplugin.h"
+# include "private/qfactoryloader_p.h"
+#endif
+#include "qstringlist.h"
+
+#ifdef Q_OS_UNIX
+# include "qiconvcodec_p.h"
+#endif
+
+#include "qutfcodec_p.h"
+#include "qsimplecodec_p.h"
+#include "qlatincodec_p.h"
+#ifndef QT_NO_CODECS
+# include "qtsciicodec_p.h"
+# include "qisciicodec_p.h"
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
+# if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
+// no iconv(3) support, must build all codecs into the library
+# include "../../plugins/codecs/cn/qgb18030codec.h"
+# include "../../plugins/codecs/jp/qeucjpcodec.h"
+# include "../../plugins/codecs/jp/qjiscodec.h"
+# include "../../plugins/codecs/jp/qsjiscodec.h"
+# include "../../plugins/codecs/kr/qeuckrcodec.h"
+# include "../../plugins/codecs/tw/qbig5codec.h"
+# endif // QT_NO_ICONV
+# if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
+# include "qfontlaocodec_p.h"
+# include "../../plugins/codecs/jp/qfontjpcodec.h"
+# endif
+#endif // QT_NO_SYMBIAN
+#endif // QT_NO_CODECS
+#include "qlocale.h"
+#include "qmutex.h"
+#include "qhash.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <locale.h>
+#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
+#include <langinfo.h>
+#endif
+
+#if defined(Q_OS_WINCE)
+# define QT_NO_SETLOCALE
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#include "qtextcodec_symbian.cpp"
+#endif
+
+
+// enabling this is not exception safe!
+// #define Q_DEBUG_TEXTCODEC
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_TEXTCODECPLUGIN)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QTextCodecFactoryInterface_iid, QLatin1String("/codecs")))
+#endif
+
+//Cache for QTextCodec::codecForName and codecForMib.
+typedef QHash<QByteArray, QTextCodec *> QTextCodecCache;
+Q_GLOBAL_STATIC(QTextCodecCache, qTextCodecCache)
+
+
+static char qtolower(register char c)
+{ if (c >= 'A' && c <= 'Z') return c + 0x20; return c; }
+static bool qisalnum(register char c)
+{ return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
+
+static bool nameMatch(const QByteArray &name, const QByteArray &test)
+{
+ // if they're the same, return a perfect score
+ if (qstricmp(name, test) == 0)
+ return true;
+
+ const char *n = name.constData();
+ const char *h = test.constData();
+
+ // if the letters and numbers are the same, we have a match
+ while (*n != '\0') {
+ if (qisalnum(*n)) {
+ for (;;) {
+ if (*h == '\0')
+ return false;
+ if (qisalnum(*h))
+ break;
+ ++h;
+ }
+ if (qtolower(*n) != qtolower(*h))
+ return false;
+ ++h;
+ }
+ ++n;
+ }
+ while (*h && !qisalnum(*h))
+ ++h;
+ return (*h == '\0');
+}
+
+
+static QTextCodec *createForName(const QByteArray &name)
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_TEXTCODECPLUGIN)
+ QFactoryLoader *l = loader();
+ QStringList keys = l->keys();
+ for (int i = 0; i < keys.size(); ++i) {
+ if (nameMatch(name, keys.at(i).toLatin1())) {
+ QString realName = keys.at(i);
+ if (QTextCodecFactoryInterface *factory
+ = qobject_cast<QTextCodecFactoryInterface*>(l->instance(realName))) {
+ return factory->create(realName);
+ }
+ }
+ }
+#else
+ Q_UNUSED(name);
+#endif
+ return 0;
+}
+
+static QTextCodec *createForMib(int mib)
+{
+#ifndef QT_NO_TEXTCODECPLUGIN
+ QString name = QLatin1String("MIB: ") + QString::number(mib);
+ if (QTextCodecFactoryInterface *factory
+ = qobject_cast<QTextCodecFactoryInterface*>(loader()->instance(name)))
+ return factory->create(name);
+#else
+ Q_UNUSED(mib);
+#endif
+ return 0;
+}
+
+static QList<QTextCodec*> *all = 0;
+#ifdef Q_DEBUG_TEXTCODEC
+static bool destroying_is_ok = false;
+#endif
+
+static QTextCodec *localeMapper = 0;
+QTextCodec *QTextCodec::cftr = 0;
+
+
+class QTextCodecCleanup
+{
+public:
+ ~QTextCodecCleanup();
+};
+
+/*
+ Deletes all the created codecs. This destructor is called just
+ before exiting to delete any QTextCodec objects that may be lying
+ around.
+*/
+QTextCodecCleanup::~QTextCodecCleanup()
+{
+ if (!all)
+ return;
+
+#ifdef Q_DEBUG_TEXTCODEC
+ destroying_is_ok = true;
+#endif
+
+ for (QList<QTextCodec *>::const_iterator it = all->constBegin()
+ ; it != all->constEnd(); ++it) {
+ delete *it;
+ }
+ delete all;
+ all = 0;
+ localeMapper = 0;
+
+#ifdef Q_DEBUG_TEXTCODEC
+ destroying_is_ok = false;
+#endif
+}
+
+Q_GLOBAL_STATIC(QTextCodecCleanup, createQTextCodecCleanup)
+
+bool QTextCodec::validCodecs()
+{
+#ifdef Q_OS_SYMBIAN
+ // If we don't have a trap handler, we're outside of the main() function,
+ // ie. in global constructors or destructors. Don't use codecs in this
+ // case as it would lead to crashes because we don't have a cleanup stack on Symbian
+ return (User::TrapHandler() != NULL);
+#else
+ return true;
+#endif
+}
+
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+class QWindowsLocalCodec: public QTextCodec
+{
+public:
+ QWindowsLocalCodec();
+ ~QWindowsLocalCodec();
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicodeCharByChar(const char *chars, int length, ConverterState *state) const;
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+};
+
+QWindowsLocalCodec::QWindowsLocalCodec()
+{
+}
+
+QWindowsLocalCodec::~QWindowsLocalCodec()
+{
+}
+
+QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, ConverterState *state) const
+{
+ const char *mb = chars;
+ int mblen = length;
+
+ if (!mb || !mblen)
+ return QString();
+
+ const int wclen_auto = 4096;
+ wchar_t wc_auto[wclen_auto];
+ int wclen = wclen_auto;
+ wchar_t *wc = wc_auto;
+ int len;
+ 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 charcter (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, wclen);
+ if (len) {
+ prepend = true;
+ sp.append(QChar(wc[0]));
+ mb++;
+ mblen--;
+ wc[0] = 0;
+ }
+ }
+
+ while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+ mb, mblen, wc, wclen))) {
+ int r = GetLastError();
+ if (r == ERROR_INSUFFICIENT_BUFFER) {
+ if (wc != wc_auto) {
+ qWarning("MultiByteToWideChar: Size changed");
+ break;
+ } else {
+ wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+ mb, mblen, 0, 0);
+ wc = new wchar_t[wclen];
+ // and try again...
+ }
+ } 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--;
+ } else {
+ // Fail.
+ qWarning("MultiByteToWideChar: Cannot convert multibyte text");
+ break;
+ }
+ }
+ if (len <= 0)
+ return QString();
+ if (wc[len-1] == 0) // len - 1: we don't want terminator
+ --len;
+
+ //save the new state information
+ if (state) {
+ state->state_data[0] = (char)state_data;
+ state->remainingChars = remainingChars;
+ }
+ QString s((QChar*)wc, len);
+ if (wc != wc_auto)
+ delete [] wc;
+ if (prepend) {
+ return sp+s;
+ }
+ return s;
+}
+
+QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int length, ConverterState *state) const
+{
+ 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;
+#ifndef Q_OS_WINCE
+ 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;
+ }
+#else
+ QString s;
+ int size = mbstowcs(NULL, mb, length);
+ if (size < 0) {
+ Q_ASSERT("Error in CE TextCodec");
+ return QString();
+ }
+ wchar_t* ws = new wchar_t[size + 2];
+ ws[size +1] = 0;
+ ws[size] = 0;
+ size = mbstowcs(ws, mb, length);
+ for (int i=0; i< size; i++)
+ s.append(QChar(ws[i]));
+ delete [] ws;
+#endif
+ delete mbcs;
+ return s;
+}
+
+QByteArray QWindowsLocalCodec::convertFromUnicode(const QChar *ch, int uclen, ConverterState *) const
+{
+ 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...
+ } else {
+#ifndef QT_NO_DEBUG
+ // Fail.
+ qWarning("WideCharToMultiByte: Cannot convert multibyte text (error %d): %s (UTF-8)",
+ r, QString(ch, uclen).toLocal8Bit().data());
+#endif
+ break;
+ }
+ }
+ mb.resize(len);
+ return mb;
+}
+
+
+QByteArray QWindowsLocalCodec::name() const
+{
+ return "System";
+}
+
+int QWindowsLocalCodec::mibEnum() const
+{
+ return 0;
+}
+
+#else
+
+/* locale names mostly copied from XFree86 */
+static const char * const iso8859_2locales[] = {
+ "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr",
+ "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro",
+ "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk",
+ "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 };
+
+static const char * const iso8859_3locales[] = {
+ "eo", 0 };
+
+static const char * const iso8859_4locales[] = {
+ "ee", "ee_EE", 0 };
+
+static const char * const iso8859_5locales[] = {
+ "mk", "mk_MK", "sp", "sp_YU", 0 };
+
+static const char * const cp_1251locales[] = {
+ "be", "be_BY", "bg", "bg_BG", "bulgarian", 0 };
+
+static const char * const pt_154locales[] = {
+ "ba_RU", "ky", "ky_KG", "kk", "kk_KZ", 0 };
+
+static const char * const iso8859_6locales[] = {
+ "ar_AA", "ar_SA", "arabic", 0 };
+
+static const char * const iso8859_7locales[] = {
+ "el", "el_GR", "greek", 0 };
+
+static const char * const iso8859_8locales[] = {
+ "hebrew", "he", "he_IL", "iw", "iw_IL", 0 };
+
+static const char * const iso8859_9locales[] = {
+ "tr", "tr_TR", "turkish", 0 };
+
+static const char * const iso8859_13locales[] = {
+ "lt", "lt_LT", "lv", "lv_LV", 0 };
+
+static const char * const iso8859_15locales[] = {
+ "et", "et_EE",
+ // Euro countries
+ "br_FR", "ca_ES", "de", "de_AT", "de_BE", "de_DE", "de_LU", "en_IE",
+ "es", "es_ES", "eu_ES", "fi", "fi_FI", "finnish", "fr", "fr_FR",
+ "fr_BE", "fr_LU", "french", "ga_IE", "gl_ES", "it", "it_IT", "oc_FR",
+ "nl", "nl_BE", "nl_NL", "pt", "pt_PT", "sv_FI", "wa_BE",
+ 0 };
+
+static const char * const koi8_ulocales[] = {
+ "uk", "uk_UA", "ru_UA", "ukrainian", 0 };
+
+static const char * const tis_620locales[] = {
+ "th", "th_TH", "thai", 0 };
+
+// static const char * const tcvnlocales[] = {
+// "vi", "vi_VN", 0 };
+
+static bool try_locale_list(const char * const locale[], const QByteArray &lang)
+{
+ int i;
+ for(i=0; locale[i] && lang != locale[i]; i++)
+ ;
+ return locale[i] != 0;
+}
+
+// For the probably_koi8_locales we have to look. the standard says
+// these are 8859-5, but almost all Russian users use KOI8-R and
+// incorrectly set $LANG to ru_RU. We'll check tolower() to see what
+// it thinks ru_RU means.
+
+// If you read the history, it seems that many Russians blame ISO and
+// Perestroika for the confusion.
+//
+// The real bug is that some programs break if the user specifies
+// ru_RU.KOI8-R.
+
+static const char * const probably_koi8_rlocales[] = {
+ "ru", "ru_SU", "ru_RU", "russian", 0 };
+
+static QTextCodec * ru_RU_hack(const char * i) {
+ QTextCodec * ru_RU_codec = 0;
+
+#if !defined(QT_NO_SETLOCALE)
+ QByteArray origlocale(setlocale(LC_CTYPE, i));
+#else
+ QByteArray origlocale(i);
+#endif
+ // unicode koi8r latin5 name
+ // 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU
+ // 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU
+ int latin5 = tolower(0xCE);
+ int koi8r = tolower(0xE0);
+ if (koi8r == 0xC0 && latin5 != 0xEE) {
+ ru_RU_codec = QTextCodec::codecForName("KOI8-R");
+ } else if (koi8r != 0xC0 && latin5 == 0xEE) {
+ ru_RU_codec = QTextCodec::codecForName("ISO 8859-5");
+ } else {
+ // something else again... let's assume... *throws dice*
+ ru_RU_codec = QTextCodec::codecForName("KOI8-R");
+ qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)",
+ koi8r, latin5, i);
+ }
+#if !defined(QT_NO_SETLOCALE)
+ setlocale(LC_CTYPE, origlocale);
+#endif
+
+ return ru_RU_codec;
+}
+
+#endif
+
+#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)
+static QTextCodec *checkForCodec(const QByteArray &name) {
+ QTextCodec *c = QTextCodec::codecForName(name);
+ if (!c) {
+ const int index = name.indexOf('@');
+ if (index != -1) {
+ c = QTextCodec::codecForName(name.left(index));
+ }
+ }
+ return c;
+}
+#endif
+
+/* the next two functions are implicitely thread safe,
+ as they are only called by setup() which uses a mutex.
+*/
+static void setupLocaleMapper()
+{
+#ifdef Q_OS_SYMBIAN
+ localeMapper = QSymbianTextCodec::localeMapper;
+ if (localeMapper)
+ return;
+#endif
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ localeMapper = QTextCodec::codecForName("System");
+#else
+
+#ifndef QT_NO_ICONV
+ localeMapper = QTextCodec::codecForName("System");
+#endif
+
+#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
+ if (!localeMapper) {
+ char *charset = nl_langinfo (CODESET);
+ if (charset)
+ localeMapper = QTextCodec::codecForName(charset);
+ }
+#endif
+
+ if (!localeMapper) {
+ // Very poorly defined and followed standards causes lots of
+ // code to try to get all the cases... This logic is
+ // duplicated in QIconvCodec, so if you change it here, change
+ // it there too.
+
+ // Try to determine locale codeset from locale name assigned to
+ // LC_CTYPE category.
+
+ // First part is getting that locale name. First try setlocale() which
+ // definitely knows it, but since we cannot fully trust it, get ready
+ // to fall back to environment variables.
+#if !defined(QT_NO_SETLOCALE)
+ const QByteArray ctype = setlocale(LC_CTYPE, 0);
+#else
+ const QByteArray ctype;
+#endif
+
+ // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
+ // environment variables.
+ QByteArray lang = qgetenv("LC_ALL");
+ if (lang.isEmpty() || lang == "C") {
+ lang = qgetenv("LC_CTYPE");
+ }
+ if (lang.isEmpty() || lang == "C") {
+ lang = qgetenv("LANG");
+ }
+
+ // Now try these in order:
+ // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15)
+ // 2. CODESET from lang if it contains a .CODESET part
+ // 3. ctype (maybe the locale is named "ISO-8859-1" or something)
+ // 4. locale (ditto)
+ // 5. check for "@euro"
+ // 6. guess locale from ctype unless ctype is "C"
+ // 7. guess locale from lang
+
+ // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15)
+ int indexOfDot = ctype.indexOf('.');
+ if (indexOfDot != -1)
+ localeMapper = checkForCodec( ctype.mid(indexOfDot + 1) );
+
+ // 2. CODESET from lang if it contains a .CODESET part
+ if (!localeMapper) {
+ indexOfDot = lang.indexOf('.');
+ if (indexOfDot != -1)
+ localeMapper = checkForCodec( lang.mid(indexOfDot + 1) );
+ }
+
+ // 3. ctype (maybe the locale is named "ISO-8859-1" or something)
+ if (!localeMapper && !ctype.isEmpty() && ctype != "C")
+ localeMapper = checkForCodec(ctype);
+
+ // 4. locale (ditto)
+ if (!localeMapper && !lang.isEmpty())
+ localeMapper = checkForCodec(lang);
+
+ // 5. "@euro"
+ if ((!localeMapper && ctype.contains("@euro")) || lang.contains("@euro"))
+ localeMapper = checkForCodec("ISO 8859-15");
+
+ // 6. guess locale from ctype unless ctype is "C"
+ // 7. guess locale from lang
+ const QByteArray &try_by_name = (!ctype.isEmpty() && ctype != "C") ? lang : ctype;
+
+ // Now do the guessing.
+ if (!lang.isEmpty() && !localeMapper && !try_by_name.isEmpty()) {
+ if (try_locale_list(iso8859_15locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-15");
+ else if (try_locale_list(iso8859_2locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-2");
+ else if (try_locale_list(iso8859_3locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-3");
+ else if (try_locale_list(iso8859_4locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-4");
+ else if (try_locale_list(iso8859_5locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-5");
+ else if (try_locale_list(iso8859_6locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-6");
+ else if (try_locale_list(iso8859_7locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-7");
+ else if (try_locale_list(iso8859_8locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-8-I");
+ else if (try_locale_list(iso8859_9locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-9");
+ else if (try_locale_list(iso8859_13locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-13");
+ else if (try_locale_list(tis_620locales, lang))
+ localeMapper = QTextCodec::codecForName("ISO 8859-11");
+ else if (try_locale_list(koi8_ulocales, lang))
+ localeMapper = QTextCodec::codecForName("KOI8-U");
+ else if (try_locale_list(cp_1251locales, lang))
+ localeMapper = QTextCodec::codecForName("CP 1251");
+ else if (try_locale_list(pt_154locales, lang))
+ localeMapper = QTextCodec::codecForName("PT 154");
+ else if (try_locale_list(probably_koi8_rlocales, lang))
+ localeMapper = ru_RU_hack(lang);
+ }
+
+ }
+
+ // If everything failed, we default to 8859-1
+ // We could perhaps default to 8859-15.
+ if (!localeMapper)
+ localeMapper = QTextCodec::codecForName("ISO 8859-1");
+#endif
+}
+
+#ifndef QT_NO_THREAD
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
+#endif
+
+// textCodecsMutex need to be locked to enter this function
+static void setup()
+{
+ if (all)
+ return;
+
+#ifdef Q_OS_SYMBIAN
+ // If we don't have a trap handler, we're outside of the main() function,
+ // ie. in global constructors or destructors. Don't create codecs in this
+ // case as it would lead to crashes because of a missing cleanup stack on Symbian
+ if (User::TrapHandler() == NULL)
+ return;
+#endif
+
+#ifdef Q_DEBUG_TEXTCODEC
+ if (destroying_is_ok)
+ qWarning("QTextCodec: Creating new codec during codec cleanup");
+#endif
+ all = new QList<QTextCodec*>;
+ // create the cleanup object to cleanup all codecs on exit
+ (void) createQTextCodecCleanup();
+
+#ifndef QT_NO_CODECS
+ (void)new QTsciiCodec;
+ for (int i = 0; i < 9; ++i)
+ (void)new QIsciiCodec(i);
+
+ for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
+ (void)new QSimpleTextCodec(i);
+
+#ifdef Q_OS_SYMBIAN
+ localeMapper = QSymbianTextCodec::init();
+#endif
+
+# if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
+ // no font codecs when bootstrapping
+ (void)new QFontLaoCodec;
+# if defined(QT_NO_ICONV)
+ // no iconv(3) support, must build all codecs into the library
+ (void)new QFontGb2312Codec;
+ (void)new QFontGbkCodec;
+ (void)new QFontGb18030_0Codec;
+ (void)new QFontJis0208Codec;
+ (void)new QFontJis0201Codec;
+ (void)new QFontKsc5601Codec;
+ (void)new QFontBig5hkscsCodec;
+ (void)new QFontBig5Codec;
+# endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
+# endif // Q_WS_X11
+
+
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
+# if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
+ // no asian codecs when bootstrapping, sorry
+ (void)new QGb18030Codec;
+ (void)new QGbkCodec;
+ (void)new QGb2312Codec;
+ (void)new QEucJpCodec;
+ (void)new QJisCodec;
+ (void)new QSjisCodec;
+ (void)new QEucKrCodec;
+ (void)new QCP949Codec;
+ (void)new QBig5Codec;
+ (void)new QBig5hkscsCodec;
+# endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
+#endif //Q_OS_SYMBIAN
+#endif // QT_NO_CODECS
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ (void) new QWindowsLocalCodec;
+#endif // Q_OS_WIN32
+
+ (void)new QUtf16Codec;
+ (void)new QUtf16BECodec;
+ (void)new QUtf16LECodec;
+ (void)new QUtf32Codec;
+ (void)new QUtf32BECodec;
+ (void)new QUtf32LECodec;
+#ifndef Q_OS_SYMBIAN
+ (void)new QLatin15Codec;
+#endif
+ (void)new QLatin1Codec;
+ (void)new QUtf8Codec;
+
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
+#if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
+ // QIconvCodec depends on the UTF-16 codec, so it needs to be created last
+ (void) new QIconvCodec();
+#endif
+#endif
+
+ if (!localeMapper)
+ setupLocaleMapper();
+}
+
+/*!
+ \enum QTextCodec::ConversionFlag
+
+ \value DefaultConversion No flag is set.
+ \value ConvertInvalidToNull If this flag is set, each invalid input
+ character is output as a null character.
+ \value IgnoreHeader Ignore any Unicode byte-order mark and don't generate any.
+
+ \omitvalue FreeFunction
+*/
+
+/*!
+ \fn QTextCodec::ConverterState::ConverterState(ConversionFlags flags)
+
+ Constructs a ConverterState object initialized with the given \a flags.
+*/
+
+/*!
+ Destroys the ConverterState object.
+*/
+QTextCodec::ConverterState::~ConverterState()
+{
+ if (flags & FreeFunction)
+ (QTextCodecUnalignedPointer::decode(state_data))(this);
+ else if (d)
+ qFree(d);
+}
+
+/*!
+ \class QTextCodec
+ \brief The QTextCodec class provides conversions between text encodings.
+ \reentrant
+ \ingroup i18n
+
+ Qt uses Unicode to store, draw and manipulate strings. In many
+ situations you may wish to deal with data that uses a different
+ encoding. For example, most Japanese documents are still stored
+ in Shift-JIS or ISO 2022-JP, while Russian users often have their
+ documents in KOI8-R or Windows-1251.
+
+ Qt provides a set of QTextCodec classes to help with converting
+ non-Unicode formats to and from Unicode. You can also create your
+ own codec classes.
+
+ The supported encodings are:
+
+ \list
+ \o Apple Roman
+ \o \l{Big5 Text Codec}{Big5}
+ \o \l{Big5-HKSCS Text Codec}{Big5-HKSCS}
+ \o CP949
+ \o \l{EUC-JP Text Codec}{EUC-JP}
+ \o \l{EUC-KR Text Codec}{EUC-KR}
+ \o \l{GBK Text Codec}{GB18030-0}
+ \o IBM 850
+ \o IBM 866
+ \o IBM 874
+ \o \l{ISO 2022-JP (JIS) Text Codec}{ISO 2022-JP}
+ \o ISO 8859-1 to 10
+ \o ISO 8859-13 to 16
+ \o Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml
+ \o JIS X 0201
+ \o JIS X 0208
+ \o KOI8-R
+ \o KOI8-U
+ \o MuleLao-1
+ \o ROMAN8
+ \o \l{Shift-JIS Text Codec}{Shift-JIS}
+ \o TIS-620
+ \o \l{TSCII Text Codec}{TSCII}
+ \o UTF-8
+ \o UTF-16
+ \o UTF-16BE
+ \o UTF-16LE
+ \o UTF-32
+ \o UTF-32BE
+ \o UTF-32LE
+ \o Windows-1250 to 1258
+ \o WINSAMI2
+ \endlist
+
+ QTextCodecs can be used as follows to convert some locally encoded
+ string to Unicode. Suppose you have some string encoded in Russian
+ KOI8-R encoding, and want to convert it to Unicode. The simple way
+ to do it is like this:
+
+ \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 0
+
+ After this, \c string holds the text converted to Unicode.
+ Converting a string from Unicode to the local encoding is just as
+ easy:
+
+ \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 1
+
+ To read or write files in various encodings, use QTextStream and
+ its \l{QTextStream::setCodec()}{setCodec()} function. See the
+ \l{tools/codecs}{Codecs} example for an application of QTextCodec
+ to file I/O.
+
+ Some care must be taken when trying to convert the data in chunks,
+ for example, when receiving it over a network. In such cases it is
+ possible that a multi-byte character will be split over two
+ chunks. At best this might result in the loss of a character and
+ at worst cause the entire conversion to fail.
+
+ The approach to use in these situations is to create a QTextDecoder
+ object for the codec and use this QTextDecoder for the whole
+ decoding process, as shown below:
+
+ \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 2
+
+ The QTextDecoder object maintains state between chunks and therefore
+ works correctly even if a multi-byte character is split between
+ chunks.
+
+ \section1 Creating Your Own Codec Class
+
+ Support for new text encodings can be added to Qt by creating
+ QTextCodec subclasses.
+
+ The pure virtual functions describe the encoder to the system and
+ the coder is used as required in the different text file formats
+ supported by QTextStream, and under X11, for the locale-specific
+ character input and output.
+
+ To add support for another encoding to Qt, make a subclass of
+ QTextCodec and implement the functions listed in the table below.
+
+ \table
+ \header \o Function \o Description
+
+ \row \o name()
+ \o Returns the official name for the encoding. If the
+ encoding is listed in the
+ \l{IANA character-sets encoding file}, the name
+ should be the preferred MIME name for the encoding.
+
+ \row \o aliases()
+ \o Returns a list of alternative names for the encoding.
+ QTextCodec provides a default implementation that returns
+ an empty list. For example, "ISO-8859-1" has "latin1",
+ "CP819", "IBM819", and "iso-ir-100" as aliases.
+
+ \row \o mibEnum()
+ \o Return the MIB enum for the encoding if it is listed in
+ the \l{IANA character-sets encoding file}.
+
+ \row \o convertToUnicode()
+ \o Converts an 8-bit character string to Unicode.
+
+ \row \o convertFromUnicode()
+ \o Converts a Unicode string to an 8-bit character string.
+ \endtable
+
+ You may find it more convenient to make your codec class
+ available as a plugin; see \l{How to Create Qt Plugins} for
+ details.
+
+ \sa QTextStream, QTextDecoder, QTextEncoder, {Codecs Example}
+*/
+
+/*!
+ Constructs a QTextCodec, and gives it the highest precedence. The
+ QTextCodec should always be constructed on the heap (i.e. with \c
+ new). Qt takes ownership and will delete it when the application
+ terminates.
+*/
+QTextCodec::QTextCodec()
+{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+ all->prepend(this);
+}
+
+
+/*!
+ \nonreentrant
+
+ Destroys the QTextCodec. Note that you should not delete codecs
+ yourself: once created they become Qt's responsibility.
+*/
+QTextCodec::~QTextCodec()
+{
+#ifdef Q_DEBUG_TEXTCODEC
+ if (!destroying_is_ok)
+ qWarning("QTextCodec::~QTextCodec: Called by application");
+#endif
+ if (all) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ all->removeAll(this);
+ QTextCodecCache *cache = qTextCodecCache();
+ if (cache)
+ cache->clear();
+ }
+}
+
+/*!
+ \fn QTextCodec *QTextCodec::codecForName(const char *name)
+
+ Searches all installed QTextCodec objects and returns the one
+ which best matches \a name; the match is case-insensitive. Returns
+ 0 if no codec matching the name \a name could be found.
+*/
+
+/*!
+ Searches all installed QTextCodec objects and returns the one
+ which best matches \a name; the match is case-insensitive. Returns
+ 0 if no codec matching the name \a name could be found.
+*/
+QTextCodec *QTextCodec::codecForName(const QByteArray &name)
+{
+ if (name.isEmpty())
+ return 0;
+
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+
+ if (!validCodecs())
+ return 0;
+
+ QTextCodecCache *cache = qTextCodecCache();
+ QTextCodec *codec;
+ if (cache) {
+ codec = cache->value(name);
+ if (codec)
+ return codec;
+ }
+
+ for (int i = 0; i < all->size(); ++i) {
+ QTextCodec *cursor = all->at(i);
+ if (nameMatch(cursor->name(), name)) {
+ if (cache)
+ cache->insert(name, cursor);
+ return cursor;
+ }
+ QList<QByteArray> aliases = cursor->aliases();
+ for (int y = 0; y < aliases.size(); ++y)
+ if (nameMatch(aliases.at(y), name)) {
+ if (cache)
+ cache->insert(name, cursor);
+ return cursor;
+ }
+ }
+
+ codec = createForName(name);
+ if (codec && cache)
+ cache->insert(name, codec);
+ return codec;
+}
+
+
+/*!
+ Returns the QTextCodec which matches the \link
+ QTextCodec::mibEnum() MIBenum\endlink \a mib.
+*/
+QTextCodec* QTextCodec::codecForMib(int mib)
+{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+
+ if (!validCodecs())
+ return 0;
+
+ QByteArray key = "MIB: " + QByteArray::number(mib);
+ QTextCodecCache *cache = qTextCodecCache();
+ QTextCodec *codec;
+ if (cache) {
+ codec = cache->value(key);
+ if (codec)
+ return codec;
+ }
+
+ QList<QTextCodec*>::ConstIterator i;
+ for (int i = 0; i < all->size(); ++i) {
+ QTextCodec *cursor = all->at(i);
+ if (cursor->mibEnum() == mib) {
+ if (cache)
+ cache->insert(key, cursor);
+ return cursor;
+ }
+ }
+
+ codec = createForMib(mib);
+
+ // Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
+ // this correctly for compatibility.
+ if (!codec && mib == 1000)
+ return codecForMib(1015);
+
+ if (codec && cache)
+ cache->insert(key, codec);
+ return codec;
+}
+
+/*!
+ Returns the list of all available codecs, by name. Call
+ QTextCodec::codecForName() to obtain the QTextCodec for the name.
+
+ The list may contain many mentions of the same codec
+ if the codec has aliases.
+
+ \sa availableMibs(), name(), aliases()
+*/
+QList<QByteArray> QTextCodec::availableCodecs()
+{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+
+ QList<QByteArray> codecs;
+
+ if (!validCodecs())
+ return codecs;
+
+ for (int i = 0; i < all->size(); ++i) {
+ codecs += all->at(i)->name();
+ codecs += all->at(i)->aliases();
+ }
+
+#ifndef QT_NO_THREAD
+ locker.unlock();
+#endif
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_TEXTCODECPLUGIN)
+ QFactoryLoader *l = loader();
+ QStringList keys = l->keys();
+ for (int i = 0; i < keys.size(); ++i) {
+ if (!keys.at(i).startsWith(QLatin1String("MIB: "))) {
+ QByteArray name = keys.at(i).toLatin1();
+ if (!codecs.contains(name))
+ codecs += name;
+ }
+ }
+#endif
+
+ return codecs;
+}
+
+/*!
+ Returns the list of MIBs for all available codecs. Call
+ QTextCodec::codecForMib() to obtain the QTextCodec for the MIB.
+
+ \sa availableCodecs(), mibEnum()
+*/
+QList<int> QTextCodec::availableMibs()
+{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+
+ QList<int> codecs;
+
+ if (!validCodecs())
+ return codecs;
+
+ for (int i = 0; i < all->size(); ++i)
+ codecs += all->at(i)->mibEnum();
+
+#ifndef QT_NO_THREAD
+ locker.unlock();
+#endif
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_TEXTCODECPLUGIN)
+ QFactoryLoader *l = loader();
+ QStringList keys = l->keys();
+ for (int i = 0; i < keys.size(); ++i) {
+ if (keys.at(i).startsWith(QLatin1String("MIB: "))) {
+ int mib = keys.at(i).mid(5).toInt();
+ if (!codecs.contains(mib))
+ codecs += mib;
+ }
+ }
+#endif
+
+ return codecs;
+}
+
+/*!
+ Set the codec to \a c; this will be returned by
+ codecForLocale(). If \a c is a null pointer, the codec is reset to
+ the default.
+
+ This might be needed for some applications that want to use their
+ own mechanism for setting the locale.
+
+ \sa codecForLocale()
+*/
+void QTextCodec::setCodecForLocale(QTextCodec *c)
+{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ localeMapper = c;
+ if (!localeMapper)
+ setupLocaleMapper();
+}
+
+/*!
+ Returns a pointer to the codec most suitable for this locale.
+
+ On Windows, the codec will be based on a system locale. On Unix
+ systems, starting with Qt 4.2, the codec will be using the \e
+ iconv library. Note that in both cases the codec's name will be
+ "System".
+*/
+
+QTextCodec* QTextCodec::codecForLocale()
+{
+ if (!validCodecs())
+ return 0;
+
+ if (localeMapper)
+ return localeMapper;
+
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
+ setup();
+
+ return localeMapper;
+}
+
+
+/*!
+ \fn QByteArray QTextCodec::name() const
+
+ QTextCodec subclasses must reimplement this function. It returns
+ the name of the encoding supported by the subclass.
+
+ If the codec is registered as a character set in the
+ \l{IANA character-sets encoding file} this method should
+ return the preferred mime name for the codec if defined,
+ otherwise its name.
+*/
+
+/*!
+ \fn int QTextCodec::mibEnum() const
+
+ Subclasses of QTextCodec must reimplement this function. It
+ returns the MIBenum (see \l{IANA character-sets encoding file}
+ for more information). It is important that each QTextCodec
+ subclass returns the correct unique value for this function.
+*/
+
+/*!
+ Subclasses can return a number of aliases for the codec in question.
+
+ Standard aliases for codecs can be found in the
+ \l{IANA character-sets encoding file}.
+*/
+QList<QByteArray> QTextCodec::aliases() const
+{
+ return QList<QByteArray>();
+}
+
+/*!
+ \fn QString QTextCodec::convertToUnicode(const char *chars, int len,
+ ConverterState *state) const
+
+ QTextCodec subclasses must reimplement this function.
+
+ Converts the first \a len characters of \a chars from the
+ encoding of the subclass to Unicode, and returns the result in a
+ QString.
+
+ \a state can be 0, in which case the conversion is stateless and
+ default conversion rules should be used. If state is not 0, the
+ codec should save the state after the conversion in \a state, and
+ adjust the remainingChars and invalidChars members of the struct.
+*/
+
+/*!
+ \fn QByteArray QTextCodec::convertFromUnicode(const QChar *input, int number,
+ ConverterState *state) const
+
+ QTextCodec subclasses must reimplement this function.
+
+ Converts the first \a number of characters from the \a input array
+ from Unicode to the encoding of the subclass, and returns the result
+ in a QByteArray.
+
+ \a state can be 0 in which case the conversion is stateless and
+ default conversion rules should be used. If state is not 0, the
+ codec should save the state after the conversion in \a state, and
+ adjust the remainingChars and invalidChars members of the struct.
+*/
+
+/*!
+ Creates a QTextDecoder which stores enough state to decode chunks
+ of \c{char *} data to create chunks of Unicode data.
+
+ The caller is responsible for deleting the returned object.
+*/
+QTextDecoder* QTextCodec::makeDecoder() const
+{
+ return new QTextDecoder(this);
+}
+
+/*!
+ Creates a QTextDecoder with a specified \a flags to decode chunks
+ of \c{char *} data to create chunks of Unicode data.
+
+ The caller is responsible for deleting the returned object.
+
+ \since 4.7
+*/
+QTextDecoder* QTextCodec::makeDecoder(QTextCodec::ConversionFlags flags) const
+{
+ return new QTextDecoder(this, flags);
+}
+
+
+/*!
+ Creates a QTextEncoder which stores enough state to encode chunks
+ of Unicode data as \c{char *} data.
+
+ The caller is responsible for deleting the returned object.
+*/
+QTextEncoder* QTextCodec::makeEncoder() const
+{
+ return new QTextEncoder(this);
+}
+
+/*!
+ Creates a QTextEncoder with a specified \a flags to encode chunks
+ of Unicode data as \c{char *} data.
+
+ The caller is responsible for deleting the returned object.
+
+ \since 4.7
+*/
+QTextEncoder* QTextCodec::makeEncoder(QTextCodec::ConversionFlags flags) const
+{
+ return new QTextEncoder(this, flags);
+}
+
+/*!
+ \fn QByteArray QTextCodec::fromUnicode(const QChar *input, int number,
+ ConverterState *state) const
+
+ Converts the first \a number of characters from the \a input array
+ from Unicode to the encoding of this codec, and returns the result
+ in a QByteArray.
+
+ The \a state of the convertor used is updated.
+*/
+
+/*!
+ Converts \a str from Unicode to the encoding of this codec, and
+ returns the result in a QByteArray.
+*/
+QByteArray QTextCodec::fromUnicode(const QString& str) const
+{
+ return convertFromUnicode(str.constData(), str.length(), 0);
+}
+
+/*!
+ \fn QString QTextCodec::toUnicode(const char *input, int size,
+ ConverterState *state) const
+
+ Converts the first \a size characters from the \a input from the
+ encoding of this codec to Unicode, and returns the result in a
+ QString.
+
+ The \a state of the convertor used is updated.
+*/
+
+/*!
+ Converts \a a from the encoding of this codec to Unicode, and
+ returns the result in a QString.
+*/
+QString QTextCodec::toUnicode(const QByteArray& a) const
+{
+ return convertToUnicode(a.constData(), a.length(), 0);
+}
+
+/*!
+ Returns true if the Unicode character \a ch can be fully encoded
+ with this codec; otherwise returns false.
+*/
+bool QTextCodec::canEncode(QChar ch) const
+{
+ ConverterState state;
+ state.flags = ConvertInvalidToNull;
+ convertFromUnicode(&ch, 1, &state);
+ return (state.invalidChars == 0);
+}
+
+/*!
+ \overload
+
+ \a s contains the string being tested for encode-ability.
+*/
+bool QTextCodec::canEncode(const QString& s) const
+{
+ ConverterState state;
+ state.flags = ConvertInvalidToNull;
+ convertFromUnicode(s.constData(), s.length(), &state);
+ return (state.invalidChars == 0);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Returns a string representing the current language and
+ sublanguage, e.g. "pt" for Portuguese, or "pt_br" for Portuguese/Brazil.
+
+ \sa QLocale
+*/
+const char *QTextCodec::locale()
+{
+ static char locale[6];
+ QByteArray l = QLocale::system().name().toLatin1();
+ int len = qMin(l.length(), 5);
+ memcpy(locale, l.constData(), len);
+ locale[len] = '\0';
+
+ return locale;
+}
+
+/*!
+ \overload
+*/
+
+QByteArray QTextCodec::fromUnicode(const QString& uc, int& lenInOut) const
+{
+ QByteArray result = convertFromUnicode(uc.constData(), lenInOut, 0);
+ lenInOut = result.length();
+ return result;
+}
+
+/*!
+ \overload
+
+ \a a contains the source characters; \a len contains the number of
+ characters in \a a to use.
+*/
+QString QTextCodec::toUnicode(const QByteArray& a, int len) const
+{
+ len = qMin(a.size(), len);
+ return convertToUnicode(a.constData(), len, 0);
+}
+#endif
+
+/*!
+ \overload
+
+ \a chars contains the source characters.
+*/
+QString QTextCodec::toUnicode(const char *chars) const
+{
+ int len = qstrlen(chars);
+ return convertToUnicode(chars, len, 0);
+}
+
+
+/*!
+ \class QTextEncoder
+ \brief The QTextEncoder class provides a state-based encoder.
+ \reentrant
+ \ingroup i18n
+
+ A text encoder converts text from Unicode into an encoded text format
+ using a specific codec.
+
+ The encoder converts Unicode into another format, remembering any
+ state that is required between calls.
+
+ \sa QTextCodec::makeEncoder(), QTextDecoder
+*/
+
+/*!
+ \fn QTextEncoder::QTextEncoder(const QTextCodec *codec)
+
+ Constructs a text encoder for the given \a codec.
+*/
+
+/*!
+ Constructs a text encoder for the given \a codec and conversion \a flags.
+
+ \since 4.7
+*/
+QTextEncoder::QTextEncoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags)
+ : c(codec), state()
+{
+ state.flags = flags;
+}
+
+/*!
+ Destroys the encoder.
+*/
+QTextEncoder::~QTextEncoder()
+{
+}
+
+/*! \internal
+ \since 4.5
+ Determines whether the eecoder encountered a failure while decoding the input. If
+ an error was encountered, the produced result is undefined, and gets converted as according
+ to the conversion flags.
+ */
+bool QTextEncoder::hasFailure() const
+{
+ return state.invalidChars != 0;
+}
+
+/*!
+ Converts the Unicode string \a str into an encoded QByteArray.
+*/
+QByteArray QTextEncoder::fromUnicode(const QString& str)
+{
+ QByteArray result = c->fromUnicode(str.constData(), str.length(), &state);
+ return result;
+}
+
+/*!
+ \overload
+
+ Converts \a len characters (not bytes) from \a uc, and returns the
+ result in a QByteArray.
+*/
+QByteArray QTextEncoder::fromUnicode(const QChar *uc, int len)
+{
+ QByteArray result = c->fromUnicode(uc, len, &state);
+ return result;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+
+ Converts \a lenInOut characters (not bytes) from \a uc, and returns the
+ result in a QByteArray. The number of characters read is returned in
+ the \a lenInOut parameter.
+*/
+QByteArray QTextEncoder::fromUnicode(const QString& uc, int& lenInOut)
+{
+ QByteArray result = c->fromUnicode(uc.constData(), lenInOut, &state);
+ lenInOut = result.length();
+ return result;
+}
+#endif
+
+/*!
+ \class QTextDecoder
+ \brief The QTextDecoder class provides a state-based decoder.
+ \reentrant
+ \ingroup i18n
+
+ A text decoder converts text from an encoded text format into Unicode
+ using a specific codec.
+
+ The decoder converts text in this format into Unicode, remembering any
+ state that is required between calls.
+
+ \sa QTextCodec::makeDecoder(), QTextEncoder
+*/
+
+/*!
+ \fn QTextDecoder::QTextDecoder(const QTextCodec *codec)
+
+ Constructs a text decoder for the given \a codec.
+*/
+
+/*!
+ Constructs a text decoder for the given \a codec and conversion \a flags.
+
+ \since 4.7
+*/
+
+QTextDecoder::QTextDecoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags)
+ : c(codec), state()
+{
+ state.flags = flags;
+}
+
+/*!
+ Destroys the decoder.
+*/
+QTextDecoder::~QTextDecoder()
+{
+}
+
+/*!
+ \fn QString QTextDecoder::toUnicode(const char *chars, int len)
+
+ Converts the first \a len bytes in \a chars to Unicode, returning
+ the result.
+
+ If not all characters are used (e.g. if only part of a multi-byte
+ encoding is at the end of the characters), the decoder remembers
+ enough state to continue with the next call to this function.
+*/
+QString QTextDecoder::toUnicode(const char *chars, int len)
+{
+ return c->toUnicode(chars, len, &state);
+}
+
+
+/*! \overload
+
+ The converted string is returned in \a target.
+ */
+void QTextDecoder::toUnicode(QString *target, const char *chars, int len)
+{
+ Q_ASSERT(target);
+ switch (c->mibEnum()) {
+ case 106: // utf8
+ static_cast<const QUtf8Codec*>(c)->convertToUnicode(target, chars, len, &state);
+ break;
+ case 4: { // latin1
+ target->resize(len);
+ ushort *data = (ushort*)target->data();
+ for (int i = len; i >=0; --i)
+ data[i] = (uchar) chars[i];
+ } break;
+ default:
+ *target = c->toUnicode(chars, len, &state);
+ }
+}
+
+
+/*!
+ \overload
+
+ Converts the bytes in the byte array specified by \a ba to Unicode
+ and returns the result.
+*/
+QString QTextDecoder::toUnicode(const QByteArray &ba)
+{
+ return c->toUnicode(ba.constData(), ba.length(), &state);
+}
+
+
+/*!
+ \fn QTextCodec* QTextCodec::codecForTr()
+
+ Returns the codec used by QObject::tr() on its argument. If this
+ function returns 0 (the default), tr() assumes Latin-1.
+
+ \sa setCodecForTr()
+*/
+
+/*!
+ \fn void QTextCodec::setCodecForTr(QTextCodec *c)
+ \nonreentrant
+
+ Sets the codec used by QObject::tr() on its argument to \a c. If
+ \a c is 0 (the default), tr() assumes Latin-1.
+
+ If the literal quoted text in the program is not in the Latin-1
+ encoding, this function can be used to set the appropriate
+ encoding. For example, software developed by Korean programmers
+ might use eucKR for all the text in the program, in which case the
+ main() function might look like this:
+
+ \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 3
+
+ Note that this is not the way to select the encoding that the \e
+ user has chosen. For example, to convert an application containing
+ literal English strings to Korean, all that is needed is for the
+ English strings to be passed through tr() and for translation
+ files to be loaded. For details of internationalization, see
+ \l{Internationalization with Qt}.
+
+ \sa codecForTr(), setCodecForCStrings()
+*/
+
+
+/*!
+ \fn QTextCodec* QTextCodec::codecForCStrings()
+
+ Returns the codec used by QString to convert to and from \c{const
+ char *} and QByteArrays. If this function returns 0 (the default),
+ QString assumes Latin-1.
+
+ \sa setCodecForCStrings()
+*/
+
+/*!
+ \fn void QTextCodec::setCodecForCStrings(QTextCodec *codec)
+ \nonreentrant
+
+ Sets the codec used by QString to convert to and from \c{const
+ char *} and QByteArrays. If the \a codec is 0 (the default),
+ QString assumes Latin-1.
+
+ \warning Some codecs do not preserve the characters in the ASCII
+ range (0x00 to 0x7F). For example, the Japanese Shift-JIS
+ encoding maps the backslash character (0x5A) to the Yen
+ character. To avoid undesirable side-effects, we recommend
+ avoiding such codecs with setCodecsForCString().
+
+ \sa codecForCStrings(), setCodecForTr()
+*/
+
+/*!
+ \since 4.4
+
+ Tries to detect the encoding of the provided snippet of HTML in
+ the given byte array, \a ba, by checking the BOM (Byte Order Mark)
+ and the content-type meta header and returns a QTextCodec instance
+ that is capable of decoding the html to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForUtfText()
+*/
+QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
+{
+ // determine charset
+ int pos;
+ QTextCodec *c = 0;
+
+ c = QTextCodec::codecForUtfText(ba, c);
+ if (!c) {
+ QByteArray header = ba.left(512).toLower();
+ if ((pos = header.indexOf("http-equiv=")) != -1) {
+ if ((pos = header.lastIndexOf("meta ", pos)) != -1) {
+ pos = header.indexOf("charset=", pos) + int(strlen("charset="));
+ if (pos != -1) {
+ int pos2 = header.indexOf('\"', pos+1);
+ QByteArray cs = header.mid(pos, pos2-pos);
+ // qDebug("found charset: %s", cs.data());
+ c = QTextCodec::codecForName(cs);
+ }
+ }
+ }
+ }
+ if (!c)
+ c = defaultCodec;
+
+ return c;
+}
+
+/*!
+ \overload
+
+ Tries to detect the encoding of the provided snippet of HTML in
+ the given byte array, \a ba, by checking the BOM (Byte Order Mark)
+ and the content-type meta header and returns a QTextCodec instance
+ that is capable of decoding the html to unicode. If the codec cannot
+ be detected, this overload returns a Latin-1 QTextCodec.
+*/
+QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
+{
+ return codecForHtml(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+}
+
+/*!
+ \since 4.6
+
+ Tries to detect the encoding of the provided snippet \a ba by
+ using the BOM (Byte Order Mark) and returns a QTextCodec instance
+ that is capable of decoding the text to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForHtml()
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec)
+{
+ const int arraySize = ba.size();
+
+ if (arraySize > 3) {
+ if ((uchar)ba[0] == 0x00
+ && (uchar)ba[1] == 0x00
+ && (uchar)ba[2] == 0xFE
+ && (uchar)ba[3] == 0xFF)
+ return QTextCodec::codecForMib(1018); // utf-32 be
+ else if ((uchar)ba[0] == 0xFF
+ && (uchar)ba[1] == 0xFE
+ && (uchar)ba[2] == 0x00
+ && (uchar)ba[3] == 0x00)
+ return QTextCodec::codecForMib(1019); // utf-32 le
+ }
+
+ if (arraySize < 2)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
+ return QTextCodec::codecForMib(1013); // utf16 be
+ else if ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe)
+ return QTextCodec::codecForMib(1014); // utf16 le
+
+ if (arraySize < 3)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xef
+ && (uchar)ba[1] == 0xbb
+ && (uchar)ba[2] == 0xbf)
+ return QTextCodec::codecForMib(106); // utf-8
+
+ return defaultCodec;
+}
+
+/*!
+ \overload
+
+ Tries to detect the encoding of the provided snippet \a ba by
+ using the BOM (Byte Order Mark) and returns a QTextCodec instance
+ that is capable of decoding the text to unicode. If the codec
+ cannot be detected, this overload returns a Latin-1 QTextCodec.
+
+ \sa codecForHtml()
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
+{
+ return codecForUtfText(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+}
+
+
+/*! \internal
+ \since 4.3
+ Determines whether the decoder encountered a failure while decoding the input. If
+ an error was encountered, the produced result is undefined, and gets converted as according
+ to the conversion flags.
+ */
+bool QTextDecoder::hasFailure() const
+{
+ return state.invalidChars != 0;
+}
+
+/*!
+ \fn QTextCodec *QTextCodec::codecForContent(const char *str, int size)
+
+ This functionality is no longer provided by Qt. This
+ compatibility function always returns a null pointer.
+*/
+
+/*!
+ \fn QTextCodec *QTextCodec::codecForName(const char *hint, int accuracy)
+
+ Use the codecForName(const QByteArray &) overload instead.
+*/
+
+/*!
+ \fn QTextCodec *QTextCodec::codecForIndex(int i)
+
+ Use availableCodecs() or availableMibs() instead and iterate
+ through the resulting list.
+*/
+
+
+/*!
+ \fn QByteArray QTextCodec::mimeName() const
+
+ Use name() instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TEXTCODEC
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
new file mode 100644
index 0000000000..759a59b66a
--- /dev/null
+++ b/src/corelib/codecs/qtextcodec.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTCODEC_H
+#define QTEXTCODEC_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_TEXTCODEC
+
+class QTextCodec;
+class QIODevice;
+
+class QTextDecoder;
+class QTextEncoder;
+
+class Q_CORE_EXPORT QTextCodec
+{
+ Q_DISABLE_COPY(QTextCodec)
+public:
+ static QTextCodec* codecForName(const QByteArray &name);
+ static QTextCodec* codecForName(const char *name) { return codecForName(QByteArray(name)); }
+ static QTextCodec* codecForMib(int mib);
+
+ static QList<QByteArray> availableCodecs();
+ static QList<int> availableMibs();
+
+ static QTextCodec* codecForLocale();
+ static void setCodecForLocale(QTextCodec *c);
+
+ static QTextCodec* codecForTr();
+ static void setCodecForTr(QTextCodec *c);
+
+ static QTextCodec* codecForCStrings();
+ static void setCodecForCStrings(QTextCodec *c);
+
+ static QTextCodec *codecForHtml(const QByteArray &ba);
+ static QTextCodec *codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec);
+
+ static QTextCodec *codecForUtfText(const QByteArray &ba);
+ static QTextCodec *codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec);
+
+ bool canEncode(QChar) const;
+ bool canEncode(const QString&) const;
+
+ QString toUnicode(const QByteArray&) const;
+ QString toUnicode(const char* chars) const;
+ QByteArray fromUnicode(const QString& uc) const;
+ enum ConversionFlag {
+ DefaultConversion,
+ ConvertInvalidToNull = 0x80000000,
+ IgnoreHeader = 0x1,
+ FreeFunction = 0x2
+ };
+ Q_DECLARE_FLAGS(ConversionFlags, ConversionFlag)
+
+ struct Q_CORE_EXPORT ConverterState {
+ ConverterState(ConversionFlags f = DefaultConversion)
+ : flags(f), remainingChars(0), invalidChars(0), d(0) { state_data[0] = state_data[1] = state_data[2] = 0; }
+ ~ConverterState();
+ ConversionFlags flags;
+ int remainingChars;
+ int invalidChars;
+ uint state_data[3];
+ void *d;
+ private:
+ Q_DISABLE_COPY(ConverterState)
+ };
+
+ QString toUnicode(const char *in, int length, ConverterState *state = 0) const
+ { return convertToUnicode(in, length, state); }
+ QByteArray fromUnicode(const QChar *in, int length, ConverterState *state = 0) const
+ { return convertFromUnicode(in, length, state); }
+
+ // ### Qt 5: merge these functions.
+ QTextDecoder* makeDecoder() const;
+ QTextDecoder* makeDecoder(ConversionFlags flags) const;
+ QTextEncoder* makeEncoder() const;
+ QTextEncoder* makeEncoder(ConversionFlags flags) const;
+
+ virtual QByteArray name() const = 0;
+ virtual QList<QByteArray> aliases() const;
+ virtual int mibEnum() const = 0;
+
+protected:
+ virtual QString convertToUnicode(const char *in, int length, ConverterState *state) const = 0;
+ virtual QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const = 0;
+
+ QTextCodec();
+ virtual ~QTextCodec();
+
+public:
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QTextCodec* codecForContent(const char*, int) { return 0; }
+ static QT3_SUPPORT const char* locale();
+ static QT3_SUPPORT QTextCodec* codecForName(const char* hint, int) { return codecForName(QByteArray(hint)); }
+ QT3_SUPPORT QByteArray fromUnicode(const QString& uc, int& lenInOut) const;
+ QT3_SUPPORT QString toUnicode(const QByteArray&, int len) const;
+ QT3_SUPPORT QByteArray mimeName() const { return name(); }
+ static QT3_SUPPORT QTextCodec *codecForIndex(int i) { return codecForName(availableCodecs().value(i)); }
+#endif
+
+private:
+ friend class QTextCodecCleanup;
+ static QTextCodec *cftr;
+ static bool validCodecs();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QTextCodec::ConversionFlags)
+
+ inline QTextCodec* QTextCodec::codecForTr() { return validCodecs() ? cftr : 0; }
+inline void QTextCodec::setCodecForTr(QTextCodec *c) { cftr = c; }
+inline QTextCodec* QTextCodec::codecForCStrings() { return validCodecs() ? QString::codecForCStrings : 0; }
+inline void QTextCodec::setCodecForCStrings(QTextCodec *c) { QString::codecForCStrings = c; }
+
+class Q_CORE_EXPORT QTextEncoder {
+ Q_DISABLE_COPY(QTextEncoder)
+public:
+ explicit QTextEncoder(const QTextCodec *codec) : c(codec), state() {}
+ QTextEncoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
+ ~QTextEncoder();
+ QByteArray fromUnicode(const QString& str);
+ QByteArray fromUnicode(const QChar *uc, int len);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QByteArray fromUnicode(const QString& uc, int& lenInOut);
+#endif
+ bool hasFailure() const;
+private:
+ const QTextCodec *c;
+ QTextCodec::ConverterState state;
+};
+
+class Q_CORE_EXPORT QTextDecoder {
+ Q_DISABLE_COPY(QTextDecoder)
+public:
+ explicit QTextDecoder(const QTextCodec *codec) : c(codec), state() {}
+ QTextDecoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
+ ~QTextDecoder();
+ QString toUnicode(const char* chars, int len);
+ QString toUnicode(const QByteArray &ba);
+ void toUnicode(QString *target, const char *chars, int len);
+ bool hasFailure() const;
+private:
+ const QTextCodec *c;
+ QTextCodec::ConverterState state;
+};
+
+#endif // QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTEXTCODEC_H
diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h
new file mode 100644
index 0000000000..fbf5c1255a
--- /dev/null
+++ b/src/corelib/codecs/qtextcodec_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTCODEC_P_H
+#define QTEXTCODEC_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 QTextCodec class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtextcodec.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_TEXTCODEC
+
+typedef void (*QTextCodecStateFreeFunction)(QTextCodec::ConverterState*);
+
+struct QTextCodecUnalignedPointer
+{
+ static inline QTextCodecStateFreeFunction decode(const uint *src)
+ {
+ quintptr data;
+ memcpy(&data, src, sizeof(data));
+ return reinterpret_cast<QTextCodecStateFreeFunction>(data);
+ }
+ static inline void encode(uint *dst, QTextCodecStateFreeFunction fn)
+ {
+ quintptr data = reinterpret_cast<quintptr>(fn);
+ memcpy(dst, &data, sizeof(data));
+ }
+};
+
+#else
+
+class QTextCodec
+{
+public:
+ enum ConversionFlag {
+ DefaultConversion,
+ ConvertInvalidToNull = 0x80000000,
+ IgnoreHeader = 0x1,
+ FreeFunction = 0x2
+ };
+ Q_DECLARE_FLAGS(ConversionFlags, ConversionFlag)
+
+ struct ConverterState {
+ ConverterState(ConversionFlags f = DefaultConversion)
+ : flags(f), remainingChars(0), invalidChars(0), d(0) { state_data[0] = state_data[1] = state_data[2] = 0; }
+ ~ConverterState() { }
+ ConversionFlags flags;
+ int remainingChars;
+ int invalidChars;
+ uint state_data[3];
+ void *d;
+ private:
+ Q_DISABLE_COPY(ConverterState)
+ };
+};
+
+#endif //QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/codecs/qtextcodec_symbian.cpp b/src/corelib/codecs/qtextcodec_symbian.cpp
new file mode 100644
index 0000000000..9ad8ccae1b
--- /dev/null
+++ b/src/corelib/codecs/qtextcodec_symbian.cpp
@@ -0,0 +1,689 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtextcodec_p.h"
+
+#include <private/qcore_symbian_p.h>
+#include <QThreadStorage>
+#include <QScopedPointer>
+
+#include <charconv.h>
+
+struct QSymbianCodecInitData {
+ uint charsetId;
+ int mib;
+ const char *aliases;
+};
+
+/* This table contains the known Symbian codecs aliases.
+ It is required because symbian does not provide aliases for codecs.
+ It is also faster to have a name here than asking the system.
+ It is ordered by charsetId to allow binary search lookup
+ */
+static const QSymbianCodecInitData codecsData[] = {
+ { /*268439485*/ KCharacterSetIdentifierShiftJis, 17, "Shift_JIS\0MS_Kanji\0csShiftJIS\0SJIS\0" },
+ { /*268439486*/ KCharacterSetIdentifierGb2312, 57, "GB2312\0csGB2312\0CN-GB\0EUC-CN\0" }, // Note: ConvertCharacterSetIdentifierToMibEnumL returns Mib 0 instaead of 57
+ { /*268439487*/ KCharacterSetIdentifierBig5, 2026, "Big5\0csBig5\0Big5-ETen\0CP950\0BIG-FIVE\0CN-BIG5\0" },
+ { /*268440246*/ KCharacterSetIdentifierCodePage1252, 2252, "windows-1252\0Code Page 1252\0CP1252\0MS-ANSI\0" },
+// { /*268450576*/ KCharacterSetIdentifierIso88591, 4, "ISO-8859-1\0ISO_8859-1:1987\0iso-ir-100\0ISO_8859-1\0latin1\0l1\0IBM819\0CP819\0csISOLatin1\0ISO-IR-100\0ISO8859-1\0L1\0LATIN1\0CSISOLATIN1\0" },
+ { /*268451531*/ KCharacterSetIdentifierGbk, 113, "GBK\0MS936\0windows-936\0CP936\0" },
+ { /*268451866*/ KCharacterSetIdentifierGb12345, 0, "GB12345\0" },
+ { /*268455110*/ KCharacterSetIdentifierAscii, 3, "US-ASCII\0ANSI_X3.4-1968\0iso-ir-6\0ANSI_X3.4-1986\0ISO_646.irv:1991\0ASCII\0ISO646-US\0us\0IBM367\0cp367\0csASCII\0ISO-IR-6\0ISO_646.IRV:1991\0"},
+ { /*268456062*/ KCharacterSetIdentifierIso88592, 5, "ISO-8859-2\0ISO_8859-2:1987\0iso-ir-101\0latin2\0l2\0csISOLatin2\0" },
+ { /*268456063*/ KCharacterSetIdentifierIso88594, 7, "ISO-8859-4\0ISO_8859-4:1988\0iso-ir-110\0latin4\0l4\0csISOLatin4\0" },
+ { /*268456064*/ KCharacterSetIdentifierIso88595, 8, "ISO-8859-5\0ISO_8859-5:1988\0iso-ir-144\0cyrillic\0csISOLatinCyrillic\0" },
+ { /*268456065*/ KCharacterSetIdentifierIso88597, 10, "ISO-8859-7\0ISO_8859-7:1987\0iso-ir-126\0ELOT_928\0ECMA-118\0greek\0greek8\0csISOLatinGreek\0" },
+ { /*268456066*/ KCharacterSetIdentifierIso88599, 12, "ISO-8859-9\0ISO_8859-9:1989\0iso-ir-148\0latin5\0l5\0csISOLatin5\0" },
+ { /*268456875*/ KCharacterSetIdentifierSms7Bit, 0, "SMS 7-bit\0" },
+ { /*268458028*/ KCharacterSetIdentifierUtf7, 103, "UTF-7\0UNICODE-1-1-UTF-7\0CSUNICODE11UTF7\0" },
+// { /*268458029*/ KCharacterSetIdentifierUtf8, 106, "UTF-8\0" },
+ { /*268458030*/ KCharacterSetIdentifierImapUtf7, 0, "IMAP UTF-7\0" },
+ { /*268458031*/ KCharacterSetIdentifierJavaConformantUtf8, 0, "JAVA UTF-8\0" },
+ { /*268458454*/ 268458454, 2250, "Windows-1250\0CP1250\0MS-EE\0" },
+ { /*268458455*/ 268458455, 2251, "Windows-1251\0CP1251\0MS-CYRL\0" },
+ { /*268458456*/ 268458456, 2253, "Windows-1253\0CP1253\0MS-GREEK\0" },
+ { /*268458457*/ 268458457, 2254, "Windows-1254\0CP1254\0MS-TURK\0" },
+ { /*268458458*/ 268458458, 2257, "Windows-1257\0CP1257\0WINBALTRIM\0" },
+ { /*268460133*/ KCharacterSetIdentifierHz, 2085, "HZ-GB-2312\0HZ\0" },
+ { /*268460134*/ KCharacterSetIdentifierJis, 16, "JIS_Encoding\0JIS\0" },
+ { /*268460135*/ KCharacterSetIdentifierEucJpPacked, 18, "EUC-JP\0Extended_UNIX_Code_Packed_Format_for_Japanese\0csEUCPkdFmtJapanese\0EUCJP_PACKED\0" },
+ { /*268461728*/ KCharacterSetIdentifierIso2022Jp, 39, "ISO-2022-JP\0csISO2022JP\0JIS7\0" },
+ { /*268461731*/ KCharacterSetIdentifierIso2022Jp1, 0, "ISO2022JP1\0" },
+ { /*268470824*/ KCharacterSetIdentifierIso88593, 6, "ISO-8859-3\0ISO_8859-3:1988\0iso-ir-109\0latin3\0l3\0csISOLatin3\0" },
+ { /*268470825*/ KCharacterSetIdentifierIso88596, 9, "ISO-8859-6\0ISO_8859-6:1987\0iso-ir-127\0ECMA-114\0ASMO-708\0arabic\0ISO88596\0csISOLatinArabic\0ARABIC\0" },
+ { /*268470826*/ KCharacterSetIdentifierIso88598, 11, "ISO-8859-8\0ISO_8859-8:1988\0iso-ir-138\0hebrew\0csISOLatinHebrew\0" },
+ { /*268470827*/ KCharacterSetIdentifierIso885910, 13, "ISO-8859-10\0iso-ir-157\0l6\0ISO_8859-10:1992\0csISOLatin6\0latin6\0" },
+ { /*268470828*/ KCharacterSetIdentifierIso885913, 109, "ISO-8859-13\0ISO885913\0ISO-IR-179\0ISO8859-13\0L7\0LATIN7\0CSISOLATIN7\0" },
+ { /*268470829*/ KCharacterSetIdentifierIso885914, 110, "ISO-8859-14\0iso-ir-199\0ISO_8859-14:1998\0latin8\0iso-celtic\0l8\0" },
+ { /*268470830*/ KCharacterSetIdentifierIso885915, 111, "ISO-8859-15\0latin-9\0ISO-IR-203\0" },
+// { /*270483374*/ KCharacterSetIdentifierUnicodeLittle, 1014, "UTF-16LE\0Little-Endian UNICODE\0" },
+// { /*270483538*/ KCharacterSetIdentifierUnicodeBig, 1013, "UTF-16BE\0Big-Endian UNICODE\0" },
+ { /*270501191*/ 270501191, 2255, "Windows-1255\0CP1255\0MS-HEBR\0" },
+ { /*270501192*/ 270501192, 2256, "Windows-1256\0CP1256\0MS-ARAB\0" },
+ { /*270501193*/ 270501193, 2259, "TIS-620\0ISO-IR-166\0TIS620-0\0TIS620.2529-1\0TIS620.2533-0\0TIS620.2533-1\0" },
+ { /*270501194*/ 270501194, 0, "windows-874\0CP874\0IBM874\0" },
+ { /*270501325*/ 270501325, 0, "SmsStrict\0" },
+ { /*270501521*/ 270501521, 0, "ShiftJisDirectmap\0" },
+ { /*270501542*/ 270501542, 0, "EucJpDirectmap\0" },
+ /* 270501691 (duplicate) Windows-1252 | windows-1252 |Windows-1252 |Code Page 1252 |CP1252 |MS-ANSI |WINDOWS-1252 |2252 */
+ { /*270501729*/ 270501729, 2088, "KOI8-U\0" },
+ { /*270501752*/ 270501752, 2084, "KOI8-R\0csKOI8R\0" },
+ { /*270529682*/ 270529682, 1000, "ISO-10646-UCS-2\0UCS-2\0CSUNICODE\0" },
+ { /*270562232*/ 270562232, 2258, "Windows-1258\0CP1258\0WINDOWS-1258\0" },
+ { /*270586888*/ 270586888, 0, "J5\0" },
+ { /*271011982*/ 271011982, 0, "ISCII\0" },
+ { /*271066541*/ 271066541, 2009, "CP850\0IBM850\0""850\0csPC850Multilingual\0" }, // Note: ConvertCharacterSetIdentifierToMibEnumL returns Mib 0 instead of 2009
+ { /*271082493*/ 271082493, 0, "EXTENDED_SMS_7BIT\0" },
+ { /*271082494*/ 271082494, 0, "gsm7_turkish_single\0" },
+ { /*271082495*/ 271082495, 0, "turkish_locking_gsm7ext\0" },
+ { /*271082496*/ 271082496, 0, "turkish_locking_single\0" },
+ { /*271082503*/ 271082503, 0, "portuguese_gsm7_single\0" },
+ { /*271082504*/ 271082504, 0, "portuguese_locking_gsm7ext\0" },
+ { /*271082505*/ 271082505, 0, "portuguese_locking_single\0" },
+ { /*271082506*/ 271082506, 0, "spanish_gsm7_single\0" },
+ { /*271085624*/ 271085624, 114, "GB18030\0" },
+ { /*536929574*/ 536929574, 38, "EUC-KR\0" },
+ { /*536936703*/ 536936703, 0, "CP949\0" },
+ { /*536936705*/ 536936705, 37, "ISO-2022-KR\0csISO2022KR\0" },
+ { /*536941517*/ 536941517, 36, "KS_C_5601-1987\0iso-ir-149\0KS_C_5601-1989\0KSC_5601\0Korean\0csKSC56011987\0" }
+ };
+
+
+class QSymbianTextCodec : public QTextCodec
+{
+public:
+ QString convertToUnicode(const char*, int, ConverterState*) const;
+ QByteArray convertFromUnicode(const QChar*, int, ConverterState*) const;
+ QList<QByteArray> aliases() const;
+ QByteArray name() const;
+ int mibEnum() const;
+
+ explicit QSymbianTextCodec(uint charsetId, int staticIndex = -1) : m_charsetId(charsetId), m_staticIndex(staticIndex) { }
+
+ static QSymbianTextCodec *init();
+ static QSymbianTextCodec *localeMapper;
+private:
+ static CCnvCharacterSetConverter *converter();
+ static uint getLanguageDependentCharacterSet();
+ uint m_charsetId;
+ int m_staticIndex;
+};
+
+QSymbianTextCodec *QSymbianTextCodec::localeMapper = 0;
+
+class QSymbianTextCodecWithName : public QSymbianTextCodec
+{
+public:
+ QSymbianTextCodecWithName(uint charsetId, const QByteArray &name)
+ : QSymbianTextCodec(charsetId) , m_name(name) { }
+ QByteArray name() const { return m_name; }
+ QList<QByteArray> aliases() const { return QList<QByteArray>(); }
+private:
+ QByteArray m_name;
+};
+
+Q_GLOBAL_STATIC(QThreadStorage<CCnvCharacterSetConverter *>,gs_converterStore);
+
+CCnvCharacterSetConverter *QSymbianTextCodec::converter()
+{
+ CCnvCharacterSetConverter *&conv = gs_converterStore()->localData();
+ if (!conv)
+ QT_TRAP_THROWING(conv = CCnvCharacterSetConverter::NewL())
+ return conv;
+}
+
+
+QByteArray QSymbianTextCodec::name() const
+{
+ if (m_staticIndex >= 0)
+ return QByteArray(codecsData[m_staticIndex].aliases);
+ QScopedPointer<HBufC8> buf;
+ QT_TRAP_THROWING(buf.reset(converter()->ConvertCharacterSetIdentifierToStandardNameL(m_charsetId, qt_s60GetRFs())))
+ if (buf)
+ return QByteArray(reinterpret_cast<const char *>(buf->Ptr()), buf->Length());
+ return QByteArray();
+}
+
+int QSymbianTextCodec::mibEnum() const
+{
+ if (m_staticIndex >= 0)
+ return codecsData[m_staticIndex].mib;
+ int mib;
+ QT_TRAP_THROWING(mib = converter()->ConvertCharacterSetIdentifierToMibEnumL(m_charsetId, qt_s60GetRFs()))
+ return mib;
+}
+
+QList<QByteArray> QSymbianTextCodec::aliases() const
+{
+ QList<QByteArray> result;
+ if (m_staticIndex >= 0) {
+ const char *aliases = codecsData[m_staticIndex].aliases;
+ aliases += strlen(aliases) + 1;
+ while (*aliases) {
+ int len = strlen(aliases);
+ result += QByteArray(aliases, len);
+ aliases += len + 1;
+ }
+ }
+ return result;
+}
+
+
+QString QSymbianTextCodec::convertToUnicode(const char *str, int len, ConverterState *state) const
+{
+ uint charsetId = m_charsetId;
+
+ // no support for utf7 with state
+ if (state && (charsetId == KCharacterSetIdentifierUtf7 ||
+ charsetId == KCharacterSetIdentifierImapUtf7)) {
+ return QString();
+ }
+ CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter();
+ if (!str) {
+ return QString();
+ }
+
+ //Search the character set array containing all of the character sets for which conversion is available
+ CCnvCharacterSetConverter::TAvailability av;
+ QT_TRAP_THROWING(av = converter->PrepareToConvertToOrFromL(charsetId, qt_s60GetRFs()))
+ if (av == CCnvCharacterSetConverter::ENotAvailable) {
+ return QString();
+ }
+
+ char *str2;
+ int len2;
+ QByteArray helperBA;
+ if (state && (state->remainingChars > 0)) {
+ // we should prepare the input string ourselves
+ // the real size
+ len2 = len + state->remainingChars;
+ helperBA.resize(len2);
+ str2 = helperBA.data();
+ if (state->remainingChars > 3) { // doesn't happen usually
+ memcpy(str2, state->d, state->remainingChars);
+ qFree(state->d);
+ state->d = 0;
+ } else {
+ char charTbl[3];
+ charTbl[0] = state->state_data[0];
+ charTbl[1] = state->state_data[1];
+ charTbl[2] = state->state_data[2];
+ memcpy(str2, charTbl, state->remainingChars);
+ }
+ memcpy(str2+state->remainingChars, str, len);
+ }
+ else {
+ len2 = len;
+ str2 = const_cast<char*>(str);
+ }
+
+ QString UnicodeText(len2, Qt::Uninitialized);
+ TPtrC8 remainderOfForeignText;
+ remainderOfForeignText.Set(reinterpret_cast<const unsigned char *>(str2), len2);
+
+ int numberOfUnconvertibleCharacters = 0;
+ int indexOfFirstUnconvertibleCharacter;
+
+ // Use null character as replacement, if it is asked
+ bool convertToNull = (state && (state->flags & QTextCodec::ConvertInvalidToNull));
+ if (convertToNull) {
+ _LIT8(KReplacement, "\x00");
+ QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement))
+ }
+ // use state->invalidChars for keeping symbian state
+ int sState = CCnvCharacterSetConverter::KStateDefault;
+ if (state && (state->invalidChars != CCnvCharacterSetConverter::KStateDefault)) {
+ sState = state->invalidChars;
+ }
+ //Convert text encoded in a non-Unicode character set into the Unicode character set (UCS-2).
+ int remainingChars = -1;
+ int initial_size=0;
+ while (1) {
+ TPtr16 UnicodePtr(reinterpret_cast<unsigned short *>(UnicodeText.data()+initial_size), UnicodeText.size());
+ QT_TRAP_THROWING(remainingChars = converter->ConvertToUnicode(UnicodePtr,
+ remainderOfForeignText,
+ sState,
+ numberOfUnconvertibleCharacters,
+ indexOfFirstUnconvertibleCharacter))
+
+ initial_size += UnicodePtr.Length();
+ // replace 0xFFFD with 0x0000 and only if state set to convert to it
+ if (numberOfUnconvertibleCharacters>0 && convertToNull) {
+ int len2 = UnicodePtr.Length();
+ for (int i = indexOfFirstUnconvertibleCharacter; i < len2; i++) {
+ UnicodePtr[i] = 0x0000;
+ }
+ }
+ // success
+ if (remainingChars==KErrNone) {
+ break;
+ }
+ // if ConvertToUnicode could not consume the foreign text at all
+ // UTF-8: EErrorIllFormedInput = KErrCorrupt
+ // UCS-2: KErrNotFound
+ if (remainingChars == CCnvCharacterSetConverter::EErrorIllFormedInput ||
+ remainingChars == KErrNotFound) {
+ remainingChars = remainderOfForeignText.Size();
+ break;
+ }
+ else {
+ if (remainingChars < 0) {
+ return QString();
+ }
+ }
+ //
+ UnicodeText.resize(UnicodeText.size() + remainingChars*2);
+ remainderOfForeignText.Set(reinterpret_cast<const unsigned char *>(str2+len2-remainingChars), remainingChars);
+ }
+ // save symbian state
+ if (state) {
+ state->invalidChars = sState;
+ }
+
+ if (remainingChars > 0) {
+ if (!state) {
+ // No way to signal, if there is still remaining chars, for ex. UTF-8 still can have
+ // some characters hanging around.
+ return QString();
+ }
+ const unsigned char *charPtr = remainderOfForeignText.Right(remainingChars).Ptr();
+ if (remainingChars > 3) { // doesn't happen usually
+ state->d = (void*)qMalloc(remainingChars);
+ if (!state->d)
+ return QString();
+ // copy characters there
+ memcpy(state->d, charPtr, remainingChars);
+ }
+ else {
+ // fallthru is correct
+ switch (remainingChars) {
+ case 3:
+ state->state_data[2] = charPtr[2];
+ case 2:
+ state->state_data[1] = charPtr[1];
+ case 1:
+ state->state_data[0] = charPtr[0];
+ }
+ }
+ state->remainingChars = remainingChars;
+ }
+ else {
+ if (state) {
+ // If we continued from an earlier iteration
+ state->remainingChars = 0;
+ }
+ }
+ // check if any ORIGINAL headers should be left
+ if (initial_size > 0) {
+ if (!state || (state && !(state->flags & QTextCodec::IgnoreHeader))) {
+ // always skip headers on following state loops
+ if (state) {
+ state->flags |= QTextCodec::IgnoreHeader;
+ }
+ const TUint16 *ptr = reinterpret_cast<const TUint16 *>(UnicodeText.data());
+ if (ptr[0] == QChar::ByteOrderMark || ptr[0] == QChar::ByteOrderSwapped) {
+ return UnicodeText.mid(1, initial_size - 1);
+ }
+ }
+ }
+ if (initial_size >= 0) {
+ UnicodeText.resize(initial_size);
+ return UnicodeText;
+ }
+ else {
+ return QString();
+ }
+}
+
+
+QByteArray QSymbianTextCodec::convertFromUnicode(const QChar *str, int len, ConverterState *state) const
+{
+ uint charsetId = m_charsetId;
+ CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter();
+ if (!str)
+ return QByteArray();
+
+ if (len == 0)
+ return QByteArray();
+
+ // no support for utf7 with state
+ if (state && (charsetId == KCharacterSetIdentifierUtf7 ||
+ charsetId == KCharacterSetIdentifierImapUtf7))
+ return QByteArray();
+
+ //Get reference file session from backend
+ RFs &fileSession = qt_s60GetRFs();
+
+ //Search the character set array containing all of the character sets for which conversion is available
+ CCnvCharacterSetConverter::TAvailability av = CCnvCharacterSetConverter::ENotAvailable;
+ QT_TRAP_THROWING(av = converter->PrepareToConvertToOrFromL(charsetId, fileSession))
+ if (av == CCnvCharacterSetConverter::ENotAvailable)
+ return QByteArray();
+
+ // Use null character as replacement, if it is asked
+ if (state && (state->flags & QTextCodec::ConvertInvalidToNull)) {
+ _LIT8(KReplacement, "\x00");
+ QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement))
+ }
+ else {
+ _LIT8(KReplacement, "?");
+ QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement))
+ }
+ QByteArray outputBuffer;
+
+ // add header if no state (one run), or if no ignoreheader (from first state)
+ int bomofs = 0;
+ if (!state || (state && !(state->flags & QTextCodec::IgnoreHeader))) {
+
+ QChar bom(QChar::ByteOrderMark);
+
+ if (state)
+ state->flags |= QTextCodec::IgnoreHeader; // bom handling only on first state
+
+ switch (charsetId) {
+ case KCharacterSetIdentifierUcs2:
+ outputBuffer.append(bom.row());
+ outputBuffer.append(bom.cell());
+ bomofs = 2;
+ break;
+
+ case KCharacterSetIdentifierUtf8: // we don't add bom for UTF-8
+ case KCharacterSetIdentifierJavaConformantUtf8:
+ /*outputBuffer.append("\xef\xbb\xbf");
+ bomofs = 3;
+ */
+ break;
+
+ case KCharacterSetIdentifierUnicodeLittle:
+ outputBuffer.append(bom.cell());
+ outputBuffer.append(bom.row());
+ bomofs = 2;
+ break;
+
+ case KCharacterSetIdentifierUnicodeBig:
+ outputBuffer.append(bom.row());
+ outputBuffer.append(bom.cell());
+ bomofs = 2;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // len is 16bit chars, reserve 3 8bit chars for each input char
+ // jsz - it could be differentiated, to allocate less
+ outputBuffer.resize(len * 3 + bomofs);
+
+ // loop for too short output buffer
+ int unconverted;
+ int numberOfUnconvertibleCharacters = len;
+ int indexOfFirstUnconvertibleCharacter;
+ int convertedSize;
+ int lastUnconverted = 0;
+ int initial_size=0;
+ int remainderToConvert = len;
+ while (1) {
+ TPtr8 outputPtr(reinterpret_cast<unsigned char *>(outputBuffer.data() + bomofs + initial_size), outputBuffer.size() - bomofs);
+
+ TPtrC16 UnicodeText(reinterpret_cast<const unsigned short *>(str+len-remainderToConvert), remainderToConvert);
+
+ //Convert text encoded in the Unicode character set (UCS-2) into other character sets
+ unconverted = -1;
+ QT_TRAP_THROWING( unconverted = converter->ConvertFromUnicode(outputPtr,
+ UnicodeText,
+ numberOfUnconvertibleCharacters,
+ indexOfFirstUnconvertibleCharacter))
+ initial_size += outputPtr.Length();
+ if (unconverted < 0) {
+ return QByteArray();
+ }
+
+
+ if (unconverted == 0 ) {
+ convertedSize = initial_size;
+ break;
+ }
+
+ // check what means unconverted > 0
+ if (indexOfFirstUnconvertibleCharacter<0) {
+ // 8859-6 and 8859-8 break with certain input (string of \xc0 - \xd9 converted to unicode and back)
+ if (unconverted == lastUnconverted) {
+ return QByteArray();
+ }
+ lastUnconverted = unconverted;
+ }
+ else {
+ // were some character not possible to convert
+
+ }
+ remainderToConvert = unconverted; // len - indexOfFirstUnconvertibleCharacter;
+ // resize output buffer, use =op for the null check
+ outputBuffer.resize(outputBuffer.size() + remainderToConvert * 3 + bomofs);
+ };
+
+ // shorten output
+ outputBuffer.resize(convertedSize + bomofs);
+
+ if (state) {
+ state->invalidChars = numberOfUnconvertibleCharacters;
+
+ // check if any Symbian CONVERTED headers should be removed
+ if (state->flags & QTextCodec::IgnoreHeader && state->state_data[0] == 0) {
+
+ state->state_data[0] = 0xff; // bom handling only on first state
+
+ if (charsetId == KCharacterSetIdentifierUcs2 && outputBuffer.size() > 1) {
+
+ QChar bom(QChar::ByteOrderMark);
+ if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) {
+ outputBuffer.remove(0, 2);
+ } else if (outputBuffer.at(0) == bom.cell() && outputBuffer.at(1) == bom.row()) {
+ outputBuffer.remove(0, 2);
+ }
+
+ } else if ((charsetId == KCharacterSetIdentifierUtf8 ||
+ charsetId == KCharacterSetIdentifierJavaConformantUtf8) &&
+ outputBuffer.size() > 2) {
+ if (outputBuffer.at(0) == 0xef && outputBuffer.at(1) == 0xbb && outputBuffer.at(2) == 0xbf) {
+ outputBuffer.remove(0, 3);
+ }
+
+ } else if (charsetId == KCharacterSetIdentifierUnicodeLittle &&
+ outputBuffer.size() > 1) {
+
+ QChar bom(QChar::ByteOrderMark);
+ if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) {
+ outputBuffer.remove(0, 2);
+ }
+
+ } else if (charsetId == KCharacterSetIdentifierUnicodeBig &&
+ outputBuffer.size() > 1) {
+
+ QChar bom(QChar::ByteOrderSwapped);
+ if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) {
+ outputBuffer.remove(0, 2);
+ }
+ }
+
+ }
+ }
+
+ return outputBuffer;
+}
+
+
+uint QSymbianTextCodec::getLanguageDependentCharacterSet()
+{
+ TLanguage lang = User::Language();
+
+ uint langIndex = 0;
+
+ switch (lang) {
+ case 14: //ELangTurkish
+ langIndex = KCharacterSetIdentifierIso88599; break;
+ case 16: //ELangRussian
+ langIndex = KCharacterSetIdentifierIso88595; break;
+ case 17: //ELangHungarian
+ langIndex = KCharacterSetIdentifierIso88592; break;
+ case 25: //ELangCzec
+ case 26: //ELangSlovak
+ case 27: //ELangPolish
+ case 28: //ELangSlovenian
+ langIndex = KCharacterSetIdentifierIso88592; break;
+ case 29: //ELangTaiwanChinese
+ case 30: //ELangHongKongChinese
+ langIndex = KCharacterSetIdentifierBig5; break;
+ case 31: //ELangPrcChinese
+ langIndex = KCharacterSetIdentifierGbk; break;
+ case 32: //ELangJapanese
+ langIndex = KCharacterSetIdentifierShiftJis; break;
+ case 33: //ELangThai
+ langIndex = 270501193 /*KCharacterSetIdentifierTis620*/; break;
+ case 37: //ELangArabic
+ langIndex = KCharacterSetIdentifierIso88596; break;
+ case 40: //ELangBelarussian
+ case 42: //ELangBulgarian
+ langIndex = KCharacterSetIdentifierIso88595; break;
+ case 45: //ELangCroatian
+ langIndex = KCharacterSetIdentifierIso88592; break;
+ case 49: //ELangEstonian
+ langIndex = KCharacterSetIdentifierIso88594; break;
+ case 54: //ELangGreek
+ case 55: //ELangCyprusGreek
+ langIndex = KCharacterSetIdentifierIso88597; break;
+ case 57: //ELangHebrew
+ langIndex = KCharacterSetIdentifierIso88598; break;
+ case 58: //ELangHindi
+ langIndex = 271011982/*KCharacterSetIdentifierIscii*/; break;
+ case 67: //ELangLatvian
+ case 68: //ELangLithuanian
+ langIndex = KCharacterSetIdentifierIso88594; break;
+ case 69: //ELangMacedonian
+ langIndex = KCharacterSetIdentifierIso88595; break;
+ case 78: //ELangRomanian
+ langIndex = KCharacterSetIdentifierIso88592; break;
+ case 79: //ELangSerbian
+ langIndex = KCharacterSetIdentifierIso88592; break;
+ case 91: //ELangCyprusTurkish
+ langIndex = KCharacterSetIdentifierIso88599; break;
+ case 93: //ELangUkrainian
+ langIndex = KCharacterSetIdentifierIso88595; break;
+ case 94: //ELangUrdu
+ langIndex = KCharacterSetIdentifierIso88596; break;
+ case 157: //ELangEnglish_Taiwan
+ case 158: //ELangEnglish_HongKong
+ langIndex = KCharacterSetIdentifierBig5; break;
+ case 159: //ELangEnglish_Prc
+ langIndex = KCharacterSetIdentifierGbk; break;
+ case 160:
+ langIndex = KCharacterSetIdentifierShiftJis; break;
+ case 161: //ELangEnglish_Thailand
+ langIndex = 270501193/*KCharacterSetIdentifierTis620*/; break;
+ }
+
+ if (langIndex > 0) {
+ return langIndex;
+ }
+ return KCharacterSetIdentifierCodePage1252;
+}
+
+/* Create the codecs that have aliases and return the locale mapper*/
+QSymbianTextCodec *QSymbianTextCodec::init()
+{
+ const uint localeMapperId = getLanguageDependentCharacterSet();
+ QScopedPointer<CArrayFix<CCnvCharacterSetConverter::SCharacterSet> > array;
+ QT_TRAP_THROWING(array.reset(CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(qt_s60GetRFs())))
+ CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter();
+ int count = array->Count();
+ for (int i = 0; i < count; i++) {
+ int charsetId = array->At(i).Identifier();
+
+ // skip builtin Qt codecs
+ if (charsetId == KCharacterSetIdentifierUtf8 || charsetId == KCharacterSetIdentifierUnicodeLittle
+ || charsetId == KCharacterSetIdentifierUnicodeLittle || charsetId == KCharacterSetIdentifierUnicodeBig
+ || charsetId == KCharacterSetIdentifierIso88591
+ || charsetId == 270501691 /* skip Windows-1252 duplicate*/) {
+ continue;
+ }
+
+ int begin = 0;
+ int n = sizeof(codecsData) / sizeof(codecsData[0]);
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ int middle = begin + half;
+ if (codecsData[middle].charsetId < charsetId) {
+ begin = middle + 1;
+ n -= half + 1;
+ } else {
+ n = half;
+ }
+ }
+ if (codecsData[begin].charsetId == charsetId) {
+ QSymbianTextCodec *c = new QSymbianTextCodec(charsetId, begin);
+ if (charsetId == localeMapperId)
+ localeMapper = c;
+ } else {
+ // We did not find the charsetId in our codecsData[], therefore we ask
+ // the OS for the codec name. We first try to get a "standard name" and fall
+ // back to array->At(i).Name(), if really needed. array->At(i).Name() is not
+ // guaranteed to be a correct name for QTextCodec::codecFromName().
+ QScopedPointer<HBufC8> buf;
+ QT_TRAP_THROWING(buf.reset(converter->ConvertCharacterSetIdentifierToStandardNameL(charsetId, qt_s60GetRFs())))
+ QByteArray name;
+ if (buf && buf->Length()) {
+ name = QByteArray(reinterpret_cast<const char *>(buf->Ptr()), buf->Length());
+ } else {
+ TPtrC charSetName = array->At(i).NameIsFileName() ? TParsePtrC(array->At(i).Name()).Name() : array->At(i).Name();
+ int len = charSetName.Length();
+ QString str;
+ str.setUnicode(reinterpret_cast<const QChar*>(charSetName.Ptr()), len);
+ name = str.toLatin1();
+ }
+ if (!name.isEmpty())
+ new QSymbianTextCodecWithName(charsetId, name);
+ }
+
+ }
+ return localeMapper;
+}
diff --git a/src/corelib/codecs/qtextcodecplugin.cpp b/src/corelib/codecs/qtextcodecplugin.cpp
new file mode 100644
index 0000000000..aac98f4362
--- /dev/null
+++ b/src/corelib/codecs/qtextcodecplugin.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtextcodecplugin.h"
+#include "qstringlist.h"
+
+#ifndef QT_NO_TEXTCODECPLUGIN
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QTextCodecPlugin
+ \brief The QTextCodecPlugin class provides an abstract base for custom QTextCodec plugins.
+ \reentrant
+ \ingroup plugins
+
+ The text codec plugin is a simple plugin interface that makes it
+ easy to create custom text codecs that can be loaded dynamically
+ into applications.
+
+ Writing a text codec plugin is achieved by subclassing this base
+ class, reimplementing the pure virtual functions names(),
+ aliases(), createForName(), mibEnums() and createForMib(), and
+ exporting the class with the Q_EXPORT_PLUGIN2() macro. See \l{How
+ to Create Qt Plugins} for details.
+
+ See the \l{http://www.iana.org/assignments/character-sets}{IANA
+ character-sets encoding file} for more information on mime
+ names and mib enums.
+*/
+
+/*!
+ \fn QStringList QTextCodecPlugin::names() const
+
+ Returns the list of MIME names supported by this plugin.
+
+ If a codec has several names, the extra names are returned by aliases().
+
+ \sa createForName(), aliases()
+*/
+
+/*!
+ \fn QList<QByteArray> QTextCodecPlugin::aliases() const
+
+ Returns the list of aliases supported by this plugin.
+*/
+
+/*!
+ \fn QTextCodec *QTextCodecPlugin::createForName(const QByteArray &name)
+
+ Creates a QTextCodec object for the codec called \a name. The \a name
+ must come from the list of encodings returned by names(). Encoding
+ names are case sensitive.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodecplugin.cpp 0
+
+ \sa names()
+*/
+
+
+/*!
+ \fn QList<int> QTextCodecPlugin::mibEnums() const
+
+ Returns the list of mib enums supported by this plugin.
+
+ \sa createForMib()
+*/
+
+/*!
+ \fn QTextCodec *QTextCodecPlugin::createForMib(int mib);
+
+ Creates a QTextCodec object for the mib enum \a mib.
+
+ See \l{http://www.iana.org/assignments/character-sets}{the
+ IANA character-sets encoding file} for more information.
+
+ \sa mibEnums()
+*/
+
+/*!
+ Constructs a text codec plugin with the given \a parent. This is
+ invoked automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QTextCodecPlugin::QTextCodecPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the text codec plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QTextCodecPlugin::~QTextCodecPlugin()
+{
+}
+
+QStringList QTextCodecPlugin::keys() const
+{
+ QStringList keys;
+ QList<QByteArray> list = names();
+ list += aliases();
+ for (int i = 0; i < list.size(); ++i)
+ keys += QString::fromLatin1(list.at(i));
+ QList<int> mibs = mibEnums();
+ for (int i = 0; i < mibs.count(); ++i)
+ keys += QLatin1String("MIB: ") + QString::number(mibs.at(i));
+ return keys;
+}
+
+QTextCodec *QTextCodecPlugin::create(const QString &name)
+{
+ if (name.startsWith(QLatin1String("MIB: ")))
+ return createForMib(name.mid(4).toInt());
+ return createForName(name.toLatin1());
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TEXTCODECPLUGIN
diff --git a/src/corelib/codecs/qtextcodecplugin.h b/src/corelib/codecs/qtextcodecplugin.h
new file mode 100644
index 0000000000..80c1d17344
--- /dev/null
+++ b/src/corelib/codecs/qtextcodecplugin.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTCODECPLUGIN_H
+#define QTEXTCODECPLUGIN_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_TEXTCODECPLUGIN
+
+class QTextCodec;
+
+struct Q_CORE_EXPORT QTextCodecFactoryInterface : public QFactoryInterface
+{
+ virtual QTextCodec *create(const QString &key) = 0;
+};
+
+#define QTextCodecFactoryInterface_iid "com.trolltech.Qt.QTextCodecFactoryInterface"
+
+Q_DECLARE_INTERFACE(QTextCodecFactoryInterface, QTextCodecFactoryInterface_iid)
+
+
+class Q_CORE_EXPORT QTextCodecPlugin : public QObject, public QTextCodecFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QTextCodecFactoryInterface:QFactoryInterface)
+public:
+ explicit QTextCodecPlugin(QObject *parent = 0);
+ ~QTextCodecPlugin();
+
+ virtual QList<QByteArray> names() const = 0;
+ virtual QList<QByteArray> aliases() const = 0;
+ virtual QTextCodec *createForName(const QByteArray &name) = 0;
+
+ virtual QList<int> mibEnums() const = 0;
+ virtual QTextCodec *createForMib(int mib) = 0;
+
+private:
+ QStringList keys() const;
+ QTextCodec *create(const QString &name);
+};
+
+#endif // QT_NO_TEXTCODECPLUGIN
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTEXTCODECPLUGIN_H
diff --git a/src/corelib/codecs/qtsciicodec.cpp b/src/corelib/codecs/qtsciicodec.cpp
new file mode 100644
index 0000000000..2550b07eb5
--- /dev/null
+++ b/src/corelib/codecs/qtsciicodec.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Most of the code here was originally written by Hans Petter Bieker,
+// and is included in Qt with the author's permission, and the grateful
+// thanks of the Qt team.
+
+#include "qtsciicodec_p.h"
+#include "qlist.h"
+
+#ifndef QT_NO_CODECS
+
+QT_BEGIN_NAMESPACE
+
+static unsigned char qt_UnicodeToTSCII(ushort u1, ushort u2, ushort u3);
+static unsigned int qt_TSCIIToUnicode(unsigned int code, uint *s);
+
+#define IsTSCIIChar(c) (((c) >= 0x80) && ((c) <= 0xfd))
+
+/*! \class QTsciiCodec
+ \reentrant
+ \internal
+*/
+
+/*!
+ Destroys the text codec object.
+*/
+QTsciiCodec::~QTsciiCodec()
+{
+}
+
+/*!
+ Converts the first \a len characters in \a uc from Unicode to this
+ encoding, and returns the result in a byte array. The \a state contains
+ some conversion flags, and is used by the codec to maintain state
+ information.
+*/
+QByteArray QTsciiCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
+{
+ char replacement = '?';
+ if (state) {
+ if (state->flags & ConvertInvalidToNull)
+ replacement = 0;
+ }
+ int invalid = 0;
+
+ QByteArray rstr(len, Qt::Uninitialized);
+ uchar* cursor = (uchar*)rstr.data();
+ for (int i = 0; i < len; i++) {
+ QChar ch = uc[i];
+ uchar j;
+ if (ch.row() == 0x00 && ch.cell() < 0x80) {
+ // ASCII
+ j = ch.cell();
+ } else if ((j = qt_UnicodeToTSCII(uc[i].unicode(),
+ uc[i + 1].unicode(),
+ uc[i + 2].unicode()))) {
+ // We have to check the combined chars first!
+ i += 2;
+ } else if ((j = qt_UnicodeToTSCII(uc[i].unicode(),
+ uc[i + 1].unicode(), 0))) {
+ i++;
+ } else if ((j = qt_UnicodeToTSCII(uc[i].unicode(), 0, 0))) {
+ } else {
+ // Error
+ j = replacement;
+ ++invalid;
+ }
+ *cursor++ = j;
+ }
+ rstr.resize(cursor - (const uchar*)rstr.constData());
+
+ if (state) {
+ state->invalidChars += invalid;
+ }
+ return rstr;
+}
+
+/*!
+ Converts the first \a len characters in \a chars from this encoding
+ to Unicode, and returns the result in a QString. The \a state contains
+ some conversion flags, and is used by the codec to maintain state
+ information.
+*/
+QString QTsciiCodec::convertToUnicode(const char* chars, int len, ConverterState *state) const
+{
+ QChar replacement = QChar::ReplacementCharacter;
+ if (state) {
+ if (state->flags & ConvertInvalidToNull)
+ replacement = QChar::Null;
+ }
+ int invalid = 0;
+
+ QString result;
+ for (int i = 0; i < len; i++) {
+ uchar ch = chars[i];
+ if (ch < 0x80) {
+ // ASCII
+ result += QLatin1Char(ch);
+ } else if (IsTSCIIChar(ch)) {
+ // TSCII
+ uint s[3];
+ uint u = qt_TSCIIToUnicode(ch, s);
+ uint *p = s;
+ while (u--) {
+ uint c = *p++;
+ if (c)
+ result += QChar(c);
+ else {
+ result += replacement;
+ ++invalid;
+ }
+ }
+ } else {
+ // Invalid
+ result += replacement;
+ ++invalid;
+ }
+ }
+
+ if (state) {
+ state->invalidChars += invalid;
+ }
+ return result;
+}
+
+/*!
+ Returns the official name for the encoding that is handled by the codec.
+
+ \sa QTextCodec::name()
+*/
+QByteArray QTsciiCodec::name() const
+{
+ return "TSCII";
+}
+
+/*!
+ Returns the MIB enum for the encoding.
+
+ \sa QTextCodec::mibEnum()
+*/
+int QTsciiCodec::mibEnum() const
+{
+ return 2107;
+}
+
+static const int UnToTsLast = 124; // 125 items -- so the last will be 124
+static const ushort UnToTs [][4] = {
+ // *Sorted* list of TSCII maping for unicode chars
+ //FIRST SECOND THIRD TSCII
+ {0x00A0, 0x0000, 0x0000, 0xA0},
+ {0x00A9, 0x0000, 0x0000, 0xA9},
+ {0x0B83, 0x0000, 0x0000, 0xB7},
+ {0x0B85, 0x0000, 0x0000, 0xAB},
+ {0x0B86, 0x0000, 0x0000, 0xAC},
+ {0x0B87, 0x0000, 0x0000, 0xAD},
+ {0x0B88, 0x0000, 0x0000, 0xAE},
+ {0x0B89, 0x0000, 0x0000, 0xAF},
+ {0x0B8A, 0x0000, 0x0000, 0xB0},
+ {0x0B8E, 0x0000, 0x0000, 0xB1},
+ {0x0B8F, 0x0000, 0x0000, 0xB2},
+ {0x0B90, 0x0000, 0x0000, 0xB3},
+ {0x0B92, 0x0000, 0x0000, 0xB4},
+ {0x0B93, 0x0000, 0x0000, 0xB5},
+ {0x0B94, 0x0000, 0x0000, 0xB6},
+ {0x0B95, 0x0000, 0x0000, 0xB8},
+ {0x0B95, 0x0B82, 0x0000, 0xEC},
+ {0x0B95, 0x0BC1, 0x0000, 0xCC},
+ {0x0B95, 0x0BC2, 0x0000, 0xDC},
+ {0x0B99, 0x0000, 0x0000, 0xB9},
+ {0x0B99, 0x0B82, 0x0000, 0xED},
+ {0x0B99, 0x0BC1, 0x0000, 0x99},
+ {0x0B99, 0x0BC2, 0x0000, 0x9B},
+ {0x0B9A, 0x0000, 0x0000, 0xBA},
+ {0x0B9A, 0x0B82, 0x0000, 0xEE},
+ {0x0B9A, 0x0BC1, 0x0000, 0xCD},
+ {0x0B9A, 0x0BC2, 0x0000, 0xDD},
+ {0x0B9C, 0x0000, 0x0000, 0x83},
+ {0x0B9C, 0x0B82, 0x0000, 0x88},
+ {0x0B9E, 0x0000, 0x0000, 0xBB},
+ {0x0B9E, 0x0B82, 0x0000, 0xEF},
+ {0x0B9E, 0x0BC1, 0x0000, 0x9A},
+ {0x0B9E, 0x0BC2, 0x0000, 0x9C},
+ {0x0B9F, 0x0000, 0x0000, 0xBC},
+ {0x0B9F, 0x0B82, 0x0000, 0xF0},
+ {0x0B9F, 0x0BBF, 0x0000, 0xCA},
+ {0x0B9F, 0x0BC0, 0x0000, 0xCB},
+ {0x0B9F, 0x0BC1, 0x0000, 0xCE},
+ {0x0B9F, 0x0BC2, 0x0000, 0xDE},
+ {0x0BA1, 0x0B82, 0x0000, 0xF2},
+ {0x0BA3, 0x0000, 0x0000, 0xBD},
+ {0x0BA3, 0x0B82, 0x0000, 0xF1},
+ {0x0BA3, 0x0BC1, 0x0000, 0xCF},
+ {0x0BA3, 0x0BC2, 0x0000, 0xDF},
+ {0x0BA4, 0x0000, 0x0000, 0xBE},
+ {0x0BA4, 0x0BC1, 0x0000, 0xD0},
+ {0x0BA4, 0x0BC2, 0x0000, 0xE0},
+ {0x0BA8, 0x0000, 0x0000, 0xBF},
+ {0x0BA8, 0x0B82, 0x0000, 0xF3},
+ {0x0BA8, 0x0BC1, 0x0000, 0xD1},
+ {0x0BA8, 0x0BC2, 0x0000, 0xE1},
+ {0x0BA9, 0x0000, 0x0000, 0xC9},
+ {0x0BA9, 0x0B82, 0x0000, 0xFD},
+ {0x0BA9, 0x0BC1, 0x0000, 0xDB},
+ {0x0BA9, 0x0BC2, 0x0000, 0xEB},
+ {0x0BAA, 0x0000, 0x0000, 0xC0},
+ {0x0BAA, 0x0B82, 0x0000, 0xF4},
+ {0x0BAA, 0x0BC1, 0x0000, 0xD2},
+ {0x0BAA, 0x0BC2, 0x0000, 0xE2},
+ {0x0BAE, 0x0000, 0x0000, 0xC1},
+ {0x0BAE, 0x0B82, 0x0000, 0xF5},
+ {0x0BAE, 0x0BC1, 0x0000, 0xD3},
+ {0x0BAE, 0x0BC2, 0x0000, 0xE3},
+ {0x0BAF, 0x0000, 0x0000, 0xC2},
+ {0x0BAF, 0x0B82, 0x0000, 0xF6},
+ {0x0BAF, 0x0BC1, 0x0000, 0xD4},
+ {0x0BAF, 0x0BC2, 0x0000, 0xE4},
+ {0x0BB0, 0x0000, 0x0000, 0xC3},
+ {0x0BB0, 0x0B82, 0x0000, 0xF7},
+ {0x0BB0, 0x0BC1, 0x0000, 0xD5},
+ {0x0BB0, 0x0BC2, 0x0000, 0xE5},
+ {0x0BB1, 0x0000, 0x0000, 0xC8},
+ {0x0BB1, 0x0B82, 0x0000, 0xFC},
+ {0x0BB1, 0x0BC1, 0x0000, 0xDA},
+ {0x0BB1, 0x0BC2, 0x0000, 0xEA},
+ {0x0BB2, 0x0000, 0x0000, 0xC4},
+ {0x0BB2, 0x0B82, 0x0000, 0xF8},
+ {0x0BB2, 0x0BC1, 0x0000, 0xD6},
+ {0x0BB2, 0x0BC2, 0x0000, 0xE6},
+ {0x0BB3, 0x0000, 0x0000, 0xC7},
+ {0x0BB3, 0x0B82, 0x0000, 0xFB},
+ {0x0BB3, 0x0BC1, 0x0000, 0xD9},
+ {0x0BB3, 0x0BC2, 0x0000, 0xE9},
+ {0x0BB4, 0x0000, 0x0000, 0xC6},
+ {0x0BB4, 0x0B82, 0x0000, 0xFA},
+ {0x0BB4, 0x0BC1, 0x0000, 0xD8},
+ {0x0BB4, 0x0BC2, 0x0000, 0xE8},
+ {0x0BB5, 0x0000, 0x0000, 0xC5},
+ {0x0BB5, 0x0B82, 0x0000, 0xF9},
+ {0x0BB5, 0x0BC1, 0x0000, 0xD7},
+ {0x0BB5, 0x0BC2, 0x0000, 0xE7},
+ {0x0BB7, 0x0000, 0x0000, 0x84},
+ {0x0BB7, 0x0B82, 0x0000, 0x89},
+ {0x0BB8, 0x0000, 0x0000, 0x85},
+ {0x0BB8, 0x0B82, 0x0000, 0x8A},
+ {0x0BB9, 0x0000, 0x0000, 0x86},
+ {0x0BB9, 0x0B82, 0x0000, 0x8B},
+ {0x0BBE, 0x0000, 0x0000, 0xA1},
+ {0x0BBF, 0x0000, 0x0000, 0xA2},
+ {0x0BC0, 0x0000, 0x0000, 0xA3},
+ {0x0BC1, 0x0000, 0x0000, 0xA4},
+ {0x0BC2, 0x0000, 0x0000, 0xA5},
+ {0x0BC6, 0x0000, 0x0000, 0xA6},
+ {0x0BC7, 0x0000, 0x0000, 0xA7},
+ {0x0BC8, 0x0000, 0x0000, 0xA8},
+ {0x0BCC, 0x0000, 0x0000, 0xAA},
+ {0x0BE6, 0x0000, 0x0000, 0x80},
+ {0x0BE7, 0x0000, 0x0000, 0x81},
+ {0x0BE7, 0x0BB7, 0x0000, 0x87},
+ {0x0BE7, 0x0BB7, 0x0B82, 0x8C},
+ {0x0BE8, 0x0000, 0x0000, 0x8D},
+ {0x0BE9, 0x0000, 0x0000, 0x8E},
+ {0x0BEA, 0x0000, 0x0000, 0x8F},
+ {0x0BEB, 0x0000, 0x0000, 0x90},
+ {0x0BEC, 0x0000, 0x0000, 0x95},
+ {0x0BED, 0x0000, 0x0000, 0x96},
+ {0x0BEE, 0x0000, 0x0000, 0x97},
+ {0x0BEF, 0x0000, 0x0000, 0x98},
+ {0x0BF0, 0x0000, 0x0000, 0x9D},
+ {0x0BF1, 0x0000, 0x0000, 0x9E},
+ {0x0BF2, 0x0000, 0x0000, 0x9F},
+ {0x2018, 0x0000, 0x0000, 0x91},
+ {0x2019, 0x0000, 0x0000, 0x92},
+ {0x201C, 0x0000, 0x0000, 0x93},
+ {0x201C, 0x0000, 0x0000, 0x94}
+};
+
+static const ushort TsToUn [][3] = {
+ // Starting at 0x80
+ {0x0BE6, 0x0000, 0x0000},
+ {0x0BE7, 0x0000, 0x0000},
+ {0x0000, 0x0000, 0x0000}, // unknown
+ {0x0B9C, 0x0000, 0x0000},
+ {0x0BB7, 0x0000, 0x0000},
+ {0x0BB8, 0x0000, 0x0000},
+ {0x0BB9, 0x0000, 0x0000},
+ {0x0BE7, 0x0BB7, 0x0000},
+ {0x0B9C, 0x0B82, 0x0000},
+ {0x0BB7, 0x0B82, 0x0000},
+ {0x0BB8, 0x0B82, 0x0000},
+ {0x0BB9, 0x0B82, 0x0000},
+ {0x0BE7, 0x0BB7, 0x0B82},
+ {0x0BE8, 0x0000, 0x0000},
+ {0x0BE9, 0x0000, 0x0000},
+ {0x0BEA, 0x0000, 0x0000},
+ {0x0BEB, 0x0000, 0x0000},
+ {0x2018, 0x0000, 0x0000},
+ {0x2019, 0x0000, 0x0000},
+ {0x201C, 0x0000, 0x0000},
+ {0x201C, 0x0000, 0x0000}, // two of the same??
+ {0x0BEC, 0x0000, 0x0000},
+ {0x0BED, 0x0000, 0x0000},
+ {0x0BEE, 0x0000, 0x0000},
+ {0x0BEF, 0x0000, 0x0000},
+ {0x0B99, 0x0BC1, 0x0000},
+ {0x0B9E, 0x0BC1, 0x0000},
+ {0x0B99, 0x0BC2, 0x0000},
+ {0x0B9E, 0x0BC2, 0x0000},
+ {0x0BF0, 0x0000, 0x0000},
+ {0x0BF1, 0x0000, 0x0000},
+ {0x0BF2, 0x0000, 0x0000},
+ {0x00A0, 0x0000, 0x0000},
+ {0x0BBE, 0x0000, 0x0000},
+ {0x0BBF, 0x0000, 0x0000},
+ {0x0BC0, 0x0000, 0x0000},
+ {0x0BC1, 0x0000, 0x0000},
+ {0x0BC2, 0x0000, 0x0000},
+ {0x0BC6, 0x0000, 0x0000},
+ {0x0BC7, 0x0000, 0x0000},
+ {0x0BC8, 0x0000, 0x0000},
+ {0x00A9, 0x0000, 0x0000},
+ {0x0BCC, 0x0000, 0x0000},
+ {0x0B85, 0x0000, 0x0000},
+ {0x0B86, 0x0000, 0x0000},
+ {0x0B87, 0x0000, 0x0000},
+ {0x0B88, 0x0000, 0x0000},
+ {0x0B89, 0x0000, 0x0000},
+ {0x0B8A, 0x0000, 0x0000},
+ {0x0B8E, 0x0000, 0x0000},
+ {0x0B8F, 0x0000, 0x0000},
+ {0x0B90, 0x0000, 0x0000},
+ {0x0B92, 0x0000, 0x0000},
+ {0x0B93, 0x0000, 0x0000},
+ {0x0B94, 0x0000, 0x0000},
+ {0x0B83, 0x0000, 0x0000},
+ {0x0B95, 0x0000, 0x0000},
+ {0x0B99, 0x0000, 0x0000},
+ {0x0B9A, 0x0000, 0x0000},
+ {0x0B9E, 0x0000, 0x0000},
+ {0x0B9F, 0x0000, 0x0000},
+ {0x0BA3, 0x0000, 0x0000},
+ {0x0BA4, 0x0000, 0x0000},
+ {0x0BA8, 0x0000, 0x0000},
+ {0x0BAA, 0x0000, 0x0000},
+ {0x0BAE, 0x0000, 0x0000},
+ {0x0BAF, 0x0000, 0x0000},
+ {0x0BB0, 0x0000, 0x0000},
+ {0x0BB2, 0x0000, 0x0000},
+ {0x0BB5, 0x0000, 0x0000},
+ {0x0BB4, 0x0000, 0x0000},
+ {0x0BB3, 0x0000, 0x0000},
+ {0x0BB1, 0x0000, 0x0000},
+ {0x0BA9, 0x0000, 0x0000},
+ {0x0B9F, 0x0BBF, 0x0000},
+ {0x0B9F, 0x0BC0, 0x0000},
+ {0x0B95, 0x0BC1, 0x0000},
+ {0x0B9A, 0x0BC1, 0x0000},
+ {0x0B9F, 0x0BC1, 0x0000},
+ {0x0BA3, 0x0BC1, 0x0000},
+ {0x0BA4, 0x0BC1, 0x0000},
+ {0x0BA8, 0x0BC1, 0x0000},
+ {0x0BAA, 0x0BC1, 0x0000},
+ {0x0BAE, 0x0BC1, 0x0000},
+ {0x0BAF, 0x0BC1, 0x0000},
+ {0x0BB0, 0x0BC1, 0x0000},
+ {0x0BB2, 0x0BC1, 0x0000},
+ {0x0BB5, 0x0BC1, 0x0000},
+ {0x0BB4, 0x0BC1, 0x0000},
+ {0x0BB3, 0x0BC1, 0x0000},
+ {0x0BB1, 0x0BC1, 0x0000},
+ {0x0BA9, 0x0BC1, 0x0000},
+ {0x0B95, 0x0BC2, 0x0000},
+ {0x0B9A, 0x0BC2, 0x0000},
+ {0x0B9F, 0x0BC2, 0x0000},
+ {0x0BA3, 0x0BC2, 0x0000},
+ {0x0BA4, 0x0BC2, 0x0000},
+ {0x0BA8, 0x0BC2, 0x0000},
+ {0x0BAA, 0x0BC2, 0x0000},
+ {0x0BAE, 0x0BC2, 0x0000},
+ {0x0BAF, 0x0BC2, 0x0000},
+ {0x0BB0, 0x0BC2, 0x0000},
+ {0x0BB2, 0x0BC2, 0x0000},
+ {0x0BB5, 0x0BC2, 0x0000},
+ {0x0BB4, 0x0BC2, 0x0000},
+ {0x0BB3, 0x0BC2, 0x0000},
+ {0x0BB1, 0x0BC2, 0x0000},
+ {0x0BA9, 0x0BC2, 0x0000},
+ {0x0B95, 0x0B82, 0x0000},
+ {0x0B99, 0x0B82, 0x0000},
+ {0x0B9A, 0x0B82, 0x0000},
+ {0x0B9E, 0x0B82, 0x0000},
+ {0x0B9F, 0x0B82, 0x0000},
+ {0x0BA3, 0x0B82, 0x0000},
+ {0x0BA1, 0x0B82, 0x0000},
+ {0x0BA8, 0x0B82, 0x0000},
+ {0x0BAA, 0x0B82, 0x0000},
+ {0x0BAE, 0x0B82, 0x0000},
+ {0x0BAF, 0x0B82, 0x0000},
+ {0x0BB0, 0x0B82, 0x0000},
+ {0x0BB2, 0x0B82, 0x0000},
+ {0x0BB5, 0x0B82, 0x0000},
+ {0x0BB4, 0x0B82, 0x0000},
+ {0x0BB3, 0x0B82, 0x0000},
+ {0x0BB1, 0x0B82, 0x0000},
+ {0x0BA9, 0x0B82, 0x0000}
+};
+
+static int cmp(const ushort *s1, const ushort *s2, size_t len)
+{
+ int diff = 0;
+
+ while (len-- && (diff = *s1++ - *s2++) == 0)
+ ;
+
+ return diff;
+}
+
+static unsigned char qt_UnicodeToTSCII(ushort u1, ushort u2, ushort u3)
+{
+ ushort s[3];
+ s[0] = u1;
+ s[1] = u2;
+ s[2] = u3;
+
+ int a = 0; // start pos
+ int b = UnToTsLast; // end pos
+
+ // do a binary search for the composed unicode in the list
+ while (a <= b) {
+ int w = (a + b) / 2;
+ int j = cmp(UnToTs[w], s, 3);
+
+ if (j == 0)
+ // found it
+ return UnToTs[w][3];
+
+ if (j < 0)
+ a = w + 1;
+ else
+ b = w - 1;
+ }
+
+ return 0;
+}
+
+static unsigned int qt_TSCIIToUnicode(uint code, uint *s)
+{
+ int len = 0;
+ for (int i = 0; i < 3; i++) {
+ uint u = TsToUn[code & 0x7f][i];
+ s[i] = u;
+ if (s[i]) len = i + 1;
+ }
+
+ return len;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CODECS
diff --git a/src/corelib/codecs/qtsciicodec_p.h b/src/corelib/codecs/qtsciicodec_p.h
new file mode 100644
index 0000000000..7e2bed4e64
--- /dev/null
+++ b/src/corelib/codecs/qtsciicodec_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Most of the code here was originally written by Hans Petter Bieker,
+// and is included in Qt with the author's permission, and the grateful
+// thanks of the Qt team.
+
+/*
+ * Copyright (C) 2000 Hans Petter Bieker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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.
+ */
+
+#ifndef QTSCIICODEC_P_H
+#define QTSCIICODEC_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/qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_CODECS
+
+class QTsciiCodec : public QTextCodec {
+public:
+ ~QTsciiCodec();
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+};
+
+#endif // QT_NO_CODECS
+
+QT_END_NAMESPACE
+
+#endif // QTSCIICODEC_P_H
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
new file mode 100644
index 0000000000..c44832936d
--- /dev/null
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -0,0 +1,670 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qutfcodec_p.h"
+#include "qlist.h"
+#include "qendian.h"
+#include "qchar.h"
+
+QT_BEGIN_NAMESPACE
+
+enum { Endian = 0, Data = 1 };
+
+static inline bool isUnicodeNonCharacter(uint ucs4)
+{
+ // Unicode has a couple of "non-characters" that one can use internally,
+ // but are not allowed to be used for text interchange.
+ //
+ // Those are the last two entries each Unicode Plane (U+FFFE, U+FFFF,
+ // U+1FFFE, U+1FFFF, etc.) as well as the entries between U+FDD0 and
+ // U+FDEF (inclusive)
+
+ return (ucs4 & 0xfffe) == 0xfffe
+ || (ucs4 - 0xfdd0U) < 16;
+}
+
+QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state)
+{
+ uchar replacement = '?';
+ int rlen = 3*len;
+ int surrogate_high = -1;
+ if (state) {
+ if (state->flags & QTextCodec::ConvertInvalidToNull)
+ replacement = 0;
+ if (!(state->flags & QTextCodec::IgnoreHeader))
+ rlen += 3;
+ if (state->remainingChars)
+ surrogate_high = state->state_data[0];
+ }
+
+ QByteArray rstr;
+ rstr.resize(rlen);
+ uchar* cursor = (uchar*)rstr.data();
+ const QChar *ch = uc;
+ int invalid = 0;
+ if (state && !(state->flags & QTextCodec::IgnoreHeader)) {
+ *cursor++ = 0xef;
+ *cursor++ = 0xbb;
+ *cursor++ = 0xbf;
+ }
+
+ const QChar *end = ch + len;
+ while (ch < end) {
+ uint u = ch->unicode();
+ if (surrogate_high >= 0) {
+ if (u >= 0xdc00 && u < 0xe000) {
+ u = (surrogate_high - 0xd800)*0x400 + (u - 0xdc00) + 0x10000;
+ surrogate_high = -1;
+ } else {
+ // high surrogate without low
+ *cursor = replacement;
+ ++ch;
+ ++invalid;
+ surrogate_high = -1;
+ continue;
+ }
+ } else if (u >= 0xdc00 && u < 0xe000) {
+ // low surrogate without high
+ *cursor = replacement;
+ ++ch;
+ ++invalid;
+ continue;
+ } else if (u >= 0xd800 && u < 0xdc00) {
+ surrogate_high = u;
+ ++ch;
+ continue;
+ }
+
+ if (u < 0x80) {
+ *cursor++ = (uchar)u;
+ } else {
+ if (u < 0x0800) {
+ *cursor++ = 0xc0 | ((uchar) (u >> 6));
+ } else {
+ // is it one of the Unicode non-characters?
+ if (isUnicodeNonCharacter(u)) {
+ *cursor++ = replacement;
+ ++ch;
+ ++invalid;
+ continue;
+ }
+
+ if (u > 0xffff) {
+ *cursor++ = 0xf0 | ((uchar) (u >> 18));
+ *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f);
+ } else {
+ *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f);
+ }
+ *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f);
+ }
+ *cursor++ = 0x80 | ((uchar) (u&0x3f));
+ }
+ ++ch;
+ }
+
+ rstr.resize(cursor - (const uchar*)rstr.constData());
+ if (state) {
+ state->invalidChars += invalid;
+ state->flags |= QTextCodec::IgnoreHeader;
+ state->remainingChars = 0;
+ if (surrogate_high >= 0) {
+ state->remainingChars = 1;
+ state->state_data[0] = surrogate_high;
+ }
+ }
+ return rstr;
+}
+
+QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state)
+{
+ bool headerdone = false;
+ ushort replacement = QChar::ReplacementCharacter;
+ int need = 0;
+ int error = -1;
+ uint uc = 0;
+ uint min_uc = 0;
+ if (state) {
+ if (state->flags & QTextCodec::IgnoreHeader)
+ headerdone = true;
+ if (state->flags & QTextCodec::ConvertInvalidToNull)
+ replacement = QChar::Null;
+ need = state->remainingChars;
+ if (need) {
+ uc = state->state_data[0];
+ min_uc = state->state_data[1];
+ }
+ }
+ if (!headerdone && len > 3
+ && (uchar)chars[0] == 0xef && (uchar)chars[1] == 0xbb && (uchar)chars[2] == 0xbf) {
+ // starts with a byte order mark
+ chars += 3;
+ len -= 3;
+ headerdone = true;
+ }
+
+ QString result(need + len + 1, Qt::Uninitialized); // worst case
+ ushort *qch = (ushort *)result.unicode();
+ uchar ch;
+ int invalid = 0;
+
+ for (int i = 0; i < len; ++i) {
+ ch = chars[i];
+ if (need) {
+ if ((ch&0xc0) == 0x80) {
+ uc = (uc << 6) | (ch & 0x3f);
+ --need;
+ if (!need) {
+ // utf-8 bom composes into 0xfeff code point
+ bool nonCharacter;
+ if (!headerdone && uc == 0xfeff) {
+ // don't do anything, just skip the BOM
+ } else if (!(nonCharacter = isUnicodeNonCharacter(uc)) && uc > 0xffff && uc < 0x110000) {
+ // surrogate pair
+ Q_ASSERT((qch - (ushort*)result.unicode()) + 2 < result.length());
+ *qch++ = QChar::highSurrogate(uc);
+ *qch++ = QChar::lowSurrogate(uc);
+ } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || nonCharacter || uc >= 0x110000) {
+ // error: overlong sequence, UTF16 surrogate or non-character
+ *qch++ = replacement;
+ ++invalid;
+ } else {
+ *qch++ = uc;
+ }
+ headerdone = true;
+ }
+ } else {
+ // error
+ i = error;
+ *qch++ = replacement;
+ ++invalid;
+ need = 0;
+ headerdone = true;
+ }
+ } else {
+ if (ch < 128) {
+ *qch++ = ushort(ch);
+ headerdone = true;
+ } else if ((ch & 0xe0) == 0xc0) {
+ uc = ch & 0x1f;
+ need = 1;
+ error = i;
+ min_uc = 0x80;
+ headerdone = true;
+ } else if ((ch & 0xf0) == 0xe0) {
+ uc = ch & 0x0f;
+ need = 2;
+ error = i;
+ min_uc = 0x800;
+ } else if ((ch&0xf8) == 0xf0) {
+ uc = ch & 0x07;
+ need = 3;
+ error = i;
+ min_uc = 0x10000;
+ headerdone = true;
+ } else {
+ // error
+ *qch++ = replacement;
+ ++invalid;
+ headerdone = true;
+ }
+ }
+ }
+ if (!state && need > 0) {
+ // unterminated UTF sequence
+ for (int i = error; i < len; ++i) {
+ *qch++ = replacement;
+ ++invalid;
+ }
+ }
+ result.truncate(qch - (ushort *)result.unicode());
+ if (state) {
+ state->invalidChars += invalid;
+ state->remainingChars = need;
+ if (headerdone)
+ state->flags |= QTextCodec::IgnoreHeader;
+ state->state_data[0] = need ? uc : 0;
+ state->state_data[1] = need ? min_uc : 0;
+ }
+ return result;
+}
+
+QByteArray QUtf16::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state, DataEndianness e)
+{
+ DataEndianness endian = e;
+ int length = 2*len;
+ if (!state || (!(state->flags & QTextCodec::IgnoreHeader))) {
+ length += 2;
+ }
+ if (e == DetectEndianness) {
+ endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
+ }
+
+ QByteArray d;
+ d.resize(length);
+ char *data = d.data();
+ if (!state || !(state->flags & QTextCodec::IgnoreHeader)) {
+ QChar bom(QChar::ByteOrderMark);
+ if (endian == BigEndianness) {
+ data[0] = bom.row();
+ data[1] = bom.cell();
+ } else {
+ data[0] = bom.cell();
+ data[1] = bom.row();
+ }
+ data += 2;
+ }
+ if (endian == BigEndianness) {
+ for (int i = 0; i < len; ++i) {
+ *(data++) = uc[i].row();
+ *(data++) = uc[i].cell();
+ }
+ } else {
+ for (int i = 0; i < len; ++i) {
+ *(data++) = uc[i].cell();
+ *(data++) = uc[i].row();
+ }
+ }
+
+ if (state) {
+ state->remainingChars = 0;
+ state->flags |= QTextCodec::IgnoreHeader;
+ }
+ return d;
+}
+
+QString QUtf16::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e)
+{
+ DataEndianness endian = e;
+ bool half = false;
+ uchar buf = 0;
+ bool headerdone = false;
+ if (state) {
+ headerdone = state->flags & QTextCodec::IgnoreHeader;
+ if (endian == DetectEndianness)
+ endian = (DataEndianness)state->state_data[Endian];
+ if (state->remainingChars) {
+ half = true;
+ buf = state->state_data[Data];
+ }
+ }
+ if (headerdone && endian == DetectEndianness)
+ endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
+
+ QString result(len, Qt::Uninitialized); // worst case
+ QChar *qch = (QChar *)result.unicode();
+ while (len--) {
+ if (half) {
+ QChar ch;
+ if (endian == LittleEndianness) {
+ ch.setRow(*chars++);
+ ch.setCell(buf);
+ } else {
+ ch.setRow(buf);
+ ch.setCell(*chars++);
+ }
+ if (!headerdone) {
+ headerdone = true;
+ if (endian == DetectEndianness) {
+ if (ch == QChar::ByteOrderSwapped) {
+ endian = LittleEndianness;
+ } else if (ch == QChar::ByteOrderMark) {
+ endian = BigEndianness;
+ } else {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ endian = BigEndianness;
+ } else {
+ endian = LittleEndianness;
+ ch = QChar((ch.unicode() >> 8) | ((ch.unicode() & 0xff) << 8));
+ }
+ *qch++ = ch;
+ }
+ } else if (ch != QChar::ByteOrderMark) {
+ *qch++ = ch;
+ }
+ } else {
+ *qch++ = ch;
+ }
+ half = false;
+ } else {
+ buf = *chars++;
+ half = true;
+ }
+ }
+ result.truncate(qch - result.unicode());
+
+ if (state) {
+ if (headerdone)
+ state->flags |= QTextCodec::IgnoreHeader;
+ state->state_data[Endian] = endian;
+ if (half) {
+ state->remainingChars = 1;
+ state->state_data[Data] = buf;
+ } else {
+ state->remainingChars = 0;
+ state->state_data[Data] = 0;
+ }
+ }
+ return result;
+}
+
+QByteArray QUtf32::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state, DataEndianness e)
+{
+ DataEndianness endian = e;
+ int length = 4*len;
+ if (!state || (!(state->flags & QTextCodec::IgnoreHeader))) {
+ length += 4;
+ }
+ if (e == DetectEndianness) {
+ endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
+ }
+
+ QByteArray d(length, Qt::Uninitialized);
+ char *data = d.data();
+ if (!state || !(state->flags & QTextCodec::IgnoreHeader)) {
+ if (endian == BigEndianness) {
+ data[0] = 0;
+ data[1] = 0;
+ data[2] = (char)0xfe;
+ data[3] = (char)0xff;
+ } else {
+ data[0] = (char)0xff;
+ data[1] = (char)0xfe;
+ data[2] = 0;
+ data[3] = 0;
+ }
+ data += 4;
+ }
+ if (endian == BigEndianness) {
+ for (int i = 0; i < len; ++i) {
+ uint cp = uc[i].unicode();
+ if (uc[i].isHighSurrogate() && i < len - 1)
+ cp = QChar::surrogateToUcs4(cp, uc[++i].unicode());
+ *(data++) = cp >> 24;
+ *(data++) = (cp >> 16) & 0xff;
+ *(data++) = (cp >> 8) & 0xff;
+ *(data++) = cp & 0xff;
+ }
+ } else {
+ for (int i = 0; i < len; ++i) {
+ uint cp = uc[i].unicode();
+ if (uc[i].isHighSurrogate() && i < len - 1)
+ cp = QChar::surrogateToUcs4(cp, uc[++i].unicode());
+ *(data++) = cp & 0xff;
+ *(data++) = (cp >> 8) & 0xff;
+ *(data++) = (cp >> 16) & 0xff;
+ *(data++) = cp >> 24;
+ }
+ }
+
+ if (state) {
+ state->remainingChars = 0;
+ state->flags |= QTextCodec::IgnoreHeader;
+ }
+ return d;
+}
+
+QString QUtf32::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e)
+{
+ DataEndianness endian = e;
+ uchar tuple[4];
+ int num = 0;
+ bool headerdone = false;
+ if (state) {
+ headerdone = state->flags & QTextCodec::IgnoreHeader;
+ if (endian == DetectEndianness) {
+ endian = (DataEndianness)state->state_data[Endian];
+ }
+ num = state->remainingChars;
+ memcpy(tuple, &state->state_data[Data], 4);
+ }
+ if (headerdone && endian == DetectEndianness)
+ endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
+
+ QString result;
+ result.resize((num + len) >> 2 << 1); // worst case
+ QChar *qch = (QChar *)result.unicode();
+
+ const char *end = chars + len;
+ while (chars < end) {
+ tuple[num++] = *chars++;
+ if (num == 4) {
+ if (!headerdone) {
+ if (endian == DetectEndianness) {
+ if (endian == DetectEndianness) {
+ if (tuple[0] == 0xff && tuple[1] == 0xfe && tuple[2] == 0 && tuple[3] == 0 && endian != BigEndianness) {
+ endian = LittleEndianness;
+ num = 0;
+ continue;
+ } else if (tuple[0] == 0 && tuple[1] == 0 && tuple[2] == 0xfe && tuple[3] == 0xff && endian != LittleEndianness) {
+ endian = BigEndianness;
+ num = 0;
+ continue;
+ } else if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ endian = BigEndianness;
+ } else {
+ endian = LittleEndianness;
+ }
+ }
+ } else if (((endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple)) == QChar::ByteOrderMark) {
+ num = 0;
+ continue;
+ }
+ }
+ uint code = (endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple);
+ if (code >= 0x10000) {
+ *qch++ = QChar::highSurrogate(code);
+ *qch++ = QChar::lowSurrogate(code);
+ } else {
+ *qch++ = code;
+ }
+ num = 0;
+ }
+ }
+ result.truncate(qch - result.unicode());
+
+ if (state) {
+ if (headerdone)
+ state->flags |= QTextCodec::IgnoreHeader;
+ state->state_data[Endian] = endian;
+ state->remainingChars = num;
+ memcpy(&state->state_data[Data], tuple, 4);
+ }
+ return result;
+}
+
+
+#ifndef QT_NO_TEXTCODEC
+
+QUtf8Codec::~QUtf8Codec()
+{
+}
+
+QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
+{
+ return QUtf8::convertFromUnicode(uc, len, state);
+}
+
+void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, ConverterState *state) const
+{
+ *target += QUtf8::convertToUnicode(chars, len, state);
+}
+
+QString QUtf8Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const
+{
+ return QUtf8::convertToUnicode(chars, len, state);
+}
+
+QByteArray QUtf8Codec::name() const
+{
+ return "UTF-8";
+}
+
+int QUtf8Codec::mibEnum() const
+{
+ return 106;
+}
+
+QUtf16Codec::~QUtf16Codec()
+{
+}
+
+QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
+{
+ return QUtf16::convertFromUnicode(uc, len, state, e);
+}
+
+QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const
+{
+ return QUtf16::convertToUnicode(chars, len, state, e);
+}
+
+int QUtf16Codec::mibEnum() const
+{
+ return 1015;
+}
+
+QByteArray QUtf16Codec::name() const
+{
+ return "UTF-16";
+}
+
+QList<QByteArray> QUtf16Codec::aliases() const
+{
+ return QList<QByteArray>();
+}
+
+int QUtf16BECodec::mibEnum() const
+{
+ return 1013;
+}
+
+QByteArray QUtf16BECodec::name() const
+{
+ return "UTF-16BE";
+}
+
+QList<QByteArray> QUtf16BECodec::aliases() const
+{
+ QList<QByteArray> list;
+ return list;
+}
+
+int QUtf16LECodec::mibEnum() const
+{
+ return 1014;
+}
+
+QByteArray QUtf16LECodec::name() const
+{
+ return "UTF-16LE";
+}
+
+QList<QByteArray> QUtf16LECodec::aliases() const
+{
+ QList<QByteArray> list;
+ return list;
+}
+
+QUtf32Codec::~QUtf32Codec()
+{
+}
+
+QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
+{
+ return QUtf32::convertFromUnicode(uc, len, state, e);
+}
+
+QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const
+{
+ return QUtf32::convertToUnicode(chars, len, state, e);
+}
+
+int QUtf32Codec::mibEnum() const
+{
+ return 1017;
+}
+
+QByteArray QUtf32Codec::name() const
+{
+ return "UTF-32";
+}
+
+QList<QByteArray> QUtf32Codec::aliases() const
+{
+ QList<QByteArray> list;
+ return list;
+}
+
+int QUtf32BECodec::mibEnum() const
+{
+ return 1018;
+}
+
+QByteArray QUtf32BECodec::name() const
+{
+ return "UTF-32BE";
+}
+
+QList<QByteArray> QUtf32BECodec::aliases() const
+{
+ QList<QByteArray> list;
+ return list;
+}
+
+int QUtf32LECodec::mibEnum() const
+{
+ return 1019;
+}
+
+QByteArray QUtf32LECodec::name() const
+{
+ return "UTF-32LE";
+}
+
+QList<QByteArray> QUtf32LECodec::aliases() const
+{
+ QList<QByteArray> list;
+ return list;
+}
+
+#endif //QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h
new file mode 100644
index 0000000000..89d27909ae
--- /dev/null
+++ b/src/corelib/codecs/qutfcodec_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUTFCODEC_P_H
+#define QUTFCODEC_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/qtextcodec.h"
+#include "private/qtextcodec_p.h"
+
+QT_BEGIN_NAMESPACE
+
+enum DataEndianness
+{
+ DetectEndianness,
+ BigEndianness,
+ LittleEndianness
+};
+
+struct QUtf8
+{
+ static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *);
+ static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *);
+};
+
+struct QUtf16
+{
+ static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness);
+ static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness);
+};
+
+struct QUtf32
+{
+ static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness);
+ static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness);
+};
+
+#ifndef QT_NO_TEXTCODEC
+
+class QUtf8Codec : public QTextCodec {
+public:
+ ~QUtf8Codec();
+
+ QByteArray name() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ void convertToUnicode(QString *target, const char *, int, ConverterState *) const;
+};
+
+class QUtf16Codec : public QTextCodec {
+protected:
+public:
+ QUtf16Codec() { e = DetectEndianness; }
+ ~QUtf16Codec();
+
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+protected:
+ DataEndianness e;
+};
+
+class QUtf16BECodec : public QUtf16Codec {
+public:
+ QUtf16BECodec() : QUtf16Codec() { e = BigEndianness; }
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+class QUtf16LECodec : public QUtf16Codec {
+public:
+ QUtf16LECodec() : QUtf16Codec() { e = LittleEndianness; }
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+class QUtf32Codec : public QTextCodec {
+public:
+ QUtf32Codec() { e = DetectEndianness; }
+ ~QUtf32Codec();
+
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+
+ QString convertToUnicode(const char *, int, ConverterState *) const;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+
+protected:
+ DataEndianness e;
+};
+
+class QUtf32BECodec : public QUtf32Codec {
+public:
+ QUtf32BECodec() : QUtf32Codec() { e = BigEndianness; }
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+class QUtf32LECodec : public QUtf32Codec {
+public:
+ QUtf32LECodec() : QUtf32Codec() { e = LittleEndianness; }
+ QByteArray name() const;
+ QList<QByteArray> aliases() const;
+ int mibEnum() const;
+};
+
+
+#endif // QT_NO_TEXTCODEC
+
+QT_END_NAMESPACE
+
+#endif // QUTFCODEC_P_H
diff --git a/src/corelib/concurrent/concurrent.pri b/src/corelib/concurrent/concurrent.pri
new file mode 100644
index 0000000000..940297139c
--- /dev/null
+++ b/src/corelib/concurrent/concurrent.pri
@@ -0,0 +1,42 @@
+SOURCES += \
+ concurrent/qfuture.cpp \
+ concurrent/qfutureinterface.cpp \
+ concurrent/qfuturesynchronizer.cpp \
+ concurrent/qfuturewatcher.cpp \
+ concurrent/qrunnable.cpp \
+ concurrent/qtconcurrentfilter.cpp \
+ concurrent/qtconcurrentmap.cpp \
+ concurrent/qtconcurrentresultstore.cpp \
+ concurrent/qtconcurrentthreadengine.cpp \
+ concurrent/qtconcurrentiteratekernel.cpp \
+ concurrent/qtconcurrentexception.cpp \
+ concurrent/qthreadpool.cpp
+
+HEADERS += \
+ concurrent/qfuture.h \
+ concurrent/qfutureinterface.h \
+ concurrent/qfuturesynchronizer.h \
+ concurrent/qfuturewatcher.h \
+ concurrent/qrunnable.h \
+ concurrent/qtconcurrentcompilertest.h \
+ concurrent/qtconcurrentexception.h \
+ concurrent/qtconcurrentfilter.h \
+ concurrent/qtconcurrentfilterkernel.h \
+ concurrent/qtconcurrentfunctionwrappers.h \
+ concurrent/qtconcurrentiteratekernel.h \
+ concurrent/qtconcurrentmap.h \
+ concurrent/qtconcurrentmapkernel.h \
+ concurrent/qtconcurrentmedian.h \
+ concurrent/qtconcurrentreducekernel.h \
+ concurrent/qtconcurrentresultstore.h \
+ concurrent/qtconcurrentrun.h \
+ concurrent/qtconcurrentrunbase.h \
+ concurrent/qtconcurrentstoredfunctioncall.h \
+ concurrent/qtconcurrentthreadengine.h \
+ concurrent/qthreadpool.h
+
+# private headers
+HEADERS += \
+ concurrent/qfutureinterface_p.h \
+ concurrent/qfuturewatcher_p.h \
+ concurrent/qthreadpool_p.h
diff --git a/src/corelib/concurrent/qfuture.cpp b/src/corelib/concurrent/qfuture.cpp
new file mode 100644
index 0000000000..dfae1de16e
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.cpp
@@ -0,0 +1,697 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFuture
+ \threadsafe
+ \brief The QFuture class represents the result of an asynchronous computation.
+ \since 4.4
+
+ \ingroup thread
+
+ To start a computation, use one of the APIs in the
+ \l {Concurrent Programming}{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 a default constructor and a copy constructor. If a result is not
+ available at the time of calling the result(), resultAt(), or results()
+ 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().
+
+ QFuture provides a \l{Java-style iterators}{Java-style iterator}
+ (QFutureIterator) and an \l{STL-style iterators}{STL-style iterator}
+ (QFuture::const_iterator). Using these iterators is another way to access
+ results in the future.
+
+ QFuture also offers ways to interact with a runnning computation. For
+ instance, the computation can be canceled with the cancel() function. To
+ pause the computation, use the setPaused() function or one of the pause(),
+ resume(), or togglePaused() convenience functions. Be aware that not all
+ asynchronous computations can be canceled or paused. For example, the
+ future returned by QtConcurrent::run() cannot be canceled; but the
+ future returned by QtConcurrent::mappedReduced() can.
+
+ Progress information is provided by the progressValue(),
+ progressMinimum(), progressMaximum(), and progressText() functions. The
+ waitForFinished() function causes the calling thread to block and wait for
+ the computation to finish, ensuring that all results are available.
+
+ The state of the computation represented by a QFuture can be queried using
+ the isCanceled(), isStarted(), isFinished(), isRunning(), or isPaused()
+ 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
+ - not the actual result data.
+
+ To interact with running tasks using signals and slots, use QFutureWatcher.
+
+ \sa QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*! \fn QFuture::QFuture()
+
+ Constructs an empty future.
+*/
+
+/*! \fn QFuture::QFuture(const QFuture &other)
+
+ Constructs a copy of \a other.
+
+ \sa operator=()
+*/
+
+/*! \fn QFuture::QFuture(QFutureInterface<T> *resultHolder)
+ \internal
+*/
+
+/*! \fn QFuture::~QFuture()
+
+ Destroys the future.
+
+ Note that this neither waits nor cancels the asynchronous computation. Use
+ waitForFinished() or QFutureSynchronizer when you need to ensure that the
+ computation is completed before the future is destroyed.
+*/
+
+/*! \fn QFuture &QFuture::operator=(const QFuture &other)
+
+ Assigns \a other to this future and returns a reference to this future.
+*/
+
+/*! \fn bool QFuture::operator==(const QFuture &other) const
+
+ Returns true if \a other is a copy of this future; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::operator!=(const QFuture &other) const
+
+ Returns true if \a other is \e not a copy of this future; otherwise returns
+ false.
+*/
+
+/*! \fn void QFuture::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.
+
+ Results currently available may still be accessed on a canceled future,
+ but new results will \e not become available after calling this function.
+ Any QFutureWatcher object that is watching this future will not deliver
+ progress and result ready signals on a canceled future.
+
+ Be aware that not all asynchronous computations can be canceled. For
+ example, the future returned by QtConcurrent::run() cannot be canceled;
+ but the future returned by QtConcurrent::mappedReduced() can.
+*/
+
+/*! \fn bool QFuture::isCanceled() const
+
+ Returns true if the asynchronous computation has been canceled with the
+ cancel() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See cancel() for more details.
+*/
+
+/*! \fn void QFuture::setPaused(bool paused)
+
+ If \a paused is true, this function pauses the asynchronous computation
+ represented by the future. If the computation is already paused, this
+ function does nothing. Any QFutureWatcher object that is watching this
+ future will stop delivering progress and result ready signals while the
+ future is paused. Signal delivery will continue once the future is
+ resumed.
+
+ If \a paused is false, this function resumes the asynchronous computation.
+ If the computation was not previously paused, this function does nothing.
+
+ Be aware that not all computations can be paused. For example, the future
+ returned by QtConcurrent::run() cannot be paused; but the future returned
+ by QtConcurrent::mappedReduced() can.
+
+ \sa pause(), resume(), togglePaused()
+*/
+
+/*! \fn bool QFuture::isPaused() const
+
+ Returns true if the asynchronous computation has been paused with the
+ pause() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See setPaused() for more details.
+
+ \sa setPaused(), togglePaused()
+*/
+
+/*! \fn void QFuture::pause()
+
+ Pauses the asynchronous computation represented by this future. This is a
+ convenience method that simply calls setPaused(true).
+
+ \sa resume()
+*/
+
+/*! \fn void QFuture::resume()
+
+ Resumes the asynchronous computation represented by this future. This is a
+ convenience method that simply calls setPaused(false).
+
+ \sa pause()
+*/
+
+/*! \fn void QFuture::togglePaused()
+
+ 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()
+*/
+
+/*! \fn bool QFuture::isStarted() const
+
+ Returns true if the asynchronous computation represented by this future
+ has been started; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::isFinished() const
+
+ Returns true if the asynchronous computation represented by this future
+ has finished; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::isRunning() const
+
+ Returns true if the asynchronous computation represented by this future is
+ currently running; otherwise returns false.
+*/
+
+/*! \fn int QFuture::resultCount() const
+
+ Returns the number of continuous results available in this future. The real
+ 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()
+*/
+
+/*! \fn int QFuture::progressValue() const
+
+ Returns the current progress value, which is between the progressMinimum()
+ and progressMaximum().
+
+ \sa progressMinimum(), progressMaximum()
+*/
+
+/*! \fn int QFuture::progressMinimum() const
+
+ Returns the minimum progressValue().
+
+ \sa progressValue(), progressMaximum()
+*/
+
+/*! \fn int QFuture::progressMaximum() const
+
+ Returns the maximum progressValue().
+
+ \sa progressValue(), progressMinimum()
+*/
+
+/*! \fn QString QFuture::progressText() const
+
+ Returns the (optional) textual representation of the progress as reported
+ by the asynchronous computation.
+
+ Be aware that not all computations provide a textual representation of the
+ progress, and as such, this function may return an empty string.
+*/
+
+/*! \fn void QFuture::waitForFinished()
+
+ Waits for the asynchronous computation to finish (including cancel()ed
+ computations).
+*/
+
+/*! \fn T QFuture::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).
+
+ \sa resultAt(), results()
+*/
+
+/*! \fn T QFuture::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
+ become available.
+
+ \sa result(), results(), resultCount()
+*/
+
+/*! \fn bool QFuture::isResultReadyAt(int index) const
+
+ Returns true if the result at \a index is immediately available; otherwise
+ returns false.
+
+ \sa resultAt(), resultCount()
+*/
+
+/*! \fn QFuture::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).
+
+ \sa result(), resultAt(), results()
+*/
+
+/*! \fn QList<T> QFuture::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.
+
+ \sa result(), resultAt(), resultCount()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::begin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first result in the
+ future.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::end() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary result
+ after the last result in the future.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first result in the
+ future.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary result
+ after the last result in the future.
+
+ \sa constBegin(), end()
+*/
+
+/*! \class QFuture::const_iterator
+ \reentrant
+ \since 4.4
+
+ \brief The QFuture::const_iterator class provides an STL-style const
+ iterator for QFuture.
+
+ QFuture provides 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.
+
+ The default QFuture::const_iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QFuture function like
+ QFuture::constBegin() or QFuture::constEnd() before you start iterating.
+ Here's a typical loop that prints all the results available in a future:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 0
+
+ \sa QFutureIterator, QFuture
+*/
+
+/*! \typedef QFuture::const_iterator::iterator_category
+
+ Typedef for std::bidirectional_iterator_tag. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called on an
+ uninitialized iterartor. Use operator=() to assign a value to it before
+ using it.
+
+ \sa QFuture::constBegin() QFuture::constEnd()
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator(QFuture const * const future, int index)
+ \internal
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator=(const const_iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*! \fn const T &QFuture::const_iterator::operator*() const
+
+ Returns the current result.
+*/
+
+/*! \fn const T *QFuture::const_iterator::operator->() const
+
+ Returns a pointer to the current result.
+*/
+
+/*! \fn bool QFuture::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different result than this iterator;
+ otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn bool QFuture::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same result as this iterator;
+ otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator++()
+
+ The prefix ++ 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::constEnd() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the next
+ result in the future and returns an iterator to the previously current
+ result.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding result current and
+ returns an iterator to the new current result.
+
+ Calling this function on QFuture::constBegin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding result current and
+ returns an iterator to the previously current result.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j results. (If \a j is negative, the iterator
+ goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j results. (If \a j is negative, the
+ iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator+(int j) const
+
+ Returns an iterator to the results at \a j positions forward from this
+ iterator. (If \a j is negative, the iterator goes backward.)
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator-(int j) const
+
+ Returns an iterator to the result at \a j positions backward from this
+ iterator. (If \a j is negative, the iterator goes forward.)
+
+ \sa operator+(), operator-=()
+*/
+
+/*! \typedef QFuture::ConstIterator
+
+ Qt-style synonym for QFuture::const_iterator.
+*/
+
+/*!
+ \class QFutureIterator
+ \reentrant
+ \since 4.4
+ \inmodule QtCore
+
+ \brief The QFutureIterator class provides a Java-style const iterator for
+ QFuture.
+
+ QFuture 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.
+
+ An alternative to using iterators is to use index positions. Some QFuture
+ member functions take an index as their first parameter, making it
+ possible to access results without using iterators.
+
+ QFutureIterator\<T\> allows you to iterate over a QFuture\<T\>. Note that
+ there is no mutable iterator for QFuture (unlike the other Java-style
+ iterators).
+
+ The QFutureIterator constructor takes a QFuture as its argument. After
+ construction, the iterator is located at the very beginning of the result
+ list (i.e. before the first result). Here's how to iterate over all the
+ results sequentially:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 1
+
+ The next() function returns the next result (waiting for it to become
+ available, if necessary) from the future and advances the iterator. Unlike
+ STL-style iterators, Java-style iterators point \e between results rather
+ than directly \e at results. The first call to next() advances the iterator
+ to the position between the first and second result, and returns the first
+ result; the second call to next() advances the iterator to the position
+ between the second and third result, and returns the second result; and
+ so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 2
+
+ If you want to find all occurrences of a particular value, use findNext()
+ or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same future. If the future is
+ modified while a QFutureIterator is active, the QFutureIterator will
+ continue iterating over the original future, ignoring the modified copy.
+
+ \sa QFuture::const_iterator, QFuture
+*/
+
+/*!
+ \fn QFutureIterator::QFutureIterator(const QFuture<T> &future)
+
+ Constructs an iterator for traversing \a future. The iterator is set to be
+ at the front of the result list (before the first result).
+
+ \sa operator=()
+*/
+
+/*! \fn QFutureIterator &QFutureIterator::operator=(const QFuture<T> &future)
+
+ Makes the iterator operate on \a future. The iterator is set to be at the
+ front of the result list (before the first result).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QFutureIterator::toFront()
+
+ Moves the iterator to the front of the result list (before the first
+ result).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QFutureIterator::toBack()
+
+ Moves the iterator to the back of the result list (after the last result).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QFutureIterator::hasNext() const
+
+ Returns true if there is at least one result ahead of the iterator, e.g.,
+ the iterator is \e not at the back of the result list; otherwise returns
+ false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn const T &QFutureIterator::next()
+
+ Returns the next result and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the result
+ list leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn const T &QFutureIterator::peekNext() const
+
+ Returns the next result without moving the iterator.
+
+ Calling this function on an iterator located at the back of the result
+ list leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn bool QFutureIterator::hasPrevious() const
+
+ Returns true if there is at least one result ahead of the iterator, e.g.,
+ the iterator is \e not at the front of the result list; otherwise returns
+ false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn const T &QFutureIterator::previous()
+
+ Returns the previous result and moves the iterator back by one position.
+
+ Calling this function on an iterator located at the front of the result
+ list leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn const T &QFutureIterator::peekPrevious() const
+
+ Returns the previous result without moving the iterator.
+
+ Calling this function on an iterator located at the front of the result
+ list leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn bool QFutureIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position forward.
+ Returns true if \a value is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned just
+ after the matching result; otherwise, the iterator is positioned at the
+ back of the result list.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QFutureIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if \a value is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned just
+ before the matching result; otherwise, the iterator is positioned at the
+ front of the result list.
+
+ \sa findNext()
+*/
diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h
new file mode 100644
index 0000000000..e8a6e264b3
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTURE_H
+#define QFUTURE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qfutureinterface.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtconcurrentcompilertest.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T>
+class QFutureWatcher;
+template <>
+class QFutureWatcher<void>;
+
+template <typename T>
+class QFuture
+{
+public:
+ QFuture()
+ : d(QFutureInterface<T>::canceledResult())
+ { }
+ explicit QFuture(QFutureInterface<T> *p) // internal
+ : d(*p)
+ { }
+ QFuture(const QFuture &other)
+ : d(other.d)
+ { }
+ ~QFuture()
+ { }
+
+ inline QFuture &operator=(const QFuture &other);
+ 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(); }
+
+ void setPaused(bool paused) { d.setPaused(paused); }
+ bool isPaused() const { return d.isPaused(); }
+ void pause() { setPaused(true); }
+ void resume() { setPaused(false); }
+ void togglePaused() { d.togglePaused(); }
+
+ bool isStarted() const { return d.isStarted(); }
+ bool isFinished() const { return d.isFinished(); }
+ bool isRunning() const { return d.isRunning(); }
+
+ int resultCount() const { return d.resultCount(); }
+ int progressValue() const { return d.progressValue(); }
+ int progressMinimum() const { return d.progressMinimum(); }
+ int progressMaximum() const { return d.progressMaximum(); }
+ QString progressText() const { return d.progressText(); }
+ void waitForFinished() { d.waitForFinished(); }
+
+ inline T result() const;
+ inline T resultAt(int index) const;
+ bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
+
+ operator T() const { return result(); }
+ QList<T> results() const { return d.results(); }
+
+ class const_iterator
+ {
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline const_iterator() {}
+ inline const_iterator(QFuture const * const _future, int _index) : future(_future), index(_index) {}
+ inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
+ inline const_iterator &operator=(const const_iterator &o)
+ { 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
+ {
+ if (index == -1 && other.index == -1) // comparing end != end?
+ return false;
+ if (other.index == -1)
+ return (future->isRunning() || (index < future->resultCount()));
+ return (index != other.index);
+ }
+
+ inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
+ inline const_iterator &operator++() { ++index; return *this; }
+ inline const_iterator operator++(int) { const_iterator r = *this; ++index; return r; }
+ inline const_iterator &operator--() { --index; return *this; }
+ inline const_iterator operator--(int) { const_iterator r = *this; --index; return r; }
+ inline const_iterator operator+(int j) const { return const_iterator(future, index + j); }
+ inline const_iterator operator-(int j) const { return const_iterator(future, index - j); }
+ inline const_iterator &operator+=(int j) { index += j; return *this; }
+ inline const_iterator &operator-=(int j) { index -= j; return *this; }
+ private:
+ QFuture const * future;
+ int index;
+ };
+ friend class const_iterator;
+ typedef const_iterator ConstIterator;
+
+ const_iterator begin() const { return const_iterator(this, 0); }
+ const_iterator constBegin() const { return const_iterator(this, 0); }
+ const_iterator end() const { return const_iterator(this, -1); }
+ const_iterator constEnd() const { return const_iterator(this, -1); }
+
+private:
+ friend class QFutureWatcher<T>;
+
+public: // Warning: the d pointer is not documented and is considered private.
+ mutable QFutureInterface<T> d;
+};
+
+template <typename T>
+inline QFuture<T> &QFuture<T>::operator=(const QFuture<T> &other)
+{
+ d = other.d;
+ return *this;
+}
+
+template <typename T>
+inline T QFuture<T>::result() const
+{
+ d.waitForResult(0);
+ return d.resultReference(0);
+}
+
+template <typename T>
+inline T QFuture<T>::resultAt(int index) const
+{
+ d.waitForResult(index);
+ return d.resultReference(index);
+}
+
+template <typename T>
+inline QFuture<T> QFutureInterface<T>::future()
+{
+ return QFuture<T>(this);
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
+
+template <>
+class QFuture<void>
+{
+public:
+ QFuture()
+ : d(QFutureInterface<void>::canceledResult())
+ { }
+ explicit QFuture(QFutureInterfaceBase *p) // internal
+ : d(*p)
+ { }
+ QFuture(const QFuture &other)
+ : d(other.d)
+ { }
+ ~QFuture()
+ { }
+
+ QFuture &operator=(const QFuture &other);
+ bool operator==(const QFuture &other) const { return (d == other.d); }
+ bool operator!=(const QFuture &other) const { return (d != other.d); }
+
+#if !defined(Q_CC_XLC)
+ template <typename T>
+ QFuture(const QFuture<T> &other)
+ : d(other.d)
+ { }
+
+ template <typename T>
+ QFuture<void> &operator=(const QFuture<T> &other)
+ {
+ d = other.d;
+ return *this;
+ }
+#endif
+
+ void cancel() { d.cancel(); }
+ bool isCanceled() const { return d.isCanceled(); }
+
+ void setPaused(bool paused) { d.setPaused(paused); }
+ bool isPaused() const { return d.isPaused(); }
+ void pause() { setPaused(true); }
+ void resume() { setPaused(false); }
+ void togglePaused() { d.togglePaused(); }
+
+ bool isStarted() const { return d.isStarted(); }
+ bool isFinished() const { return d.isFinished(); }
+ bool isRunning() const { return d.isRunning(); }
+
+ int resultCount() const { return d.resultCount(); }
+ int progressValue() const { return d.progressValue(); }
+ int progressMinimum() const { return d.progressMinimum(); }
+ int progressMaximum() const { return d.progressMaximum(); }
+ QString progressText() const { return d.progressText(); }
+ void waitForFinished() { d.waitForFinished(); }
+
+private:
+ friend class QFutureWatcher<void>;
+
+#ifdef QFUTURE_TEST
+public:
+#endif
+ mutable QFutureInterfaceBase d;
+};
+
+inline QFuture<void> &QFuture<void>::operator=(const QFuture<void> &other)
+{
+ d = other.d;
+ return *this;
+}
+
+inline QFuture<void> QFutureInterface<void>::future()
+{
+ return QFuture<void>(this);
+}
+
+template <typename T>
+QFuture<void> qToVoidFuture(const QFuture<T> &future)
+{
+ return QFuture<void>(future.d);
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTURE_H
diff --git a/src/corelib/concurrent/qfutureinterface.cpp b/src/corelib/concurrent/qfutureinterface.cpp
new file mode 100644
index 0000000000..c5bd802480
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// qfutureinterface.h included from qfuture.h
+#include "qfuture.h"
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qthreadpool.h>
+#include <private/qthreadpool_p.h>
+
+#include "qfutureinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ MaxProgressEmitsPerSecond = 25
+};
+
+QFutureInterfaceBase::QFutureInterfaceBase(State initialState)
+ : d(new QFutureInterfaceBasePrivate(initialState))
+{ }
+
+QFutureInterfaceBase::QFutureInterfaceBase(const QFutureInterfaceBase &other)
+ : d(other.d)
+{
+ d->refCount.ref();
+}
+
+QFutureInterfaceBase::~QFutureInterfaceBase()
+{
+ if (!d->refCount.deref())
+ delete d;
+}
+
+void QFutureInterfaceBase::cancel()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->state & Canceled)
+ return;
+
+ d->state = State((d->state & ~Paused) | Canceled);
+ d->waitCondition.wakeAll();
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+}
+
+void QFutureInterfaceBase::setPaused(bool paused)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (paused) {
+ d->state = State(d->state | Paused);
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+ } else {
+ d->state = State(d->state & ~Paused);
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
+ }
+}
+
+void QFutureInterfaceBase::togglePaused()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->state & Paused) {
+ d->state = State(d->state & ~Paused);
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
+ } else {
+ d->state = State(d->state | Paused);
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+ }
+}
+
+void QFutureInterfaceBase::setThrottled(bool enable)
+{
+ // bail out if we are not changing the state
+ if ((enable && (d->state & Throttled)) || (!enable && !(d->state & Throttled)))
+ return;
+
+ // lock and change the state
+ QMutexLocker lock(&d->m_mutex);
+ if (enable) {
+ d->state = State(d->state | Throttled);
+ } else {
+ d->state = State(d->state & ~Throttled);
+ if (!(d->state & Paused))
+ d->pausedWaitCondition.wakeAll();
+ }
+}
+
+
+bool QFutureInterfaceBase::isRunning() const
+{
+ return queryState(Running);
+}
+
+bool QFutureInterfaceBase::isStarted() const
+{
+ return queryState(Started);
+}
+
+bool QFutureInterfaceBase::isCanceled() const
+{
+ return queryState(Canceled);
+}
+
+bool QFutureInterfaceBase::isFinished() const
+{
+ return queryState(Finished);
+}
+
+bool QFutureInterfaceBase::isPaused() const
+{
+ return queryState(Paused);
+}
+
+bool QFutureInterfaceBase::isThrottled() const
+{
+ return queryState(Throttled);
+}
+
+bool QFutureInterfaceBase::isResultReadyAt(int index) const
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_isResultReadyAt(index);
+}
+
+bool QFutureInterfaceBase::waitForNextResult()
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_waitForNextResult();
+}
+
+void QFutureInterfaceBase::waitForResume()
+{
+ // return early if possible to avoid taking the mutex lock.
+ if ((d->state & Paused) == false || (d->state & Canceled))
+ return;
+
+ QMutexLocker lock(&d->m_mutex);
+ if ((d->state & Paused) == false || (d->state & Canceled))
+ return;
+
+ // decrease active thread count since this thread will wait.
+ QThreadPool::globalInstance()->releaseThread();
+
+ d->pausedWaitCondition.wait(&d->m_mutex);
+
+ QThreadPool::globalInstance()->reserveThread();
+}
+
+int QFutureInterfaceBase::progressValue() const
+{
+ return d->m_progressValue;
+}
+
+int QFutureInterfaceBase::progressMinimum() const
+{
+ return d->m_progressMinimum;
+}
+
+int QFutureInterfaceBase::progressMaximum() const
+{
+ return d->m_progressMaximum;
+}
+
+int QFutureInterfaceBase::resultCount() const
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_resultCount();
+}
+
+QString QFutureInterfaceBase::progressText() const
+{
+ QMutexLocker locker(&d->m_mutex);
+ return d->m_progressText;
+}
+
+bool QFutureInterfaceBase::isProgressUpdateNeeded() const
+{
+ QMutexLocker locker(&d->m_mutex);
+ return !d->progressTime.isValid() || (d->progressTime.elapsed() > (1000 / MaxProgressEmitsPerSecond));
+}
+
+void QFutureInterfaceBase::reportStarted()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if ((d->state & Started) || (d->state & Canceled) || (d->state & Finished))
+ return;
+
+ d->setState(State(Started | Running));
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Started));
+}
+
+void QFutureInterfaceBase::reportCanceled()
+{
+ cancel();
+}
+
+#ifndef QT_NO_EXCEPTIONS
+void QFutureInterfaceBase::reportException(const QtConcurrent::Exception &exception)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if ((d->state & Canceled) || (d->state & Finished))
+ return;
+
+ d->m_exceptionStore.setException(exception);
+ d->state = State(d->state | Canceled);
+ d->waitCondition.wakeAll();
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+}
+#endif
+
+void QFutureInterfaceBase::reportFinished()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (!(d->state & Finished)) {
+ d->state = State((d->state & ~Running) | Finished);
+ d->waitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+ }
+}
+
+void QFutureInterfaceBase::setExpectedResultCount(int resultCount)
+{
+ if (d->manualProgress == false)
+ setProgressRange(0, resultCount);
+ d->m_expectedResultCount = resultCount;
+}
+
+int QFutureInterfaceBase::expectedResultCount()
+{
+ return d->m_expectedResultCount;
+}
+
+bool QFutureInterfaceBase::queryState(State state) const
+{
+ return (d->state & state);
+}
+
+void QFutureInterfaceBase::waitForResult(int resultIndex)
+{
+ d->m_exceptionStore.throwPossibleException();
+
+ if (!(d->state & Running))
+ return;
+
+ // To avoid deadlocks and reduce the number of threads used, try to
+ // run the runnable in the current thread.
+ QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
+
+ QMutexLocker lock(&d->m_mutex);
+
+ if (!(d->state & Running))
+ return;
+
+ const int waitIndex = (resultIndex == -1) ? INT_MAX : resultIndex;
+ while ((d->state & Running) && d->internal_isResultReadyAt(waitIndex) == false)
+ d->waitCondition.wait(&d->m_mutex);
+
+ d->m_exceptionStore.throwPossibleException();
+}
+
+void QFutureInterfaceBase::waitForFinished()
+{
+ if (d->state & Running) {
+ QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
+
+ QMutexLocker lock(&d->m_mutex);
+
+ while (d->state & Running)
+ d->waitCondition.wait(&d->m_mutex);
+ }
+
+ d->m_exceptionStore.throwPossibleException();
+}
+
+void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
+{
+ if ((d->state & Canceled) || (d->state & Finished) || beginIndex == endIndex)
+ return;
+
+ d->waitCondition.wakeAll();
+
+ if (d->manualProgress == false) {
+ if (d->internal_updateProgress(d->m_progressValue + endIndex - beginIndex) == false) {
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ beginIndex,
+ endIndex));
+ return;
+ }
+
+ d->sendCallOuts(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ d->m_progressValue,
+ d->m_progressText),
+ QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ beginIndex,
+ endIndex));
+ return;
+ }
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady, beginIndex, endIndex));
+}
+
+void QFutureInterfaceBase::setRunnable(QRunnable *runnable)
+{
+ d->runnable = runnable;
+}
+
+void QFutureInterfaceBase::setFilterMode(bool enable)
+{
+ QMutexLocker locker(&d->m_mutex);
+ resultStoreBase().setFilterMode(enable);
+}
+
+void QFutureInterfaceBase::setProgressRange(int minimum, int maximum)
+{
+ QMutexLocker locker(&d->m_mutex);
+ d->m_progressMinimum = minimum;
+ d->m_progressMaximum = maximum;
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange, minimum, maximum));
+}
+
+void QFutureInterfaceBase::setProgressValue(int progressValue)
+{
+ setProgressValueAndText(progressValue, QString());
+}
+
+void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
+ const QString &progressText)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->manualProgress == false)
+ d->manualProgress = true;
+ if (d->m_progressValue >= progressValue)
+ return;
+
+ if ((d->state & Canceled) || (d->state & Finished))
+ return;
+
+ if (d->internal_updateProgress(progressValue, progressText)) {
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ d->m_progressValue,
+ d->m_progressText));
+ }
+}
+
+QMutex *QFutureInterfaceBase::mutex() const
+{
+ return &d->m_mutex;
+}
+
+QtConcurrent::internal::ExceptionStore &QFutureInterfaceBase::exceptionStore()
+{
+ return d->m_exceptionStore;
+}
+
+QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase()
+{
+ return d->m_results;
+}
+
+const QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const
+{
+ return d->m_results;
+}
+
+QFutureInterfaceBase &QFutureInterfaceBase::operator=(const QFutureInterfaceBase &other)
+{
+ other.d->refCount.ref();
+ if (!d->refCount.deref())
+ delete d;
+ d = other.d;
+ return *this;
+}
+
+bool QFutureInterfaceBase::referenceCountIsOne() const
+{
+ return d->refCount == 1;
+}
+
+QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
+ : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0),
+ state(initialState), pendingResults(0),
+ manualProgress(false), m_expectedResultCount(0), runnable(0)
+{
+ progressTime.invalidate();
+}
+
+int QFutureInterfaceBasePrivate::internal_resultCount() const
+{
+ return m_results.count(); // ### subtract canceled results.
+}
+
+bool QFutureInterfaceBasePrivate::internal_isResultReadyAt(int index) const
+{
+ return (m_results.contains(index));
+}
+
+bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
+{
+ if (m_results.hasNextResult())
+ return true;
+
+ while ((state & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ waitCondition.wait(&m_mutex);
+
+ return (!(state & QFutureInterfaceBase::Canceled) && m_results.hasNextResult());
+}
+
+bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
+ const QString &progressText)
+{
+ if (m_progressValue >= progress)
+ return false;
+
+ m_progressValue = progress;
+ m_progressText = progressText;
+
+ if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted.
+ if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond))
+ return false;
+
+ progressTime.start();
+ return true;
+}
+
+void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
+{
+ // bail out if we are not changing the state
+ if ((enable && (state & QFutureInterfaceBase::Throttled))
+ || (!enable && !(state & QFutureInterfaceBase::Throttled)))
+ return;
+
+ // change the state
+ if (enable) {
+ state = QFutureInterfaceBase::State(state | QFutureInterfaceBase::Throttled);
+ } else {
+ state = QFutureInterfaceBase::State(state & ~QFutureInterfaceBase::Throttled);
+ if (!(state & QFutureInterfaceBase::Paused))
+ pausedWaitCondition.wakeAll();
+ }
+}
+
+void QFutureInterfaceBasePrivate::sendCallOut(const QFutureCallOutEvent &callOutEvent)
+{
+ if (outputConnections.isEmpty())
+ return;
+
+ for (int i = 0; i < outputConnections.count(); ++i)
+ outputConnections.at(i)->postCallOutEvent(callOutEvent);
+}
+
+void QFutureInterfaceBasePrivate::sendCallOuts(const QFutureCallOutEvent &callOutEvent1,
+ const QFutureCallOutEvent &callOutEvent2)
+{
+ if (outputConnections.isEmpty())
+ return;
+
+ for (int i = 0; i < outputConnections.count(); ++i) {
+ QFutureCallOutInterface *interface = outputConnections.at(i);
+ interface->postCallOutEvent(callOutEvent1);
+ interface->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)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (state & QFutureInterfaceBase::Started) {
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
+ m_progressMinimum,
+ m_progressMaximum));
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ m_progressValue,
+ m_progressText));
+ }
+
+ QtConcurrent::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,
+ begin,
+ end));
+ it.batchedAdvance();
+ }
+
+ if (state & QFutureInterfaceBase::Paused)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+
+ if (state & QFutureInterfaceBase::Canceled)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+
+ if (state & QFutureInterfaceBase::Finished)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+
+ outputConnections.append(interface);
+}
+
+void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterface *interface)
+{
+ QMutexLocker lock(&m_mutex);
+ const int index = outputConnections.indexOf(interface);
+ if (index == -1)
+ return;
+ outputConnections.removeAt(index);
+
+ interface->callOutInterfaceDisconnected();
+}
+
+void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
+{
+ state = newState;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qfutureinterface.h b/src/corelib/concurrent/qfutureinterface.h
new file mode 100644
index 0000000000..7f90519a74
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREINTERFACE_H
+#define QFUTUREINTERFACE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qrunnable.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qtconcurrentexception.h>
+#include <QtCore/qtconcurrentresultstore.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T> class QFuture;
+class QFutureInterfaceBasePrivate;
+class QFutureWatcherBase;
+class QFutureWatcherBasePrivate;
+
+class Q_CORE_EXPORT QFutureInterfaceBase
+{
+public:
+ enum State {
+ NoState = 0x00,
+ Running = 0x01,
+ Started = 0x02,
+ Finished = 0x04,
+ Canceled = 0x08,
+ Paused = 0x10,
+ Throttled = 0x20
+ };
+
+ QFutureInterfaceBase(State initialState = NoState);
+ QFutureInterfaceBase(const QFutureInterfaceBase &other);
+ virtual ~QFutureInterfaceBase();
+
+ // reporting functions available to the engine author:
+ void reportStarted();
+ void reportFinished();
+ void reportCanceled();
+#ifndef QT_NO_EXCEPTIONS
+ void reportException(const QtConcurrent::Exception &e);
+#endif
+ void reportResultsReady(int beginIndex, int endIndex);
+
+ void setRunnable(QRunnable *runnable);
+ void setFilterMode(bool enable);
+ void setProgressRange(int minimum, int maximum);
+ int progressMinimum() const;
+ int progressMaximum() const;
+ bool isProgressUpdateNeeded() const;
+ void setProgressValue(int progressValue);
+ int progressValue() const;
+ void setProgressValueAndText(int progressValue, const QString &progressText);
+ QString progressText() const;
+
+ void setExpectedResultCount(int resultCount);
+ int expectedResultCount();
+ int resultCount() const;
+
+ bool queryState(State state) const;
+ bool isRunning() const;
+ bool isStarted() const;
+ bool isCanceled() const;
+ bool isFinished() const;
+ bool isPaused() const;
+ bool isThrottled() const;
+ bool isResultReadyAt(int index) const;
+
+ void cancel();
+ void setPaused(bool paused);
+ void togglePaused();
+ void setThrottled(bool enable);
+
+ void waitForFinished();
+ bool waitForNextResult();
+ void waitForResult(int resultIndex);
+ void waitForResume();
+
+ QMutex *mutex() const;
+ QtConcurrent::internal::ExceptionStore &exceptionStore();
+ QtConcurrent::ResultStoreBase &resultStoreBase();
+ const QtConcurrent::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);
+
+protected:
+ bool referenceCountIsOne() const;
+public:
+
+#ifndef QFUTURE_TEST
+private:
+#endif
+ QFutureInterfaceBasePrivate *d;
+
+private:
+ friend class QFutureWatcherBase;
+ friend class QFutureWatcherBasePrivate;
+};
+
+template <typename T>
+class QFutureInterface : public QFutureInterfaceBase
+{
+public:
+ QFutureInterface(State initialState = NoState)
+ : QFutureInterfaceBase(initialState)
+ { }
+ QFutureInterface(const QFutureInterface &other)
+ : QFutureInterfaceBase(other)
+ { }
+ ~QFutureInterface()
+ {
+ if (referenceCountIsOne())
+ resultStore().clear();
+ }
+
+ static QFutureInterface canceledResult()
+ { return QFutureInterface(State(Started | Finished | Canceled)); }
+
+ QFutureInterface &operator=(const QFutureInterface &other)
+ {
+ if (referenceCountIsOne())
+ resultStore().clear();
+ QFutureInterfaceBase::operator=(other);
+ return *this;
+ }
+
+ inline QFuture<T> future(); // implemented in qfuture.h
+
+ inline void reportResult(const T *result, int index = -1);
+ inline void reportResult(const T &result, int index = -1);
+ inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
+ inline void reportFinished(const T *result = 0);
+
+ inline const T &resultReference(int index) const;
+ inline const T *resultPointer(int index) const;
+ inline QList<T> results();
+private:
+ QtConcurrent::ResultStore<T> &resultStore()
+ { return static_cast<QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
+ const QtConcurrent::ResultStore<T> &resultStore() const
+ { return static_cast<const QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
+};
+
+template <typename T>
+inline void QFutureInterface<T>::reportResult(const T *result, int index)
+{
+ QMutexLocker locker(mutex());
+ if (this->queryState(Canceled) || this->queryState(Finished)) {
+ return;
+ }
+
+ QtConcurrent::ResultStore<T> &store = resultStore();
+
+
+ if (store.filterMode()) {
+ const int resultCountBefore = store.count();
+ store.addResult(index, result);
+ this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
+ } else {
+ const int insertIndex = store.addResult(index, result);
+ this->reportResultsReady(insertIndex, insertIndex + 1);
+ }
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportResult(const T &result, int index)
+{
+ reportResult(&result, index);
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
+{
+ QMutexLocker locker(mutex());
+ if (this->queryState(Canceled) || this->queryState(Finished)) {
+ return;
+ }
+
+ QtConcurrent::ResultStore<T> &store = resultStore();
+
+ 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());
+ }
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportFinished(const T *result)
+{
+ if (result)
+ reportResult(result);
+ QFutureInterfaceBase::reportFinished();
+}
+
+template <typename T>
+inline const T &QFutureInterface<T>::resultReference(int index) const
+{
+ QMutexLocker lock(mutex());
+ return resultStore().resultAt(index).value();
+}
+
+template <typename T>
+inline const T *QFutureInterface<T>::resultPointer(int index) const
+{
+ QMutexLocker lock(mutex());
+ return resultStore().resultAt(index).pointer();
+}
+
+template <typename T>
+inline QList<T> QFutureInterface<T>::results()
+{
+ if (this->isCanceled()) {
+ exceptionStore().throwPossibleException();
+ return QList<T>();
+ }
+ QFutureInterfaceBase::waitForResult(-1);
+
+ QList<T> res;
+ QMutexLocker lock(mutex());
+
+ QtConcurrent::ResultIterator<T> it = resultStore().begin();
+ while (it != resultStore().end()) {
+ res.append(it.value());
+ ++it;
+ }
+
+ return res;
+}
+
+template <>
+class QFutureInterface<void> : public QFutureInterfaceBase
+{
+public:
+ QFutureInterface<void>(State initialState = NoState)
+ : QFutureInterfaceBase(initialState)
+ { }
+ QFutureInterface<void>(const QFutureInterface<void> &other)
+ : QFutureInterfaceBase(other)
+ { }
+
+ static QFutureInterface<void> canceledResult()
+ { return QFutureInterface(State(Started | Finished | Canceled)); }
+
+ QFutureInterface<void> &operator=(const QFutureInterface<void> &other)
+ {
+ QFutureInterfaceBase::operator=(other);
+ return *this;
+ }
+
+ inline QFuture<void> future(); // implemented in qfuture.h
+
+ void reportResult(const void *, int) { }
+ void reportResults(const QVector<void> &, int) { }
+ void reportFinished(void * = 0) { QFutureInterfaceBase::reportFinished(); }
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTUREINTERFACE_H
diff --git a/src/corelib/concurrent/qfutureinterface_p.h b/src/corelib/concurrent/qfutureinterface_p.h
new file mode 100644
index 0000000000..538947ead0
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface_p.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREINTERFACE_P_H
+#define QFUTUREINTERFACE_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/qelapsedtimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qrunnable.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFutureCallOutEvent : public QEvent
+{
+public:
+ enum CallOutType {
+ Started,
+ Finished,
+ Canceled,
+ Paused,
+ Resumed,
+ Progress,
+ ProgressRange,
+ ResultsReady
+ };
+
+ QFutureCallOutEvent()
+ : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1)
+ { }
+ QFutureCallOutEvent(CallOutType callOutType, int index1 = -1)
+ : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1)
+ { }
+ QFutureCallOutEvent(CallOutType callOutType, int index1, int index2)
+ : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(index2)
+ { }
+
+ QFutureCallOutEvent(CallOutType callOutType, int index1, const QString &text)
+ : QEvent(QEvent::FutureCallOut),
+ callOutType(callOutType),
+ index1(index1),
+ index2(-1),
+ text(text)
+ { }
+
+ CallOutType callOutType;
+ 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
+{
+public:
+ virtual ~QFutureCallOutInterface() {}
+ virtual void postCallOutEvent(const QFutureCallOutEvent &) = 0;
+ virtual void callOutInterfaceDisconnected() = 0;
+};
+
+class QFutureInterfaceBasePrivate
+{
+public:
+ QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState);
+
+ QAtomicInt refCount;
+ mutable QMutex m_mutex;
+ QWaitCondition waitCondition;
+ QList<QFutureCallOutInterface *> outputConnections;
+ int m_progressValue;
+ int m_progressMinimum;
+ int m_progressMaximum;
+ QFutureInterfaceBase::State state;
+ QElapsedTimer progressTime;
+ QWaitCondition pausedWaitCondition;
+ int pendingResults;
+ QtConcurrent::ResultStoreBase m_results;
+ bool manualProgress;
+ int m_expectedResultCount;
+ QtConcurrent::internal::ExceptionStore m_exceptionStore;
+ QString m_progressText;
+ QRunnable *runnable;
+
+ // Internal functions that does not change the mutex state.
+ // The mutex must be locked when calling these.
+ int internal_resultCount() const;
+ bool internal_isResultReadyAt(int index) const;
+ bool internal_waitForNextResult();
+ bool internal_updateProgress(int progress, const QString &progressText = QString());
+ void internal_setThrottled(bool enable);
+ void sendCallOut(const QFutureCallOutEvent &callOut);
+ void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2);
+ void connectOutputInterface(QFutureCallOutInterface *iface);
+ void disconnectOutputInterface(QFutureCallOutInterface *iface);
+
+ void setState(QFutureInterfaceBase::State state);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/concurrent/qfuturesynchronizer.cpp b/src/corelib/concurrent/qfuturesynchronizer.cpp
new file mode 100644
index 0000000000..b52e5fb73d
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFutureSynchronizer
+ \since 4.4
+
+ \brief The QFutureSynchronizer class is a convenience class that simplifies
+ QFuture synchronization.
+
+ \ingroup thread
+
+ QFutureSynchronizer is a template class that simplifies synchronization of
+ one or more QFuture objects. Futures are added using the addFuture() or
+ setFuture() functions. The futures() function returns a list of futures.
+ Use clearFutures() to remove all futures from the QFutureSynchronizer.
+
+ The waitForFinished() function waits for all futures to finish.
+ The destructor of QFutureSynchronizer calls waitForFinished(), providing
+ an easy way to ensure that all futures have finished before returning from
+ a function:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuturesynchronizer.cpp 0
+
+ The behavior of waitForFinished() can be changed using the
+ setCancelOnWait() function. Calling setCancelOnWait(true) will cause
+ waitForFinished() to cancel all futures before waiting for them to finish.
+ You can query the status of the cancel-on-wait feature using the
+ cancelOnWait() function.
+
+ \sa QFuture, QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*!
+ \fn QFutureSynchronizer::QFutureSynchronizer()
+
+ Constructs a QFutureSynchronizer.
+*/
+
+/*!
+ \fn QFutureSynchronizer::QFutureSynchronizer(const QFuture<T> &future)
+
+ Constructs a QFutureSynchronizer and begins watching \a future by calling
+ addFuture().
+
+ \sa addFuture()
+*/
+
+/*!
+ \fn QFutureSynchronizer::~QFutureSynchronizer()
+
+ Calls waitForFinished() function to ensure that all futures have finished
+ before destroying this QFutureSynchronizer.
+
+ \sa waitForFinished()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::setFuture(const QFuture<T> &future)
+
+ Sets \a future to be the only future managed by this QFutureSynchronizer.
+ This is a convenience function that calls waitForFinished(),
+ then clearFutures(), and finally passes \a future to addFuture().
+
+ \sa addFuture(), waitForFinished(), clearFutures()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::addFuture(const QFuture<T> &future)
+
+ Adds \a future to the list of managed futures.
+
+ \sa futures()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::waitForFinished()
+
+ Waits for all futures to finish. If cancelOnWait() returns true, each
+ future is canceled before waiting for them to finish.
+
+ \sa cancelOnWait(), setCancelOnWait()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::clearFutures()
+
+ Removes all managed futures from this QFutureSynchronizer.
+
+ \sa addFuture(), setFuture()
+*/
+
+/*!
+ \fn QList<QFuture<T> > QFutureSynchronizer::futures() const
+
+ Returns a list of all managed futures.
+
+ \sa addFuture(), setFuture()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::setCancelOnWait(bool enabled)
+
+ Enables or disables the cancel-on-wait feature based on the \a enabled
+ argument. If \a enabled is true, the waitForFinished() function will cancel
+ all futures before waiting for them to finish.
+
+ \sa waitForFinished()
+*/
+
+/*!
+ \fn bool QFutureSynchronizer::cancelOnWait() const
+
+ Returns true if the cancel-on-wait feature is enabled; otherwise returns
+ false. If cancel-on-wait is enabled, the waitForFinished() function will
+ cancel all futures before waiting for them to finish.
+
+ \sa waitForFinished()
+*/
diff --git a/src/corelib/concurrent/qfuturesynchronizer.h b/src/corelib/concurrent/qfuturesynchronizer.h
new file mode 100644
index 0000000000..23a2c242aa
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTRUESYNCHRONIZER_H
+#define QFUTRUESYNCHRONIZER_H
+
+#include <QtCore/qfuture.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T>
+class QFutureSynchronizer
+{
+ Q_DISABLE_COPY(QFutureSynchronizer)
+
+public:
+ QFutureSynchronizer() : m_cancelOnWait(false) { }
+ explicit QFutureSynchronizer(const QFuture<T> &future)
+ : m_cancelOnWait(false)
+ { addFuture(future); }
+ ~QFutureSynchronizer() { waitForFinished(); }
+
+ void setFuture(const QFuture<T> &future)
+ {
+ waitForFinished();
+ m_futures.clear();
+ addFuture(future);
+ }
+
+ void addFuture(const QFuture<T> &future)
+ {
+ m_futures.append(future);
+ }
+
+ void waitForFinished()
+ {
+ if (m_cancelOnWait) {
+ for (int i = 0; i < m_futures.count(); ++i) {
+ m_futures[i].cancel();
+ }
+ }
+
+ for (int i = 0; i < m_futures.count(); ++i) {
+ m_futures[i].waitForFinished();
+ }
+ }
+
+ void clearFutures()
+ {
+ m_futures.clear();
+ }
+
+ QList<QFuture<T> > futures() const
+ {
+ return m_futures;
+ }
+
+ void setCancelOnWait(bool enabled)
+ {
+ m_cancelOnWait = enabled;
+ }
+
+ bool cancelOnWait() const
+ {
+ return m_cancelOnWait;
+ }
+
+protected:
+ QList<QFuture<T> > m_futures;
+ bool m_cancelOnWait;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTRUESYNCHRONIZER_H
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp
new file mode 100644
index 0000000000..ea12bc9302
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfuturewatcher.h"
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qthread.h>
+
+#include "qfuturewatcher_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class QFutureWatcher
+ \reentrant
+ \since 4.4
+
+ \ingroup thread
+
+ \brief The QFutureWatcher class allows monitoring a QFuture using signals
+ and slots.
+
+ QFutureWatcher provides information and notifications about a QFuture. Use
+ the setFuture() function to start watching a particular QFuture. The
+ future() function returns the future set with setFuture().
+
+ For convenience, several of QFuture's functions are also available in
+ QFutureWatcher: progressValue(), progressMinimum(), progressMaximum(),
+ progressText(), isStarted(), isFinished(), isRunning(), isCanceled(),
+ isPaused(), waitForFinished(), result(), and resultAt(). The cancel(),
+ setPaused(), pause(), resume(), and togglePaused() functions are slots in
+ QFutureWatcher.
+
+ Status changes are reported via the started(), finished(), canceled(),
+ paused(), resumed(), resultReadyAt(), and resultsReadyAt() signals.
+ Progress information is provided from the progressRangeChanged(),
+ void progressValueChanged(), and progressTextChanged() signals.
+
+ Throttling control is provided by the setPendingResultsLimit() function.
+ When the number of pending resultReadyAt() or resultsReadyAt() signals
+ exceeds the limit, the computation represented by the future will be
+ throttled automatically. The computation will resume once the number of
+ pending signals drops below the limit.
+
+ Example: Starting a computation and getting a slot callback when it's
+ finished:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuturewatcher.cpp 0
+
+ Be aware that not all asynchronous computations can be canceled or paused.
+ For example, the future returned by QtConcurrent::run() cannot be
+ canceled; but the future returned by QtConcurrent::mappedReduced() can.
+
+ QFutureWatcher<void> is specialized to not contain any of the result
+ fetching functions. Any QFuture<T> can be watched by a
+ QFutureWatcher<void> as well. This is useful if only status or progress
+ information is needed; not the actual result data.
+
+ \sa QFuture, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)
+
+ Constructs a new QFutureWatcher with the given \a parent.
+*/
+QFutureWatcherBase::QFutureWatcherBase(QObject *parent)
+ :QObject(*new QFutureWatcherBasePrivate, parent)
+{ }
+
+/*! \fn QFutureWatcher::~QFutureWatcher()
+
+ Destroys the QFutureWatcher.
+*/
+
+/*! \fn void QFutureWatcher::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.
+
+ Currently available results may still be accessed on a canceled QFuture,
+ but new results will \e not become available after calling this function.
+ Also, this QFutureWatcher will not deliver progress and result ready
+ signals once canceled. This includes the progressValueChanged(),
+ progressRangeChanged(), progressTextChanged(), resultReadyAt(), and
+ resultsReadyAt() signals.
+
+ Be aware that not all asynchronous computations can be canceled. For
+ example, the QFuture returned by QtConcurrent::run() cannot be canceled;
+ but the QFuture returned by QtConcurrent::mappedReduced() can.
+*/
+void QFutureWatcherBase::cancel()
+{
+ futureInterface().cancel();
+}
+
+/*! \fn void QFutureWatcher::setPaused(bool paused)
+
+ If \a paused is true, this function pauses the asynchronous computation
+ represented by the future(). If the computation is already paused, this
+ function does nothing. This QFutureWatcher will stop delivering progress
+ and result ready signals while the future is paused. Signal delivery will
+ continue once the computation is resumed.
+
+ If \a paused is false, this function resumes the asynchronous computation.
+ If the computation was not previously paused, this function does nothing.
+
+ Be aware that not all computations can be paused. For example, the
+ QFuture returned by QtConcurrent::run() cannot be paused; but the QFuture
+ returned by QtConcurrent::mappedReduced() can.
+
+ \sa pause(), resume(), togglePaused()
+*/
+void QFutureWatcherBase::setPaused(bool paused)
+{
+ futureInterface().setPaused(paused);
+}
+
+/*! \fn void QFutureWatcher::pause()
+
+ Pauses the asynchronous computation represented by the future(). This is a
+ convenience method that simply calls setPaused(true).
+
+ \sa resume()
+*/
+void QFutureWatcherBase::pause()
+{
+ futureInterface().setPaused(true);
+}
+
+/*! \fn void QFutureWatcher::resume()
+
+ Resumes the asynchronous computation represented by the future(). This is
+ a convenience method that simply calls setPaused(false).
+
+ \sa pause()
+*/
+void QFutureWatcherBase::resume()
+{
+ futureInterface().setPaused(false);
+}
+
+/*! \fn void QFutureWatcher::togglePaused()
+
+ 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 becomes paused. This is a convenience
+ method for calling setPaused(!isPaused()).
+
+ \sa setPaused(), pause(), resume()
+*/
+void QFutureWatcherBase::togglePaused()
+{
+ futureInterface().togglePaused();
+}
+
+/*! \fn int QFutureWatcher::progressValue() const
+
+ Returns the current progress value, which is between the progressMinimum()
+ and progressMaximum().
+
+ \sa progressMinimum(), progressMaximum()
+*/
+int QFutureWatcherBase::progressValue() const
+{
+ return futureInterface().progressValue();
+}
+
+/*! \fn int QFutureWatcher::progressMinimum() const
+
+ Returns the minimum progressValue().
+
+ \sa progressValue(), progressMaximum()
+*/
+int QFutureWatcherBase::progressMinimum() const
+{
+ return futureInterface().progressMinimum();
+}
+
+/*! \fn int QFutureWatcher::progressMaximum() const
+
+ Returns the maximum progressValue().
+
+ \sa progressValue(), progressMinimum()
+*/
+int QFutureWatcherBase::progressMaximum() const
+{
+ return futureInterface().progressMaximum();
+}
+
+/*! \fn QString QFutureWatcher::progressText() const
+
+ Returns the (optional) textual representation of the progress as reported
+ by the asynchronous computation.
+
+ Be aware that not all computations provide a textual representation of the
+ progress, and as such, this function may return an empty string.
+*/
+QString QFutureWatcherBase::progressText() const
+{
+ return futureInterface().progressText();
+}
+
+/*! \fn bool QFutureWatcher::isStarted() const
+
+ Returns true if the asynchronous computation represented by the future()
+ has been started; otherwise returns false.
+*/
+bool QFutureWatcherBase::isStarted() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Started);
+}
+
+/*! \fn bool QFutureWatcher::isFinished() const
+
+ Returns true if the asynchronous computation represented by the future()
+ has finished; otherwise returns false.
+*/
+bool QFutureWatcherBase::isFinished() const
+{
+ Q_D(const QFutureWatcherBase);
+ return d->finished;
+}
+
+/*! \fn bool QFutureWatcher::isRunning() const
+
+ Returns true if the asynchronous computation represented by the future()
+ is currently running; otherwise returns false.
+*/
+bool QFutureWatcherBase::isRunning() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Running);
+}
+
+/*! \fn bool QFutureWatcher::isCanceled() const
+
+ Returns true if the asynchronous computation has been canceled with the
+ cancel() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See cancel() for more details.
+*/
+bool QFutureWatcherBase::isCanceled() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Canceled);
+}
+
+/*! \fn bool QFutureWatcher::isPaused() const
+
+ Returns true if the asynchronous computation has been paused with the
+ pause() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See setPaused() for more details.
+
+ \sa setPaused(), togglePaused()
+*/
+bool QFutureWatcherBase::isPaused() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Paused);
+}
+
+/*! \fn void QFutureWatcher::waitForFinished()
+
+ Waits for the asynchronous computation to finish (including cancel()ed
+ computations).
+*/
+void QFutureWatcherBase::waitForFinished()
+{
+ futureInterface().waitForFinished();
+}
+
+/*! \fn void QFutureWatcher::setPendingResultsLimit(int limit)
+
+ The setPendingResultsLimit() provides throttling control. When the number
+ of pending resultReadyAt() or resultsReadyAt() signals exceeds the
+ \a limit, the computation represented by the future will be throttled
+ automatically. The computation will resume once the number of pending
+ signals drops below the \a limit.
+*/
+
+bool QFutureWatcherBase::event(QEvent *event)
+{
+ Q_D(QFutureWatcherBase);
+ if (event->type() == QEvent::FutureCallOut) {
+ QFutureCallOutEvent *callOutEvent = static_cast<QFutureCallOutEvent *>(event);
+
+ if (futureInterface().isPaused()) {
+ d->pendingCallOutEvents.append(callOutEvent->clone());
+ return true;
+ }
+
+ if (callOutEvent->callOutType == QFutureCallOutEvent::Resumed
+ && !d->pendingCallOutEvents.isEmpty()) {
+ // send the resume
+ d->sendCallOutEvent(callOutEvent);
+
+ // next send all pending call outs
+ for (int i = 0; i < d->pendingCallOutEvents.count(); ++i)
+ d->sendCallOutEvent(d->pendingCallOutEvents.at(i));
+ qDeleteAll(d->pendingCallOutEvents);
+ d->pendingCallOutEvents.clear();
+ } else {
+ d->sendCallOutEvent(callOutEvent);
+ }
+ return true;
+ }
+ return QObject::event(event);
+}
+
+void QFutureWatcherBase::setPendingResultsLimit(int limit)
+{
+ Q_D(QFutureWatcherBase);
+ d->maximumPendingResultsReady = limit;
+}
+
+void QFutureWatcherBase::connectNotify(const char * signal)
+{
+ Q_D(QFutureWatcherBase);
+ if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0)
+ d->resultAtConnected.ref();
+#ifndef QT_NO_DEBUG
+ if (qstrcmp(signal, SIGNAL(finished())) == 0) {
+ if (futureInterface().isRunning()) {
+ //connections should be established before calling stFuture to avoid race.
+ // (The future could finish before the connection is made.)
+ qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race");
+ }
+ }
+#endif
+}
+
+void QFutureWatcherBase::disconnectNotify(const char * signal)
+{
+ Q_D(QFutureWatcherBase);
+ if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0)
+ d->resultAtConnected.deref();
+}
+
+/*!
+ \internal
+*/
+QFutureWatcherBasePrivate::QFutureWatcherBasePrivate()
+ : maximumPendingResultsReady(QThread::idealThreadCount() * 2),
+ resultAtConnected(0)
+{ }
+
+/*!
+ \internal
+*/
+void QFutureWatcherBase::connectOutputInterface()
+{
+ futureInterface().d->connectOutputInterface(d_func());
+}
+
+/*!
+ \internal
+*/
+void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment)
+{
+ if (pendingAssignment) {
+ Q_D(QFutureWatcherBase);
+ d->pendingResultsReady = 0;
+ qDeleteAll(d->pendingCallOutEvents);
+ d->pendingCallOutEvents.clear();
+ d->finished = false;
+ }
+
+ futureInterface().d->disconnectOutputInterface(d_func());
+}
+
+void QFutureWatcherBasePrivate::postCallOutEvent(const QFutureCallOutEvent &callOutEvent)
+{
+ Q_Q(QFutureWatcherBase);
+
+ if (callOutEvent.callOutType == QFutureCallOutEvent::ResultsReady) {
+ if (pendingResultsReady.fetchAndAddRelaxed(1) >= maximumPendingResultsReady)
+ q->futureInterface().d->internal_setThrottled(true);
+ }
+
+ QCoreApplication::postEvent(q, callOutEvent.clone());
+}
+
+void QFutureWatcherBasePrivate::callOutInterfaceDisconnected()
+{
+ QCoreApplication::removePostedEvents(q_func(), QEvent::FutureCallOut);
+}
+
+void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
+{
+ Q_Q(QFutureWatcherBase);
+
+ switch (event->callOutType) {
+ case QFutureCallOutEvent::Started:
+ emit q->started();
+ break;
+ case QFutureCallOutEvent::Finished:
+ finished = true;
+ emit q->finished();
+ break;
+ case QFutureCallOutEvent::Canceled:
+ pendingResultsReady = 0;
+ emit q->canceled();
+ break;
+ case QFutureCallOutEvent::Paused:
+ if (q->futureInterface().isCanceled())
+ break;
+ emit q->paused();
+ break;
+ case QFutureCallOutEvent::Resumed:
+ if (q->futureInterface().isCanceled())
+ break;
+ emit q->resumed();
+ break;
+ case QFutureCallOutEvent::ResultsReady: {
+ if (q->futureInterface().isCanceled())
+ break;
+
+ if (pendingResultsReady.fetchAndAddRelaxed(-1) <= maximumPendingResultsReady)
+ q->futureInterface().setThrottled(false);
+
+ const int beginIndex = event->index1;
+ const int endIndex = event->index2;
+
+ emit q->resultsReadyAt(beginIndex, endIndex);
+
+ if (int(resultAtConnected) <= 0)
+ break;
+
+ for (int i = beginIndex; i < endIndex; ++i)
+ emit q->resultReadyAt(i);
+
+ } break;
+ case QFutureCallOutEvent::Progress:
+ if (q->futureInterface().isCanceled())
+ break;
+
+ emit q->progressValueChanged(event->index1);
+ if (!event->text.isNull()) // ###
+ q->progressTextChanged(event->text);
+ break;
+ case QFutureCallOutEvent::ProgressRange:
+ emit q->progressRangeChanged(event->index1, event->index2);
+ break;
+ default: break;
+ }
+}
+
+
+/*! \fn const T &QFutureWatcher::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).
+
+ \sa resultAt()
+*/
+
+/*! \fn const T &QFutureWatcher::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
+ become available.
+
+ \sa result()
+*/
+
+/*! \fn void QFutureWatcher::setFuture(const QFuture<T> &future)
+
+ 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.
+
+ To avoid a race condition, it is important to call this function
+ \e after doing the connections.
+*/
+
+/*! \fn QFuture<T> QFutureWatcher::future() const
+
+ Returns the watched future.
+*/
+
+/*! \fn void QFutureWatcher::started()
+
+ This signal is emitted when this QFutureWatcher starts watching the future
+ set with setFuture().
+*/
+
+/*!
+ \fn void QFutureWatcher::finished()
+ This signal is emitted when the watched future finishes.
+*/
+
+/*!
+ \fn void QFutureWatcher::canceled()
+ This signal is emitted if the watched future is canceled.
+*/
+
+/*! \fn void QFutureWatcher::paused()
+ This signal is emitted when the watched future is paused.
+*/
+
+/*! \fn void QFutureWatcher::resumed()
+ This signal is emitted when the watched future is resumed.
+*/
+
+/*!
+ \fn void QFutureWatcher::progressRangeChanged(int minimum, int maximum)
+
+ The progress range for the watched future has changed to \a minimum and
+ \a maximum
+*/
+
+/*!
+ \fn void QFutureWatcher::progressValueChanged(int progressValue)
+
+ This signal is emitted when the watched future reports progress,
+ \a progressValue gives the current progress. In order to avoid overloading
+ the GUI event loop, QFutureWatcher limits the progress signal emission
+ rate. This means that listeners connected to this slot might not get all
+ progress reports the future makes. The last progress update (where
+ \a progressValue equals the maximum value) will always be delivered.
+*/
+
+/*! \fn void QFutureWatcher::progressTextChanged(const QString &progressText)
+
+ This signal is emitted when the watched future reports textual progress
+ information, \a progressText.
+*/
+
+/*!
+ \fn void QFutureWatcher::resultReadyAt(int index)
+
+ This signal is emitted when the watched future reports a ready result at
+ \a index. If the future reports multiple results, the index will indicate
+ which one it is. Results can be reported out-of-order. To get the result,
+ call future().result(index);
+*/
+
+/*!
+ \fn void QFutureWatcher::resultsReadyAt(int beginIndex, int endIndex);
+
+ This signal is emitted when the watched future reports ready results.
+ The results are indexed from \a beginIndex to \a endIndex.
+
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qfuturewatcher.h b/src/corelib/concurrent/qfuturewatcher.h
new file mode 100644
index 0000000000..5fe2007a01
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREWATCHER_H
+#define QFUTUREWATCHER_H
+
+#include <QtCore/qfuture.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+
+class QFutureWatcherBasePrivate;
+class Q_CORE_EXPORT QFutureWatcherBase : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFutureWatcherBase)
+
+public:
+ QFutureWatcherBase(QObject *parent = 0);
+
+ int progressValue() const;
+ int progressMinimum() const;
+ int progressMaximum() const;
+ QString progressText() const;
+
+ bool isStarted() const;
+ bool isFinished() const;
+ bool isRunning() const;
+ bool isCanceled() const;
+ bool isPaused() const;
+
+ void waitForFinished();
+
+ void setPendingResultsLimit(int limit);
+
+ bool event(QEvent *event);
+
+Q_SIGNALS:
+ void started();
+ void finished();
+ void canceled();
+ void paused();
+ void resumed();
+ void resultReadyAt(int resultIndex);
+ void resultsReadyAt(int beginIndex, int endIndex);
+ void progressRangeChanged(int minimum, int maximum);
+ void progressValueChanged(int progressValue);
+ void progressTextChanged(const QString &progressText);
+
+public Q_SLOTS:
+ void cancel();
+ void setPaused(bool paused);
+ void pause();
+ void resume();
+ void togglePaused();
+
+protected:
+ void connectNotify (const char * signal);
+ void disconnectNotify (const char * signal);
+
+ // called from setFuture() implemented in template sub-classes
+ void connectOutputInterface();
+ void disconnectOutputInterface(bool pendingAssignment = false);
+
+private:
+ // implemented in the template sub-classes
+ virtual const QFutureInterfaceBase &futureInterface() const = 0;
+ virtual QFutureInterfaceBase &futureInterface() = 0;
+};
+
+template <typename T>
+class QFutureWatcher : public QFutureWatcherBase
+{
+public:
+ QFutureWatcher(QObject *_parent = 0)
+ : QFutureWatcherBase(_parent)
+ { }
+ ~QFutureWatcher()
+ { disconnectOutputInterface(); }
+
+ void setFuture(const QFuture<T> &future);
+ QFuture<T> future() const
+ { return m_future; }
+
+ T result() const { return m_future.result(); }
+ T resultAt(int index) const { return m_future.resultAt(index); }
+
+#ifdef qdoc
+ int progressValue() const;
+ int progressMinimum() const;
+ int progressMaximum() const;
+ QString progressText() const;
+
+ bool isStarted() const;
+ bool isFinished() const;
+ bool isRunning() const;
+ bool isCanceled() const;
+ bool isPaused() const;
+
+ void waitForFinished();
+
+ void setPendingResultsLimit(int limit);
+
+Q_SIGNALS:
+ void started();
+ void finished();
+ void canceled();
+ void paused();
+ void resumed();
+ void resultReadyAt(int resultIndex);
+ void resultsReadyAt(int beginIndex, int endIndex);
+ void progressRangeChanged(int minimum, int maximum);
+ void progressValueChanged(int progressValue);
+ void progressTextChanged(const QString &progressText);
+
+public Q_SLOTS:
+ void cancel();
+ void setPaused(bool paused);
+ void pause();
+ void resume();
+ void togglePaused();
+#endif
+
+private:
+ QFuture<T> m_future;
+ const QFutureInterfaceBase &futureInterface() const { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() { return m_future.d; }
+};
+
+template <typename T>
+Q_INLINE_TEMPLATE void QFutureWatcher<T>::setFuture(const QFuture<T> &_future)
+{
+ if (_future == m_future)
+ return;
+
+ disconnectOutputInterface(true);
+ m_future = _future;
+ connectOutputInterface();
+}
+
+template <>
+class QFutureWatcher<void> : public QFutureWatcherBase
+{
+public:
+ QFutureWatcher(QObject *_parent = 0)
+ : QFutureWatcherBase(_parent)
+ { }
+ ~QFutureWatcher()
+ { disconnectOutputInterface(); }
+
+ void setFuture(const QFuture<void> &future);
+ QFuture<void> future() const
+ { return m_future; }
+
+private:
+ QFuture<void> m_future;
+ const QFutureInterfaceBase &futureInterface() const { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() { return m_future.d; }
+};
+
+Q_INLINE_TEMPLATE void QFutureWatcher<void>::setFuture(const QFuture<void> &_future)
+{
+ if (_future == m_future)
+ return;
+
+ disconnectOutputInterface(true);
+ m_future = _future;
+ connectOutputInterface();
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTUREWATCHER_H
diff --git a/src/corelib/concurrent/qfuturewatcher_p.h b/src/corelib/concurrent/qfuturewatcher_p.h
new file mode 100644
index 0000000000..fd02d44773
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREWATCHER_P_H
+#define QFUTUREWATCHER_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 "qfutureinterface_p.h"
+#include <qlist.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFutureWatcherBase;
+class QFutureWatcherBasePrivate : public QObjectPrivate,
+ public QFutureCallOutInterface
+{
+ Q_DECLARE_PUBLIC(QFutureWatcherBase)
+
+public:
+ QFutureWatcherBasePrivate();
+
+ void postCallOutEvent(const QFutureCallOutEvent &callOutEvent);
+ void callOutInterfaceDisconnected();
+
+ void sendCallOutEvent(QFutureCallOutEvent *event);
+
+ QList<QFutureCallOutEvent *> pendingCallOutEvents;
+ QAtomicInt pendingResultsReady;
+ int maximumPendingResultsReady;
+
+ QAtomicInt resultAtConnected;
+ bool finished;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QFUTURE
+#endif
diff --git a/src/corelib/concurrent/qrunnable.cpp b/src/corelib/concurrent/qrunnable.cpp
new file mode 100644
index 0000000000..1aa7d59986
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QRunnable
+ \since 4.4
+ \brief The QRunnable class is the base class for all runnable objects.
+
+ \ingroup thread
+
+ The QRunnable class is an interface for representing a task or
+ piece of code that needs to be executed, represented by your
+ reimplementation of the run() function.
+
+ You can use QThreadPool to execute your code in a separate
+ thread. QThreadPool deletes the QRunnable automatically if
+ autoDelete() returns true (the default). Use setAutoDelete() to
+ change the auto-deletion flag.
+
+ QThreadPool supports executing the same QRunnable more than once
+ by calling QThreadPool::tryStart(this) from within the run() function.
+ If autoDelete is enabled the QRunnable will be deleted when
+ the last thread exits the run function. Calling QThreadPool::start()
+ multiple times with the same QRunnable when autoDelete is enabled
+ creates a race condition and is not recommended.
+
+ \sa QThreadPool
+*/
+
+/*! \fn QRunnable::run()
+ Implement this pure virtual function in your subclass.
+*/
+
+/*! \fn QRunnable::QRunnable()
+ Constructs a QRunnable. Auto-deletion is enabled by default.
+
+ \sa autoDelete(), setAutoDelete()
+*/
+
+/*! \fn QRunnable::~QRunnable()
+ QRunnable virtual destructor.
+*/
+
+/*! \fn bool QRunnable::autoDelete() const
+
+ Returns true is auto-deletion is enabled; false otherwise.
+
+ If auto-deletion is enabled, QThreadPool will automatically delete
+ this runnable after calling run(); otherwise, ownership remains
+ with the application programmer.
+
+ \sa setAutoDelete(), QThreadPool
+*/
+
+/*! \fn bool QRunnable::setAutoDelete(bool autoDelete)
+
+ Enables auto-deletion if \a autoDelete is true; otherwise
+ auto-deletion is disabled.
+
+ If auto-deletion is enabled, QThreadPool will automatically delete
+ this runnable after calling run(); otherwise, ownership remains
+ with the application programmer.
+
+ Note that this flag must be set before calling
+ QThreadPool::start(). Calling this function after
+ QThreadPool::start() results in undefined behavior.
+
+ \sa autoDelete(), QThreadPool
+*/
diff --git a/src/corelib/concurrent/qrunnable.h b/src/corelib/concurrent/qrunnable.h
new file mode 100644
index 0000000000..c4eea1184f
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRUNNABLE_H
+#define QRUNNABLE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QRunnable
+{
+ int ref;
+
+ friend class QThreadPool;
+ friend class QThreadPoolPrivate;
+ friend class QThreadPoolThread;
+
+public:
+ virtual void run() = 0;
+
+ QRunnable() : ref(0) { }
+ virtual ~QRunnable() { }
+
+ bool autoDelete() const { return ref != -1; }
+ void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentcompilertest.h b/src/corelib/concurrent/qtconcurrentcompilertest.h
new file mode 100644
index 0000000000..fad0c35109
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentcompilertest.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_COMPILERTEST_H
+#define QTCONCURRENT_COMPILERTEST_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#if defined (Q_CC_MSVC) && (_MSC_VER < 1300)
+# define QT_TYPENAME
+#else
+# define QT_TYPENAME typename
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp
new file mode 100644
index 0000000000..b4123f52ca
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentexception.h"
+
+#ifndef QT_NO_QFUTURE
+#ifndef QT_NO_EXCEPTIONS
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QtConcurrent::Exception
+ \brief The Exception class provides a base class for exceptions that can transferred across threads.
+ \since 4.4
+
+ Qt Concurrent supports throwing and catching exceptions across thread
+ boundaries, provided that the exception inherit from QtConcurrent::Exception
+ and implement two helper functions:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 0
+
+ QtConcurrent::Exception subclasses must be thrown by value and
+ caught by reference:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 1
+
+ If you throw an exception that is not a subclass of QtConcurrent::Exception,
+ the Qt Concurrent functions will throw a QtConcurrent::UnhandledException
+ in the receiver thread.
+
+ When using QFuture, transferred exceptions will be thrown when calling the following functions:
+ \list
+ \o QFuture::waitForFinished()
+ \o QFuture::result()
+ \o QFuture::resultAt()
+ \o QFuture::results()
+ \endlist
+*/
+
+/*!
+ \fn QtConcurrent::Exception::raise() const
+ In your QtConcurrent::Exception subclass, reimplement raise() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 2
+*/
+
+/*!
+ \fn QtConcurrent::Exception::clone() const
+ In your QtConcurrent::Exception subclass, reimplement clone() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 3
+*/
+
+/*!
+ \class QtConcurrent::UnhandledException
+
+ \brief The UnhandledException class represents an unhandled exception in a worker thread.
+ \since 4.4
+
+ If a worker thread throws an exception that is not a subclass of QtConcurrent::Exception,
+ the Qt Concurrent functions will throw a QtConcurrent::UnhandledException
+ on the receiver thread side.
+
+ Inheriting from this class is not supported.
+*/
+
+/*!
+ \fn QtConcurrent::UnhandledException::raise() const
+ \internal
+*/
+
+/*!
+ \fn QtConcurrent::UnhandledException::clone() const
+ \internal
+*/
+
+namespace QtConcurrent
+{
+
+void Exception::raise() const
+{
+ Exception e = *this;
+ throw e;
+}
+
+Exception *Exception::clone() const
+{
+ return new Exception(*this);
+}
+
+void UnhandledException::raise() const
+{
+ UnhandledException e = *this;
+ throw e;
+}
+
+Exception *UnhandledException::clone() const
+{
+ return new UnhandledException(*this);
+}
+
+#ifndef qdoc
+
+namespace internal {
+
+class Base
+{
+public:
+ Base(Exception *exception)
+ : exception(exception), refCount(1), hasThrown(false) { }
+ ~Base() { delete exception; }
+
+ Exception *exception;
+ QAtomicInt refCount;
+ bool hasThrown;
+};
+
+ExceptionHolder::ExceptionHolder(Exception *exception)
+: base(new Base(exception)) {}
+
+ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
+: base(other.base)
+{
+ base->refCount.ref();
+}
+
+void ExceptionHolder::operator=(const ExceptionHolder &other)
+{
+ if (base == other.base)
+ return;
+
+ if (base->refCount.deref() == false)
+ delete base;
+
+ base = other.base;
+ base->refCount.ref();
+}
+
+ExceptionHolder::~ExceptionHolder()
+{
+ if (base->refCount.deref() == 0)
+ delete base;
+}
+
+Exception *ExceptionHolder::exception() const
+{
+ return base->exception;
+}
+
+void ExceptionStore::setException(const Exception &e)
+{
+ if (hasException() == false)
+ exceptionHolder = ExceptionHolder(e.clone());
+}
+
+bool ExceptionStore::hasException() const
+{
+ return (exceptionHolder.exception() != 0);
+}
+
+ExceptionHolder ExceptionStore::exception()
+{
+ return exceptionHolder;
+}
+
+void ExceptionStore::throwPossibleException()
+{
+ if (hasException() ) {
+ exceptionHolder.base->hasThrown = true;
+ exceptionHolder.exception()->raise();
+ }
+}
+
+bool ExceptionStore::hasThrown() const { return exceptionHolder.base->hasThrown; }
+
+} // namespace internal
+
+#endif //qdoc
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_EXCEPTIONS
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentexception.h b/src/corelib/concurrent/qtconcurrentexception.h
new file mode 100644
index 0000000000..044b100e99
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_EXCEPTION_H
+#define QTCONCURRENT_EXCEPTION_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qatomic.h>
+
+#ifndef QT_NO_EXCEPTIONS
+# include <exception>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtConcurrent
+{
+
+#ifndef QT_NO_EXCEPTIONS
+
+class Q_CORE_EXPORT Exception : public std::exception
+{
+public:
+ virtual void raise() const;
+ virtual Exception *clone() const;
+};
+
+class Q_CORE_EXPORT UnhandledException : public Exception
+{
+public:
+ void raise() const;
+ Exception *clone() const;
+};
+
+namespace internal {
+
+class Base;
+class ExceptionHolder
+{
+public:
+ ExceptionHolder(Exception *exception = 0);
+ ExceptionHolder(const ExceptionHolder &other);
+ void operator=(const ExceptionHolder &other);
+ ~ExceptionHolder();
+ Exception *exception() const;
+ Base *base;
+};
+
+class Q_CORE_EXPORT ExceptionStore
+{
+public:
+ void setException(const Exception &e);
+ bool hasException() const;
+ ExceptionHolder exception();
+ void throwPossibleException();
+ bool hasThrown() const;
+ ExceptionHolder exceptionHolder;
+};
+
+} // namespace internal
+
+#else // QT_NO_EXCEPTIONS
+
+namespace internal {
+
+class Q_CORE_EXPORT ExceptionStore
+{
+public:
+ ExceptionStore() { }
+ inline void throwPossibleException() const {}
+};
+
+} // namespace internal
+
+#endif
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfilter.cpp b/src/corelib/concurrent/qtconcurrentfilter.cpp
new file mode 100644
index 0000000000..6646e02afc
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtConcurrentFilter>
+ \title Concurrent Filter and Filter-Reduce
+ \ingroup thread
+
+ \brief The <QtConcurrentFilter> header provides concurrent Filter and
+ Filter-Reduce.
+
+ These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::filter(), QtConcurrent::filtered() and
+ QtConcurrent::filteredReduced() functions filter items in a sequence such
+ as a QList or a QVector in parallel. QtConcurrent::filter() modifies a
+ sequence in-place, QtConcurrent::filtered() returns a new sequence
+ containing the filtered content, and QtConcurrent::filteredReduced()
+ returns a single result.
+
+ Each of the above functions have a blocking variant that returns the final
+ result instead of a QFuture. You use them in the same way as the
+ asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 6
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QStringList and QSet<QString>).
+
+ \section1 Concurrent Filter
+
+ QtConcurrent::filtered() takes an input sequence and a filter function.
+ This filter function is then called for each item in the sequence, and a
+ new sequence containing the filtered values is returned.
+
+ The filter function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 0
+
+ T must match the type stored in the sequence. The function returns true if
+ the item should be kept, false if it should be discarded.
+
+ This example shows how to keep strings that are all lower-case from a
+ QStringList:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 1
+
+ The results of the filter are made available through QFuture. See the
+ QFuture and QFutureWatcher documentation for more information on how to
+ use QFuture in your applications.
+
+ If you want to modify a sequence in-place, use QtConcurrent::filter():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 2
+
+ Since the sequence is modified in place, QtConcurrent::filter() does not
+ return any results via QFuture. However, you can still use QFuture and
+ QFutureWatcher to monitor the status of the filter.
+
+ \section1 Concurrent Filter-Reduce
+
+ QtConcurrent::filteredReduced() is similar to QtConcurrent::filtered(),
+ but instead of returing a sequence with the filtered results, the results
+ are combined into a single value using a reduce function.
+
+ The reduce function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 3
+
+ T is the type of the final result, U is the type of items being filtered.
+ Note that the return value and return type of the reduce function are not
+ used.
+
+ Call QtConcurrent::filteredReduced() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 4
+
+ The reduce function will be called once for each result kept by the filter
+ function, and should merge the \e{intermediate} into the \e{result}
+ variable. QtConcurrent::filteredReduced() guarantees that only one thread
+ will call reduce at a time, so using a mutex to lock the result variable
+ is not necessary. The QtConcurrent::ReduceOptions enum provides a way to
+ control the order in which the reduction is done.
+
+ \section1 Additional API Features
+
+ \section2 Using Iterators instead of Sequence
+
+ Each of the above functions has a variant that takes an iterator range
+ instead of a sequence. You use them in the same way as the sequence
+ variants:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 5
+
+
+ \section2 Using Member Functions
+
+ QtConcurrent::filter(), QtConcurrent::filtered(), and
+ QtConcurrent::filteredReduced() accept pointers to member functions.
+ The member function class type must match the type stored in the sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 7
+
+ Note that when using QtConcurrent::filteredReduced(), you can mix the use of
+ normal and member functions freely:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 8
+
+ \section2 Using Function Objects
+
+ QtConcurrent::filter(), QtConcurrent::filtered(), and
+ QtConcurrent::filteredReduced() accept function objects, which can be used to
+ add state to a function call. The result_type typedef must define the
+ result type of the function call operator:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 13
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}
+ {C++ TR1 Library Extensions}.
+
+ If you want to use a filter function takes more than one argument, you can
+ use boost::bind() or std::tr1::bind() to transform it onto a function that
+ takes one argument.
+
+ As an example, we use QString::contains():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 9
+
+ QString::contains() takes 2 arguments (including the "this" pointer) and
+ can't be used with QtConcurrent::filtered() directly, because
+ QtConcurrent::filtered() expects a function that takes one argument. To
+ use QString::contains() with QtConcurrent::filtered() we have to provide a
+ value for the \e regexp argument:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 10
+
+ The return value from boost::bind() is a function object (functor) with
+ the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 11
+
+ This matches what QtConcurrent::filtered() expects, and the complete
+ example becomes:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 12
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::filter(Sequence &sequence, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true, the item is kept in \a sequence;
+ otherwise, the item is removed from \a sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filtered(const Sequence &sequence, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence and returns a
+ new Sequence of kept items. If \a filterFunction returns true, a copy of
+ the item is put in the new Sequence. Otherwise, the item will \e not
+ appear in the new Sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filtered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item from \a begin to \a end and
+ returns a new Sequence of kept items. If \a filterFunction returns true, a
+ copy of the item is put in the new Sequence. Otherwise, the item will
+ \e not appear in the new Sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which \a reduceFunction
+ is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
+ the original sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item from \a begin to \a end. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which
+ \a reduceFunction is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
+ of the original sequence.
+*/
+
+/*!
+ \fn void QtConcurrent::blockingFilter(Sequence &sequence, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true, the item is kept in \a sequence;
+ otherwise, the item is removed from \a sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+*/
+
+/*!
+ \fn Sequence QtConcurrent::blockingFiltered(const Sequence &sequence, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item in \a sequence and returns a
+ new Sequence of kept items. If \a filterFunction returns true, a copy of
+ the item is put in the new Sequence. Otherwise, the item will \e not
+ appear in the new Sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa filtered()
+*/
+
+/*!
+ \fn Sequence QtConcurrent::blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item from \a begin to \a end and
+ returns a new Sequence of kept items. If \a filterFunction returns true, a
+ copy of the item is put in the new Sequence. Otherwise, the item will
+ \e not appear in the new Sequence.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa filtered()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingFilteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which \a reduceFunction
+ is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
+ the original sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa filteredReduced()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingFilteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ Calls \a filterFunction once for each item from \a begin to \a end. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which
+ \a reduceFunction is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
+ of the original sequence.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa filteredReduced()
+*/
diff --git a/src/corelib/concurrent/qtconcurrentfilter.h b/src/corelib/concurrent/qtconcurrentfilter.h
new file mode 100644
index 0000000000..e392212b12
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.h
@@ -0,0 +1,736 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FILTER_H
+#define QTCONCURRENT_FILTER_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentfilterkernel.h>
+#include <QtCore/qtconcurrentfunctionwrappers.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ QFuture<void> filter(Sequence &sequence, FilterFunction filterFunction);
+
+ template <typename T>
+ QFuture<T> filtered(const Sequence &sequence, FilterFunction filterFunction);
+ template <typename T>
+ QFuture<T> filtered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction);
+
+ template <typename T>
+ QFuture<T> filteredReduced(const Sequence &sequence,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ QFuture<T> filteredReduced(ConstIterator begin,
+ ConstIterator end,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+
+ void blockingFilter(Sequence &sequence, FilterFunction filterFunction);
+
+ template <typename Sequence>
+ Sequence blockingFiltered(const Sequence &sequence, FilterFunction filterFunction);
+ template <typename Sequence>
+ Sequence blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction);
+
+ template <typename T>
+ T blockingFilteredReduced(const Sequence &sequence,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ T blockingFilteredReduced(ConstIterator begin,
+ ConstIterator end,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+ThreadEngineStarter<void> filterInternal(Sequence &sequence, KeepFunctor keep, T (C::*reduce)(U))
+{
+ typedef MemberFunctionWrapper1<T, C, U> ReduceFunctor;
+ typedef typename Sequence::const_iterator Iterator;
+ typedef FilterKernel<Sequence, KeepFunctor, ReduceFunctor> KernelType;
+ return startThreadEngine(new KernelType(sequence, keep, reduce));
+}
+
+// filter() on sequences
+template <typename Sequence, typename KeepFunctor>
+QFuture<void> filter(Sequence &sequence, KeepFunctor keep)
+{
+ return filterInternal(sequence, keep, &Sequence::push_back);
+}
+
+template <typename Sequence, typename T>
+QFuture<void> filter(Sequence &sequence, bool (keep)(T))
+{
+ return filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back);
+}
+
+template <typename Sequence, typename C>
+QFuture<void> filter(Sequence &sequence, bool (C::*keep)() const)
+{
+ return filterInternal(sequence, ConstMemberFunctionWrapper<bool, C>(keep), &Sequence::push_back);
+}
+
+// filteredReduced() on sequences
+template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(sequence, keep, reduce, options);
+ }
+
+template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(sequence,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
+QFuture<U> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(sequence,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+QFuture<C> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(sequence,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W>
+QFuture<V> filteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<V>(sequence,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename U, typename V>
+QFuture<U> filteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename C, typename V>
+QFuture<C> filteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(sequence,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename D, typename U>
+QFuture<D> filteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<D>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// filteredReduced() on iterators
+template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(begin, end, keep, reduce, options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(begin,
+ end,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
+QFuture<U> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(begin,
+ end,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
+QFuture<C> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(begin,
+ end,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W>
+QFuture<V> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<V>(begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename U, typename V>
+QFuture<U> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename C, typename V>
+QFuture<C> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename D, typename U>
+QFuture<D> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<D>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+
+// filtered() on sequences
+template <typename Sequence, typename KeepFunctor>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, KeepFunctor keep)
+{
+ return startFiltered(sequence, keep);
+}
+
+template <typename Sequence, typename T>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (keep)(T))
+{
+ return startFiltered(sequence, FunctionWrapper1<bool, T>(keep));
+}
+
+template <typename Sequence, typename C>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (C::*keep)() const)
+{
+ return startFiltered(sequence, ConstMemberFunctionWrapper<bool, C>(keep));
+}
+
+// filtered() on iterators
+template <typename Iterator, typename KeepFunctor>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, KeepFunctor keep)
+{
+ return startFiltered(begin, end, keep);
+}
+
+template <typename Iterator, typename T>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, bool (keep)(T))
+{
+ return startFiltered(begin, end, FunctionWrapper1<bool, T>(keep));
+}
+
+template <typename Iterator, typename C>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const)
+{
+ return startFiltered(begin, end, ConstMemberFunctionWrapper<bool, C>(keep));
+}
+
+
+// blocking filter() on sequences
+template <typename Sequence, typename KeepFunctor>
+void blockingFilter(Sequence &sequence, KeepFunctor keep)
+{
+ filterInternal(sequence, keep, &Sequence::push_back).startBlocking();
+}
+
+template <typename Sequence, typename T>
+void blockingFilter(Sequence &sequence, bool (keep)(T))
+{
+ filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back)
+ .startBlocking();
+}
+
+template <typename Sequence, typename C>
+void blockingFilter(Sequence &sequence, bool (C::*keep)() const)
+{
+ filterInternal(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ &Sequence::push_back)
+ .startBlocking();
+}
+
+// blocking filteredReduced() on sequences
+template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(sequence, keep, reduce, options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (sequence,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
+U blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (sequence,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+C blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (sequence,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W>
+V blockingFilteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<V>
+ (sequence,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename U, typename V>
+U blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename C, typename V>
+C blockingFilteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (sequence,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename D, typename U>
+D blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<D>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// blocking filteredReduced() on iterators
+template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(begin, end, keep, reduce, options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
+U blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (begin,
+ end,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
+C blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (begin,
+ end,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W>
+V blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<V>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename U, typename V>
+U blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename C, typename V>
+C blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename D, typename U>
+D blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<D>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// blocking filtered() on sequences
+template <typename Sequence, typename KeepFunctor>
+Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep)
+{
+ return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
+}
+
+template <typename Sequence, typename T>
+Sequence blockingFiltered(const Sequence &sequence, bool (keep)(T))
+{
+ return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
+}
+
+template <typename Sequence, typename C>
+Sequence blockingFiltered(const Sequence &sequence, bool (C::*filter)() const)
+{
+ return blockingFilteredReduced(sequence,
+ filter,
+ &Sequence::push_back,
+ OrderedReduce);
+}
+
+// blocking filtered() on iterators
+template <typename OutputSequence, typename Iterator, typename KeepFunctor>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, KeepFunctor keep)
+{
+ return blockingFilteredReduced(begin,
+ end,
+ keep,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+template <typename OutputSequence, typename Iterator, typename T>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (keep)(T))
+{
+ return blockingFilteredReduced(begin,
+ end,
+ keep,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+template <typename OutputSequence, typename Iterator, typename C>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (C::*filter)() const)
+{
+ return blockingFilteredReduced(begin,
+ end,
+ filter,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfilterkernel.h b/src/corelib/concurrent/qtconcurrentfilterkernel.h
new file mode 100644
index 0000000000..cd926c006f
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilterkernel.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FILTERKERNEL_H
+#define QTCONCURRENT_FILTERKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentiteratekernel.h>
+#include <QtCore/qtconcurrentmapkernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+struct qValueType
+{
+ typedef typename T::value_type value_type;
+};
+
+template <typename T>
+struct qValueType<const T*>
+{
+ typedef T value_type;
+};
+
+template <typename T>
+struct qValueType<T*>
+{
+ typedef T value_type;
+};
+
+// Implementation of filter
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+class FilterKernel : public IterateKernel<typename Sequence::const_iterator, void>
+{
+ typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer;
+ typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType;
+ typedef typename ReduceFunctor::result_type T;
+
+ Sequence reducedResult;
+ Sequence &sequence;
+ KeepFunctor keep;
+ ReduceFunctor reduce;
+ Reducer reducer;
+
+public:
+ FilterKernel(Sequence &_sequence, KeepFunctor _keep, ReduceFunctor _reduce)
+ : IterateKernelType(const_cast<const Sequence &>(_sequence).begin(), const_cast<const Sequence &>(_sequence).end()), reducedResult(),
+ sequence(_sequence),
+ keep(_keep),
+ reduce(_reduce),
+ reducer(OrderedReduce)
+ { }
+
+ bool runIteration(typename Sequence::const_iterator it, int index, T *)
+ {
+ IntermediateResults<typename Sequence::value_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ if (keep(*it))
+ results.vector.append(*it);
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *)
+ {
+ IntermediateResults<typename Sequence::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+
+ typename Sequence::const_iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ sequence = reducedResult;
+ }
+
+ inline bool shouldThrottleThread()
+ {
+ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ inline bool shouldStartThread()
+ {
+ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef void ReturnType;
+ typedef void ResultType;
+};
+
+// Implementation of filter-reduce
+template <typename ReducedResultType,
+ typename Iterator,
+ typename KeepFunctor,
+ typename ReduceFunctor,
+ typename Reducer = ReduceKernel<ReduceFunctor,
+ ReducedResultType,
+ typename qValueType<Iterator>::value_type> >
+class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType>
+{
+ ReducedResultType reducedResult;
+ KeepFunctor keep;
+ ReduceFunctor reduce;
+ Reducer reducer;
+ typedef IterateKernel<Iterator, ReducedResultType> IterateKernelType;
+
+public:
+ FilteredReducedKernel(Iterator begin,
+ Iterator end,
+ KeepFunctor _keep,
+ ReduceFunctor _reduce,
+ ReduceOptions reduceOption)
+ : IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption)
+ { }
+
+#if 0
+ FilteredReducedKernel(ReducedResultType initialValue,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOption reduceOption)
+ : reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption)
+ { }
+#endif
+
+ bool runIteration(Iterator it, int index, ReducedResultType *)
+ {
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ if (keep(*it))
+ results.vector.append(*it);
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
+ {
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ }
+
+ inline bool shouldThrottleThread()
+ {
+ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ inline bool shouldStartThread()
+ {
+ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef ReducedResultType ReturnType;
+ typedef ReducedResultType ResultType;
+ ReducedResultType *result()
+ {
+ return &reducedResult;
+ }
+};
+
+// Implementation of filter that reports individual results via QFutureInterface
+template <typename Iterator, typename KeepFunctor>
+class FilteredEachKernel : public IterateKernel<Iterator, typename qValueType<Iterator>::value_type>
+{
+ typedef typename qValueType<Iterator>::value_type T;
+ typedef IterateKernel<Iterator, T> IterateKernelType;
+
+ KeepFunctor keep;
+
+public:
+ typedef T ReturnType;
+ typedef T ResultType;
+
+ FilteredEachKernel(Iterator begin, Iterator end, KeepFunctor _keep)
+ : IterateKernelType(begin, end), keep(_keep)
+ { }
+
+ void start()
+ {
+ if (this->futureInterface)
+ this->futureInterface->setFilterMode(true);
+ IterateKernelType::start();
+ }
+
+ bool runIteration(Iterator it, int index, T *)
+ {
+ if (keep(*it))
+ this->reportResult(&(*it), index);
+ else
+ this->reportResult(0, index);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *)
+ {
+ const int count = end - begin;
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(count);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ this->reportResults(results.vector, begin, count);
+ return false;
+ }
+};
+
+template <typename Iterator, typename KeepFunctor>
+inline
+ThreadEngineStarter<typename qValueType<Iterator>::value_type>
+startFiltered(Iterator begin, Iterator end, KeepFunctor functor)
+{
+ return startThreadEngine(new FilteredEachKernel<Iterator, KeepFunctor>(begin, end, functor));
+}
+
+template <typename Sequence, typename KeepFunctor>
+inline ThreadEngineStarter<typename Sequence::value_type>
+startFiltered(const Sequence &sequence, KeepFunctor functor)
+{
+ typedef SequenceHolder1<Sequence,
+ FilteredEachKernel<typename Sequence::const_iterator, KeepFunctor>,
+ KeepFunctor>
+ SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, functor));
+}
+
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef typename Sequence::const_iterator Iterator;
+ typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer;
+ typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
+ typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
+}
+
+
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer;
+ typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
+ return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options));
+}
+
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
new file mode 100644
index 0000000000..f31f7d2877
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FUNCTIONWRAPPERS_H
+#define QTCONCURRENT_FUNCTIONWRAPPERS_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+class FunctionWrapper0
+{
+public:
+ typedef T (*FunctionPointerType)();
+ typedef T result_type;
+ inline FunctionWrapper0(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()()
+ {
+ return functionPointer();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename U>
+class FunctionWrapper1
+{
+public:
+ typedef T (*FunctionPointerType)(U u);
+ typedef T result_type;
+ inline FunctionWrapper1(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(U u)
+ {
+ return functionPointer(u);
+ }
+
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename U, typename V>
+class FunctionWrapper2
+{
+public:
+ typedef T (*FunctionPointerType)(U u, V v);
+ typedef T result_type;
+ inline FunctionWrapper2(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(U u, V v)
+ {
+ return functionPointer(u, v);
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C>
+class MemberFunctionWrapper
+{
+public:
+ typedef T (C::*FunctionPointerType)();
+ typedef T result_type;
+ inline MemberFunctionWrapper(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(C &c)
+ {
+ return (c.*functionPointer)();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C, typename U>
+class MemberFunctionWrapper1
+{
+public:
+ typedef T (C::*FunctionPointerType)(U);
+ typedef T result_type;
+
+ inline MemberFunctionWrapper1(FunctionPointerType _functionPointer)
+ : functionPointer(_functionPointer)
+ { }
+
+ inline T operator()(C &c, U u)
+ {
+ return (c.*functionPointer)(u);
+ }
+
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C>
+class ConstMemberFunctionWrapper
+{
+public:
+ typedef T (C::*FunctionPointerType)() const;
+ typedef T result_type;
+ inline ConstMemberFunctionWrapper(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(const C &c) const
+ {
+ return (c.*functionPointer)();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+} // namespace QtConcurrent.
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp
new file mode 100644
index 0000000000..a59e6cfa47
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentiteratekernel.h"
+
+#if defined(Q_OS_MAC)
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <unistd.h>
+#elif defined(Q_OS_UNIX)
+#if defined(Q_OS_HURD)
+#include <sys/time.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+#elif defined(Q_OS_WIN)
+#include <qt_windows.h>
+#endif
+
+#include "private/qfunctions_p.h"
+
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ TargetRatio = 100,
+ MedianSize = 7
+};
+
+#if defined(Q_OS_MAC)
+
+static qint64 getticks()
+{
+ return mach_absolute_time();
+}
+
+#elif defined(Q_OS_UNIX)
+
+
+static qint64 getticks()
+{
+#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+ clockid_t clockId;
+
+#ifndef _POSIX_THREAD_CPUTIME
+ clockId = CLOCK_REALTIME;
+#elif (_POSIX_THREAD_CPUTIME-0 <= 0)
+ // if we don't have CLOCK_THREAD_CPUTIME_ID, we have to just use elapsed realtime instead
+ clockId = CLOCK_REALTIME;
+
+# if (_POSIX_THREAD_CPUTIME-0 == 0)
+ // detect availablility of CLOCK_THREAD_CPUTIME_ID
+ static long useThreadCpuTime = -2;
+ if (useThreadCpuTime == -2) {
+ // sysconf() will return either -1 or _POSIX_VERSION (don't care about thread races here)
+ useThreadCpuTime = sysconf(_SC_THREAD_CPUTIME);
+ }
+ if (useThreadCpuTime != -1)
+ clockId = CLOCK_THREAD_CPUTIME_ID;
+# endif
+#else
+ clockId = CLOCK_THREAD_CPUTIME_ID;
+#endif
+
+ struct timespec ts;
+ if (clock_gettime(clockId, &ts) == -1)
+ return 0;
+ return (ts.tv_sec * 1000000000) + ts.tv_nsec;
+#else
+
+#ifdef Q_OS_SYMBIAN
+ return clock();
+#else
+ // no clock_gettime(), fall back to wall time
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (tv.tv_sec * 1000000) + tv.tv_usec;
+#endif
+
+#endif
+}
+
+#elif defined(Q_OS_WIN)
+
+static qint64 getticks()
+{
+ LARGE_INTEGER x;
+ if (!QueryPerformanceCounter(&x))
+ return 0;
+ return x.QuadPart;
+}
+
+#endif
+
+static double elapsed(qint64 after, qint64 before)
+{
+ return double(after - before);
+}
+
+namespace QtConcurrent {
+
+/*! \internal
+
+*/
+BlockSizeManager::BlockSizeManager(int iterationCount)
+: maxBlockSize(iterationCount / (QThreadPool::globalInstance()->maxThreadCount() * 2)),
+ beforeUser(0), afterUser(0),
+ controlPartElapsed(MedianSize), userPartElapsed(MedianSize),
+ m_blockSize(1)
+{ }
+
+// Records the time before user code.
+void BlockSizeManager::timeBeforeUser()
+{
+ if (blockSizeMaxed())
+ return;
+
+ beforeUser = getticks();
+ controlPartElapsed.addValue(elapsed(beforeUser, afterUser));
+}
+
+ // Records the time after user code and adjust the block size if we are spending
+ // to much time in the for control code compared with the user code.
+void BlockSizeManager::timeAfterUser()
+{
+ if (blockSizeMaxed())
+ return;
+
+ afterUser = getticks();
+ userPartElapsed.addValue(elapsed(afterUser, beforeUser));
+
+ if (controlPartElapsed.isMedianValid() == false)
+ return;
+
+ if (controlPartElapsed.median() * TargetRatio < userPartElapsed.median())
+ return;
+
+ m_blockSize = qMin(m_blockSize * 2, maxBlockSize);
+
+#ifdef QTCONCURRENT_FOR_DEBUG
+ qDebug() << QThread::currentThread() << "adjusting block size" << controlPartElapsed.median() << userPartElapsed.median() << m_blockSize;
+#endif
+
+ // Reset the medians after adjusting the block size so we get
+ // new measurements with the new block size.
+ controlPartElapsed.reset();
+ userPartElapsed.reset();
+}
+
+int BlockSizeManager::blockSize()
+{
+ return m_blockSize;
+}
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.h b/src/corelib/concurrent/qtconcurrentiteratekernel.h
new file mode 100644
index 0000000000..186f752e63
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_ITERATEKERNEL_H
+#define QTCONCURRENT_ITERATEKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qtconcurrentmedian.h>
+#include <QtCore/qtconcurrentthreadengine.h>
+
+#ifndef QT_NO_STL
+# include <iterator>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+#ifndef QT_NO_STL
+ using std::advance;
+#else
+ template <typename It, typename T>
+ void advance(It &it, T value)
+ {
+ it+=value;
+ }
+#endif
+
+/*
+ The BlockSizeManager class manages how many iterations a thread should
+ reserve and process at a time. This is done by measuring the time spent
+ in the user code versus the control part code, and then increasing
+ the block size if the ratio between them is to small. The block size
+ management is done on the basis of the median of several timing measuremens,
+ and it is done induvidualy for each thread.
+*/
+class Q_CORE_EXPORT BlockSizeManager
+{
+public:
+ BlockSizeManager(int iterationCount);
+ void timeBeforeUser();
+ void timeAfterUser();
+ int blockSize();
+private:
+ inline bool blockSizeMaxed()
+ {
+ return (m_blockSize >= maxBlockSize);
+ }
+
+ const int maxBlockSize;
+ qint64 beforeUser;
+ qint64 afterUser;
+ Median<double> controlPartElapsed;
+ Median<double> userPartElapsed;
+ int m_blockSize;
+};
+
+template <typename T>
+class ResultReporter
+{
+public:
+ ResultReporter(ThreadEngine<T> *_threadEngine)
+ :threadEngine(_threadEngine)
+ {
+
+ }
+
+ void reserveSpace(int resultCount)
+ {
+ currentResultCount = resultCount;
+ vector.resize(qMax(resultCount, vector.count()));
+ }
+
+ void reportResults(int begin)
+ {
+ const int useVectorThreshold = 4; // Tunable parameter.
+ if (currentResultCount > useVectorThreshold) {
+ vector.resize(currentResultCount);
+ threadEngine->reportResults(vector, begin);
+ } else {
+ for (int i = 0; i < currentResultCount; ++i)
+ threadEngine->reportResult(&vector.at(i), begin + i);
+ }
+ }
+
+ inline T * getPointer()
+ {
+ return vector.data();
+ }
+
+ int currentResultCount;
+ ThreadEngine<T> *threadEngine;
+ QVector<T> vector;
+};
+
+template <>
+class ResultReporter<void>
+{
+public:
+ inline ResultReporter(ThreadEngine<void> *) { }
+ inline void reserveSpace(int) { };
+ inline void reportResults(int) { };
+ inline void * getPointer() { return 0; }
+};
+
+#ifndef QT_NO_STL
+inline bool selectIteration(std::bidirectional_iterator_tag)
+{
+ return false; // while
+}
+
+inline bool selectIteration(std::forward_iterator_tag)
+{
+ return false; // while
+}
+
+inline bool selectIteration(std::random_access_iterator_tag)
+{
+ return true; // for
+}
+#else
+// no stl support, always use while iteration
+template <typename T>
+inline bool selectIteration(T)
+{
+ return false; // while
+}
+#endif
+
+template <typename Iterator, typename T>
+class IterateKernel : public ThreadEngine<T>
+{
+public:
+ typedef T ResultType;
+
+ IterateKernel(Iterator _begin, Iterator _end)
+#if defined (QT_NO_STL)
+ : begin(_begin), end(_end), current(_begin), currentIndex(0),
+ forIteration(false), progressReportingEnabled(true)
+#else
+ : begin(_begin), end(_end), current(_begin), currentIndex(0),
+ forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true)
+#endif
+ {
+#if defined (QT_NO_STL)
+ iterationCount = 0;
+#else
+ iterationCount = forIteration ? std::distance(_begin, _end) : 0;
+
+#endif
+ }
+
+ virtual ~IterateKernel() { }
+
+ virtual bool runIteration(Iterator it, int index , T *result)
+ { Q_UNUSED(it); Q_UNUSED(index); Q_UNUSED(result); return false; }
+ virtual bool runIterations(Iterator _begin, int beginIndex, int endIndex, T *results)
+ { Q_UNUSED(_begin); Q_UNUSED(beginIndex); Q_UNUSED(endIndex); Q_UNUSED(results); return false; }
+
+ void start()
+ {
+ progressReportingEnabled = this->isProgressReportingEnabled();
+ if (progressReportingEnabled && iterationCount > 0)
+ this->setProgressRange(0, iterationCount);
+ }
+
+ bool shouldStartThread()
+ {
+ if (forIteration)
+ return (currentIndex < iterationCount) && !this->shouldThrottleThread();
+ else // whileIteration
+ return (iteratorThreads == 0);
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ if (forIteration)
+ return this->forThreadFunction();
+ else // whileIteration
+ return this->whileThreadFunction();
+ }
+
+ ThreadFunctionResult forThreadFunction()
+ {
+ BlockSizeManager blockSizeManager(iterationCount);
+ ResultReporter<T> resultReporter(this);
+
+ for(;;) {
+ if (this->isCanceled())
+ break;
+
+ const int currentBlockSize = blockSizeManager.blockSize();
+
+ if (currentIndex >= iterationCount)
+ break;
+
+ // Atomically reserve a block of iterationCount for this thread.
+ const int beginIndex = currentIndex.fetchAndAddRelease(currentBlockSize);
+ const int endIndex = qMin(beginIndex + currentBlockSize, iterationCount);
+
+ if (beginIndex >= endIndex) {
+ // No more work
+ break;
+ }
+
+ this->waitForResume(); // (only waits if the qfuture is paused.)
+
+ if (shouldStartThread())
+ this->startThread();
+
+ const int finalBlockSize = endIndex - beginIndex; // block size adjusted for possible end-of-range
+ resultReporter.reserveSpace(finalBlockSize);
+
+ // Call user code with the current iteration range.
+ blockSizeManager.timeBeforeUser();
+ const bool resultsAvailable = this->runIterations(begin, beginIndex, endIndex, resultReporter.getPointer());
+ blockSizeManager.timeAfterUser();
+
+ if (resultsAvailable)
+ resultReporter.reportResults(beginIndex);
+
+ // Report progress if progress reporting enabled.
+ if (progressReportingEnabled) {
+ completed.fetchAndAddAcquire(finalBlockSize);
+ this->setProgressValue(this->completed);
+ }
+
+ if (this->shouldThrottleThread())
+ return ThrottleThread;
+ }
+ return ThreadFinished;
+ }
+
+ ThreadFunctionResult whileThreadFunction()
+ {
+ if (iteratorThreads.testAndSetAcquire(0, 1) == false)
+ return ThreadFinished;
+
+ ResultReporter<T> resultReporter(this);
+ resultReporter.reserveSpace(1);
+
+ while (current != end) {
+ // The following two lines breaks support for input iterators according to
+ // the sgi docs: dereferencing prev after calling ++current is not allowed
+ // on input iterators. (prev is dereferenced inside user.runIteration())
+ Iterator prev = current;
+ ++current;
+ int index = currentIndex.fetchAndAddRelaxed(1);
+ iteratorThreads.testAndSetRelease(1, 0);
+
+ this->waitForResume(); // (only waits if the qfuture is paused.)
+
+ if (shouldStartThread())
+ this->startThread();
+
+ const bool resultAavailable = this->runIteration(prev, index, resultReporter.getPointer());
+ if (resultAavailable)
+ resultReporter.reportResults(index);
+
+ if (this->shouldThrottleThread())
+ return ThrottleThread;
+
+ if (iteratorThreads.testAndSetAcquire(0, 1) == false)
+ return ThreadFinished;
+ }
+
+ return ThreadFinished;
+ }
+
+
+public:
+ const Iterator begin;
+ const Iterator end;
+ Iterator current;
+ QAtomicInt currentIndex;
+ bool forIteration;
+ QAtomicInt iteratorThreads;
+ int iterationCount;
+
+ bool progressReportingEnabled;
+ QAtomicInt completed;
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmap.cpp b/src/corelib/concurrent/qtconcurrentmap.cpp
new file mode 100644
index 0000000000..fe083f17a2
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.cpp
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \namespace QtConcurrent
+ \inmodule QtCore
+ \since 4.4
+ \brief The QtConcurrent namespace provides high-level APIs that make it
+ possible to write multi-threaded programs without using low-level
+ threading primitives.
+
+ See the \l {Concurrent Programming}{Qt Concurrent} chapter in
+ the \l{threads.html}{threading} documentation.
+
+ \inheaderfile QtCore
+ \ingroup thread
+*/
+
+/*!
+ \namespace QtConcurrent::internal
+ \internal
+
+ \brief The QtConcurrent::internal namespace contains QtConcurrent
+ implementation details.
+*/
+
+/*!
+ \enum QtConcurrent::ReduceOption
+ This enum specifies the order of which results from the map or filter
+ function are passed to the reduce function.
+
+ \value UnorderedReduce Reduction is done in an arbitrary order.
+ \value OrderedReduce Reduction is done in the order of the
+ original sequence.
+ \value SequentialReduce Reduction is done sequentially: only one
+ thread will enter the reduce function at a time. (Parallel reduction
+ might be supported in a future version of Qt Concurrent.)
+*/
+
+/*!
+ \headerfile <QtConcurrentMap>
+ \title Concurrent Map and Map-Reduce
+ \ingroup thread
+
+ \brief The <QtConcurrentMap> header provides concurrent Map and MapReduce.
+
+ These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::map(), QtConcurrent::mapped() and
+ QtConcurrent::mappedReduced() functions run computations in parallel on
+ the items in a sequence such as a QList or a QVector. QtConcurrent::map()
+ modifies a sequence in-place, QtConcurrent::mapped() returns a new
+ sequence containing the modified content, and QtConcurrent::mappedReduced()
+ returns a single result.
+
+ Each of the above functions has a blocking variant that returns
+ the final result instead of a QFuture. You use them in the same
+ way as the asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 7
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QList<QImage> and QImage).
+
+ \section1 Concurrent Map
+
+ QtConcurrent::mapped() takes an input sequence and a map function. This map
+ function is then called for each item in the sequence, and a new sequence
+ containing the return values from the map function is returned.
+
+ The map function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 0
+
+ T and U can be any type (and they can even be the same type), but T must
+ match the type stored in the sequence. The function returns the modified
+ or \e mapped content.
+
+ This example shows how to apply a scale function to all the items
+ in a sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 1
+
+ The results of the map are made available through QFuture. See the
+ QFuture and QFutureWatcher documentation for more information on how to
+ use QFuture in your applications.
+
+ If you want to modify a sequence in-place, use QtConcurrent::map(). The
+ map function must then be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 2
+
+ Note that the return value and return type of the map function are not
+ used.
+
+ Using QtConcurrent::map() is similar to using QtConcurrent::mapped():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 3
+
+ Since the sequence is modified in place, QtConcurrent::map() does not
+ return any results via QFuture. However, you can still use QFuture and
+ QFutureWatcher to monitor the status of the map.
+
+ \section1 Concurrent Map-Reduce
+
+ QtConcurrent::mappedReduced() is similar to QtConcurrent::mapped(), but
+ instead of returning a sequence with the new results, the results are
+ combined into a single value using a reduce function.
+
+ The reduce function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 4
+
+ T is the type of the final result, U is the return type of the map
+ function. Note that the return value and return type of the reduce
+ function are not used.
+
+ Call QtConcurrent::mappedReduced() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 5
+
+ The reduce function will be called once for each result returned by the map
+ function, and should merge the \e{intermediate} into the \e{result}
+ variable. QtConcurrent::mappedReduced() guarantees that only one thread
+ will call reduce at a time, so using a mutex to lock the result variable
+ is not necessary. The QtConcurrent::ReduceOptions enum provides a way to
+ control the order in which the reduction is done. If
+ QtConcurrent::UnorderedReduce is used (the default), the order is
+ undefined, while QtConcurrent::OrderedReduce ensures that the reduction
+ is done in the order of the original sequence.
+
+ \section1 Additional API Features
+
+ \section2 Using Iterators instead of Sequence
+
+ Each of the above functions has a variant that takes an iterator range
+ instead of a sequence. You use them in the same way as the sequence
+ variants:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 6
+
+ \section2 Blocking Variants
+
+ Each of the above functions has a blocking variant that returns
+ the final result instead of a QFuture. You use them in the same
+ way as the asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 7
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QList<QImage> and QImage).
+
+ \section2 Using Member Functions
+
+ QtConcurrent::map(), QtConcurrent::mapped(), and
+ QtConcurrent::mappedReduced() accept pointers to member functions.
+ The member function class type must match the type stored in the sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 8
+
+ Note that when using QtConcurrent::mappedReduced(), you can mix the use of
+ normal and member functions freely:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 9
+
+ \section2 Using Function Objects
+
+ QtConcurrent::map(), QtConcurrent::mapped(), and
+ QtConcurrent::mappedReduced() accept function objects, which can be used to
+ add state to a function call. The result_type typedef must define the
+ result type of the function call operator:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 14
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}{C++
+ TR1 Library Extensions}.
+
+ If you want to use a map function that takes more than one argument you can
+ use boost::bind() or std::tr1::bind() to transform it onto a function that
+ takes one argument.
+
+ As an example, we'll use QImage::scaledToWidth():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 10
+
+ scaledToWidth takes three arguments (including the "this" pointer) and
+ can't be used with QtConcurrent::mapped() directly, because
+ QtConcurrent::mapped() expects a function that takes one argument. To use
+ QImage::scaledToWidth() with QtConcurrent::mapped() we have to provide a
+ value for the \e{width} and the \e{transformation mode}:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 11
+
+ The return value from boost::bind() is a function object (functor) with
+ the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 12
+
+ This matches what QtConcurrent::mapped() expects, and the complete example
+ becomes:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 13
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::map(Sequence &sequence, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item in \a sequence. The \a function is
+ passed a reference to the item, so that any modifications done to the item
+ will appear in \a sequence.
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::map(Iterator begin, Iterator end, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item from \a begin to \a end. The
+ \a function is passed a reference to the item, so that any modifications
+ done to the item will appear in the sequence which the iterators belong to.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mapped(const Sequence &sequence, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item in \a sequence and returns a future
+ with each mapped item as a result. You can use QFuture::const_iterator or
+ QFutureIterator to iterate through the results.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mapped(ConstIterator begin, ConstIterator end, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item from \a begin to \a end and returns a
+ future with each mapped item as a result. You can use
+ QFuture::const_iterator or QFutureIterator to iterate through the results.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mappedReduced(const Sequence &sequence,
+ MapFunction mapFunction, ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item in \a sequence. The return value of
+ each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is determined by \a reduceOptions.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mappedReduced(ConstIterator begin,
+ ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item from \a begin to \a end. The return
+ value of each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. By default, the order in which
+ \a reduceFunction is called is undefined.
+
+ \note QtConcurrent::OrderedReduce results in the ordered reduction.
+*/
+
+/*!
+ \fn void QtConcurrent::blockingMap(Sequence &sequence, MapFunction function)
+
+ Calls \a function once for each item in \a sequence. The \a function is
+ passed a reference to the item, so that any modifications done to the item
+ will appear in \a sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa map()
+*/
+
+/*!
+ \fn void QtConcurrent::blockingMap(Iterator begin, Iterator end, MapFunction function)
+
+ Calls \a function once for each item from \a begin to \a end. The
+ \a function is passed a reference to the item, so that any modifications
+ done to the item will appear in the sequence which the iterators belong to.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa map()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMapped(const Sequence &sequence, MapFunction function)
+
+ Calls \a function once for each item in \a sequence and returns a Sequence containing
+ the results. The type of the results will match the type returned my the MapFunction.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function)
+
+ Calls \a function once for each item from \a begin to \a end and returns a
+ container with the results. Specify the type of container as the a template
+ argument, like this:
+
+ \code
+ QList<int> ints = QtConcurrent::blockingMapped<QList<int> >(beginIterator, endIterator, fn);
+ \endcode
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item in \a sequence. The return value of
+ each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is determined by \a reduceOptions.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMappedReduced(ConstIterator begin, ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item from \a begin to \a end. The return
+ value of each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is undefined.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa blockingMappedReduced()
+*/
diff --git a/src/corelib/concurrent/qtconcurrentmap.h b/src/corelib/concurrent/qtconcurrentmap.h
new file mode 100644
index 0000000000..80edf7e136
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.h
@@ -0,0 +1,780 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MAP_H
+#define QTCONCURRENT_MAP_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentmapkernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+#include <QtCore/qtconcurrentfunctionwrappers.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ QFuture<void> map(Sequence &sequence, MapFunction function);
+ QFuture<void> map(Iterator begin, Iterator end, MapFunction function);
+
+ template <typename T>
+ QFuture<T> mapped(const Sequence &sequence, MapFunction function);
+ template <typename T>
+ QFuture<T> mapped(ConstIterator begin, ConstIterator end, MapFunction function);
+
+ template <typename T>
+ QFuture<T> mappedReduced(const Sequence &sequence,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ QFuture<T> mappedReduced(ConstIterator begin,
+ ConstIterator end,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+
+ void blockingMap(Sequence &sequence, MapFunction function);
+ void blockingMap(Iterator begin, Iterator end, MapFunction function);
+
+ template <typename T>
+ T blockingMapped(const Sequence &sequence, MapFunction function);
+ template <typename T>
+ T blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function);
+
+ template <typename T>
+ T blockingMappedReduced(const Sequence &sequence,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ T blockingMappedReduced(ConstIterator begin,
+ ConstIterator end,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+// map() on sequences
+template <typename Sequence, typename MapFunctor>
+QFuture<void> map(Sequence &sequence, MapFunctor map)
+{
+ return startMap(sequence.begin(), sequence.end(), map);
+}
+
+template <typename Sequence, typename T, typename U>
+QFuture<void> map(Sequence &sequence, T (map)(U))
+{
+ return startMap(sequence.begin(), sequence.end(), FunctionWrapper1<T, U>(map));
+}
+
+template <typename Sequence, typename T, typename C>
+QFuture<void> map(Sequence &sequence, T (C::*map)())
+{
+ return startMap(sequence.begin(), sequence.end(), MemberFunctionWrapper<T, C>(map));
+}
+
+// map() on iterators
+template <typename Iterator, typename MapFunctor>
+QFuture<void> map(Iterator begin, Iterator end, MapFunctor map)
+{
+ return startMap(begin, end, map);
+}
+
+template <typename Iterator, typename T, typename U>
+QFuture<void> map(Iterator begin, Iterator end, T (map)(U))
+{
+ return startMap(begin, end, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Iterator, typename T, typename C>
+QFuture<void> map(Iterator begin, Iterator end, T (C::*map)())
+{
+ return startMap(begin, end, MemberFunctionWrapper<T, C>(map));
+}
+
+// mappedReduced() for sequences.
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (sequence, map, reduce, options);
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
+QFuture<U> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, U>
+ (sequence, map, FunctionWrapper2<T, U &, V>(reduce), options);
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
+QFuture<C> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, C>
+ (sequence, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+}
+
+template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (sequence, FunctionWrapper1<T, U>(map), reduce, options);
+}
+
+template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (sequence, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
+QFuture<W> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (reduce)(W &, X),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, W>
+ (sequence, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
+QFuture<V> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, V> (sequence, ConstMemberFunctionWrapper<T, C>(map),
+ FunctionWrapper2<U, V &, W>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
+QFuture<C> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (C::*reduce)(W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, C> (sequence, FunctionWrapper1<T, U>(map),
+ MemberFunctionWrapper1<V, C, W>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
+QFuture<D> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, D>(sequence, ConstMemberFunctionWrapper<T, C>(map),
+ MemberFunctionWrapper1<U, D, V>(reduce), options);
+}
+
+// mappedReduced() for iterators
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<ResultType, typename MapFunctor::result_type>
+ (begin, end, map, reduce, options);
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
+QFuture<U> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, U>
+ (begin, end, map, FunctionWrapper2<T, U &, V>(reduce), options);
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
+QFuture<C> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, C>
+ (begin, end, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (begin, end, FunctionWrapper1<T, U>(map), reduce, options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (begin, end, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
+QFuture<W> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (reduce)(W &, X),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, W>
+ (begin, end, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
+QFuture<V> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, V>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
+ FunctionWrapper2<U, V &, W>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
+QFuture<C> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (C::*reduce)(W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, C>
+ (begin, end, FunctionWrapper1<T, U>(map), MemberFunctionWrapper1<V, C, W>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
+QFuture<D> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, D>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
+ MemberFunctionWrapper1<U, D, V>(reduce), options);
+}
+
+// mapped() for sequences
+template <typename Sequence, typename MapFunctor>
+QFuture<typename MapFunctor::result_type> mapped(const Sequence &sequence, MapFunctor map)
+{
+ return startMapped<typename MapFunctor::result_type>(sequence, map);
+}
+
+template <typename Sequence, typename T, typename U>
+QFuture<T> mapped(const Sequence &sequence, T (map)(U))
+{
+ return startMapped<T>(sequence, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Sequence, typename T, typename C>
+QFuture<T> mapped(const Sequence &sequence, T (C::*map)() const)
+{
+ return startMapped<T>(sequence, ConstMemberFunctionWrapper<T, C>(map));
+}
+
+// mapped() for iterator ranges.
+template <typename Iterator, typename MapFunctor>
+QFuture<typename MapFunctor::result_type> mapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ return startMapped<Q_TYPENAME MapFunctor::result_type>(begin, end, map);
+}
+
+template <typename Iterator, typename T, typename U>
+QFuture<T> mapped(Iterator begin, Iterator end, T (map)(U))
+{
+ return startMapped<T>(begin, end, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Iterator, typename T, typename C>
+QFuture<T> mapped(Iterator begin, Iterator end, T (C::*map)() const)
+{
+ return startMapped<T>(begin, end, ConstMemberFunctionWrapper<T, C>(map));
+}
+
+
+template <typename Sequence, typename MapFunctor>
+void blockingMap(Sequence &sequence, MapFunctor map)
+{
+ startMap(sequence.begin(), sequence.end(), map).startBlocking();
+}
+
+template <typename Sequence, typename T, typename U>
+void blockingMap(Sequence &sequence, T (map)(U))
+{
+ startMap(sequence.begin(), sequence.end(), QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
+}
+
+template <typename Sequence, typename T, typename C>
+void blockingMap(Sequence &sequence, T (C::*map)())
+{
+ startMap(sequence.begin(), sequence.end(), QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor>
+void blockingMap(Iterator begin, Iterator end, MapFunctor map)
+{
+ startMap(begin, end, map).startBlocking();
+}
+
+template <typename Iterator, typename T, typename U>
+void blockingMap(Iterator begin, Iterator end, T (map)(U))
+{
+ startMap(begin, end, QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
+}
+
+template <typename Iterator, typename T, typename C>
+void blockingMap(Iterator begin, Iterator end, T (C::*map)())
+{
+ startMap(begin, end, QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (sequence, map, reduce, options).startBlocking();
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
+U blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
+ (sequence,
+ map,
+ QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
+C blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
+ (sequence,
+ map,
+ QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
+W blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (reduce)(W &, X),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, W>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
+V blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, V>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
+C blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (C::*reduce)(W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, C>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
+D blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, D>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (begin, end, map, reduce, options).startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
+U blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
+ (begin,
+ end,
+ map,
+ QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
+C blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
+ (begin,
+ end,
+ map,
+ QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
+W blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (reduce)(W &, X),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, W>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
+V blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, V>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
+C blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (C::*reduce)(W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, C>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
+D blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, D>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+// mapped() for sequences with a different putput sequence type.
+template <typename OutputSequence, typename InputSequence, typename MapFunctor>
+OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map)
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename OutputSequence, typename InputSequence, typename T, typename U>
+OutputSequence blockingMapped(const InputSequence &sequence, T (map)(U))
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename OutputSequence, typename InputSequence, typename T, typename C>
+OutputSequence blockingMapped(const InputSequence &sequence, T (C::*map)() const)
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
+
+// overloads for changing the container value type:
+template <template <typename> class Sequence, typename MapFunctor, typename T>
+Sequence<typename MapFunctor::result_type> blockingMapped(const Sequence<T> &sequence, MapFunctor map)
+{
+ typedef Sequence<typename MapFunctor::result_type> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <template <typename> class Sequence, typename T, typename U, typename V>
+Sequence<U> blockingMapped(const Sequence<T> &sequence, U (map)(V))
+{
+ typedef Sequence<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <template <typename> class Sequence, typename T, typename U, typename C>
+Sequence<U> blockingMapped(const Sequence<T> &sequence, U (C::*map)() const)
+{
+ typedef Sequence<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
+
+// overloads for changing the container value type from a QStringList:
+template <typename MapFunctor>
+QList<typename MapFunctor::result_type> blockingMapped(const QStringList &sequence, MapFunctor map)
+{
+ typedef QList<typename MapFunctor::result_type> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename U, typename V>
+QList<U> blockingMapped(const QStringList &sequence, U (map)(V))
+{
+ typedef QList<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename U, typename C>
+QList<U> blockingMapped(const QStringList &sequence, U (C::*map)() const)
+{
+ typedef QList<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+// mapped() for iterator ranges
+template <typename Sequence, typename Iterator, typename MapFunctor>
+Sequence blockingMapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename Sequence, typename Iterator, typename T, typename U>
+Sequence blockingMapped(Iterator begin, Iterator end, T (map)(U))
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename Sequence, typename Iterator, typename T, typename C>
+Sequence blockingMapped(Iterator begin, Iterator end, T (C::*map)() const)
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmapkernel.h b/src/corelib/concurrent/qtconcurrentmapkernel.h
new file mode 100644
index 0000000000..20b9944b16
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmapkernel.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MAPKERNEL_H
+#define QTCONCURRENT_MAPKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentiteratekernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+namespace QtConcurrent {
+
+// map kernel, works with both parallel-for and parallel-while
+template <typename Iterator, typename MapFunctor>
+class MapKernel : public IterateKernel<Iterator, void>
+{
+ MapFunctor map;
+public:
+ typedef void ReturnType;
+ MapKernel(Iterator begin, Iterator end, MapFunctor _map)
+ : IterateKernel<Iterator, void>(begin, end), map(_map)
+ { }
+
+ bool runIteration(Iterator it, int, void *)
+ {
+ map(*it);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *)
+ {
+ Iterator it = sequenceBeginIterator;
+ advance(it, beginIndex);
+ for (int i = beginIndex; i < endIndex; ++i) {
+ runIteration(it, i, 0);
+ advance(it, 1);
+ }
+
+ return false;
+ }
+};
+
+template <typename ReducedResultType,
+ typename Iterator,
+ typename MapFunctor,
+ typename ReduceFunctor,
+ typename Reducer = ReduceKernel<ReduceFunctor,
+ ReducedResultType,
+ typename MapFunctor::result_type> >
+class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
+{
+ ReducedResultType reducedResult;
+ MapFunctor map;
+ ReduceFunctor reduce;
+ Reducer reducer;
+public:
+ typedef ReducedResultType ReturnType;
+ MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce, ReduceOptions reduceOptions)
+ : IterateKernel<Iterator, ReducedResultType>(begin, end), reducedResult(), map(_map), reduce(_reduce), reducer(reduceOptions)
+ { }
+
+ MappedReducedKernel(ReducedResultType initialValue,
+ MapFunctor _map,
+ ReduceFunctor _reduce)
+ : reducedResult(initialValue), map(_map), reduce(_reduce)
+ { }
+
+ bool runIteration(Iterator it, int index, ReducedResultType *)
+ {
+ IntermediateResults<typename MapFunctor::result_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ results.vector.append(map(*it));
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
+ {
+ IntermediateResults<typename MapFunctor::result_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ results.vector.append(map(*(it)));
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ }
+
+ bool shouldThrottleThread()
+ {
+ return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ bool shouldStartThread()
+ {
+ return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef ReducedResultType ResultType;
+ ReducedResultType *result()
+ {
+ return &reducedResult;
+ }
+};
+
+template <typename Iterator, typename MapFunctor>
+class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
+{
+ MapFunctor map;
+ typedef typename MapFunctor::result_type T;
+public:
+ typedef T ReturnType;
+ typedef T ResultType;
+
+ MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
+ : IterateKernel<Iterator, T>(begin, end), map(_map) { }
+
+ bool runIteration(Iterator it, int, T *result)
+ {
+ *result = map(*it);
+ return true;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *results)
+ {
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ runIteration(it, i, results + (i - begin));
+ advance(it, 1);
+ }
+
+ return true;
+ }
+};
+
+template <typename Iterator, typename Functor>
+inline ThreadEngineStarter<void> startMap(Iterator begin, Iterator end, Functor functor)
+{
+ return startThreadEngine(new MapKernel<Iterator, Functor>(begin, end, functor));
+}
+
+template <typename T, typename Iterator, typename Functor>
+inline ThreadEngineStarter<T> startMapped(Iterator begin, Iterator end, Functor functor)
+{
+ return startThreadEngine(new MappedEachKernel<Iterator, Functor>(begin, end, functor));
+}
+
+/*
+ The SequnceHolder class is used to hold a reference to the
+ sequence we are working on.
+*/
+template <typename Sequence, typename Base, typename Functor>
+struct SequenceHolder1 : public Base
+{
+ SequenceHolder1(const Sequence &_sequence, Functor functor)
+ : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
+ { }
+
+ Sequence sequence;
+
+ void finish()
+ {
+ Base::finish();
+ // Clear the sequence to make sure all temporaries are destroyed
+ // before finished is signaled.
+ sequence = Sequence();
+ }
+};
+
+template <typename T, typename Sequence, typename Functor>
+inline ThreadEngineStarter<T> startMapped(const Sequence &sequence, Functor functor)
+{
+ typedef SequenceHolder1<Sequence,
+ MappedEachKernel<typename Sequence::const_iterator , Functor>, Functor>
+ SequenceHolderType;
+
+ return startThreadEngine(new SequenceHolderType(sequence, functor));
+}
+
+template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startMappedReduced(const Sequence & sequence,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef typename Sequence::const_iterator Iterator;
+ typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
+ typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
+ typedef SequenceHolder2<Sequence, MappedReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
+}
+
+template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterator end,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
+ typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
+ return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor, options));
+}
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmedian.h b/src/corelib/concurrent/qtconcurrentmedian.h
new file mode 100644
index 0000000000..42b338b146
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmedian.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MEDIAN_H
+#define QTCONCURRENT_MEDIAN_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qvector.h>
+#include <QtCore/qalgorithms.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+class Median
+{
+public:
+ Median(int _bufferSize)
+ : currentMedian(), bufferSize(_bufferSize), currentIndex(0), valid(false), dirty(true)
+ {
+ values.resize(bufferSize);
+ }
+
+ void reset()
+ {
+ values.fill(0);
+ currentIndex = 0;
+ valid = false;
+ dirty = true;
+ }
+
+ void addValue(T value)
+ {
+ currentIndex = ((currentIndex + 1) % bufferSize);
+ if (valid == false && currentIndex % bufferSize == 0)
+ valid = true;
+
+ // Only update the cached median value when we have to, that
+ // is when the new value is on then other side of the median
+ // compared to the current value at the index.
+ const T currentIndexValue = values[currentIndex];
+ if ((currentIndexValue > currentMedian && currentMedian > value)
+ || (currentMedian > currentIndexValue && value > currentMedian)) {
+ dirty = true;
+ }
+
+ values[currentIndex] = value;
+ }
+
+ bool isMedianValid() const
+ {
+ return valid;
+ }
+
+ T median()
+ {
+ if (dirty) {
+ dirty = false;
+ QVector<T> sorted = values;
+ qSort(sorted);
+ currentMedian = sorted.at(bufferSize / 2 + 1);
+ }
+ return currentMedian;
+ }
+private:
+ QVector<T> values;
+ T currentMedian;
+ int bufferSize;
+ int currentIndex;
+ bool valid;
+ bool dirty;
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentreducekernel.h b/src/corelib/concurrent/qtconcurrentreducekernel.h
new file mode 100644
index 0000000000..d8651ab4cc
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentreducekernel.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_REDUCEKERNEL_H
+#define QTCONCURRENT_REDUCEKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qthreadpool.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtConcurrent {
+
+#ifndef qdoc
+
+/*
+ The ReduceQueueStartLimit and ReduceQueueThrottleLimit constants
+ limit the reduce queue size for MapReduce. When the number of
+ reduce blocks in the queue exceeds ReduceQueueStartLimit,
+ MapReduce won't start any new threads, and when it exceeds
+ ReduceQueueThrottleLimit running threads will be stopped.
+*/
+enum {
+ ReduceQueueStartLimit = 20,
+ ReduceQueueThrottleLimit = 30
+};
+
+// IntermediateResults holds a block of intermediate results from a
+// map or filter functor. The begin/end offsets indicates the origin
+// and range of the block.
+template <typename T>
+class IntermediateResults
+{
+public:
+ int begin, end;
+ QVector<T> vector;
+};
+
+#endif // qdoc
+
+enum ReduceOption {
+ UnorderedReduce = 0x1,
+ OrderedReduce = 0x2,
+ SequentialReduce = 0x4
+ // ParallelReduce = 0x8
+};
+Q_DECLARE_FLAGS(ReduceOptions, ReduceOption)
+Q_DECLARE_OPERATORS_FOR_FLAGS(ReduceOptions)
+
+#ifndef qdoc
+
+// supports both ordered and out-of-order reduction
+template <typename ReduceFunctor, typename ReduceResultType, typename T>
+class ReduceKernel
+{
+ typedef QMap<int, IntermediateResults<T> > ResultsMap;
+
+ const ReduceOptions reduceOptions;
+
+ QMutex mutex;
+ int progress, resultsMapSize, threadCount;
+ ResultsMap resultsMap;
+
+ bool canReduce(int begin) const
+ {
+ return (((reduceOptions & UnorderedReduce)
+ && progress == 0)
+ || ((reduceOptions & OrderedReduce)
+ && progress == begin));
+ }
+
+ void reduceResult(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ const IntermediateResults<T> &result)
+ {
+ for (int i = 0; i < result.vector.size(); ++i) {
+ reduce(r, result.vector.at(i));
+ }
+ }
+
+ void reduceResults(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ ResultsMap &map)
+ {
+ typename ResultsMap::iterator it = map.begin();
+ while (it != map.end()) {
+ reduceResult(reduce, r, it.value());
+ ++it;
+ }
+ }
+
+public:
+ ReduceKernel(ReduceOptions _reduceOptions)
+ : reduceOptions(_reduceOptions), progress(0), resultsMapSize(0),
+ threadCount(QThreadPool::globalInstance()->maxThreadCount())
+ { }
+
+ void runReduce(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ const IntermediateResults<T> &result)
+ {
+ QMutexLocker locker(&mutex);
+ if (!canReduce(result.begin)) {
+ ++resultsMapSize;
+ resultsMap.insert(result.begin, result);
+ return;
+ }
+
+ if (reduceOptions & UnorderedReduce) {
+ // UnorderedReduce
+ progress = -1;
+
+ // reduce this result
+ locker.unlock();
+ reduceResult(reduce, r, result);
+ locker.relock();
+
+ // reduce all stored results as well
+ while (!resultsMap.isEmpty()) {
+ ResultsMap resultsMapCopy = resultsMap;
+ resultsMap.clear();
+
+ locker.unlock();
+ reduceResults(reduce, r, resultsMapCopy);
+ locker.relock();
+
+ resultsMapSize -= resultsMapCopy.size();
+ }
+
+ progress = 0;
+ } else {
+ // reduce this result
+ locker.unlock();
+ reduceResult(reduce, r, result);
+ locker.relock();
+
+ // OrderedReduce
+ progress += result.end - result.begin;
+
+ // reduce as many other results as possible
+ typename ResultsMap::iterator it = resultsMap.begin();
+ while (it != resultsMap.end()) {
+ if (it.value().begin != progress)
+ break;
+
+ locker.unlock();
+ reduceResult(reduce, r, it.value());
+ locker.relock();
+
+ --resultsMapSize;
+ progress += it.value().end - it.value().begin;
+ it = resultsMap.erase(it);
+ }
+ }
+ }
+
+ // final reduction
+ void finish(ReduceFunctor &reduce, ReduceResultType &r)
+ {
+ reduceResults(reduce, r, resultsMap);
+ }
+
+ inline bool shouldThrottle()
+ {
+ return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount));
+ }
+
+ inline bool shouldStartThread()
+ {
+ return (resultsMapSize <= (ReduceQueueStartLimit * threadCount));
+ }
+};
+
+template <typename Sequence, typename Base, typename Functor1, typename Functor2>
+struct SequenceHolder2 : public Base
+{
+ SequenceHolder2(const Sequence &_sequence,
+ Functor1 functor1,
+ Functor2 functor2,
+ ReduceOptions reduceOptions)
+ : Base(_sequence.begin(), _sequence.end(), functor1, functor2, reduceOptions),
+ sequence(_sequence)
+ { }
+
+ Sequence sequence;
+
+ void finish()
+ {
+ Base::finish();
+ // Clear the sequence to make sure all temporaries are destroyed
+ // before finished is signaled.
+ sequence = Sequence();
+ }
+};
+
+#endif //qdoc
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentresultstore.cpp b/src/corelib/concurrent/qtconcurrentresultstore.cpp
new file mode 100644
index 0000000000..16714caa74
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentresultstore.h"
+
+#ifndef QT_NO_QFUTURE
+
+QT_BEGIN_NAMESPACE
+
+namespace QtConcurrent {
+
+ResultIteratorBase::ResultIteratorBase()
+ : mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
+ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex)
+ : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { }
+
+int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; }
+int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; }
+
+ResultIteratorBase ResultIteratorBase::operator++()
+{
+ if (canIncrementVectorIndex()) {
+ ++m_vectorIndex;
+ } else {
+ ++mapIterator;
+ m_vectorIndex = 0;
+ }
+ return *this;
+}
+
+int ResultIteratorBase::batchSize() const
+{
+ return mapIterator.value().count();
+}
+
+void ResultIteratorBase::batchedAdvance()
+{
+ ++mapIterator;
+ m_vectorIndex = 0;
+}
+
+bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const
+{
+ return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex);
+}
+
+bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const
+{
+ return !operator==(other);
+}
+
+bool ResultIteratorBase::isVector() const
+{
+ return mapIterator.value().isVector();
+}
+
+bool ResultIteratorBase::canIncrementVectorIndex() const
+{
+ return (m_vectorIndex + 1 < mapIterator.value().m_count);
+}
+
+ResultStoreBase::ResultStoreBase()
+ : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
+
+void ResultStoreBase::setFilterMode(bool enable)
+{
+ m_filterMode = enable;
+}
+
+bool ResultStoreBase::filterMode() const
+{
+ return m_filterMode;
+}
+
+void ResultStoreBase::syncResultCount()
+{
+ ResultIteratorBase it = resultAt(resultCount);
+ while (it != end()) {
+ resultCount += it.batchSize();
+ it = resultAt(resultCount);
+ }
+}
+
+void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem)
+{
+ if (resultItem.isValid()) {
+ m_results[index] = resultItem;
+ syncResultCount();
+ } else {
+ filteredResults += resultItem.count();
+ }
+}
+
+int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
+{
+ int storeIndex;
+ if (m_filterMode && index != -1 && index > insertIndex) {
+ pendingResults[index] = resultItem;
+ storeIndex = index;
+ } else {
+ storeIndex = updateInsertIndex(index, resultItem.count());
+ insertResultItemIfValid(storeIndex - filteredResults, resultItem);
+ }
+ syncPendingResults();
+ return storeIndex;
+}
+
+void ResultStoreBase::syncPendingResults()
+{
+ // check if we can insert any of the pending results:
+ QMap<int, ResultItem>::iterator it = pendingResults.begin();
+ while (it != pendingResults.end()) {
+ int index = it.key();
+ if (index != resultCount + filteredResults)
+ break;
+
+ ResultItem result = it.value();
+ insertResultItemIfValid(index - filteredResults, result);
+ pendingResults.erase(it);
+ it = pendingResults.begin();
+ }
+}
+
+int ResultStoreBase::addResult(int index, const void *result)
+{
+ ResultItem resultItem(result, 0); // 0 means "not a vector"
+ return insertResultItem(index, resultItem);
+}
+
+int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
+{
+ if (m_filterMode == false || vectorSize == totalCount) {
+ ResultItem resultItem(results, vectorSize);
+ return insertResultItem(index, resultItem);
+ } else {
+ if (vectorSize > 0) {
+ ResultItem filteredIn(results, vectorSize);
+ insertResultItem(index, filteredIn);
+ }
+ ResultItem filteredAway(0, totalCount - vectorSize);
+ return insertResultItem(index + vectorSize, filteredAway);
+ }
+}
+
+ResultIteratorBase ResultStoreBase::begin() const
+{
+ return ResultIteratorBase(m_results.begin());
+}
+
+ResultIteratorBase ResultStoreBase::end() const
+{
+ return ResultIteratorBase(m_results.end());
+}
+
+bool ResultStoreBase::hasNextResult() const
+{
+ return begin() != end();
+}
+
+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);
+}
+
+bool ResultStoreBase::contains(int index) const
+{
+ return (resultAt(index) != end());
+}
+
+int ResultStoreBase::count() const
+{
+ return resultCount;
+}
+
+// returns the insert index, calling this function with
+// index equal to -1 returns the next available index.
+int ResultStoreBase::updateInsertIndex(int index, int _count)
+{
+ if (index == -1) {
+ index = insertIndex;
+ insertIndex += _count;
+ } else {
+ insertIndex = qMax(index + _count, insertIndex);
+ }
+ return index;
+}
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentresultstore.h b/src/corelib/concurrent/qtconcurrentresultstore.h
new file mode 100644
index 0000000000..428de717c9
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_RESULTSTORE_H
+#define QTCONCURRENT_RESULTSTORE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qmap.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*
+ ResultStore stores indexed results. Results can be added and retrieved
+ either individually batched in a QVector. 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,
+ either individually or in batches.
+*/
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+class ResultItem
+{
+public:
+ ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
+ ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
+ ResultItem() : m_count(0), result(0) { }
+ bool isValid() const { return result != 0; }
+ bool isVector() const { return m_count != 0; }
+ int count() const { return (m_count == 0) ? 1 : m_count; }
+ int m_count; // result is either a pointer to a result or to a vector of results,
+ const void *result; // if count is 0 it's a result, otherwise it's a vector.
+};
+
+class Q_CORE_EXPORT ResultIteratorBase
+{
+public:
+ ResultIteratorBase();
+ ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
+ int vectorIndex() const;
+ int resultIndex() const;
+
+ ResultIteratorBase operator++();
+ int batchSize() const;
+ void batchedAdvance();
+ bool operator==(const ResultIteratorBase &other) const;
+ bool operator!=(const ResultIteratorBase &other) const;
+ bool isVector() const;
+ bool canIncrementVectorIndex() const;
+protected:
+ QMap<int, ResultItem>::const_iterator mapIterator;
+ int m_vectorIndex;
+};
+
+template <typename T>
+class ResultIterator : public ResultIteratorBase
+{
+public:
+ ResultIterator(const ResultIteratorBase &base)
+ : ResultIteratorBase(base) { }
+
+ const T &value() const
+ {
+ return *pointer();
+ }
+
+ const T *pointer() const
+ {
+ if (mapIterator.value().isVector())
+ return &(reinterpret_cast<const QVector<T> *>(mapIterator.value().result)->at(m_vectorIndex));
+ else
+ return reinterpret_cast<const T *>(mapIterator.value().result);
+ }
+};
+
+class Q_CORE_EXPORT ResultStoreBase
+{
+public:
+ ResultStoreBase();
+ void setFilterMode(bool enable);
+ bool filterMode() const;
+ int addResult(int index, const void *result);
+ int addResults(int index, const void *results, int vectorSize, int logicalCount);
+ ResultIteratorBase begin() const;
+ ResultIteratorBase end() const;
+ bool hasNextResult() const;
+ ResultIteratorBase resultAt(int index) const;
+ bool contains(int index) const;
+ int count() const;
+ virtual ~ResultStoreBase() { };
+
+protected:
+ int insertResultItem(int index, ResultItem &resultItem);
+ void insertResultItemIfValid(int index, ResultItem &resultItem);
+ void syncPendingResults();
+ void syncResultCount();
+ int updateInsertIndex(int index, int _count);
+
+ QMap<int, ResultItem> m_results;
+ int insertIndex; // The index where the next results(s) will be inserted.
+ int resultCount; // The number of consecutive results stored, starting at index 0.
+
+ bool m_filterMode;
+ QMap<int, ResultItem> pendingResults;
+ int filteredResults;
+
+};
+
+template <typename T>
+class ResultStore : public ResultStoreBase
+{
+public:
+ ResultStore() { }
+
+ ResultStore(const ResultStoreBase &base)
+ : ResultStoreBase(base) { }
+
+ int addResult(int index, const T *result)
+ {
+ if (result == 0)
+ return ResultStoreBase::addResult(index, result);
+ else
+ return ResultStoreBase::addResult(index, new T(*result));
+ }
+
+ int addResults(int index, const QVector<T> *results)
+ {
+ return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), results->count());
+ }
+
+ int addResults(int index, const QVector<T> *results, int totalCount)
+ {
+ return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount);
+ }
+
+ int addCanceledResult(int index)
+ {
+ return addResult(index, 0);
+ }
+
+ int addCanceledResults(int index, int _count)
+ {
+ QVector<T> empty;
+ return addResults(index, &empty, _count);
+ }
+
+ ResultIterator<T> begin() const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::begin());
+ }
+
+ ResultIterator<T> end() const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::end());
+ }
+
+ ResultIterator<T> resultAt(int index) const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::resultAt(index));
+ }
+
+ void clear()
+ {
+ QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
+ while (mapIterator != m_results.constEnd()) {
+ if (mapIterator.value().isVector())
+ delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
+ else
+ delete reinterpret_cast<const T *>(mapIterator.value().result);
+ ++mapIterator;
+ }
+ resultCount = 0;
+ m_results.clear();
+ }
+
+ ~ResultStore()
+ {
+ clear();
+ }
+
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentrun.cpp b/src/corelib/concurrent/qtconcurrentrun.cpp
new file mode 100644
index 0000000000..4c685dd23b
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtConcurrentRun>
+ \title Asynchronous Run
+
+ \brief The <QtConcurrentRun> header provides a way to run a function in a
+ separate thread.
+
+ \ingroup thread
+
+ This function is a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::run() function runs a function in a separate thread.
+ The return value of the function is made available through the QFuture API.
+
+ \section1 Running a Function in a Separate Thread
+
+ To run a function in another thread, use QtConcurrent::run():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 0
+
+ This will run \e aFunction in a separate thread obtained from the default
+ QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor
+ the status of the function.
+
+ \section1 Passing Arguments to the Function
+
+ Passing arguments to the function is done by adding them to the
+ QtConcurrent::run() call immediately after the function name. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 1
+
+ A copy of each argument is made at the point where QtConcurrent::run() is
+ called, and these values are passed to the thread when it begins executing
+ the function. Changes made to the arguments after calling
+ QtConcurrent::run() are \e not visible to the thread.
+
+ \section1 Returning Values from the Function
+
+ Any return value from the function is available via QFuture:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 2
+
+ As documented above, passing arguments is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 3
+
+ Note that the QFuture::result() function blocks and waits for the result
+ to become available. Use QFutureWatcher to get notification when the
+ function has finished execution and the result is available.
+
+ \section1 Additional API Features
+
+ \section2 Using Member Functions
+
+ QtConcurrent::run() also accepts pointers to member functions. The first
+ argument must be either a const reference or a pointer to an instance of
+ the class. Passing by const reference is useful when calling const member
+ functions; passing by pointer is useful for calling non-const member
+ functions that modify the instance.
+
+ For example, calling QByteArray::split() (a const member function) in a
+ separate thread is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 4
+
+ Calling a non-const member function is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 5
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}
+ {C++ TR1 Library Extensions}.
+
+ You can use boost::bind() or std::tr1::bind() to \e bind a number of
+ arguments to a function when called. There are number of reasons for doing
+ this:
+
+ \list
+ \o To call a function that takes more than 5 arguments.
+ \o To simplify calling a function with constant arguments.
+ \o Changing the order of arguments.
+ \endlist
+
+ See the documentation for the relevant functions for details on how to use
+ the bind API.
+
+ Calling a bound function is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 6
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::run(Function function, ...);
+ \relates <QtConcurrentRun>
+
+ Runs \a function in a separate thread. The thread is taken from the global
+ QThreadPool. Note that the function may not run immediately; the function
+ will only be run when a thread is available.
+
+ T is the same type as the return value of \a function. Non-void return
+ values can be accessed via the QFuture::result() function.
+
+ Note that the QFuture returned by QtConcurrent::run() does not support
+ canceling, pausing, or progress reporting. The QFuture returned can only
+ be used to query for the running/finished status and the return value of
+ the function.
+*/
diff --git a/src/corelib/concurrent/qtconcurrentrun.h b/src/corelib/concurrent/qtconcurrentrun.h
new file mode 100644
index 0000000000..9fa8a2797e
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/
+#ifndef QTCONCURRENT_RUN_H
+#define QTCONCURRENT_RUN_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentrunbase.h>
+#include <QtCore/qtconcurrentstoredfunctioncall.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ template <typename T>
+ QFuture<T> run(Function function, ...);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+template <typename T>
+QFuture<T> run(T (*functionPointer)())
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall0<T, T (*)()>::type(functionPointer))->start();
+}
+template <typename T, typename Param1, typename Arg1>
+QFuture<T> run(T (*functionPointer)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall1<T, T (*)(Param1), Arg1>::type(functionPointer, arg1))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(T (*functionPointer)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall2<T, T (*)(Param1, Param2), Arg1, Arg2>::type(functionPointer, arg1, arg2))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall3<T, T (*)(Param1, Param2, Param3), Arg1, Arg2, Arg3>::type(functionPointer, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall4<T, T (*)(Param1, Param2, Param3, Param4), Arg1, Arg2, Arg3, Arg4>::type(functionPointer, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall5<T, T (*)(Param1, Param2, Param3, Param4, Param5), Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionPointer, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename FunctionObject>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall0<QT_TYPENAME FunctionObject::result_type, FunctionObject>::type(functionObject))->start();
+}
+template <typename FunctionObject, typename Arg1>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall1<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1>::type(functionObject, arg1))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall2<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2>::type(functionObject, arg1, arg2))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall3<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>::type(functionObject, arg1, arg2, arg3))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall4<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>::type(functionObject, arg1, arg2, arg3, arg4))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall5<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename FunctionObject>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall0<QT_TYPENAME FunctionObject::result_type, FunctionObject>::type(functionObject))->start();
+}
+template <typename FunctionObject, typename Arg1>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall1<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1>::type(functionObject, arg1))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall2<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2>::type(functionObject, arg1, arg2))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall3<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>::type(functionObject, arg1, arg2, arg3))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall4<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>::type(functionObject, arg1, arg2, arg3, arg4))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall5<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class &object, T (Class::*fn)())
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class &object, T (Class::*fn)() const)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(Class *object, T (Class::*fn)())
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class *object, T (Class::*fn)() const)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+} //namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentrunbase.h b/src/corelib/concurrent/qtconcurrentrunbase.h
new file mode 100644
index 0000000000..f26a3e3a30
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrunbase.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_RUNBASE_H
+#define QTCONCURRENT_RUNBASE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qfuture.h>
+#include <QtCore/qrunnable.h>
+#include <QtCore/qthreadpool.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+struct SelectSpecialization
+{
+ template <class Normal, class Void>
+ struct Type { typedef Normal type; };
+};
+
+template <>
+struct SelectSpecialization<void>
+{
+ template <class Normal, class Void>
+ struct Type { typedef Void type; };
+};
+
+template <typename T>
+class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
+{
+public:
+ QFuture<T> start()
+ {
+ this->setRunnable(this);
+ this->reportStarted();
+ QFuture<T> future = this->future();
+ QThreadPool::globalInstance()->start(this, /*m_priority*/ 0);
+ return future;
+ }
+
+ void run() {}
+ virtual void runFunctor() = 0;
+};
+
+template <typename T>
+class RunFunctionTask : public RunFunctionTaskBase<T>
+{
+public:
+ void run()
+ {
+ if (this->isCanceled()) {
+ this->reportFinished();
+ return;
+ }
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ this->runFunctor();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ QFutureInterface<T>::reportException(e);
+ } catch (...) {
+ QFutureInterface<T>::reportException(QtConcurrent::UnhandledException());
+ }
+#endif
+
+ this->reportResult(result);
+ this->reportFinished();
+ }
+ T result;
+};
+
+template <>
+class RunFunctionTask<void> : public RunFunctionTaskBase<void>
+{
+public:
+ void run()
+ {
+ if (this->isCanceled()) {
+ this->reportFinished();
+ return;
+ }
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ this->runFunctor();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ QFutureInterface<void>::reportException(e);
+ } catch (...) {
+ QFutureInterface<void>::reportException(QtConcurrent::UnhandledException());
+ }
+#endif
+ this->reportFinished();
+ }
+};
+
+} //namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h b/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h
new file mode 100644
index 0000000000..82d95f6e21
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h
@@ -0,0 +1,1328 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/
+#ifndef QTCONCURRENT_STOREDFUNCTIONCALL_H
+#define QTCONCURRENT_STOREDFUNCTIONCALL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+#include <QtCore/qtconcurrentrunbase.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+template <typename T, typename FunctionPointer>
+struct StoredFunctorCall0: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall0(FunctionPointer _function)
+ : function(_function) {}
+ void runFunctor() { this->result = function(); }
+ FunctionPointer function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct VoidStoredFunctorCall0: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall0(FunctionPointer _function)
+ : function(_function) {}
+ void runFunctor() { function(); }
+ FunctionPointer function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct SelectStoredFunctorCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall0 <T, FunctionPointer>,
+ VoidStoredFunctorCall0<T, FunctionPointer> >::type type;
+};
+template <typename T, typename FunctionPointer>
+struct StoredFunctorPointerCall0: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall0(FunctionPointer * _function)
+ : function(_function) {}
+ void runFunctor() { this->result =(*function)(); }
+ FunctionPointer * function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct VoidStoredFunctorPointerCall0: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall0(FunctionPointer * _function)
+ : function(_function) {}
+ void runFunctor() {(*function)(); }
+ FunctionPointer * function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct SelectStoredFunctorPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall0 <T, FunctionPointer>,
+ VoidStoredFunctorPointerCall0<T, FunctionPointer> >::type type;
+};
+template <typename T, typename Class>
+class StoredMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class object;
+
+};
+template <typename T, typename Class>
+class VoidStoredMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object.*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredMemberFunctionCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall0 <T, Class>,
+ VoidStoredMemberFunctionCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredConstMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall0(T (Class::*_fn)() const, const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ const Class object;
+
+};
+template <typename T, typename Class>
+class VoidStoredConstMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall0(T (Class::*_fn)() const, const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object.*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ const Class object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredConstMemberFunctionCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall0 <T, Class>,
+ VoidStoredConstMemberFunctionCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class *object;
+
+};
+template <typename T, typename Class>
+class VoidStoredMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object->*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class *object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredMemberFunctionPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall0 <T, Class>,
+ VoidStoredMemberFunctionPointerCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredConstMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall0(T (Class::*_fn)() const, Class const *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ Class const *object;
+
+};
+template <typename T, typename Class>
+class VoidStoredConstMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall0(T (Class::*_fn)() const, Class const *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object->*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ Class const *object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredConstMemberFunctionPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall0 <T, Class>,
+ VoidStoredConstMemberFunctionPointerCall0<T, Class> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1>
+struct StoredFunctorCall1: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall1(FunctionPointer _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { this->result = function(arg1); }
+ FunctionPointer function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct VoidStoredFunctorCall1: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall1(FunctionPointer _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { function(arg1); }
+ FunctionPointer function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct SelectStoredFunctorCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall1 <T, FunctionPointer, Arg1>,
+ VoidStoredFunctorCall1<T, FunctionPointer, Arg1> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1>
+struct StoredFunctorPointerCall1: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall1(FunctionPointer * _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { this->result =(*function)(arg1); }
+ FunctionPointer * function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct VoidStoredFunctorPointerCall1: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall1(FunctionPointer * _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() {(*function)(arg1); }
+ FunctionPointer * function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct SelectStoredFunctorPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall1 <T, FunctionPointer, Arg1>,
+ VoidStoredFunctorPointerCall1<T, FunctionPointer, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredMemberFunctionCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall1 <T, Class, Param1, Arg1>,
+ VoidStoredMemberFunctionCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredConstMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall1(T (Class::*_fn)(Param1) const, const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ const Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredConstMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall1(T (Class::*_fn)(Param1) const, const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ const Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredConstMemberFunctionCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall1 <T, Class, Param1, Arg1>,
+ VoidStoredConstMemberFunctionCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredMemberFunctionPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall1 <T, Class, Param1, Arg1>,
+ VoidStoredMemberFunctionPointerCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredConstMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall1(T (Class::*_fn)(Param1) const, Class const *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ Class const *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredConstMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall1(T (Class::*_fn)(Param1) const, Class const *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ Class const *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredConstMemberFunctionPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall1 <T, Class, Param1, Arg1>,
+ VoidStoredConstMemberFunctionPointerCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct StoredFunctorCall2: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall2(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { this->result = function(arg1, arg2); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct VoidStoredFunctorCall2: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall2(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { function(arg1, arg2); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct SelectStoredFunctorCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall2 <T, FunctionPointer, Arg1, Arg2>,
+ VoidStoredFunctorCall2<T, FunctionPointer, Arg1, Arg2> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct StoredFunctorPointerCall2: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall2(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct VoidStoredFunctorPointerCall2: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall2(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() {(*function)(arg1, arg2); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct SelectStoredFunctorPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall2 <T, FunctionPointer, Arg1, Arg2>,
+ VoidStoredFunctorPointerCall2<T, FunctionPointer, Arg1, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredMemberFunctionCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredConstMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredConstMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredConstMemberFunctionCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredConstMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredMemberFunctionPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredConstMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredConstMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredConstMemberFunctionPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredConstMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct StoredFunctorCall3: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall3(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct VoidStoredFunctorCall3: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall3(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { function(arg1, arg2, arg3); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct SelectStoredFunctorCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall3 <T, FunctionPointer, Arg1, Arg2, Arg3>,
+ VoidStoredFunctorCall3<T, FunctionPointer, Arg1, Arg2, Arg3> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct StoredFunctorPointerCall3: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall3(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct VoidStoredFunctorPointerCall3: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall3(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct SelectStoredFunctorPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall3 <T, FunctionPointer, Arg1, Arg2, Arg3>,
+ VoidStoredFunctorPointerCall3<T, FunctionPointer, Arg1, Arg2, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredMemberFunctionCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredConstMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredConstMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredConstMemberFunctionCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredConstMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredMemberFunctionPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredConstMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredConstMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredConstMemberFunctionPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredConstMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct StoredFunctorCall4: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall4(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3, arg4); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct VoidStoredFunctorCall4: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall4(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { function(arg1, arg2, arg3, arg4); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct SelectStoredFunctorCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall4 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4>,
+ VoidStoredFunctorCall4<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct StoredFunctorPointerCall4: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall4(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3, arg4); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct VoidStoredFunctorPointerCall4: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall4(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3, arg4); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct SelectStoredFunctorPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall4 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4>,
+ VoidStoredFunctorPointerCall4<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredMemberFunctionCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredConstMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredConstMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredConstMemberFunctionCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredConstMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredMemberFunctionPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredConstMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredConstMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredConstMemberFunctionPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredConstMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct StoredFunctorCall5: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall5(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct VoidStoredFunctorCall5: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall5(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { function(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct SelectStoredFunctorCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall5 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5>,
+ VoidStoredFunctorCall5<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct StoredFunctorPointerCall5: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall5(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct VoidStoredFunctorPointerCall5: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall5(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct SelectStoredFunctorPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall5 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5>,
+ VoidStoredFunctorPointerCall5<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredMemberFunctionCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredConstMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredConstMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredConstMemberFunctionCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredConstMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredMemberFunctionPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredConstMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredConstMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredConstMemberFunctionPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+} //namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.cpp b/src/corelib/concurrent/qtconcurrentthreadengine.cpp
new file mode 100644
index 0000000000..db6217b83a
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentthreadengine.h"
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_NAMESPACE
+
+namespace QtConcurrent {
+
+ThreadEngineBarrier::ThreadEngineBarrier()
+:count(0) { }
+
+void ThreadEngineBarrier::acquire()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount -1))
+ return;
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return;
+ }
+ }
+}
+
+int ThreadEngineBarrier::release()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount == -1) {
+ if (count.testAndSetOrdered(-1, 0)) {
+ semaphore.release();
+ return 0;
+ }
+ } else if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return qAbs(localCount + 1);
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount - 1))
+ return localCount - 1;
+ }
+ }
+}
+
+// Wait until all threads have been released
+void ThreadEngineBarrier::wait()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount == 0)
+ return;
+
+ Q_ASSERT(localCount > 0); // multiple waiters are not allowed.
+ if (count.testAndSetOrdered(localCount, -localCount)) {
+ semaphore.acquire();
+ return;
+ }
+ }
+}
+
+int ThreadEngineBarrier::currentCount()
+{
+ return int(count);
+}
+
+// releases a thread, unless this is the last thread.
+// returns true if the thread was released.
+bool ThreadEngineBarrier::releaseUnlessLast()
+{
+ forever {
+ int localCount = int(count);
+ if (qAbs(localCount) == 1) {
+ return false;
+ } else if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return true;
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount - 1))
+ return true;
+ }
+ }
+}
+
+ThreadEngineBase::ThreadEngineBase()
+:futureInterface(0), threadPool(QThreadPool::globalInstance())
+{
+ setAutoDelete(false);
+}
+
+ThreadEngineBase::~ThreadEngineBase() {}
+
+void ThreadEngineBase::startSingleThreaded()
+{
+ start();
+ while (threadFunction() != ThreadFinished)
+ ;
+ finish();
+}
+
+void ThreadEngineBase::startBlocking()
+{
+ start();
+ barrier.acquire();
+ startThreads();
+
+ bool throttled = false;
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ while (threadFunction() == ThrottleThread) {
+ if (threadThrottleExit()) {
+ throttled = true;
+ break;
+ }
+ }
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ handleException(e);
+ } catch (...) {
+ handleException(QtConcurrent::UnhandledException());
+ }
+#endif
+
+ if (throttled == false) {
+ barrier.release();
+ }
+
+ barrier.wait();
+ finish();
+ exceptionStore.throwPossibleException();
+}
+
+void ThreadEngineBase::startThread()
+{
+ startThreadInternal();
+}
+
+void ThreadEngineBase::acquireBarrierSemaphore()
+{
+ barrier.acquire();
+}
+
+bool ThreadEngineBase::isCanceled()
+{
+ if (futureInterface)
+ return futureInterface->isCanceled();
+ else
+ return false;
+}
+
+void ThreadEngineBase::waitForResume()
+{
+ if (futureInterface)
+ futureInterface->waitForResume();
+}
+
+bool ThreadEngineBase::isProgressReportingEnabled()
+{
+ // If we don't have a QFuture, there is no-one to report the progress to.
+ return (futureInterface != 0);
+}
+
+void ThreadEngineBase::setProgressValue(int progress)
+{
+ if (futureInterface)
+ futureInterface->setProgressValue(progress);
+}
+
+void ThreadEngineBase::setProgressRange(int minimum, int maximum)
+{
+ if (futureInterface)
+ futureInterface->setProgressRange(minimum, maximum);
+}
+
+bool ThreadEngineBase::startThreadInternal()
+{
+ if (this->isCanceled())
+ return false;
+
+ barrier.acquire();
+ if (!threadPool->tryStart(this)) {
+ barrier.release();
+ return false;
+ }
+ return true;
+}
+
+void ThreadEngineBase::startThreads()
+{
+ while (shouldStartThread() && startThreadInternal())
+ ;
+}
+
+void ThreadEngineBase::threadExit()
+{
+ const bool asynchronous = futureInterface != 0;
+ const int lastThread = (barrier.release() == 0);
+
+ if (lastThread && asynchronous)
+ this->asynchronousFinish();
+}
+
+// Called by a worker thread that wants to be throttled. If the current number
+// of running threads is larger than one the thread is allowed to exit and
+// this function returns one.
+bool ThreadEngineBase::threadThrottleExit()
+{
+ return barrier.releaseUnlessLast();
+}
+
+void ThreadEngineBase::run() // implements QRunnable.
+{
+ if (this->isCanceled()) {
+ threadExit();
+ return;
+ }
+
+ startThreads();
+
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ while (threadFunction() == ThrottleThread) {
+ // threadFunction returning ThrottleThread means it that the user
+ // struct wants to be throttled by making a worker thread exit.
+ // Respect that request unless this is the only worker thread left
+ // running, in which case it has to keep going.
+ if (threadThrottleExit())
+ return;
+ }
+
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ handleException(e);
+ } catch (...) {
+ handleException(QtConcurrent::UnhandledException());
+ }
+#endif
+ threadExit();
+}
+
+#ifndef QT_NO_EXCEPTIONS
+
+void ThreadEngineBase::handleException(const QtConcurrent::Exception &exception)
+{
+ if (futureInterface)
+ futureInterface->reportException(exception);
+ else
+ exceptionStore.setException(exception);
+}
+#endif
+
+
+} // namepsace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.h b/src/corelib/concurrent/qtconcurrentthreadengine.h
new file mode 100644
index 0000000000..e07dd37c9f
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_THREADENGINE_H
+#define QTCONCURRENT_THREADENGINE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qthreadpool.h>
+#include <QtCore/qfuture.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qtconcurrentexception.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qsemaphore.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+// The ThreadEngineBarrier counts worker threads, and allows one
+// thread to wait for all others to finish. Tested for its use in
+// QtConcurrent, requires more testing for use as a general class.
+class ThreadEngineBarrier
+{
+private:
+ // The thread count is maintained as an integer in the count atomic
+ // variable. The count can be either positive or negative - a negative
+ // count signals that a thread is waiting on the barrier.
+
+ // BC note: inlined code from Qt < 4.6 will expect to find the QMutex
+ // and QAtomicInt here. ### Qt 5: remove.
+ QMutex mutex;
+ QAtomicInt count;
+
+ QSemaphore semaphore;
+public:
+ ThreadEngineBarrier();
+ void acquire();
+ int release();
+ void wait();
+ int currentCount();
+ bool releaseUnlessLast();
+};
+
+enum ThreadFunctionResult { ThrottleThread, ThreadFinished };
+
+// The ThreadEngine controls the threads used in the computation.
+// Can be run in three modes: single threaded, multi-threaded blocking
+// and multi-threaded asynchronous.
+// The code for the single threaded mode is
+class Q_CORE_EXPORT ThreadEngineBase: public QRunnable
+{
+public:
+ // Public API:
+ ThreadEngineBase();
+ virtual ~ThreadEngineBase();
+ void startSingleThreaded();
+ void startBlocking();
+ void startThread();
+ bool isCanceled();
+ void waitForResume();
+ bool isProgressReportingEnabled();
+ void setProgressValue(int progress);
+ void setProgressRange(int minimum, int maximum);
+ void acquireBarrierSemaphore();
+
+protected: // The user overrides these:
+ virtual void start() {}
+ virtual void finish() {}
+ virtual ThreadFunctionResult threadFunction() { return ThreadFinished; }
+ virtual bool shouldStartThread() { return futureInterface ? !futureInterface->isPaused() : true; }
+ virtual bool shouldThrottleThread() { return futureInterface ? futureInterface->isPaused() : false; }
+private:
+ bool startThreadInternal();
+ void startThreads();
+ void threadExit();
+ bool threadThrottleExit();
+ void run();
+ virtual void asynchronousFinish() = 0;
+#ifndef QT_NO_EXCEPTIONS
+ void handleException(const QtConcurrent::Exception &exception);
+#endif
+protected:
+ QFutureInterfaceBase *futureInterface;
+ QThreadPool *threadPool;
+ ThreadEngineBarrier barrier;
+ QtConcurrent::internal::ExceptionStore exceptionStore;
+};
+
+
+template <typename T>
+class ThreadEngine : public virtual ThreadEngineBase
+{
+public:
+ typedef T ResultType;
+
+ virtual T *result() { return 0; }
+
+ QFutureInterface<T> *futureInterfaceTyped()
+ {
+ return static_cast<QFutureInterface<T> *>(futureInterface);
+ }
+
+ // Runs the user algorithm using a single thread.
+ T *startSingleThreaded()
+ {
+ ThreadEngineBase::startSingleThreaded();
+ return result();
+ }
+
+ // Runs the user algorithm using multiple threads.
+ // This function blocks until the algorithm is finished,
+ // and then returns the result.
+ T *startBlocking()
+ {
+ ThreadEngineBase::startBlocking();
+ return result();
+ }
+
+ // Runs the user algorithm using multiple threads.
+ // Does not block, returns a future.
+ QFuture<T> startAsynchronously()
+ {
+ futureInterface = new QFutureInterface<T>();
+
+ // reportStart() must be called before starting threads, otherwise the
+ // user algorithm might finish while reportStart() is running, which
+ // is very bad.
+ futureInterface->reportStarted();
+ QFuture<T> future = QFuture<T>(futureInterfaceTyped());
+ start();
+
+ acquireBarrierSemaphore();
+ threadPool->start(this);
+ return future;
+ }
+
+ void asynchronousFinish()
+ {
+ finish();
+ futureInterfaceTyped()->reportFinished(result());
+ delete futureInterfaceTyped();
+ delete this;
+ }
+
+
+ void reportResult(const T *_result, int index = -1)
+ {
+ if (futureInterface)
+ futureInterfaceTyped()->reportResult(_result, index);
+ }
+
+ void reportResults(const QVector<T> &_result, int index = -1, int count = -1)
+ {
+ if (futureInterface)
+ futureInterfaceTyped()->reportResults(_result, index, count);
+ }
+};
+
+// The ThreadEngineStarter class ecapsulates the return type
+// from the thread engine.
+// Depending on how the it is used, it will run
+// the engine in either blocking mode or asynchronous mode.
+template <typename T>
+class ThreadEngineStarterBase
+{
+public:
+ ThreadEngineStarterBase(ThreadEngine<T> *_threadEngine)
+ : threadEngine(_threadEngine) { }
+
+ inline ThreadEngineStarterBase(const ThreadEngineStarterBase &other)
+ : threadEngine(other.threadEngine) { }
+
+ QFuture<T> startAsynchronously()
+ {
+ return threadEngine->startAsynchronously();
+ }
+
+ operator QFuture<T>()
+ {
+ return startAsynchronously();
+ }
+
+protected:
+ ThreadEngine<T> *threadEngine;
+};
+
+
+// We need to factor out the code that dereferences the T pointer,
+// with a specialization where T is void. (code that dereferences a void *
+// won't compile)
+template <typename T>
+class ThreadEngineStarter : public ThreadEngineStarterBase<T>
+{
+ typedef ThreadEngineStarterBase<T> Base;
+ typedef ThreadEngine<T> TypedThreadEngine;
+public:
+ ThreadEngineStarter(TypedThreadEngine *eng)
+ : Base(eng) { }
+
+ T startBlocking()
+ {
+ T t = *this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ return t;
+ }
+};
+
+// Full template specialization where T is void.
+template <>
+class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
+{
+public:
+ ThreadEngineStarter<void>(ThreadEngine<void> *_threadEngine)
+ :ThreadEngineStarterBase<void>(_threadEngine) {}
+
+ void startBlocking()
+ {
+ this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ }
+};
+
+template <typename ThreadEngine>
+inline ThreadEngineStarter<typename ThreadEngine::ResultType> startThreadEngine(ThreadEngine *threadEngine)
+{
+ return ThreadEngineStarter<typename ThreadEngine::ResultType>(threadEngine);
+}
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp
new file mode 100644
index 0000000000..1a07b5bc8e
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthreadpool.h"
+#include "qthreadpool_p.h"
+#include "qelapsedtimer.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
+{
+ return p.second < priority;
+}
+inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
+{
+ return priority < p.second;
+}
+
+Q_GLOBAL_STATIC(QThreadPool, theInstance)
+
+/*
+ QThread wrapper, provides synchronizitaion against a ThreadPool
+*/
+class QThreadPoolThread : public QThread
+{
+public:
+ QThreadPoolThread(QThreadPoolPrivate *manager);
+ void run();
+ void registerTheadInactive();
+
+ QThreadPoolPrivate *manager;
+ QRunnable *runnable;
+};
+
+/*
+ QThreadPool private class.
+*/
+
+
+/*!\internal
+
+*/
+QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)
+ :manager(manager), runnable(0)
+{ }
+
+/* \internal
+
+*/
+void QThreadPoolThread::run()
+{
+ QMutexLocker locker(&manager->mutex);
+ for(;;) {
+ QRunnable *r = runnable;
+ runnable = 0;
+
+ do {
+ if (r) {
+ const bool autoDelete = r->autoDelete();
+
+
+ // run the task
+ locker.unlock();
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ r->run();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (...) {
+ qWarning("Qt Concurrent has caught an exception thrown from a worker thread.\n"
+ "This is not supported, exceptions thrown in worker threads must be\n"
+ "caught before control returns to Qt Concurrent.");
+ registerTheadInactive();
+ throw;
+ }
+#endif
+ locker.relock();
+
+ if (autoDelete && !--r->ref)
+ delete r;
+ }
+
+ // if too many threads are active, expire this thread
+ if (manager->tooManyThreadsActive())
+ break;
+
+ r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
+ } while (r != 0);
+
+ if (manager->isExiting) {
+ registerTheadInactive();
+ break;
+ }
+
+ // if too many threads are active, expire this thread
+ bool expired = manager->tooManyThreadsActive();
+ if (!expired) {
+ ++manager->waitingThreads;
+ registerTheadInactive();
+ // wait for work, exiting after the expiry timeout is reached
+ expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
+ ++manager->activeThreads;
+
+ if (expired)
+ --manager->waitingThreads;
+ }
+ if (expired) {
+ manager->expiredThreads.enqueue(this);
+ registerTheadInactive();
+ break;
+ }
+ }
+}
+
+void QThreadPoolThread::registerTheadInactive()
+{
+ if (--manager->activeThreads == 0)
+ manager->noActiveThreads.wakeAll();
+}
+
+
+/* \internal
+
+*/
+QThreadPoolPrivate:: QThreadPoolPrivate()
+ : isExiting(false),
+ expiryTimeout(30000),
+ maxThreadCount(qAbs(QThread::idealThreadCount())),
+ reservedThreads(0),
+ waitingThreads(0),
+ activeThreads(0)
+{ }
+
+bool QThreadPoolPrivate::tryStart(QRunnable *task)
+{
+ if (allThreads.isEmpty()) {
+ // always create at least one thread
+ startThread(task);
+ return true;
+ }
+
+ // can't do anything if we're over the limit
+ if (activeThreadCount() >= maxThreadCount)
+ return false;
+
+ if (waitingThreads > 0) {
+ // recycle an available thread
+ --waitingThreads;
+ enqueueTask(task);
+ return true;
+ }
+
+ if (!expiredThreads.isEmpty()) {
+ // restart an expired thread
+ QThreadPoolThread *thread = expiredThreads.dequeue();
+ Q_ASSERT(thread->runnable == 0);
+
+ ++activeThreads;
+
+ if (task->autoDelete())
+ ++task->ref;
+ thread->runnable = task;
+ thread->start();
+ return true;
+ }
+
+ // start a new thread
+ startThread(task);
+ return true;
+}
+
+void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
+{
+ if (runnable->autoDelete())
+ ++runnable->ref;
+
+ // put it on the queue
+ QList<QPair<QRunnable *, int> >::iterator at =
+ qUpperBound(queue.begin(), queue.end(), priority);
+ queue.insert(at, qMakePair(runnable, priority));
+ runnableReady.wakeOne();
+}
+
+int QThreadPoolPrivate::activeThreadCount() const
+{
+ // To improve scalability this function is called without holding
+ // the mutex lock -- keep it thread-safe.
+ return (allThreads.count()
+ - expiredThreads.count()
+ - waitingThreads
+ + reservedThreads);
+}
+
+void QThreadPoolPrivate::tryToStartMoreThreads()
+{
+ // try to push tasks on the queue to any available threads
+ while (!queue.isEmpty() && tryStart(queue.first().first))
+ queue.removeFirst();
+}
+
+bool QThreadPoolPrivate::tooManyThreadsActive() const
+{
+ const int activeThreadCount = this->activeThreadCount();
+ return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
+}
+
+/*! \internal
+
+*/
+void QThreadPoolPrivate::startThread(QRunnable *runnable)
+{
+ QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
+ thread->setObjectName(QLatin1String("Thread (pooled)"));
+ allThreads.insert(thread.data());
+ ++activeThreads;
+
+ if (runnable->autoDelete())
+ ++runnable->ref;
+ thread->runnable = runnable;
+ thread.take()->start();
+}
+
+/*! \internal
+ Makes all threads exit, waits for each tread to exit and deletes it.
+*/
+void QThreadPoolPrivate::reset()
+{
+ QMutexLocker locker(&mutex);
+ isExiting = true;
+ runnableReady.wakeAll();
+
+ do {
+ // make a copy of the set so that we can iterate without the lock
+ QSet<QThreadPoolThread *> allThreadsCopy = allThreads;
+ allThreads.clear();
+ locker.unlock();
+
+ foreach (QThreadPoolThread *thread, allThreadsCopy) {
+ thread->wait();
+ delete thread;
+ }
+
+ locker.relock();
+ // repeat until all newly arrived threads have also completed
+ } while (!allThreads.isEmpty());
+
+ waitingThreads = 0;
+ expiredThreads.clear();
+
+ isExiting = false;
+}
+
+bool QThreadPoolPrivate::waitForDone(int msecs)
+{
+ QMutexLocker locker(&mutex);
+ if (msecs < 0) {
+ while (!(queue.isEmpty() && activeThreads == 0))
+ noActiveThreads.wait(locker.mutex());
+ } else {
+ QElapsedTimer timer;
+ timer.start();
+ int t;
+ while (!(queue.isEmpty() && activeThreads == 0) &&
+ ((t = msecs - timer.elapsed()) > 0))
+ noActiveThreads.wait(locker.mutex(), t);
+ }
+ return queue.isEmpty() && activeThreads == 0;
+}
+
+/*! \internal
+ Pulls a runnable from the front queue and runs it in the current thread. Blocks
+ until the runnable has completed. Returns true if a runnable was found.
+*/
+bool QThreadPoolPrivate::startFrontRunnable()
+{
+ QMutexLocker locker(&mutex);
+ if (queue.isEmpty())
+ return false;
+
+ QRunnable *runnable = queue.takeFirst().first;
+ const bool autoDelete = runnable->autoDelete();
+ bool del = autoDelete && !--runnable->ref;
+
+ locker.unlock();
+ runnable->run();
+ locker.relock();
+
+ if (del) {
+ delete runnable;
+ }
+
+ return true;
+}
+
+/*! \internal
+ Seaches for \a runnable in the queue, removes it from the queue and
+ runs it if found. This functon does not return until the runnable
+ has completed.
+*/
+void QThreadPoolPrivate::stealRunnable(QRunnable *runnable)
+{
+ if (runnable == 0 || queue.isEmpty())
+ return;
+ bool found = false;
+ {
+ QMutexLocker locker(&mutex);
+ QList<QPair<QRunnable *, int> >::iterator it = queue.begin();
+ QList<QPair<QRunnable *, int> >::iterator end = queue.end();
+
+ while (it != end) {
+ if (it->first == runnable) {
+ found = true;
+ queue.erase(it);
+ break;
+ }
+ ++it;
+ }
+ }
+
+ if (!found)
+ return;
+
+ const bool autoDelete = runnable->autoDelete();
+ bool del = autoDelete && !--runnable->ref;
+
+ runnable->run();
+
+ if (del) {
+ delete runnable;
+ }
+}
+
+/*!
+ \class QThreadPool
+ \brief The QThreadPool class manages a collection of QThreads.
+ \since 4.4
+ \threadsafe
+
+ \ingroup thread
+
+ QThreadPool manages and recyles 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().
+
+ To use one of the QThreadPool threads, subclass QRunnable and implement
+ the run() virtual function. Then create an object of that class and pass
+ it to QThreadPool::start().
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qthreadpool.cpp 0
+
+ QThreadPool deletes the QRunnable automatically by default. Use
+ QRunnable::setAutoDelete() to change the auto-deletion flag.
+
+ QThreadPool supports executing the same QRunnable more than once
+ by calling tryStart(this) from within QRunnable::run().
+ If autoDelete is enabled the QRunnable will be deleted when
+ the last thread exits the run function. Calling start()
+ multiple times with the same QRunnable when autoDelete is enabled
+ creates a race condition and is not recommended.
+
+ Threads that are unused for a certain amount of time will expire. The
+ default expiry timeout is 30000 milliseconds (30 seconds). This can be
+ changed using setExpiryTimeout(). Setting a negative expiry timeout
+ disables the expiry mechanism.
+
+ Call maxThreadCount() to query the maximum number of threads to be used.
+ If needed, you can change the limit with setMaxThreadCount(). The default
+ maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount()
+ function returns the number of threads currently doing work.
+
+ The reserveThread() function reserves a thread for external
+ use. Use releaseThread() when your are done with the thread, so
+ that it may be reused. Essentially, these functions temporarily
+ increase or reduce the active thread count and are useful when
+ implementing time-consuming operations that are not visible to the
+ QThreadPool.
+
+ Note that QThreadPool is a low-level class for managing threads, see
+ QtConcurrent::run() or the other
+ \l {Concurrent Programming}{Qt Concurrent} APIs for higher
+ level alternatives.
+
+ \sa QRunnable
+*/
+
+/*!
+ Constructs a thread pool with the given \a parent.
+*/
+QThreadPool::QThreadPool(QObject *parent)
+ : QObject(*new QThreadPoolPrivate, parent)
+{ }
+
+/*!
+ Destroys the QThreadPool.
+ This function will block until all runnables have been completed.
+*/
+QThreadPool::~QThreadPool()
+{
+ d_func()->waitForDone();
+ d_func()->reset();
+}
+
+/*!
+ Returns the global QThreadPool instance.
+*/
+QThreadPool *QThreadPool::globalInstance()
+{
+ return theInstance();
+}
+
+/*!
+ 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
+ be used to control the run queue's order of execution.
+
+ Note that the thread pool takes ownership of the \a runnable if
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns 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 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.
+*/
+void QThreadPool::start(QRunnable *runnable, int priority)
+{
+ if (!runnable)
+ return;
+
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ if (!d->tryStart(runnable))
+ d->enqueueTask(runnable, priority);
+}
+
+/*!
+ Attempts to reserve a thread to run \a runnable.
+
+ If no threads are available at the time of calling, then this function
+ does nothing and returns false. Otherwise, \a runnable is run immediately
+ using one available thread and this function returns true.
+
+ Note that the thread pool takes ownership of the \a runnable if
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns 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 false,
+ ownership of \a runnable remains with the caller. Note that
+ changing the auto-deletion on \a runnable after calling this
+ function results in undefined behavior.
+*/
+bool QThreadPool::tryStart(QRunnable *runnable)
+{
+ if (!runnable)
+ return false;
+
+ Q_D(QThreadPool);
+
+ // To improve scalability perform a check on the thread count
+ // before locking the mutex.
+ if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount)
+ return false;
+
+ QMutexLocker locker(&d->mutex);
+ return d->tryStart(runnable);
+}
+
+/*! \property QThreadPool::expiryTimeout
+
+ Threads that are unused for \a 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.,
+ they will not exit until the thread pool is destroyed.
+
+ Note that setting \a expiryTimeout has no effect on already running
+ threads. Only newly created threads will use the new \a expiryTimeout.
+ We recommend setting the \a expiryTimeout immediately after creating the
+ thread pool, but before calling start().
+*/
+
+int QThreadPool::expiryTimeout() const
+{
+ Q_D(const QThreadPool);
+ return d->expiryTimeout;
+}
+
+void QThreadPool::setExpiryTimeout(int expiryTimeout)
+{
+ Q_D(QThreadPool);
+ if (d->expiryTimeout == expiryTimeout)
+ return;
+ d->expiryTimeout = expiryTimeout;
+}
+
+/*! \property QThreadPool::maxThreadCount
+
+ This property represents the maximum number of threads used by the thread
+ pool.
+
+ \note The thread pool will always use at least 1 thread, even if
+ \a maxThreadCount limit is zero or negative.
+
+ The default \a maxThreadCount is QThread::idealThreadCount().
+*/
+
+int QThreadPool::maxThreadCount() const
+{
+ Q_D(const QThreadPool);
+ return d->maxThreadCount;
+}
+
+void QThreadPool::setMaxThreadCount(int maxThreadCount)
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+
+ if (maxThreadCount == d->maxThreadCount)
+ return;
+
+ d->maxThreadCount = maxThreadCount;
+ d->tryToStartMoreThreads();
+}
+
+/*! \property QThreadPool::activeThreadCount
+
+ This property represents 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.
+
+ \sa reserveThread(), releaseThread()
+*/
+
+int QThreadPool::activeThreadCount() const
+{
+ Q_D(const QThreadPool);
+ return d->activeThreadCount();
+}
+
+/*!
+ Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
+
+ 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.
+ This means that by using this function, it is possible for
+ activeThreadCount() to return a value greater than maxThreadCount() .
+
+ \sa releaseThread()
+ */
+void QThreadPool::reserveThread()
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ ++d->reservedThreads;
+}
+
+/*!
+ Releases a thread previously reserved by a call to reserveThread().
+
+ \note Calling this function without previously reserving a thread
+ temporarily increases maxThreadCount(). This is useful when a
+ thread goes to sleep waiting for more work, allowing other threads
+ to continue. Be sure to call reserveThread() when done waiting, so
+ that the thread pool can correctly maintain the
+ activeThreadCount().
+
+ \sa reserveThread()
+*/
+void QThreadPool::releaseThread()
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ --d->reservedThreads;
+ d->tryToStartMoreThreads();
+}
+
+/*!
+ Waits for each thread to exit and removes all threads from the thread pool.
+*/
+void QThreadPool::waitForDone()
+{
+ Q_D(QThreadPool);
+ d->waitForDone();
+ d->reset();
+}
+
+/*!
+ \overload waitForDone()
+ \since 4.8
+
+ Waits up to \a msecs milliseconds for all threads to exit and removes all
+ threads from the thread pool. Returns true if all threads were removed;
+ otherwise it returns false.
+*/
+bool QThreadPool::waitForDone(int msecs)
+{
+ Q_D(QThreadPool);
+ bool rc = d->waitForDone(msecs);
+ if (rc)
+ d->reset();
+ return rc;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h
new file mode 100644
index 0000000000..d0326caa8c
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREADPOOL_H
+#define QTHREADPOOL_H
+
+#include <QtCore/qglobal.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qrunnable.h>
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QThreadPoolPrivate;
+class Q_CORE_EXPORT QThreadPool : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QThreadPool)
+ Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout)
+ Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount)
+ Q_PROPERTY(int activeThreadCount READ activeThreadCount)
+ friend class QFutureInterfaceBase;
+
+public:
+ QThreadPool(QObject *parent = 0);
+ ~QThreadPool();
+
+ static QThreadPool *globalInstance();
+
+ void start(QRunnable *runnable, int priority = 0);
+ bool tryStart(QRunnable *runnable);
+
+ int expiryTimeout() const;
+ void setExpiryTimeout(int expiryTimeout);
+
+ int maxThreadCount() const;
+ void setMaxThreadCount(int maxThreadCount);
+
+ int activeThreadCount() const;
+
+ void reserveThread();
+ void releaseThread();
+
+ void waitForDone();
+ bool waitForDone(int msecs);
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_THREAD
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool_p.h b/src/corelib/concurrent/qthreadpool_p.h
new file mode 100644
index 0000000000..8f38df7efc
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREADPOOL_P_H
+#define QTHREADPOOL_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/qmutex.h"
+#include "QtCore/qwaitcondition.h"
+#include "QtCore/qset.h"
+#include "QtCore/qqueue.h"
+#include "private/qobject_p.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+class QThreadPoolThread;
+class QThreadPoolPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QThreadPool)
+ friend class QThreadPoolThread;
+
+public:
+ QThreadPoolPrivate();
+
+ bool tryStart(QRunnable *task);
+ void enqueueTask(QRunnable *task, int priority = 0);
+ int activeThreadCount() const;
+
+ void tryToStartMoreThreads();
+ bool tooManyThreadsActive() const;
+
+ void startThread(QRunnable *runnable = 0);
+ void reset();
+ bool waitForDone(int msecs = -1);
+ bool startFrontRunnable();
+ void stealRunnable(QRunnable *);
+
+ mutable QMutex mutex;
+ QWaitCondition runnableReady;
+ QSet<QThreadPoolThread *> allThreads;
+ QQueue<QThreadPoolThread *> expiredThreads;
+ QList<QPair<QRunnable *, int> > queue;
+ QWaitCondition noActiveThreads;
+
+ bool isExiting;
+ int expiryTimeout;
+ int maxThreadCount;
+ int reservedThreads;
+ int waitingThreads;
+ int activeThreads;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
+#endif
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
new file mode 100644
index 0000000000..58d2c7b2c6
--- /dev/null
+++ b/src/corelib/corelib.pro
@@ -0,0 +1,48 @@
+TARGET = QtCore
+QPRO_PWD = $$PWD
+QT =
+DEFINES += QT_BUILD_CORE_LIB QT_NO_USING_NAMESPACE
+win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000
+irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
+
+include(../qbase.pri)
+include(animation/animation.pri)
+include(arch/arch.pri)
+include(concurrent/concurrent.pri)
+include(global/global.pri)
+include(thread/thread.pri)
+include(tools/tools.pri)
+include(io/io.pri)
+include(plugin/plugin.pri)
+include(kernel/kernel.pri)
+include(codecs/codecs.pri)
+include(statemachine/statemachine.pri)
+include(xml/xml.pri)
+
+!qpa:mac|darwin:LIBS_PRIVATE += -framework ApplicationServices
+qpa {
+ contains(QT_CONFIG, coreservices) {
+ LIBS_PRIVATE += -framework CoreServices
+ }
+} else:mac|darwin {
+ LIBS_PRIVATE += -framework CoreFoundation
+}
+mac:lib_bundle:DEFINES += QT_NO_DEBUG_PLUGIN_CHECK
+win32:DEFINES-=QT_NO_CAST_TO_ASCII
+
+QMAKE_LIBS += $$QMAKE_LIBS_CORE
+
+QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtCore.dynlist
+
+contains(DEFINES,QT_EVAL):include(eval.pri)
+
+symbian: {
+ TARGET.UID3=0x2001B2DC
+
+ # Problems using data exports from this DLL mean that we can't page it on releases that don't support
+ # data exports (currently that's any release before Symbian^3)
+ pagingBlock = "$${LITERAL_HASH}ifndef SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED" \
+ "UNPAGED" \
+ "$${LITERAL_HASH}endif"
+ MMP_RULES += pagingBlock
+}
diff --git a/src/corelib/eval.pri b/src/corelib/eval.pri
new file mode 100644
index 0000000000..efda56b16a
--- /dev/null
+++ b/src/corelib/eval.pri
@@ -0,0 +1,4 @@
+SOURCES += \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qtcore_eval.cpp
+INCLUDEPATH += \
+ $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
new file mode 100644
index 0000000000..68582bf2d5
--- /dev/null
+++ b/src/corelib/global/global.pri
@@ -0,0 +1,34 @@
+# Qt kernel library base module
+
+HEADERS += \
+ global/qglobal.h \
+ global/qnamespace.h \
+ global/qendian.h \
+ global/qnumeric_p.h \
+ global/qnumeric.h
+
+SOURCES += \
+ global/qglobal.cpp \
+ global/qlibraryinfo.cpp \
+ global/qmalloc.cpp \
+ global/qnumeric.cpp
+
+# 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
+
+linux*:!static:!symbian-gcce:!*-armcc* {
+ QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate
+ prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
+ DEFINES += ELF_INTERPRETER=\\\"$$system(readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
+}
+
+# Compensate for lack of platform defines in Symbian3 and Symbian4
+symbian {
+ DEFINES += SYMBIAN_VERSION_$$upper($$replace(SYMBIAN_VERSION,\\.,_)) \
+ S60_VERSION_$$upper($$replace(S60_VERSION,\\.,_))
+}
+
+include(../../../tools/shared/symbian/epocroot.pri)
diff --git a/src/corelib/global/qconfig-dist.h b/src/corelib/global/qconfig-dist.h
new file mode 100644
index 0000000000..5f60031cde
--- /dev/null
+++ b/src/corelib/global/qconfig-dist.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+/*
+ Empty leaves all features enabled. See doc/html/emb-features.html for choices.
+
+ Note that disabling some features will produce a libqt that is not
+ compatible with other libqt builds. Such modifications are only
+ supported on Qt for Embedded Linux where reducing the library size is
+ important and where the application suite is often a fixed set.
+*/
diff --git a/src/corelib/global/qconfig-large.h b/src/corelib/global/qconfig-large.h
new file mode 100644
index 0000000000..47896a7245
--- /dev/null
+++ b/src/corelib/global/qconfig-large.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Dialogs */
+#ifndef QT_NO_FILEDIALOG
+# define QT_NO_FILEDIALOG
+#endif
+#ifndef QT_NO_FONTDIALOG
+# define QT_NO_FONTDIALOG
+#endif
+#ifndef QT_NO_INPUTDIALOG
+# define QT_NO_INPUTDIALOG
+#endif
+#ifndef QT_NO_PRINTDIALOG
+# define QT_NO_PRINTDIALOG
+#endif
+#ifndef QT_NO_PROGRESSDIALOG
+# define QT_NO_PROGRESSDIALOG
+#endif
+
+/* Fonts */
+#ifndef QT_NO_QWS_QPF
+# define QT_NO_QWS_QPF
+#endif
+
+/* Images */
+#ifndef QT_NO_IMAGEFORMAT_BMP
+# define QT_NO_IMAGEFORMAT_BMP
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+# define QT_NO_IMAGEFORMAT_PPM
+#endif
+
+/* Internationalization */
+#ifndef QT_NO_CODECS
+# define QT_NO_CODECS
+#endif
+#ifndef QT_NO_TRANSLATION
+# define QT_NO_TRANSLATION
+#endif
+#ifndef QT_NO_TRANSLATION_UTF8
+# define QT_NO_TRANSLATION_UTF8
+#endif
+
+/* ItemViews */
+#ifndef QT_NO_TABLEVIEW
+# define QT_NO_TABLEVIEW
+#endif
+#ifndef QT_NO_TREEVIEW
+# define QT_NO_TREEVIEW
+#endif
+
+/* Kernel */
+#ifndef QT_NO_CLIPBOARD
+# define QT_NO_CLIPBOARD
+#endif
+#ifndef QT_NO_DRAGANDDROP
+# define QT_NO_DRAGANDDROP
+#endif
+#ifndef QT_NO_EFFECTS
+# define QT_NO_EFFECTS
+#endif
+#ifndef QT_NO_PROPERTIES
+# define QT_NO_PROPERTIES
+#endif
+#ifndef QT_NO_SOUND
+# define QT_NO_SOUND
+#endif
+
+/* Networking */
+#ifndef QT_NO_HOSTINFO
+# define QT_NO_HOSTINFO
+#endif
+#ifndef QT_NO_HTTP
+# define QT_NO_HTTP
+#endif
+#ifndef QT_NO_UDPSOCKET
+# define QT_NO_UDPSOCKET
+#endif
+#ifndef QT_NO_URLINFO
+# define QT_NO_URLINFO
+#endif
+#ifndef QT_NO_FTP
+# define QT_NO_FTP
+#endif
+
+/* Painting */
+#ifndef QT_NO_COLORNAMES
+# define QT_NO_COLORNAMES
+#endif
+#ifndef QT_NO_PICTURE
+# define QT_NO_PICTURE
+#endif
+#ifndef QT_NO_PRINTER
+# define QT_NO_PRINTER
+#endif
+#ifndef QT_NO_CUPS
+# define QT_NO_CUPS
+#endif
+
+/* Qt for Embedded Linux */
+#ifndef QT_NO_QWS_SOUNDSERVER
+# define QT_NO_QWS_SOUNDSERVER
+#endif
+
+/* Styles */
+#ifndef QT_NO_STYLE_MOTIF
+# define QT_NO_STYLE_MOTIF
+#endif
+#ifndef QT_NO_STYLE_CDE
+# define QT_NO_STYLE_CDE
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+# define QT_NO_STYLE_STYLESHEET
+#endif
+
+/* Widgets */
+#ifndef QT_NO_CALENDARWIDGET
+# define QT_NO_CALENDARWIDGET
+#endif
+#ifndef QT_NO_DATETIMEEDIT
+# define QT_NO_DATETIMEEDIT
+#endif
+#ifndef QT_NO_WORKSPACE
+# define QT_NO_WORKSPACE
+#endif
+#ifndef QT_NO_DIAL
+# define QT_NO_DIAL
+#endif
+#ifndef QT_NO_TABLEWIDGET
+# define QT_NO_TABLEWIDGET
+#endif
+#ifndef QT_NO_TREEWIDGET
+# define QT_NO_TREEWIDGET
+#endif
diff --git a/src/corelib/global/qconfig-medium.h b/src/corelib/global/qconfig-medium.h
new file mode 100644
index 0000000000..0f8494b50a
--- /dev/null
+++ b/src/corelib/global/qconfig-medium.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Dialogs */
+#ifndef QT_NO_COLORDIALOG
+# define QT_NO_COLORDIALOG
+#endif
+#ifndef QT_NO_FILEDIALOG
+# define QT_NO_FILEDIALOG
+#endif
+#ifndef QT_NO_FONTDIALOG
+# define QT_NO_FONTDIALOG
+#endif
+#ifndef QT_NO_INPUTDIALOG
+# define QT_NO_INPUTDIALOG
+#endif
+#ifndef QT_NO_PRINTDIALOG
+# define QT_NO_PRINTDIALOG
+#endif
+#ifndef QT_NO_PROGRESSDIALOG
+# define QT_NO_PROGRESSDIALOG
+#endif
+#ifndef QT_NO_TABDIALOG
+# define QT_NO_TABDIALOG
+#endif
+
+/* Fonts */
+#ifndef QT_NO_QWS_QPF
+# define QT_NO_QWS_QPF
+#endif
+
+/* Images */
+#ifndef QT_NO_IMAGEFORMAT_BMP
+# define QT_NO_IMAGEFORMAT_BMP
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+# define QT_NO_IMAGEFORMAT_PPM
+#endif
+#ifndef QT_NO_IMAGE_TEXT
+# define QT_NO_IMAGE_TEXT
+#endif
+#ifndef QT_NO_MOVIE
+# define QT_NO_MOVIE
+#endif
+
+/* Internationalization */
+#ifndef QT_NO_BIG_CODECS
+# define QT_NO_BIG_CODECS
+#endif
+#ifndef QT_NO_TEXTCODEC
+# define QT_NO_TEXTCODEC
+#endif
+#ifndef QT_NO_CODECS
+# define QT_NO_CODECS
+#endif
+#ifndef QT_NO_TEXTCODECPLUGIN
+# define QT_NO_TEXTCODECPLUGIN
+#endif
+#ifndef QT_NO_TRANSLATION
+# define QT_NO_TRANSLATION
+#endif
+#ifndef QT_NO_TRANSLATION_UTF8
+# define QT_NO_TRANSLATION_UTF8
+#endif
+
+/* ItemViews */
+#ifndef QT_NO_TABLEVIEW
+# define QT_NO_TABLEVIEW
+#endif
+#ifndef QT_NO_TREEVIEW
+# define QT_NO_TREEVIEW
+#endif
+
+/* Kernel */
+#ifndef QT_NO_ACTION
+# define QT_NO_ACTION
+#endif
+#ifndef QT_NO_CLIPBOARD
+# define QT_NO_CLIPBOARD
+#endif
+#ifndef QT_NO_DRAGANDDROP
+# define QT_NO_DRAGANDDROP
+#endif
+#ifndef QT_NO_EFFECTS
+# define QT_NO_EFFECTS
+#endif
+#ifndef QT_NO_PROPERTIES
+# define QT_NO_PROPERTIES
+#endif
+#ifndef QT_NO_SESSIONMANAGER
+# define QT_NO_SESSIONMANAGER
+#endif
+#ifndef QT_NO_SHORTCUT
+# define QT_NO_SHORTCUT
+#endif
+#ifndef QT_NO_SOUND
+# define QT_NO_SOUND
+#endif
+#ifndef QT_NO_WHEELEVENT
+# define QT_NO_WHEELEVENT
+#endif
+
+/* Networking */
+#ifndef QT_NO_COP
+# define QT_NO_COP
+#endif
+#ifndef QT_NO_HOSTINFO
+# define QT_NO_HOSTINFO
+#endif
+#ifndef QT_NO_HTTP
+# define QT_NO_HTTP
+#endif
+#ifndef QT_NO_NETWORKPROXY
+# define QT_NO_NETWORKPROXY
+#endif
+#ifndef QT_NO_SOCKS5
+# define QT_NO_SOCKS5
+#endif
+#ifndef QT_NO_UDPSOCKET
+# define QT_NO_UDPSOCKET
+#endif
+#ifndef QT_NO_URLINFO
+# define QT_NO_URLINFO
+#endif
+#ifndef QT_NO_FTP
+# define QT_NO_FTP
+#endif
+
+/* Painting */
+#ifndef QT_NO_COLORNAMES
+# define QT_NO_COLORNAMES
+#endif
+#ifndef QT_NO_PICTURE
+# define QT_NO_PICTURE
+#endif
+#ifndef QT_NO_PRINTER
+# define QT_NO_PRINTER
+#endif
+#ifndef QT_NO_CUPS
+# define QT_NO_CUPS
+#endif
+
+/* Qt for Embedded Linux */
+#ifndef QT_NO_QWSEMBEDWIDGET
+# define QT_NO_QWSEMBEDWIDGET
+#endif
+#ifndef QT_NO_QWS_SOUNDSERVER
+# define QT_NO_QWS_SOUNDSERVER
+#endif
+#ifndef QT_NO_QWS_PROPERTIES
+# define QT_NO_QWS_PROPERTIES
+#endif
+
+/* Styles */
+#ifndef QT_NO_STYLE_MOTIF
+# define QT_NO_STYLE_MOTIF
+#endif
+#ifndef QT_NO_STYLE_CDE
+# define QT_NO_STYLE_CDE
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+# define QT_NO_STYLE_STYLESHEET
+#endif
+
+/* Utilities */
+#ifndef QT_NO_UNDOCOMMAND
+# define QT_NO_UNDOCOMMAND
+#endif
+#ifndef QT_NO_UNDOGROUP
+# define QT_NO_UNDOGROUP
+#endif
+#ifndef QT_NO_UNDOSTACK
+# define QT_NO_UNDOSTACK
+#endif
+#ifndef QT_NO_UNDOVIEW
+# define QT_NO_UNDOVIEW
+#endif
+#ifndef QT_NO_GESTURES
+# define QT_NO_GESTURES
+#endif
+
+/* Widgets */
+#ifndef QT_NO_LCDNUMBER
+# define QT_NO_LCDNUMBER
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+# define QT_NO_CALENDARWIDGET
+#endif
+#ifndef QT_NO_DATETIMEEDIT
+# define QT_NO_DATETIMEEDIT
+#endif
+#ifndef QT_NO_MENU
+# define QT_NO_MENU
+#endif
+#ifndef QT_NO_CONTEXTMENU
+# define QT_NO_CONTEXTMENU
+#endif
+#ifndef QT_NO_MAINWINDOW
+# define QT_NO_MAINWINDOW
+#endif
+#ifndef QT_NO_DOCKWIDGET
+# define QT_NO_DOCKWIDGET
+#endif
+#ifndef QT_NO_TOOLBAR
+# define QT_NO_TOOLBAR
+#endif
+#ifndef QT_NO_MENUBAR
+# define QT_NO_MENUBAR
+#endif
+#ifndef QT_NO_WORKSPACE
+# define QT_NO_WORKSPACE
+#endif
+#ifndef QT_NO_PROGRESSBAR
+# define QT_NO_PROGRESSBAR
+#endif
+#ifndef QT_NO_SIZEGRIP
+# define QT_NO_SIZEGRIP
+#endif
+#ifndef QT_NO_DIAL
+# define QT_NO_DIAL
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+# define QT_NO_STACKEDWIDGET
+#endif
+#ifndef QT_NO_TABWIDGET
+# define QT_NO_TABWIDGET
+#endif
+#ifndef QT_NO_STATUSBAR
+# define QT_NO_STATUSBAR
+#endif
+#ifndef QT_NO_STATUSTIP
+# define QT_NO_STATUSTIP
+#endif
+#ifndef QT_NO_TABLEWIDGET
+# define QT_NO_TABLEWIDGET
+#endif
+#ifndef QT_NO_TOOLBUTTON
+# define QT_NO_TOOLBUTTON
+#endif
+#ifndef QT_NO_TABBAR
+# define QT_NO_TABBAR
+#endif
+#ifndef QT_NO_TOOLBOX
+# define QT_NO_TOOLBOX
+#endif
+#ifndef QT_NO_WHATSTHIS
+# define QT_NO_WHATSTHIS
+#endif
+#ifndef QT_NO_TOOLTIP
+# define QT_NO_TOOLTIP
+#endif
+#ifndef QT_NO_TREEWIDGET
+# define QT_NO_TREEWIDGET
+#endif
+
+/* Windows */
+#ifndef QT_NO_WIN_ACTIVEQT
+# define QT_NO_WIN_ACTIVEQT
+#endif
diff --git a/src/corelib/global/qconfig-minimal.h b/src/corelib/global/qconfig-minimal.h
new file mode 100644
index 0000000000..a2714a9127
--- /dev/null
+++ b/src/corelib/global/qconfig-minimal.h
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Data structures */
+#ifndef QT_NO_QUUID_STRING
+# define QT_NO_QUUID_STRING
+#endif
+#ifndef QT_NO_STL
+# define QT_NO_STL
+#endif
+#ifndef QT_NO_TEXTDATE
+# define QT_NO_TEXTDATE
+#endif
+#ifndef QT_NO_DATESTRING
+# define QT_NO_DATESTRING
+#endif
+
+/* Dialogs */
+#ifndef QT_NO_COLORDIALOG
+# define QT_NO_COLORDIALOG
+#endif
+#ifndef QT_NO_ERRORMESSAGE
+# define QT_NO_ERRORMESSAGE
+#endif
+#ifndef QT_NO_FILEDIALOG
+# define QT_NO_FILEDIALOG
+#endif
+#ifndef QT_NO_FONTDIALOG
+# define QT_NO_FONTDIALOG
+#endif
+#ifndef QT_NO_INPUTDIALOG
+# define QT_NO_INPUTDIALOG
+#endif
+#ifndef QT_NO_MESSAGEBOX
+# define QT_NO_MESSAGEBOX
+#endif
+#ifndef QT_NO_PRINTDIALOG
+# define QT_NO_PRINTDIALOG
+#endif
+#ifndef QT_NO_PRINTPREVIEWDIALOG
+# define QT_NO_PRINTPREVIEWDIALOG
+#endif
+#ifndef QT_NO_PROGRESSDIALOG
+# define QT_NO_PROGRESSDIALOG
+#endif
+#ifndef QT_NO_TABDIALOG
+# define QT_NO_TABDIALOG
+#endif
+#ifndef QT_NO_WIZARD
+# define QT_NO_WIZARD
+#endif
+
+/* File I/O */
+#ifndef QT_NO_DOM
+# define QT_NO_DOM
+#endif
+#ifndef QT_NO_FILESYSTEMWATCHER
+# define QT_NO_FILESYSTEMWATCHER
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+# define QT_NO_FILESYSTEMMODEL
+#endif
+#ifndef QT_NO_PROCESS
+# define QT_NO_PROCESS
+#endif
+#ifndef QT_NO_TEMPORARYFILE
+# define QT_NO_TEMPORARYFILE
+#endif
+#ifndef QT_NO_TEXTSTREAM
+# define QT_NO_TEXTSTREAM
+#endif
+#ifndef QT_NO_SETTINGS
+# define QT_NO_SETTINGS
+#endif
+#ifndef QT_NO_LIBRARY
+# define QT_NO_LIBRARY
+#endif
+
+/* Fonts */
+#ifndef QT_NO_FREETYPE
+# define QT_NO_FREETYPE
+#endif
+#ifndef QT_NO_QWS_QPF2
+# define QT_NO_QWS_QPF2
+#endif
+
+/* Images */
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+# define QT_NO_IMAGEFORMATPLUGIN
+#endif
+#ifndef QT_NO_IMAGEFORMAT_BMP
+# define QT_NO_IMAGEFORMAT_BMP
+#endif
+#ifndef QT_NO_IMAGEFORMAT_JPEG
+# define QT_NO_IMAGEFORMAT_JPEG
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PNG
+# define QT_NO_IMAGEFORMAT_PNG
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+# define QT_NO_IMAGEFORMAT_PPM
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XBM
+# define QT_NO_IMAGEFORMAT_XBM
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XPM
+# define QT_NO_IMAGEFORMAT_XPM
+#endif
+#ifndef QT_NO_IMAGE_HEURISTIC_MASK
+# define QT_NO_IMAGE_HEURISTIC_MASK
+#endif
+#ifndef QT_NO_IMAGE_TEXT
+# define QT_NO_IMAGE_TEXT
+#endif
+#ifndef QT_NO_MOVIE
+# define QT_NO_MOVIE
+#endif
+
+/* Internationalization */
+#ifndef QT_NO_BIG_CODECS
+# define QT_NO_BIG_CODECS
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+# define QT_NO_QWS_INPUTMETHODS
+#endif
+#ifndef QT_NO_TEXTCODEC
+# define QT_NO_TEXTCODEC
+#endif
+#ifndef QT_NO_CODECS
+# define QT_NO_CODECS
+#endif
+#ifndef QT_NO_TEXTCODECPLUGIN
+# define QT_NO_TEXTCODECPLUGIN
+#endif
+#ifndef QT_NO_TRANSLATION
+# define QT_NO_TRANSLATION
+#endif
+#ifndef QT_NO_TRANSLATION_UTF8
+# define QT_NO_TRANSLATION_UTF8
+#endif
+
+/* ItemViews */
+#ifndef QT_NO_ITEMVIEWS
+# define QT_NO_ITEMVIEWS
+#endif
+#ifndef QT_NO_DATAWIDGETMAPPER
+# define QT_NO_DATAWIDGETMAPPER
+#endif
+#ifndef QT_NO_DIRMODEL
+# define QT_NO_DIRMODEL
+#endif
+#ifndef QT_NO_LISTVIEW
+# define QT_NO_LISTVIEW
+#endif
+#ifndef QT_NO_COLUMNVIEW
+# define QT_NO_COLUMNVIEW
+#endif
+#ifndef QT_NO_PROXYMODEL
+# define QT_NO_PROXYMODEL
+#endif
+#ifndef QT_NO_SORTFILTERPROXYMODEL
+# define QT_NO_SORTFILTERPROXYMODEL
+#endif
+#ifndef QT_NO_STANDARDITEMMODEL
+# define QT_NO_STANDARDITEMMODEL
+#endif
+#ifndef QT_NO_STRINGLISTMODEL
+# define QT_NO_STRINGLISTMODEL
+#endif
+#ifndef QT_NO_TABLEVIEW
+# define QT_NO_TABLEVIEW
+#endif
+#ifndef QT_NO_TREEVIEW
+# define QT_NO_TREEVIEW
+#endif
+
+/* Kernel */
+#ifndef QT_NO_ACTION
+# define QT_NO_ACTION
+#endif
+#ifndef QT_NO_CLIPBOARD
+# define QT_NO_CLIPBOARD
+#endif
+#ifndef QT_NO_CSSPARSER
+# define QT_NO_CSSPARSER
+#endif
+#ifndef QT_NO_CURSOR
+# define QT_NO_CURSOR
+#endif
+#ifndef QT_NO_DRAGANDDROP
+# define QT_NO_DRAGANDDROP
+#endif
+#ifndef QT_NO_EFFECTS
+# define QT_NO_EFFECTS
+#endif
+#ifndef QT_NO_PROPERTIES
+# define QT_NO_PROPERTIES
+#endif
+#ifndef QT_NO_SESSIONMANAGER
+# define QT_NO_SESSIONMANAGER
+#endif
+#ifndef QT_NO_SHAREDMEMORY
+# define QT_NO_SHAREDMEMORY
+#endif
+#ifndef QT_NO_SHORTCUT
+# define QT_NO_SHORTCUT
+#endif
+#ifndef QT_NO_SOUND
+# define QT_NO_SOUND
+#endif
+#ifndef QT_NO_SYSTEMSEMAPHORE
+# define QT_NO_SYSTEMSEMAPHORE
+#endif
+#ifndef QT_NO_TABLETEVENT
+# define QT_NO_TABLETEVENT
+#endif
+#ifndef QT_NO_TEXTHTMLPARSER
+# define QT_NO_TEXTHTMLPARSER
+#endif
+#ifndef QT_NO_CONCURRENT
+# define QT_NO_CONCURRENT
+#endif
+#ifndef QT_NO_WHEELEVENT
+# define QT_NO_WHEELEVENT
+#endif
+#ifndef QT_NO_XMLSTREAM
+# define QT_NO_XMLSTREAM
+#endif
+#ifndef QT_NO_XMLSTREAMREADER
+# define QT_NO_XMLSTREAMREADER
+#endif
+#ifndef QT_NO_XMLSTREAMWRITER
+# define QT_NO_XMLSTREAMWRITER
+#endif
+
+/* Networking */
+#ifndef QT_NO_COP
+# define QT_NO_COP
+#endif
+#ifndef QT_NO_HOSTINFO
+# define QT_NO_HOSTINFO
+#endif
+#ifndef QT_NO_HTTP
+# define QT_NO_HTTP
+#endif
+#ifndef QT_NO_NETWORKPROXY
+# define QT_NO_NETWORKPROXY
+#endif
+#ifndef QT_NO_SOCKS5
+# define QT_NO_SOCKS5
+#endif
+#ifndef QT_NO_UDPSOCKET
+# define QT_NO_UDPSOCKET
+#endif
+#ifndef QT_NO_URLINFO
+# define QT_NO_URLINFO
+#endif
+#ifndef QT_NO_FTP
+# define QT_NO_FTP
+#endif
+
+/* Painting */
+#ifndef QT_NO_COLORNAMES
+# define QT_NO_COLORNAMES
+#endif
+#ifndef QT_NO_DIRECTPAINTER
+# define QT_NO_DIRECTPAINTER
+#endif
+#ifndef QT_NO_PAINTONSCREEN
+# define QT_NO_PAINTONSCREEN
+#endif
+#ifndef QT_NO_PAINT_DEBUG
+# define QT_NO_PAINT_DEBUG
+#endif
+#ifndef QT_NO_PICTURE
+# define QT_NO_PICTURE
+#endif
+#ifndef QT_NO_PRINTER
+# define QT_NO_PRINTER
+#endif
+#ifndef QT_NO_CUPS
+# define QT_NO_CUPS
+#endif
+
+/* Qt for Embedded Linux */
+#ifndef QT_NO_QWSEMBEDWIDGET
+# define QT_NO_QWSEMBEDWIDGET
+#endif
+#ifndef QT_NO_QWS_ALPHA_CURSOR
+# define QT_NO_QWS_ALPHA_CURSOR
+#endif
+#ifndef QT_NO_QWS_CURSOR
+# define QT_NO_QWS_CURSOR
+#endif
+#ifndef QT_NO_QWS_DECORATION_DEFAULT
+# define QT_NO_QWS_DECORATION_DEFAULT
+#endif
+#ifndef QT_NO_QWS_DECORATION_STYLED
+# define QT_NO_QWS_DECORATION_STYLED
+#endif
+#ifndef QT_NO_QWS_DECORATION_WINDOWS
+# define QT_NO_QWS_DECORATION_WINDOWS
+#endif
+#ifndef QT_NO_QWS_MANAGER
+# define QT_NO_QWS_MANAGER
+#endif
+#ifndef QT_NO_QWS_KEYBOARD
+# define QT_NO_QWS_KEYBOARD
+#endif
+#ifndef QT_NO_QWS_MOUSE
+# define QT_NO_QWS_MOUSE
+#endif
+#ifndef QT_NO_QWS_MOUSE_AUTO
+# define QT_NO_QWS_MOUSE_AUTO
+#endif
+#ifndef QT_NO_QWS_MOUSE_MANUAL
+# define QT_NO_QWS_MOUSE_MANUAL
+#endif
+#ifndef QT_NO_QWS_MULTIPROCESS
+# define QT_NO_QWS_MULTIPROCESS
+#endif
+#ifndef QT_NO_QWS_SOUNDSERVER
+# define QT_NO_QWS_SOUNDSERVER
+#endif
+#ifndef QT_NO_SXE
+# define QT_NO_SXE
+#endif
+#ifndef QT_NO_QWS_PROPERTIES
+# define QT_NO_QWS_PROPERTIES
+#endif
+#ifndef QT_NO_QWS_PROXYSCREEN
+# define QT_NO_QWS_PROXYSCREEN
+#endif
+#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+#endif
+
+/* SVG */
+#ifndef QT_NO_SVG
+# define QT_NO_SVG
+#endif
+#ifndef QT_NO_GRAPHICSSVGITEM
+# define QT_NO_GRAPHICSSVGITEM
+#endif
+#ifndef QT_NO_SVGGENERATOR
+# define QT_NO_SVGGENERATOR
+#endif
+#ifndef QT_NO_SVGRENDERER
+# define QT_NO_SVGRENDERER
+#endif
+#ifndef QT_NO_SVGWIDGET
+# define QT_NO_SVGWIDGET
+#endif
+
+/* Styles */
+#ifndef QT_NO_STYLE_MOTIF
+# define QT_NO_STYLE_MOTIF
+#endif
+#ifndef QT_NO_STYLE_CDE
+# define QT_NO_STYLE_CDE
+#endif
+#ifndef QT_NO_STYLE_CLEANLOOKS
+# define QT_NO_STYLE_CLEANLOOKS
+#endif
+#ifndef QT_NO_STYLE_PLASTIQUE
+# define QT_NO_STYLE_PLASTIQUE
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+# define QT_NO_STYLE_STYLESHEET
+#endif
+#ifndef QT_NO_STYLE_WINDOWSCE
+# define QT_NO_STYLE_WINDOWSCE
+#endif
+#ifndef QT_NO_STYLE_WINDOWSMOBILE
+# define QT_NO_STYLE_WINDOWSMOBILE
+#endif
+#ifndef QT_NO_STYLE_WINDOWSVISTA
+# define QT_NO_STYLE_WINDOWSVISTA
+#endif
+#ifndef QT_NO_STYLE_WINDOWSXP
+# define QT_NO_STYLE_WINDOWSXP
+#endif
+
+/* Utilities */
+#ifndef QT_NO_ACCESSIBILITY
+# define QT_NO_ACCESSIBILITY
+#endif
+#ifndef QT_NO_COMPLETER
+# define QT_NO_COMPLETER
+#endif
+#ifndef QT_NO_DESKTOPSERVICES
+# define QT_NO_DESKTOPSERVICES
+#endif
+#ifndef QT_NO_SCRIPT
+# define QT_NO_SCRIPT
+#endif
+#ifndef QT_NO_SYSTEMTRAYICON
+# define QT_NO_SYSTEMTRAYICON
+#endif
+#ifndef QT_NO_UNDOCOMMAND
+# define QT_NO_UNDOCOMMAND
+#endif
+#ifndef QT_NO_UNDOGROUP
+# define QT_NO_UNDOGROUP
+#endif
+#ifndef QT_NO_UNDOSTACK
+# define QT_NO_UNDOSTACK
+#endif
+#ifndef QT_NO_UNDOVIEW
+# define QT_NO_UNDOVIEW
+#endif
+#ifndef QT_NO_GESTURES
+# define QT_NO_GESTURES
+#endif
+
+/* Widgets */
+#ifndef QT_NO_GROUPBOX
+# define QT_NO_GROUPBOX
+#endif
+#ifndef QT_NO_BUTTONGROUP
+# define QT_NO_BUTTONGROUP
+#endif
+#ifndef QT_NO_LCDNUMBER
+# define QT_NO_LCDNUMBER
+#endif
+#ifndef QT_NO_LINEEDIT
+# define QT_NO_LINEEDIT
+#endif
+#ifndef QT_NO_COMBOBOX
+# define QT_NO_COMBOBOX
+#endif
+#ifndef QT_NO_FONTCOMBOBOX
+# define QT_NO_FONTCOMBOBOX
+#endif
+#ifndef QT_NO_SPINBOX
+# define QT_NO_SPINBOX
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+# define QT_NO_CALENDARWIDGET
+#endif
+#ifndef QT_NO_DATETIMEEDIT
+# define QT_NO_DATETIMEEDIT
+#endif
+#ifndef QT_NO_LISTWIDGET
+# define QT_NO_LISTWIDGET
+#endif
+#ifndef QT_NO_MENU
+# define QT_NO_MENU
+#endif
+#ifndef QT_NO_CONTEXTMENU
+# define QT_NO_CONTEXTMENU
+#endif
+#ifndef QT_NO_MAINWINDOW
+# define QT_NO_MAINWINDOW
+#endif
+#ifndef QT_NO_DOCKWIDGET
+# define QT_NO_DOCKWIDGET
+#endif
+#ifndef QT_NO_TOOLBAR
+# define QT_NO_TOOLBAR
+#endif
+#ifndef QT_NO_MENUBAR
+# define QT_NO_MENUBAR
+#endif
+#ifndef QT_NO_WORKSPACE
+# define QT_NO_WORKSPACE
+#endif
+#ifndef QT_NO_PROGRESSBAR
+# define QT_NO_PROGRESSBAR
+#endif
+#ifndef QT_NO_RESIZEHANDLER
+# define QT_NO_RESIZEHANDLER
+#endif
+#ifndef QT_NO_RUBBERBAND
+# define QT_NO_RUBBERBAND
+#endif
+#ifndef QT_NO_SPLITTER
+# define QT_NO_SPLITTER
+#endif
+#ifndef QT_NO_SIGNALMAPPER
+# define QT_NO_SIGNALMAPPER
+#endif
+#ifndef QT_NO_SIZEGRIP
+# define QT_NO_SIZEGRIP
+#endif
+#ifndef QT_NO_SLIDER
+# define QT_NO_SLIDER
+#endif
+#ifndef QT_NO_DIAL
+# define QT_NO_DIAL
+#endif
+#ifndef QT_NO_SCROLLBAR
+# define QT_NO_SCROLLBAR
+#endif
+#ifndef QT_NO_SCROLLAREA
+# define QT_NO_SCROLLAREA
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+# define QT_NO_GRAPHICSVIEW
+#endif
+#ifndef QT_NO_PRINTPREVIEWWIDGET
+# define QT_NO_PRINTPREVIEWWIDGET
+#endif
+#ifndef QT_NO_MDIAREA
+# define QT_NO_MDIAREA
+#endif
+#ifndef QT_NO_TEXTEDIT
+# define QT_NO_TEXTEDIT
+#endif
+#ifndef QT_NO_SYNTAXHIGHLIGHTER
+# define QT_NO_SYNTAXHIGHLIGHTER
+#endif
+#ifndef QT_NO_TEXTBROWSER
+# define QT_NO_TEXTBROWSER
+#endif
+#ifndef QT_NO_SPINWIDGET
+# define QT_NO_SPINWIDGET
+#endif
+#ifndef QT_NO_SPLASHSCREEN
+# define QT_NO_SPLASHSCREEN
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+# define QT_NO_STACKEDWIDGET
+#endif
+#ifndef QT_NO_TABWIDGET
+# define QT_NO_TABWIDGET
+#endif
+#ifndef QT_NO_STATUSBAR
+# define QT_NO_STATUSBAR
+#endif
+#ifndef QT_NO_STATUSTIP
+# define QT_NO_STATUSTIP
+#endif
+#ifndef QT_NO_TABLEWIDGET
+# define QT_NO_TABLEWIDGET
+#endif
+#ifndef QT_NO_TOOLBUTTON
+# define QT_NO_TOOLBUTTON
+#endif
+#ifndef QT_NO_TABBAR
+# define QT_NO_TABBAR
+#endif
+#ifndef QT_NO_TOOLBOX
+# define QT_NO_TOOLBOX
+#endif
+#ifndef QT_NO_WHATSTHIS
+# define QT_NO_WHATSTHIS
+#endif
+#ifndef QT_NO_TOOLTIP
+# define QT_NO_TOOLTIP
+#endif
+#ifndef QT_NO_TREEWIDGET
+# define QT_NO_TREEWIDGET
+#endif
+#ifndef QT_NO_VALIDATOR
+# define QT_NO_VALIDATOR
+#endif
+
+/* Windows */
+#ifndef QT_NO_WIN_ACTIVEQT
+# define QT_NO_WIN_ACTIVEQT
+#endif
diff --git a/src/corelib/global/qconfig-nacl.h b/src/corelib/global/qconfig-nacl.h
new file mode 100644
index 0000000000..a44391c1c9
--- /dev/null
+++ b/src/corelib/global/qconfig-nacl.h
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define QT_FONTS_ARE_RESOURCES
+
+/* Data structures */
+#ifndef QT_NO_QUUID_STRING
+# define QT_NO_QUUID_STRING
+#endif
+#ifndef QT_NO_STL
+# define QT_NO_STL
+#endif
+#ifndef QT_NO_TEXTDATE
+# define QT_NO_TEXTDATE
+#endif
+#ifndef QT_NO_DATESTRING
+# define QT_NO_DATESTRING
+#endif
+
+/* Dialogs */
+#ifndef QT_NO_FILEDIALOG
+# define QT_NO_FILEDIALOG
+#endif
+#ifndef QT_NO_PRINTDIALOG
+# define QT_NO_PRINTDIALOG
+#endif
+#ifndef QT_NO_PRINTPREVIEWDIALOG
+# define QT_NO_PRINTPREVIEWDIALOG
+#endif
+
+
+/* File I/O */
+#ifndef QT_NO_DOM
+# define QT_NO_DOM
+#endif
+#ifndef QT_NO_FILESYSTEMWATCHER
+# define QT_NO_FILESYSTEMWATCHER
+#endif
+#ifndef QT_NO_FSFILEENGINE
+# define QT_NO_FSFILEENGINE
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+# define QT_NO_FILESYSTEMMODEL
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+# define QT_NO_FILESYSTEMMODEL
+#endif
+#ifndef QT_NO_PROCESS
+# define QT_NO_PROCESS
+#endif
+#ifndef QT_NO_TEMPORARYFILE
+# define QT_NO_TEMPORARYFILE
+#endif
+#ifndef QT_NO_SETTINGS
+# define QT_NO_SETTINGS
+#endif
+#ifndef QT_NO_LIBRARY
+# define QT_NO_LIBRARY
+#endif
+
+/* Fonts */
+#ifndef QT_NO_QWS_QPF2
+# define QT_NO_QWS_QPF2
+#endif
+
+/* Images */
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+# define QT_NO_IMAGEFORMATPLUGIN
+#endif
+#ifndef QT_NO_IMAGE_HEURISTIC_MASK
+# define QT_NO_IMAGE_HEURISTIC_MASK
+#endif
+#ifndef QT_NO_IMAGE_TEXT
+# define QT_NO_IMAGE_TEXT
+#endif
+#ifndef QT_NO_MOVIE
+# define QT_NO_MOVIE
+#endif
+
+/* Internationalization */
+#ifndef QT_NO_BIG_CODECS
+# define QT_NO_BIG_CODECS
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+# define QT_NO_QWS_INPUTMETHODS
+#endif
+#ifndef QT_NO_TEXTCODEC
+# define QT_NO_TEXTCODEC
+#endif
+#ifndef QT_NO_CODECS
+# define QT_NO_CODECS
+#endif
+#ifndef QT_NO_TEXTCODECPLUGIN
+# define QT_NO_TEXTCODECPLUGIN
+#endif
+#ifndef QT_NO_TRANSLATION
+# define QT_NO_TRANSLATION
+#endif
+#ifndef QT_NO_TRANSLATION_UTF8
+# define QT_NO_TRANSLATION_UTF8
+#endif
+
+/* ItemViews */
+
+#ifndef QT_NO_DIRMODEL
+# define QT_NO_DIRMODEL
+#endif
+
+/* Kernel */
+#ifndef QT_NO_CLIPBOARD
+# define QT_NO_CLIPBOARD
+#endif
+#ifndef QT_NO_CSSPARSER
+# define QT_NO_CSSPARSER
+#endif
+#ifndef QT_NO_CURSOR
+# define QT_NO_CURSOR
+#endif
+#ifndef QT_NO_DRAGANDDROP
+# define QT_NO_DRAGANDDROP
+#endif
+#ifndef QT_NO_EFFECTS
+# define QT_NO_EFFECTS
+#endif
+#ifndef QT_NO_SESSIONMANAGER
+# define QT_NO_SESSIONMANAGER
+#endif
+#ifndef QT_NO_SHAREDMEMORY
+# define QT_NO_SHAREDMEMORY
+#endif
+#ifndef QT_NO_SOUND
+# define QT_NO_SOUND
+#endif
+#ifndef QT_NO_SYSTEMLOCALE
+# define QT_NO_SYSTEMSEMAPHORE
+#endif
+#ifndef QT_NO_SYSTEMSEMAPHORE
+# define QT_NO_SYSTEMSEMAPHORE
+#endif
+#ifndef QT_NO_TABLETEVENT
+# define QT_NO_TABLETEVENT
+#endif
+#ifndef QT_NO_CRASHHANDLER
+# define QT_NO_CRASHHANDLER
+#endif
+#ifndef QT_NO_CONCURRENT
+# define QT_NO_CONCURRENT
+#endif
+#ifndef QT_NO_XMLSTREAM
+# define QT_NO_XMLSTREAM
+#endif
+#ifndef QT_NO_XMLSTREAMREADER
+# define QT_NO_XMLSTREAMREADER
+#endif
+#ifndef QT_NO_XMLSTREAMWRITER
+# define QT_NO_XMLSTREAMWRITER
+#endif
+
+/* Networking */
+#ifndef QT_NO_COP
+# define QT_NO_COP
+#endif
+#ifndef QT_NO_HOSTINFO
+# define QT_NO_HOSTINFO
+#endif
+#ifndef QT_NO_HTTP
+# define QT_NO_HTTP
+#endif
+#ifndef QT_NO_NETWORKPROXY
+# define QT_NO_NETWORKPROXY
+#endif
+#ifndef QT_NO_SOCKS5
+# define QT_NO_SOCKS5
+#endif
+#ifndef QT_NO_UDPSOCKET
+# define QT_NO_UDPSOCKET
+#endif
+#ifndef QT_NO_URLINFO
+# define QT_NO_URLINFO
+#endif
+#ifndef QT_NO_FTP
+# define QT_NO_FTP
+#endif
+
+/* Painting */
+#ifndef QT_NO_COLORNAMES
+# define QT_NO_COLORNAMES
+#endif
+#ifndef QT_NO_DIRECTPAINTER
+# define QT_NO_DIRECTPAINTER
+#endif
+#ifndef QT_NO_PAINTONSCREEN
+# define QT_NO_PAINTONSCREEN
+#endif
+#ifndef QT_NO_PAINT_DEBUG
+# define QT_NO_PAINT_DEBUG
+#endif
+#ifndef QT_NO_PICTURE
+# define QT_NO_PICTURE
+#endif
+#ifndef QT_NO_PRINTER
+# define QT_NO_PRINTER
+#endif
+#ifndef QT_NO_CUPS
+# define QT_NO_CUPS
+#endif
+
+/* Qt for Embedded Linux */
+#ifndef QT_NO_QWSEMBEDWIDGET
+# define QT_NO_QWSEMBEDWIDGET
+#endif
+#ifndef QT_NO_QWS_ALPHA_CURSOR
+# define QT_NO_QWS_ALPHA_CURSOR
+#endif
+#ifndef QT_NO_QWS_CURSOR
+# define QT_NO_QWS_CURSOR
+#endif
+#ifndef QT_NO_QWS_DECORATION_DEFAULT
+# define QT_NO_QWS_DECORATION_DEFAULT
+#endif
+#ifndef QT_NO_QWS_DECORATION_STYLED
+# define QT_NO_QWS_DECORATION_STYLED
+#endif
+#ifndef QT_NO_QWS_DECORATION_WINDOWS
+# define QT_NO_QWS_DECORATION_WINDOWS
+#endif
+#ifndef QT_NO_QWS_MANAGER
+# define QT_NO_QWS_MANAGER
+#endif
+#ifndef QT_NO_QWS_KEYBOARD
+# define QT_NO_QWS_KEYBOARD
+#endif
+#ifndef QT_NO_QWS_MOUSE
+# define QT_NO_QWS_MOUSE
+#endif
+#ifndef QT_NO_QWS_MOUSE_AUTO
+# define QT_NO_QWS_MOUSE_AUTO
+#endif
+#ifndef QT_NO_QWS_MOUSE_MANUAL
+# define QT_NO_QWS_MOUSE_MANUAL
+#endif
+#ifndef QT_NO_QWS_MULTIPROCESS
+# define QT_NO_QWS_MULTIPROCESS
+#endif
+#ifndef QT_NO_QWS_SOUNDSERVER
+# define QT_NO_QWS_SOUNDSERVER
+#endif
+#ifndef QT_NO_SXE
+# define QT_NO_SXE
+#endif
+#ifndef QT_NO_QWS_PROPERTIES
+# define QT_NO_QWS_PROPERTIES
+#endif
+#ifndef QT_NO_QWS_PROXYSCREEN
+# define QT_NO_QWS_PROXYSCREEN
+#endif
+#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+#endif
+#ifndef QT_NO_QWS_LINUXFB
+# define QT_NO_QWS_LINUXFB
+#endif
+#ifndef QT_NO_QWS_MOUSE_PC
+# define QT_NO_QWS_MOUSE_PC
+#endif
+#ifndef QT_NO_QWS_MOUSE_LINUXTP
+# define QT_NO_QWS_MOUSE_LINUXTP
+#endif
+#ifndef QT_NO_QWS_QPF
+# define QT_NO_QWS_QPF
+#endif
+
+/* SVG */
+#ifndef QT_NO_SVG
+# define QT_NO_SVG
+#endif
+#ifndef QT_NO_GRAPHICSSVGITEM
+# define QT_NO_GRAPHICSSVGITEM
+#endif
+#ifndef QT_NO_SVGGENERATOR
+# define QT_NO_SVGGENERATOR
+#endif
+#ifndef QT_NO_SVGRENDERER
+# define QT_NO_SVGRENDERER
+#endif
+#ifndef QT_NO_SVGWIDGET
+# define QT_NO_SVGWIDGET
+#endif
+
+/* Styles */
+#ifndef QT_NO_STYLE_MOTIF
+# define QT_NO_STYLE_MOTIF
+#endif
+#ifndef QT_NO_STYLE_CDE
+# define QT_NO_STYLE_CDE
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+# define QT_NO_STYLE_STYLESHEET
+#endif
+#ifndef QT_NO_STYLE_WINDOWSCE
+# define QT_NO_STYLE_WINDOWSCE
+#endif
+#ifndef QT_NO_STYLE_WINDOWSMOBILE
+# define QT_NO_STYLE_WINDOWSMOBILE
+#endif
+#ifndef QT_NO_STYLE_WINDOWSVISTA
+# define QT_NO_STYLE_WINDOWSVISTA
+#endif
+#ifndef QT_NO_STYLE_WINDOWSXP
+# define QT_NO_STYLE_WINDOWSXP
+#endif
+
+/* Utilities */
+#ifndef QT_NO_ACCESSIBILITY
+# define QT_NO_ACCESSIBILITY
+#endif
+#ifndef QT_NO_COMPLETER
+# define QT_NO_COMPLETER
+#endif
+#ifndef QT_NO_DESKTOPSERVICES
+# define QT_NO_DESKTOPSERVICES
+#endif
+#ifndef QT_NO_SCRIPT
+# define QT_NO_SCRIPT
+#endif
+#ifndef QT_NO_SYSTEMTRAYICON
+# define QT_NO_SYSTEMTRAYICON
+#endif
+
+/* Windows */
+#ifndef QT_NO_WIN_ACTIVEQT
+# define QT_NO_WIN_ACTIVEQT
+#endif
diff --git a/src/corelib/global/qconfig-small.h b/src/corelib/global/qconfig-small.h
new file mode 100644
index 0000000000..b4ec6548e9
--- /dev/null
+++ b/src/corelib/global/qconfig-small.h
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Data structures */
+#ifndef QT_NO_QUUID_STRING
+# define QT_NO_QUUID_STRING
+#endif
+#ifndef QT_NO_STL
+# define QT_NO_STL
+#endif
+
+/* Dialogs */
+#ifndef QT_NO_COLORDIALOG
+# define QT_NO_COLORDIALOG
+#endif
+#ifndef QT_NO_ERRORMESSAGE
+# define QT_NO_ERRORMESSAGE
+#endif
+#ifndef QT_NO_FILEDIALOG
+# define QT_NO_FILEDIALOG
+#endif
+#ifndef QT_NO_FONTDIALOG
+# define QT_NO_FONTDIALOG
+#endif
+#ifndef QT_NO_INPUTDIALOG
+# define QT_NO_INPUTDIALOG
+#endif
+#ifndef QT_NO_MESSAGEBOX
+# define QT_NO_MESSAGEBOX
+#endif
+#ifndef QT_NO_PRINTDIALOG
+# define QT_NO_PRINTDIALOG
+#endif
+#ifndef QT_NO_PROGRESSDIALOG
+# define QT_NO_PROGRESSDIALOG
+#endif
+#ifndef QT_NO_TABDIALOG
+# define QT_NO_TABDIALOG
+#endif
+
+/* File I/O */
+#ifndef QT_NO_TEXTSTREAM
+# define QT_NO_TEXTSTREAM
+#endif
+#ifndef QT_NO_SETTINGS
+# define QT_NO_SETTINGS
+#endif
+#ifndef QT_NO_LIBRARY
+# define QT_NO_LIBRARY
+#endif
+
+/* Fonts */
+#ifndef QT_NO_FREETYPE
+# define QT_NO_FREETYPE
+#endif
+
+/* Images */
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+# define QT_NO_IMAGEFORMATPLUGIN
+#endif
+#ifndef QT_NO_IMAGEFORMAT_BMP
+# define QT_NO_IMAGEFORMAT_BMP
+#endif
+#ifndef QT_NO_IMAGEFORMAT_JPEG
+# define QT_NO_IMAGEFORMAT_JPEG
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+# define QT_NO_IMAGEFORMAT_PPM
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XBM
+# define QT_NO_IMAGEFORMAT_XBM
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XPM
+# define QT_NO_IMAGEFORMAT_XPM
+#endif
+#ifndef QT_NO_IMAGE_TEXT
+# define QT_NO_IMAGE_TEXT
+#endif
+#ifndef QT_NO_MOVIE
+# define QT_NO_MOVIE
+#endif
+
+/* Internationalization */
+#ifndef QT_NO_QWS_INPUTMETHODS
+# define QT_NO_QWS_INPUTMETHODS
+#endif
+#ifndef QT_NO_TEXTCODEC
+# define QT_NO_TEXTCODEC
+#endif
+#ifndef QT_NO_CODECS
+# define QT_NO_CODECS
+#endif
+#ifndef QT_NO_TEXTCODECPLUGIN
+# define QT_NO_TEXTCODECPLUGIN
+#endif
+#ifndef QT_NO_TRANSLATION
+# define QT_NO_TRANSLATION
+#endif
+#ifndef QT_NO_TRANSLATION_UTF8
+# define QT_NO_TRANSLATION_UTF8
+#endif
+
+/* ItemViews */
+#ifndef QT_NO_DIRMODEL
+# define QT_NO_DIRMODEL
+#endif
+#ifndef QT_NO_PROXYMODEL
+# define QT_NO_PROXYMODEL
+#endif
+#ifndef QT_NO_SORTFILTERPROXYMODEL
+# define QT_NO_SORTFILTERPROXYMODEL
+#endif
+#ifndef QT_NO_STRINGLISTMODEL
+# define QT_NO_STRINGLISTMODEL
+#endif
+#ifndef QT_NO_TABLEVIEW
+# define QT_NO_TABLEVIEW
+#endif
+#ifndef QT_NO_TREEVIEW
+# define QT_NO_TREEVIEW
+#endif
+
+/* Kernel */
+#ifndef QT_NO_ACTION
+# define QT_NO_ACTION
+#endif
+#ifndef QT_NO_CLIPBOARD
+# define QT_NO_CLIPBOARD
+#endif
+#ifndef QT_NO_DRAGANDDROP
+# define QT_NO_DRAGANDDROP
+#endif
+#ifndef QT_NO_EFFECTS
+# define QT_NO_EFFECTS
+#endif
+#ifndef QT_NO_PROPERTIES
+# define QT_NO_PROPERTIES
+#endif
+#ifndef QT_NO_SESSIONMANAGER
+# define QT_NO_SESSIONMANAGER
+#endif
+#ifndef QT_NO_SHORTCUT
+# define QT_NO_SHORTCUT
+#endif
+#ifndef QT_NO_SOUND
+# define QT_NO_SOUND
+#endif
+#ifndef QT_NO_WHEELEVENT
+# define QT_NO_WHEELEVENT
+#endif
+
+/* Networking */
+#ifndef QT_NO_COP
+# define QT_NO_COP
+#endif
+#ifndef QT_NO_HOSTINFO
+# define QT_NO_HOSTINFO
+#endif
+#ifndef QT_NO_HTTP
+# define QT_NO_HTTP
+#endif
+
+/* Painting */
+#ifndef QT_NO_COLORNAMES
+# define QT_NO_COLORNAMES
+#endif
+#ifndef QT_NO_PICTURE
+# define QT_NO_PICTURE
+#endif
+#ifndef QT_NO_PRINTER
+# define QT_NO_PRINTER
+#endif
+#ifndef QT_NO_CUPS
+# define QT_NO_CUPS
+#endif
+
+/* Qt for Embedded Linux */
+#ifndef QT_NO_QWS_SOUNDSERVER
+# define QT_NO_QWS_SOUNDSERVER
+#endif
+#ifndef QT_NO_QWS_PROPERTIES
+# define QT_NO_QWS_PROPERTIES
+#endif
+
+/* Styles */
+#ifndef QT_NO_STYLE_MOTIF
+# define QT_NO_STYLE_MOTIF
+#endif
+#ifndef QT_NO_STYLE_CDE
+# define QT_NO_STYLE_CDE
+#endif
+#ifndef QT_NO_STYLE_CLEANLOOKS
+# define QT_NO_STYLE_CLEANLOOKS
+#endif
+#ifndef QT_NO_STYLE_PLASTIQUE
+# define QT_NO_STYLE_PLASTIQUE
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+# define QT_NO_STYLE_STYLESHEET
+#endif
+#ifndef QT_NO_STYLE_WINDOWSXP
+# define QT_NO_STYLE_WINDOWSXP
+#endif
+
+/* Utilities */
+#ifndef QT_NO_COMPLETER
+# define QT_NO_COMPLETER
+#endif
+#ifndef QT_NO_DESKTOPSERVICES
+# define QT_NO_DESKTOPSERVICES
+#endif
+#ifndef QT_NO_SYSTEMTRAYICON
+# define QT_NO_SYSTEMTRAYICON
+#endif
+#ifndef QT_NO_GESTURES
+# define QT_NO_GESTURES
+#endif
+
+/* Widgets */
+#ifndef QT_NO_LCDNUMBER
+# define QT_NO_LCDNUMBER
+#endif
+#ifndef QT_NO_FONTCOMBOBOX
+# define QT_NO_FONTCOMBOBOX
+#endif
+#ifndef QT_NO_SPINBOX
+# define QT_NO_SPINBOX
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+# define QT_NO_CALENDARWIDGET
+#endif
+#ifndef QT_NO_DATETIMEEDIT
+# define QT_NO_DATETIMEEDIT
+#endif
+#ifndef QT_NO_MENU
+# define QT_NO_MENU
+#endif
+#ifndef QT_NO_CONTEXTMENU
+# define QT_NO_CONTEXTMENU
+#endif
+#ifndef QT_NO_MAINWINDOW
+# define QT_NO_MAINWINDOW
+#endif
+#ifndef QT_NO_DOCKWIDGET
+# define QT_NO_DOCKWIDGET
+#endif
+#ifndef QT_NO_TOOLBAR
+# define QT_NO_TOOLBAR
+#endif
+#ifndef QT_NO_MENUBAR
+# define QT_NO_MENUBAR
+#endif
+#ifndef QT_NO_WORKSPACE
+# define QT_NO_WORKSPACE
+#endif
+#ifndef QT_NO_PROGRESSBAR
+# define QT_NO_PROGRESSBAR
+#endif
+#ifndef QT_NO_SPLITTER
+# define QT_NO_SPLITTER
+#endif
+#ifndef QT_NO_SIZEGRIP
+# define QT_NO_SIZEGRIP
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+# define QT_NO_STACKEDWIDGET
+#endif
+#ifndef QT_NO_TABWIDGET
+# define QT_NO_TABWIDGET
+#endif
+#ifndef QT_NO_STATUSBAR
+# define QT_NO_STATUSBAR
+#endif
+#ifndef QT_NO_TABLEWIDGET
+# define QT_NO_TABLEWIDGET
+#endif
+#ifndef QT_NO_TOOLBUTTON
+# define QT_NO_TOOLBUTTON
+#endif
+#ifndef QT_NO_TABBAR
+# define QT_NO_TABBAR
+#endif
+#ifndef QT_NO_TOOLBOX
+# define QT_NO_TOOLBOX
+#endif
+#ifndef QT_NO_WHATSTHIS
+# define QT_NO_WHATSTHIS
+#endif
+#ifndef QT_NO_TOOLTIP
+# define QT_NO_TOOLTIP
+#endif
+#ifndef QT_NO_TREEWIDGET
+# define QT_NO_TREEWIDGET
+#endif
+#ifndef QT_NO_VALIDATOR
+# define QT_NO_VALIDATOR
+#endif
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
new file mode 100644
index 0000000000..566307b311
--- /dev/null
+++ b/src/corelib/global/qendian.h
@@ -0,0 +1,370 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QENDIAN_H
+#define QENDIAN_H
+
+#include <QtCore/qglobal.h>
+
+// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
+#include <stdlib.h>
+
+#ifdef __GLIBC__
+#include <byteswap.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*
+ * ENDIAN FUNCTIONS
+*/
+inline void qbswap_helper(const uchar *src, uchar *dest, int size)
+{
+ for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
+}
+
+/*
+ * qbswap(const T src, const uchar *dest);
+ * 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.
+*/
+template <typename T> inline void qbswap(const T src, uchar *dest)
+{
+ qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
+}
+
+// Used to implement a type-safe and alignment-safe copy operation
+// If you want to avoid the memcopy, you must write specializations for this function
+template <typename T> inline void qToUnaligned(const T src, uchar *dest)
+{
+ qMemCopy(dest, &src, sizeof(T));
+}
+
+/* T qFromLittleEndian(const uchar *src)
+ * This function will read a little-endian encoded value from \a src
+ * and return the value in host-endian encoding.
+ * There is no requirement that \a src must be aligned.
+*/
+#if defined Q_CC_SUN
+inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
+{
+ return 0
+ | src[0]
+ | src[1] * Q_UINT64_C(0x0000000000000100)
+ | src[2] * Q_UINT64_C(0x0000000000010000)
+ | src[3] * Q_UINT64_C(0x0000000001000000)
+ | src[4] * Q_UINT64_C(0x0000000100000000)
+ | src[5] * Q_UINT64_C(0x0000010000000000)
+ | src[6] * Q_UINT64_C(0x0001000000000000)
+ | src[7] * Q_UINT64_C(0x0100000000000000);
+}
+
+inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
+{
+ return 0
+ | src[0]
+ | src[1] * quint32(0x00000100)
+ | src[2] * quint32(0x00010000)
+ | src[3] * quint32(0x01000000);
+}
+
+inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
+{
+ return 0
+ | src[0]
+ | src[1] * 0x0100;
+}
+
+inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
+{ return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
+inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
+{ return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
+inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
+{ return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
+
+template <class T> inline T qFromLittleEndian(const uchar *src)
+{
+ return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
+}
+
+#else
+template <typename T> inline T qFromLittleEndian(const uchar *src);
+template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
+{
+ return 0
+ | src[0]
+ | src[1] * Q_UINT64_C(0x0000000000000100)
+ | src[2] * Q_UINT64_C(0x0000000000010000)
+ | src[3] * Q_UINT64_C(0x0000000001000000)
+ | src[4] * Q_UINT64_C(0x0000000100000000)
+ | src[5] * Q_UINT64_C(0x0000010000000000)
+ | src[6] * Q_UINT64_C(0x0001000000000000)
+ | src[7] * Q_UINT64_C(0x0100000000000000);
+}
+
+template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
+{
+ return 0
+ | src[0]
+ | src[1] * quint32(0x00000100)
+ | src[2] * quint32(0x00010000)
+ | src[3] * quint32(0x01000000);
+}
+
+template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
+{
+ return quint16(0
+ | src[0]
+ | src[1] * 0x0100);
+}
+
+// signed specializations
+template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
+{ return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
+
+template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
+{ return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
+
+template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
+{ return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
+#endif
+
+/* This function will read a big-endian (also known as network order) encoded value from \a src
+ * and return the value in host-endian encoding.
+ * There is no requirement that \a src must be aligned.
+*/
+#if defined Q_CC_SUN
+inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
+{
+ return 0
+ | src[7]
+ | src[6] * Q_UINT64_C(0x0000000000000100)
+ | src[5] * Q_UINT64_C(0x0000000000010000)
+ | src[4] * Q_UINT64_C(0x0000000001000000)
+ | src[3] * Q_UINT64_C(0x0000000100000000)
+ | src[2] * Q_UINT64_C(0x0000010000000000)
+ | src[1] * Q_UINT64_C(0x0001000000000000)
+ | src[0] * Q_UINT64_C(0x0100000000000000);
+}
+
+inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
+{
+ return 0
+ | src[3]
+ | src[2] * quint32(0x00000100)
+ | src[1] * quint32(0x00010000)
+ | src[0] * quint32(0x01000000);
+}
+
+inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
+{
+ return 0
+ | src[1]
+ | src[0] * 0x0100;
+}
+
+
+inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
+{ return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
+inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
+{ return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
+inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
+{ return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
+
+template <class T> inline T qFromBigEndian(const uchar *src)
+{
+ return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
+}
+
+#else
+template <class T> inline T qFromBigEndian(const uchar *src);
+template<>
+inline quint64 qFromBigEndian<quint64>(const uchar *src)
+{
+ return 0
+ | src[7]
+ | src[6] * Q_UINT64_C(0x0000000000000100)
+ | src[5] * Q_UINT64_C(0x0000000000010000)
+ | src[4] * Q_UINT64_C(0x0000000001000000)
+ | src[3] * Q_UINT64_C(0x0000000100000000)
+ | src[2] * Q_UINT64_C(0x0000010000000000)
+ | src[1] * Q_UINT64_C(0x0001000000000000)
+ | src[0] * Q_UINT64_C(0x0100000000000000);
+}
+
+template<>
+inline quint32 qFromBigEndian<quint32>(const uchar *src)
+{
+ return 0
+ | src[3]
+ | src[2] * quint32(0x00000100)
+ | src[1] * quint32(0x00010000)
+ | src[0] * quint32(0x01000000);
+}
+
+template<>
+inline quint16 qFromBigEndian<quint16>(const uchar *src)
+{
+ return quint16( 0
+ | src[1]
+ | src[0] * quint16(0x0100));
+}
+
+
+// signed specializations
+template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
+{ return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
+
+template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
+{ return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
+
+template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
+{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
+#endif
+/*
+ * T qbswap(T source).
+ * 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> T qbswap(T source);
+
+#ifdef __GLIBC__
+template <> inline quint64 qbswap<quint64>(quint64 source)
+{
+ return bswap_64(source);
+}
+template <> inline quint32 qbswap<quint32>(quint32 source)
+{
+ return bswap_32(source);
+}
+template <> inline quint16 qbswap<quint16>(quint16 source)
+{
+ return bswap_16(source);
+}
+#else
+template <> inline quint64 qbswap<quint64>(quint64 source)
+{
+ return 0
+ | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
+ | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
+ | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
+ | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
+ | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
+ | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
+ | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
+ | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
+}
+
+template <> inline quint32 qbswap<quint32>(quint32 source)
+{
+ return 0
+ | ((source & 0x000000ff) << 24)
+ | ((source & 0x0000ff00) << 8)
+ | ((source & 0x00ff0000) >> 8)
+ | ((source & 0xff000000) >> 24);
+}
+
+template <> inline quint16 qbswap<quint16>(quint16 source)
+{
+ return quint16( 0
+ | ((source & 0x00ff) << 8)
+ | ((source & 0xff00) >> 8) );
+}
+#endif // __GLIBC__
+
+// signed specializations
+template <> inline qint64 qbswap<qint64>(qint64 source)
+{
+ return qbswap<quint64>(quint64(source));
+}
+
+template <> inline qint32 qbswap<qint32>(qint32 source)
+{
+ return qbswap<quint32>(quint32(source));
+}
+
+template <> inline qint16 qbswap<qint16>(qint16 source)
+{
+ return qbswap<quint16>(quint16(source));
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+
+template <typename T> inline T qToBigEndian(T source)
+{ return source; }
+template <typename T> inline T qFromBigEndian(T source)
+{ return source; }
+template <typename T> inline T qToLittleEndian(T source)
+{ return qbswap<T>(source); }
+template <typename T> inline T qFromLittleEndian(T source)
+{ return qbswap<T>(source); }
+template <typename T> inline void qToBigEndian(T src, uchar *dest)
+{ qToUnaligned<T>(src, dest); }
+template <typename T> inline void qToLittleEndian(T src, uchar *dest)
+{ qbswap<T>(src, dest); }
+#else // Q_LITTLE_ENDIAN
+
+template <typename T> inline T qToBigEndian(T source)
+{ return qbswap<T>(source); }
+template <typename T> inline T qFromBigEndian(T source)
+{ return qbswap<T>(source); }
+template <typename T> inline T qToLittleEndian(T source)
+{ return source; }
+template <typename T> inline T qFromLittleEndian(T source)
+{ return source; }
+template <typename T> inline void qToBigEndian(T src, uchar *dest)
+{ qbswap<T>(src, dest); }
+template <typename T> inline void qToLittleEndian(T src, uchar *dest)
+{ qToUnaligned<T>(src, dest); }
+
+#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QENDIAN_H
diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc
new file mode 100644
index 0000000000..85d600d7a2
--- /dev/null
+++ b/src/corelib/global/qendian.qdoc
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtEndian>
+ \title Endian Conversion Functions
+ \ingroup funclists
+ \brief The <QtEndian> header provides functions to convert between
+ little and big endian representations of numbers.
+*/
+
+/*!
+ \fn T qFromBigEndian(const uchar *src)
+ \since 4.3
+ \relates <QtEndian>
+
+ Reads a big-endian number from memory location \a src and returns the number in the
+ host byte order representation.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will swap the byte order; otherwise it will just read from \a src.
+
+ \note Template type \c{T} can either be a qint16, qint32 or qint64. Other types of
+ integers, e.g., qlong, are not applicable.
+
+ There are no data alignment constraints for \a src.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn T qFromBigEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from big-endian byte order and returns the number in host byte order
+ representation of that number.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn T qFromLittleEndian(const uchar *src)
+ \since 4.3
+ \relates <QtEndian>
+
+ Reads a little-endian number from memory location \a src and returns the number in
+ the host byte order representation.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will swap the byte order; otherwise it will just read from \a src.
+
+ \note Template type \c{T} can either be a qint16, qint32 or qint64. Other types of
+ integers, e.g., qlong, are not applicable.
+
+ There are no data alignment constraints for \a src.
+
+ \sa qFromBigEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn T qFromLittleEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from little-endian byte order and returns the number in host byte
+ order representation of that number.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn void qToBigEndian(T src, uchar *dest)
+ \since 4.3
+ \relates <QtEndian>
+
+ Writes the number \a src with template type \c{T} to the memory location at \a dest
+ in big-endian byte order.
+
+ Note that template type \c{T} can only be an integer data type (signed or unsigned).
+
+ There are no data alignment constraints for \a dest.
+
+ \sa qFromBigEndian()
+ \sa qFromLittleEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn T qToBigEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from host byte order and returns the number in big-endian byte order
+ representation of that number.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn void qToLittleEndian(T src, uchar *dest)
+ \since 4.3
+ \relates <QtEndian>
+
+ Writes the number \a src with template type \c{T} to the memory location at \a dest
+ in little-endian byte order.
+
+ Note that template type \c{T} can only be an integer data type (signed or unsigned).
+
+ There are no data alignment constraints for \a dest.
+
+ \sa qFromBigEndian()
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+*/
+/*!
+ \fn T qToLittleEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from host byte order and returns the number in little-endian byte
+ order representation of that number.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+
diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h
new file mode 100644
index 0000000000..604d08a34b
--- /dev/null
+++ b/src/corelib/global/qfeatures.h
@@ -0,0 +1,893 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * All features and their dependencies.
+ *
+ * This list is generated from $QTDIR/src/corelib/global/qfeatures.txt
+ * by $QTSRCDIR/util/scripts/make_qfeatures_dot_h
+ */
+
+// QAction
+//#define QT_NO_ACTION
+
+// Big Codecs
+//#define QT_NO_BIG_CODECS
+
+// Color Names
+//#define QT_NO_COLORNAMES
+
+// QtConcurrent
+//#define QT_NO_CONCURRENT
+
+// QCopChannel
+//#define QT_NO_COP
+
+// CssParser
+//#define QT_NO_CSSPARSER
+
+// QCursor
+//#define QT_NO_CURSOR
+
+// QDesktopServices
+//#define QT_NO_DESKTOPSERVICES
+
+// QDirectPainter
+//#define QT_NO_DIRECTPAINTER
+
+// Document Object Model
+//#define QT_NO_DOM
+
+// Effects
+//#define QT_NO_EFFECTS
+
+// QFileSystemIterator
+//#define QT_NO_FILESYSTEMITERATOR
+
+// QFileSystemWatcher
+//#define QT_NO_FILESYSTEMWATCHER
+
+// Freetype Font Engine
+//#define QT_NO_FREETYPE
+
+// Gesture
+//#define QT_NO_GESTURES
+
+// QGroupBox
+//#define QT_NO_GROUPBOX
+
+// QImageIOPlugin
+//#define QT_NO_IMAGEFORMATPLUGIN
+
+// BMP Image Format
+//#define QT_NO_IMAGEFORMAT_BMP
+
+// JPEG Image Format
+//#define QT_NO_IMAGEFORMAT_JPEG
+
+// PNG Image Format
+//#define QT_NO_IMAGEFORMAT_PNG
+
+// PPM Image Format
+//#define QT_NO_IMAGEFORMAT_PPM
+
+// XBM Image Format
+//#define QT_NO_IMAGEFORMAT_XBM
+
+// QImage::createHeuristicMask()
+//#define QT_NO_IMAGE_HEURISTIC_MASK
+
+// Image Text
+//#define QT_NO_IMAGE_TEXT
+
+// QLCDNumber
+//#define QT_NO_LCDNUMBER
+
+// QLineEdit
+//#define QT_NO_LINEEDIT
+
+// QMessageBox
+//#define QT_NO_MESSAGEBOX
+
+// QMovie
+//#define QT_NO_MOVIE
+
+// QNetworkInterface
+//#define QT_NO_NETWORKINTERFACE
+
+// QNetworkProxy
+//#define QT_NO_NETWORKPROXY
+
+// Qt::WA_PaintOnScreen
+//#define QT_NO_PAINTONSCREEN
+
+// Painting Debug Utilities
+//#define QT_NO_PAINT_DEBUG
+
+// Phonon::AbstractMediaStream
+//#define QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+// Support for Audio Capture
+//#define QT_NO_PHONON_AUDIOCAPTURE
+
+// Phonon::Effect
+//#define QT_NO_PHONON_EFFECT
+
+// Phonon::MediaController
+//#define QT_NO_PHONON_MEDIACONTROLLER
+
+// Phonon::ObjectDescriptionModel
+//#define QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+// Phonon::VideoWidget
+//#define QT_NO_PHONON_VIDEO
+
+// QPicture
+//#define QT_NO_PICTURE
+
+// QProcess
+//#define QT_NO_PROCESS
+
+// QProgressBar
+//#define QT_NO_PROGRESSBAR
+
+// Properties
+//#define QT_NO_PROPERTIES
+
+// Universally Unique Identifier Convertion
+//#define QT_NO_QUUID_STRING
+
+// QWSEmbedWidget
+//#define QT_NO_QWSEMBEDWIDGET
+
+// Alpha Cursor
+//#define QT_NO_QWS_ALPHA_CURSOR
+
+// Decoration
+//#define QT_NO_QWS_DECORATION_DEFAULT
+
+// Keyboard
+//#define QT_NO_QWS_KEYBOARD
+
+// Mouse
+//#define QT_NO_QWS_MOUSE
+
+// Mouse (Auto)
+//#define QT_NO_QWS_MOUSE_AUTO
+
+// Mouse (Non-Auto)
+//#define QT_NO_QWS_MOUSE_MANUAL
+
+// Multi-Process
+//#define QT_NO_QWS_MULTIPROCESS
+
+// Properties
+//#define QT_NO_QWS_PROPERTIES
+
+// QProxyScreen
+//#define QT_NO_QWS_PROXYSCREEN
+
+// Qt Prerendered Font Format
+//#define QT_NO_QWS_QPF
+
+// Qt Prerendered Font Format 2
+//#define QT_NO_QWS_QPF2
+
+// Raster Paint Engine callback functions
+//#define QT_NO_RASTERCALLBACKS
+
+// Resize Handler
+//#define QT_NO_RESIZEHANDLER
+
+// QRubberBand
+//#define QT_NO_RUBBERBAND
+
+// Session Manager
+//#define QT_NO_SESSIONMANAGER
+
+// QSettings
+//#define QT_NO_SETTINGS
+
+// QSharedMemory
+//#define QT_NO_SHAREDMEMORY
+
+// QShortcut
+//#define QT_NO_SHORTCUT
+
+// QSignalMapper
+//#define QT_NO_SIGNALMAPPER
+
+// QSizeGrip
+//#define QT_NO_SIZEGRIP
+
+// QSlider
+//#define QT_NO_SLIDER
+
+// Sounds
+//#define QT_NO_SOUND
+
+// Spin Widget
+//#define QT_NO_SPINWIDGET
+
+// Splash screen widget
+//#define QT_NO_SPLASHSCREEN
+
+// QStackedWidget
+//#define QT_NO_STACKEDWIDGET
+
+// QStatusBar
+//#define QT_NO_STATUSBAR
+
+// Status Tip
+//#define QT_NO_STATUSTIP
+
+// Standard Template Library
+//#define QT_NO_STL
+
+// QMotifStyle
+//#define QT_NO_STYLE_MOTIF
+
+// QWindowsStyle
+//#define QT_NO_STYLE_WINDOWS
+
+// QSystemSemaphore
+//#define QT_NO_SYSTEMSEMAPHORE
+
+// QSystemTrayIcon
+//#define QT_NO_SYSTEMTRAYICON
+
+// QTabletEvent
+//#define QT_NO_TABLETEVENT
+
+// QTemporaryFile
+//#define QT_NO_TEMPORARYFILE
+
+// QTextCodec
+//#define QT_NO_TEXTCODEC
+
+// Text Date
+//#define QT_NO_TEXTDATE
+
+// HtmlParser
+//#define QT_NO_TEXTHTMLPARSER
+
+// QTextStream
+//#define QT_NO_TEXTSTREAM
+
+// QToolTip
+//#define QT_NO_TOOLTIP
+
+// Translation
+//#define QT_NO_TRANSLATION
+
+// QUdpSocket
+//#define QT_NO_UDPSOCKET
+
+// QUndoCommand
+//#define QT_NO_UNDOCOMMAND
+
+// QUrlInfo
+//#define QT_NO_URLINFO
+
+// QValidator
+//#define QT_NO_VALIDATOR
+
+// QWheelEvent
+//#define QT_NO_WHEELEVENT
+
+//
+//#define QT_NO_XMLSTREAM
+
+// Animation
+#if !defined(QT_NO_ANIMATION) && (defined(QT_NO_PROPERTIES))
+#define QT_NO_ANIMATION
+#endif
+
+// QButtonGroup
+#if !defined(QT_NO_BUTTONGROUP) && (defined(QT_NO_GROUPBOX))
+#define QT_NO_BUTTONGROUP
+#endif
+
+// QClipboard
+#if !defined(QT_NO_CLIPBOARD) && (defined(QT_NO_QWS_PROPERTIES))
+#define QT_NO_CLIPBOARD
+#endif
+
+// Codecs
+#if !defined(QT_NO_CODECS) && (defined(QT_NO_TEXTCODEC))
+#define QT_NO_CODECS
+#endif
+
+// QDate/QTime/QDateTime
+#if !defined(QT_NO_DATESTRING) && (defined(QT_NO_TEXTDATE))
+#define QT_NO_DATESTRING
+#endif
+
+// QDial
+#if !defined(QT_NO_DIAL) && (defined(QT_NO_SLIDER))
+#define QT_NO_DIAL
+#endif
+
+// QFileSystemModel
+#if !defined(QT_NO_FILESYSTEMMODEL) && (defined(QT_NO_FILESYSTEMWATCHER))
+#define QT_NO_FILESYSTEMMODEL
+#endif
+
+// QHostInfo
+#if !defined(QT_NO_HOSTINFO) && (defined(QT_NO_TEXTSTREAM))
+#define QT_NO_HOSTINFO
+#endif
+
+// XPM Image Format
+#if !defined(QT_NO_IMAGEFORMAT_XPM) && (defined(QT_NO_TEXTSTREAM))
+#define QT_NO_IMAGEFORMAT_XPM
+#endif
+
+// QLibrary
+#if !defined(QT_NO_LIBRARY) && (defined(QT_NO_SETTINGS))
+#define QT_NO_LIBRARY
+#endif
+
+// QMenu
+#if !defined(QT_NO_MENU) && (defined(QT_NO_ACTION))
+#define QT_NO_MENU
+#endif
+
+// QNetworkDiskCache
+#if !defined(QT_NO_NETWORKDISKCACHE) && (defined(QT_NO_TEMPORARYFILE))
+#define QT_NO_NETWORKDISKCACHE
+#endif
+
+// Phonon::SeekSlider
+#if !defined(QT_NO_PHONON_SEEKSLIDER) && (defined(QT_NO_SLIDER))
+#define QT_NO_PHONON_SEEKSLIDER
+#endif
+
+// Phonon::AbstractMediaStream
+#if !defined(QT_NO_PHONON_SETTINGSGROUP) && (defined(QT_NO_SETTINGS))
+#define QT_NO_PHONON_SETTINGSGROUP
+#endif
+
+// Phonon::VideoPlayer
+#if !defined(QT_NO_PHONON_VIDEOPLAYER) && (defined(QT_NO_PHONON_VIDEO))
+#define QT_NO_PHONON_VIDEOPLAYER
+#endif
+
+// Phonon::VolumeFaderEffect
+#if !defined(QT_NO_PHONON_VOLUMEFADEREFFECT) && (defined(QT_NO_PHONON_EFFECT))
+#define QT_NO_PHONON_VOLUMEFADEREFFECT
+#endif
+
+// QProgressDialog
+#if !defined(QT_NO_PROGRESSDIALOG) && (defined(QT_NO_PROGRESSBAR))
+#define QT_NO_PROGRESSDIALOG
+#endif
+
+// Cursor
+#if !defined(QT_NO_QWS_CURSOR) && (defined(QT_NO_CURSOR))
+#define QT_NO_QWS_CURSOR
+#endif
+
+// Decoration (Styled)
+#if !defined(QT_NO_QWS_DECORATION_STYLED) && (defined(QT_NO_QWS_DECORATION_DEFAULT))
+#define QT_NO_QWS_DECORATION_STYLED
+#endif
+
+// Decoration (Windows Style)
+#if !defined(QT_NO_QWS_DECORATION_WINDOWS) && (defined(QT_NO_QWS_DECORATION_DEFAULT))
+#define QT_NO_QWS_DECORATION_WINDOWS
+#endif
+
+// Dynamic screen transformation.
+#if !defined(QT_NO_QWS_DYNAMICSCREENTRANSFORMATION) && (defined(QT_NO_QWS_PROXYSCREEN))
+#define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+#endif
+
+// Manager
+#if !defined(QT_NO_QWS_MANAGER) && (defined(QT_NO_QWS_DECORATION_DEFAULT))
+#define QT_NO_QWS_MANAGER
+#endif
+
+// QVncTransformed
+#if !defined(QT_NO_QWS_TRANSFORMED) && (defined(QT_NO_QWS_PROXYSCREEN))
+#define QT_NO_QWS_TRANSFORMED
+#endif
+
+// QVncScreen
+#if !defined(QT_NO_QWS_VNC) && (defined(QT_NO_QWS_PROXYSCREEN))
+#define QT_NO_QWS_VNC
+#endif
+
+// QScrollBar
+#if !defined(QT_NO_SCROLLBAR) && (defined(QT_NO_SLIDER))
+#define QT_NO_SCROLLBAR
+#endif
+
+// SOCKS5
+#if !defined(QT_NO_SOCKS5) && (defined(QT_NO_NETWORKPROXY))
+#define QT_NO_SOCKS5
+#endif
+
+// QSoftKeyManager
+#if !defined(QT_NO_SOFTKEYMANAGER) && (defined(QT_NO_ACTION))
+#define QT_NO_SOFTKEYMANAGER
+#endif
+
+// QSplitter
+#if !defined(QT_NO_SPLITTER) && (defined(QT_NO_RUBBERBAND))
+#define QT_NO_SPLITTER
+#endif
+
+// State machine
+#if !defined(QT_NO_STATEMACHINE) && (defined(QT_NO_PROPERTIES))
+#define QT_NO_STATEMACHINE
+#endif
+
+// QCDEStyle
+#if !defined(QT_NO_STYLE_CDE) && (defined(QT_NO_STYLE_MOTIF))
+#define QT_NO_STYLE_CDE
+#endif
+
+// QWindowsXPStyle
+#if !defined(QT_NO_STYLE_WINDOWSXP) && (defined(QT_NO_STYLE_WINDOWS))
+#define QT_NO_STYLE_WINDOWSXP
+#endif
+
+// SXE
+#if !defined(QT_NO_SXE) && (defined(QT_NO_QWS_MULTIPROCESS))
+#define QT_NO_SXE
+#endif
+
+// QToolButton
+#if !defined(QT_NO_TOOLBUTTON) && (defined(QT_NO_ACTION))
+#define QT_NO_TOOLBUTTON
+#endif
+
+// QUndoStack
+#if !defined(QT_NO_UNDOSTACK) && (defined(QT_NO_UNDOCOMMAND))
+#define QT_NO_UNDOSTACK
+#endif
+
+// ActiveQt
+#if !defined(QT_NO_WIN_ACTIVEQT) && (defined(QT_NO_PROPERTIES))
+#define QT_NO_WIN_ACTIVEQT
+#endif
+
+// QWizard
+#if !defined(QT_NO_WIZARD) && (defined(QT_NO_PROPERTIES))
+#define QT_NO_WIZARD
+#endif
+
+// QXmlStreamReader
+#if !defined(QT_NO_XMLSTREAMREADER) && (defined(QT_NO_XMLSTREAM))
+#define QT_NO_XMLSTREAMREADER
+#endif
+
+// QXmlStreamWriter
+#if !defined(QT_NO_XMLSTREAMWRITER) && (defined(QT_NO_XMLSTREAM))
+#define QT_NO_XMLSTREAMWRITER
+#endif
+
+// Bearer Management
+#if !defined(QT_NO_BEARERMANAGEMENT) && (defined(QT_NO_LIBRARY))
+#define QT_NO_BEARERMANAGEMENT
+#endif
+
+// Context menu
+#if !defined(QT_NO_CONTEXTMENU) && (defined(QT_NO_MENU))
+#define QT_NO_CONTEXTMENU
+#endif
+
+// QtDBus module
+#if !defined(QT_NO_DBUS) && (defined(QT_NO_PROPERTIES) || defined(QT_NO_DOM))
+#define QT_NO_DBUS
+#endif
+
+// File Transfer Protocol
+#if !defined(QT_NO_FTP) && (defined(QT_NO_URLINFO) || defined(QT_NO_TEXTDATE))
+#define QT_NO_FTP
+#endif
+
+// QInputContext
+#if !defined(QT_NO_IM) && (defined(QT_NO_LIBRARY))
+#define QT_NO_IM
+#endif
+
+// Phonon::PlatformPlugin
+#if !defined(QT_NO_PHONON_PLATFORMPLUGIN) && (defined(QT_NO_LIBRARY))
+#define QT_NO_PHONON_PLATFORMPLUGIN
+#endif
+
+// QScrollArea
+#if !defined(QT_NO_SCROLLAREA) && (defined(QT_NO_SCROLLBAR))
+#define QT_NO_SCROLLAREA
+#endif
+
+// QWindowsVistaStyle
+#if !defined(QT_NO_STYLE_WINDOWSVISTA) && (defined(QT_NO_STYLE_WINDOWSXP))
+#define QT_NO_STYLE_WINDOWSVISTA
+#endif
+
+// QTabBar
+#if !defined(QT_NO_TABBAR) && (defined(QT_NO_TOOLBUTTON))
+#define QT_NO_TABBAR
+#endif
+
+// OdfWriter
+#if !defined(QT_NO_TEXTODFWRITER) && (defined(QT_NO_XMLSTREAMWRITER))
+#define QT_NO_TEXTODFWRITER
+#endif
+
+// Translation (UTF-8 representation)
+#if !defined(QT_NO_TRANSLATION_UTF8) && (defined(QT_NO_TRANSLATION) || defined(QT_NO_TEXTCODEC))
+#define QT_NO_TRANSLATION_UTF8
+#endif
+
+// QUndoGroup
+#if !defined(QT_NO_UNDOGROUP) && (defined(QT_NO_UNDOSTACK))
+#define QT_NO_UNDOGROUP
+#endif
+
+// QWhatsThis
+#if !defined(QT_NO_WHATSTHIS) && (defined(QT_NO_TOOLBUTTON))
+#define QT_NO_WHATSTHIS
+#endif
+
+// Drag and drop
+#if !defined(QT_NO_DRAGANDDROP) && (defined(QT_NO_QWS_PROPERTIES) || defined(QT_NO_IMAGEFORMAT_XPM))
+#define QT_NO_DRAGANDDROP
+#endif
+
+// QGraphicsView
+#if !defined(QT_NO_GRAPHICSVIEW) && (defined(QT_NO_SCROLLAREA))
+#define QT_NO_GRAPHICSVIEW
+#endif
+
+// Hyper Text Transfer Protocol
+#if !defined(QT_NO_HTTP) && defined(QT_NO_HOSTINFO)
+#define QT_NO_HTTP
+#endif
+
+// QMdiArea
+#if !defined(QT_NO_MDIAREA) && (defined(QT_NO_SCROLLAREA))
+#define QT_NO_MDIAREA
+#endif
+
+// Phonon::VolumeSlider
+#if !defined(QT_NO_PHONON_VOLUMESLIDER) && (defined(QT_NO_SLIDER) || defined(QT_NO_TOOLBUTTON))
+#define QT_NO_PHONON_VOLUMESLIDER
+#endif
+
+// QPrinter
+#if !defined(QT_NO_PRINTER) && (defined(QT_NO_TEXTSTREAM) || defined(QT_NO_PICTURE) || defined(QT_NO_TEMPORARYFILE))
+#define QT_NO_PRINTER
+#endif
+
+// QWSInputMethod
+#if !defined(QT_NO_QWS_INPUTMETHODS) && (defined(QT_NO_IM))
+#define QT_NO_QWS_INPUTMETHODS
+#endif
+
+// QSpinBox
+#if !defined(QT_NO_SPINBOX) && (defined(QT_NO_SPINWIDGET) || defined(QT_NO_LINEEDIT) || defined(QT_NO_VALIDATOR))
+#define QT_NO_SPINBOX
+#endif
+
+// QCleanLooksStyle
+#if !defined(QT_NO_STYLE_CLEANLOOKS) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM))
+#define QT_NO_STYLE_CLEANLOOKS
+#endif
+
+// QPlastiqueStyle
+#if !defined(QT_NO_STYLE_PLASTIQUE) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM))
+#define QT_NO_STYLE_PLASTIQUE
+#endif
+
+// QStyleSheetStyle
+#if !defined(QT_NO_STYLE_STYLESHEET) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_PROPERTIES) || defined(QT_NO_CSSPARSER))
+#define QT_NO_STYLE_STYLESHEET
+#endif
+
+// QWindowsCEStyle
+#if !defined(QT_NO_STYLE_WINDOWSCE) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM))
+#define QT_NO_STYLE_WINDOWSCE
+#endif
+
+// QWindowsMobileStyle
+#if !defined(QT_NO_STYLE_WINDOWSMOBILE) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM))
+#define QT_NO_STYLE_WINDOWSMOBILE
+#endif
+
+// QtSvg module
+#if !defined(QT_NO_SVG) && (defined(QT_NO_XMLSTREAMREADER) || defined(QT_NO_CSSPARSER))
+#define QT_NO_SVG
+#endif
+
+// Q3TabDialog
+#if !defined(QT_NO_TABDIALOG) && (defined(QT_NO_TABBAR))
+#define QT_NO_TABDIALOG
+#endif
+
+// QTextCodecPlugin
+#if !defined(QT_NO_TEXTCODECPLUGIN) && (defined(QT_NO_TEXTCODEC) || defined(QT_NO_LIBRARY))
+#define QT_NO_TEXTCODECPLUGIN
+#endif
+
+// QColorDialog
+#if !defined(QT_NO_COLORDIALOG) && (defined(QT_NO_SPINBOX))
+#define QT_NO_COLORDIALOG
+#endif
+
+// QGraphicsEffect
+#if !defined(QT_NO_GRAPHICSEFFECT) && (defined(QT_NO_GRAPHICSVIEW))
+#define QT_NO_GRAPHICSEFFECT
+#endif
+
+// The Model/View Framework
+#if !defined(QT_NO_ITEMVIEWS) && (defined(QT_NO_RUBBERBAND) || defined(QT_NO_SCROLLAREA))
+#define QT_NO_ITEMVIEWS
+#endif
+
+// QMenuBar
+#if !defined(QT_NO_MENUBAR) && (defined(QT_NO_MENU) || defined(QT_NO_TOOLBUTTON))
+#define QT_NO_MENUBAR
+#endif
+
+// Sound Server
+#if !defined(QT_NO_QWS_SOUNDSERVER) && (defined(QT_NO_SOUND) || defined(QT_NO_HOSTINFO) || defined(QT_NO_QWS_MULTIPROCESS))
+#define QT_NO_QWS_SOUNDSERVER
+#endif
+
+// QSvgGenerator
+#if !defined(QT_NO_SVGGENERATOR) && (defined(QT_NO_SVG))
+#define QT_NO_SVGGENERATOR
+#endif
+
+// QSvgRenderer
+#if !defined(QT_NO_SVGRENDERER) && (defined(QT_NO_SVG))
+#define QT_NO_SVGRENDERER
+#endif
+
+// QTabWidget
+#if !defined(QT_NO_TABWIDGET) && (defined(QT_NO_TABBAR) || defined(QT_NO_STACKEDWIDGET))
+#define QT_NO_TABWIDGET
+#endif
+
+// QTextEdit
+#if !defined(QT_NO_TEXTEDIT) && (defined(QT_NO_SCROLLAREA) || defined(QT_NO_PROPERTIES))
+#define QT_NO_TEXTEDIT
+#endif
+
+// QErrorMessage
+#if !defined(QT_NO_ERRORMESSAGE) && (defined(QT_NO_TEXTEDIT))
+#define QT_NO_ERRORMESSAGE
+#endif
+
+// QListView
+#if !defined(QT_NO_LISTVIEW) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_LISTVIEW
+#endif
+
+// QMainWindow
+#if !defined(QT_NO_MAINWINDOW) && (defined(QT_NO_MENU) || defined(QT_NO_RESIZEHANDLER) || defined(QT_NO_TOOLBUTTON))
+#define QT_NO_MAINWINDOW
+#endif
+
+// QAbstractProxyModel
+#if !defined(QT_NO_PROXYMODEL) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_PROXYMODEL
+#endif
+
+// QStandardItemModel
+#if !defined(QT_NO_STANDARDITEMMODEL) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_STANDARDITEMMODEL
+#endif
+
+// QStringListModel
+#if !defined(QT_NO_STRINGLISTMODEL) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_STRINGLISTMODEL
+#endif
+
+// QSvgWidget
+#if !defined(QT_NO_SVGWIDGET) && (defined(QT_NO_SVGRENDERER))
+#define QT_NO_SVGWIDGET
+#endif
+
+// QSyntaxHighlighter
+#if !defined(QT_NO_SYNTAXHIGHLIGHTER) && (defined(QT_NO_TEXTEDIT))
+#define QT_NO_SYNTAXHIGHLIGHTER
+#endif
+
+// QTableView
+#if !defined(QT_NO_TABLEVIEW) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_TABLEVIEW
+#endif
+
+// QTextBrowser
+#if !defined(QT_NO_TEXTBROWSER) && (defined(QT_NO_TEXTEDIT))
+#define QT_NO_TEXTBROWSER
+#endif
+
+// QToolBox
+#if !defined(QT_NO_TOOLBOX) && (defined(QT_NO_TOOLBUTTON) || defined(QT_NO_SCROLLAREA))
+#define QT_NO_TOOLBOX
+#endif
+
+// QTreeView
+#if !defined(QT_NO_TREEVIEW) && (defined(QT_NO_ITEMVIEWS))
+#define QT_NO_TREEVIEW
+#endif
+
+// Accessibility
+#if !defined(QT_NO_ACCESSIBILITY) && (defined(QT_NO_PROPERTIES) || defined(QT_NO_MENUBAR))
+#define QT_NO_ACCESSIBILITY
+#endif
+
+// QColumnView
+#if !defined(QT_NO_COLUMNVIEW) && (defined(QT_NO_LISTVIEW))
+#define QT_NO_COLUMNVIEW
+#endif
+
+// QCompleter
+#if !defined(QT_NO_COMPLETER) && (defined(QT_NO_PROXYMODEL))
+#define QT_NO_COMPLETER
+#endif
+
+// Common UNIX Printing System
+#if !defined(QT_NO_CUPS) && (defined(QT_NO_PRINTER) || defined(QT_NO_LIBRARY))
+#define QT_NO_CUPS
+#endif
+
+// QDataWidgetMapper
+#if !defined(QT_NO_DATAWIDGETMAPPER) && (defined(QT_NO_ITEMVIEWS) || defined(QT_NO_PROPERTIES))
+#define QT_NO_DATAWIDGETMAPPER
+#endif
+
+// QListWidget
+#if !defined(QT_NO_LISTWIDGET) && (defined(QT_NO_LISTVIEW))
+#define QT_NO_LISTWIDGET
+#endif
+
+// QSortFilterProxyModel
+#if !defined(QT_NO_SORTFILTERPROXYMODEL) && (defined(QT_NO_PROXYMODEL))
+#define QT_NO_SORTFILTERPROXYMODEL
+#endif
+
+// QTableWidget
+#if !defined(QT_NO_TABLEWIDGET) && (defined(QT_NO_TABLEVIEW))
+#define QT_NO_TABLEWIDGET
+#endif
+
+// QToolBar
+#if !defined(QT_NO_TOOLBAR) && (defined(QT_NO_MAINWINDOW))
+#define QT_NO_TOOLBAR
+#endif
+
+// QTreeWidget
+#if !defined(QT_NO_TREEWIDGET) && (defined(QT_NO_TREEVIEW))
+#define QT_NO_TREEWIDGET
+#endif
+
+// QDirModel
+#if !defined(QT_NO_DIRMODEL) && (defined(QT_NO_ITEMVIEWS) || defined(QT_NO_FILESYSTEMMODEL))
+#define QT_NO_DIRMODEL
+#endif
+
+// QDockwidget
+#if !defined(QT_NO_DOCKWIDGET) && (defined(QT_NO_RUBBERBAND) || defined(QT_NO_MAINWINDOW))
+#define QT_NO_DOCKWIDGET
+#endif
+
+// QUndoView
+#if !defined(QT_NO_UNDOVIEW) && (defined(QT_NO_UNDOSTACK) || defined(QT_NO_LISTVIEW))
+#define QT_NO_UNDOVIEW
+#endif
+
+// QCompleter
+#if !defined(QT_NO_FSCOMPLETER) && (defined(QT_NO_FILESYSTEMMODEL) || defined(QT_NO_COMPLETER))
+#define QT_NO_FSCOMPLETER
+#endif
+
+// QGraphicsSvgItem
+#if !defined(QT_NO_GRAPHICSSVGITEM) && (defined(QT_NO_SVGRENDERER) || defined(QT_NO_GRAPHICSVIEW))
+#define QT_NO_GRAPHICSSVGITEM
+#endif
+
+// QComboBox
+#if !defined(QT_NO_COMBOBOX) && (defined(QT_NO_LINEEDIT) || defined(QT_NO_STANDARDITEMMODEL) || defined(QT_NO_LISTVIEW))
+#define QT_NO_COMBOBOX
+#endif
+
+// QWorkSpace
+#if !defined(QT_NO_WORKSPACE) && (defined(QT_NO_SCROLLBAR) || defined(QT_NO_MAINWINDOW) || defined(QT_NO_MENUBAR))
+#define QT_NO_WORKSPACE
+#endif
+
+// QPrintPreviewWidget
+#if !defined(QT_NO_PRINTPREVIEWWIDGET) && (defined(QT_NO_GRAPHICSVIEW) || defined(QT_NO_PRINTER) || defined(QT_NO_MAINWINDOW))
+#define QT_NO_PRINTPREVIEWWIDGET
+#endif
+
+// QCalendarWidget
+#if !defined(QT_NO_CALENDARWIDGET) && (defined(QT_NO_TABLEVIEW) || defined(QT_NO_MENU) || defined(QT_NO_TEXTDATE) || defined(QT_NO_SPINBOX) || defined(QT_NO_TOOLBUTTON))
+#define QT_NO_CALENDARWIDGET
+#endif
+
+// QDateTimeEdit
+#if !defined(QT_NO_DATETIMEEDIT) && (defined(QT_NO_CALENDARWIDGET) || defined(QT_NO_DATESTRING))
+#define QT_NO_DATETIMEEDIT
+#endif
+
+// QInputDialog
+#if !defined(QT_NO_INPUTDIALOG) && (defined(QT_NO_COMBOBOX) || defined(QT_NO_SPINBOX) || defined(QT_NO_STACKEDWIDGET))
+#define QT_NO_INPUTDIALOG
+#endif
+
+// Phonon::EffectWidget
+#if !defined(QT_NO_PHONON_EFFECTWIDGET) && (defined(QT_NO_PHONON_EFFECT) || defined(QT_NO_COMBOBOX) || defined(QT_NO_SPINBOX))
+#define QT_NO_PHONON_EFFECTWIDGET
+#endif
+
+// QFontComboBox
+#if !defined(QT_NO_FONTCOMBOBOX) && (defined(QT_NO_COMBOBOX) || defined(QT_NO_STRINGLISTMODEL))
+#define QT_NO_FONTCOMBOBOX
+#endif
+
+// QFontDialog
+#if !defined(QT_NO_FONTDIALOG) && (defined(QT_NO_STRINGLISTMODEL) || defined(QT_NO_COMBOBOX) || defined(QT_NO_VALIDATOR) || defined(QT_NO_GROUPBOX))
+#define QT_NO_FONTDIALOG
+#endif
+
+// QPrintDialog
+#if !defined(QT_NO_PRINTDIALOG) && (defined(QT_NO_PRINTER) || defined(QT_NO_COMBOBOX) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_SPINBOX) || defined(QT_NO_TREEVIEW) || defined(QT_NO_TABWIDGET))
+#define QT_NO_PRINTDIALOG
+#endif
+
+// QFileDialog
+#if !defined(QT_NO_FILEDIALOG) && (defined(QT_NO_DIRMODEL) || defined(QT_NO_TREEVIEW) || defined(QT_NO_COMBOBOX) || defined(QT_NO_TOOLBUTTON) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_TOOLTIP) || defined(QT_NO_SPLITTER) || defined(QT_NO_STACKEDWIDGET) || defined(QT_NO_PROXYMODEL))
+#define QT_NO_FILEDIALOG
+#endif
+
+// QPrintPreviewDialog
+#if !defined(QT_NO_PRINTPREVIEWDIALOG) && (defined(QT_NO_PRINTPREVIEWWIDGET) || defined(QT_NO_PRINTDIALOG) || defined(QT_NO_TOOLBAR))
+#define QT_NO_PRINTPREVIEWDIALOG
+#endif
+
diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt
new file mode 100644
index 0000000000..6b861d4d17
--- /dev/null
+++ b/src/corelib/global/qfeatures.txt
@@ -0,0 +1,1487 @@
+# Kernel
+
+Feature: PROPERTIES
+Description: Supports scripting Qt-based applications.
+Section: Kernel
+Requires:
+Name: Properties
+SeeAlso: ???
+
+Feature: TEXTHTMLPARSER
+Description: Parser for HTML
+Section: Kernel
+Requires:
+Name: HtmlParser
+SeeAlso: ???
+
+Feature: TEXTODFWRITER
+Description: Provides an ODF writer
+Section: Kernel
+Requires: XMLSTREAMWRITER
+Name: OdfWriter
+SeeAlso: ???
+
+Feature: CSSPARSER
+Description: Parser for Style Sheets
+Section: Kernel
+Requires:
+Name: CssParser
+SeeAlso: ???
+
+Feature: CONCURRENT
+Description: Provides a high-level multi-threaded APIs
+Section: Kernel
+Requires:
+Name: QtConcurrent
+SeeAlso: ???
+
+Feature: DRAGANDDROP
+Description: Supports the drag and drop mechansim.
+Section: Kernel
+Requires: QWS_PROPERTIES IMAGEFORMAT_XPM
+Name: Drag and drop
+SeeAlso: ???
+
+Feature: SESSIONMANAGER
+Description: Supports session management.
+Section: Kernel
+Requires:
+Name: Session Manager
+SeeAlso: ???
+
+Feature: SHORTCUT
+Description: Supports keyboard accelerators and shortcuts.
+Section: Kernel
+Requires:
+Name: QShortcut
+SeeAlso: ???
+
+Feature: ACTION
+Description: Supports widget actions.
+Section: Kernel
+Requires:
+Name: QAction
+SeeAlso: ???
+
+Feature: SOFTKEYMANAGER
+Description: Supports softkeys.
+Section: Gui
+Requires: ACTION
+Name: QSoftKeyManager
+SeeAlso: ???
+
+Feature: CURSOR
+Description: Supports mouse cursors.
+Section: Kernel
+Requires:
+Name: QCursor
+SeeAlso: ???
+
+Feature: CLIPBOARD
+Description: Supports cut and paste operations.
+Section: Kernel
+Requires: QWS_PROPERTIES
+Name: QClipboard
+SeeAlso: ???
+
+Feature: WHEELEVENT
+Description: Supports wheel events.
+Section: Kernel
+Requires:
+Name: QWheelEvent
+SeeAlso: ???
+
+Feature: TABLETEVENT
+Description: Supports tablet events.
+Section: Kernel
+Requires:
+Name: QTabletEvent
+SeeAlso: ???
+
+Feature: SOUND
+Description: Supports playing audio files.
+Section: Kernel
+Requires:
+Name: Sounds
+SeeAlso: ???
+
+Feature: EFFECTS
+Description: Supports special widget effects (e.g. fading and scrolling).
+Section: Kernel
+Requires:
+Name: Effects
+SeeAlso: ???
+
+Feature: SHAREDMEMORY
+Description: Provides access to a shared memory segment.
+Section: Kernel
+Requires:
+Name: QSharedMemory
+SeeAlso: ???
+
+Feature: SYSTEMSEMAPHORE
+Description: Provides a general counting system semaphore.
+Section: Kernel
+Requires:
+Name: QSystemSemaphore
+SeeAlso: ???
+
+Feature: XMLSTREAM
+Description: Provides a simple streaming API for XML.
+Section: Kernel
+Requires:
+Name:
+SeeAlso: ???
+
+Feature: XMLSTREAMREADER
+Description: Provides a well-formed XML parser with a simple streaming API.
+Section: Kernel
+Requires: XMLSTREAM
+Name: QXmlStreamReader
+SeeAlso: ???
+
+Feature: XMLSTREAMWRITER
+Description: Provides a XML writer with a simple streaming API.
+Section: Kernel
+Requires: XMLSTREAM
+Name: QXmlStreamWriter
+SeeAlso: ???
+
+Feature: IM
+Description: Inputmethods with QInputContext
+Section: Kernel
+Requires: LIBRARY
+Name: QInputContext
+SeeAlso: ???
+# Data structures
+
+Feature: STL
+Description: Supports standard template library compatiblity.
+Section: Data structures
+Requires:
+Name: Standard Template Library
+SeeAlso: ???
+
+Feature: QUUID_STRING
+Description: Supports convertion between UUID and strings.
+Section: Data structures
+Requires:
+Name: Universally Unique Identifier Convertion
+SeeAlso: ???
+
+Feature: TEXTDATE
+Description: Supports month and day names in dates.
+Section: Data structures
+Requires:
+Name: Text Date
+SeeAlso: ???
+
+Feature: DATESTRING
+Description: Supports convertion between dates and strings.
+Section: Data structures
+Requires: TEXTDATE
+Name: QDate/QTime/QDateTime
+SeeAlso: ???
+
+# File I/O
+
+Feature: PROCESS
+Description: Supports external process invocation.
+Section: File I/O
+Requires:
+Name: QProcess
+SeeAlso: ???
+
+Feature: TEXTSTREAM
+Description: Supports reading and writing of text.
+Section: File I/O
+Requires:
+Name: QTextStream
+SeeAlso: ???
+
+Feature: TEMPORARYFILE
+Description: Provides an I/O device that operates on temporary files.
+Section: File I/O
+Requires:
+Name: QTemporaryFile
+SeeAlso: ???
+
+Feature: LIBRARY
+Description: Supports a shared library wrapper.
+Section: File I/O
+Requires: SETTINGS
+Name: QLibrary
+SeeAlso: ???
+
+Feature: SETTINGS
+Description: Supports persistent application settings.
+Section: File I/O
+Requires:
+Name: QSettings
+SeeAlso: ???
+
+Feature: DOM
+Description: Supports the Document Object Model.
+Section: File I/O
+Requires:
+Name: Document Object Model
+SeeAlso: ???
+
+Feature: FILESYSTEMMODEL
+Description: Provides a data model for the local filesystem.
+Section: File I/O
+Requires: FILESYSTEMWATCHER
+Name: QFileSystemModel
+SeeAlso: ???
+
+Feature: FILESYSTEMWATCHER
+Description: Provides an interface for monitoring files and directories
+for modications.
+Section: File I/O
+Requires:
+Name: QFileSystemWatcher
+SeeAlso: ???
+
+Feature: FILESYSTEMITERATOR
+Description: Provides fast file-system iteration.
+for modications.
+Section: File I/O
+Requires:
+Name: QFileSystemIterator
+SeeAlso: ???
+
+# Widgets
+
+Feature: TREEWIDGET
+Description: Supports views using tree models.
+Section: Widgets
+Requires: TREEVIEW
+Name: QTreeWidget
+SeeAlso: ???
+
+Feature: LISTWIDGET
+Description: Supports item-based list widgets.
+Section: Widgets
+Requires: LISTVIEW
+Name: QListWidget
+SeeAlso: ???
+
+Feature: TABLEWIDGET
+Description: Supports item-based table views.
+Section: Widgets
+Requires: TABLEVIEW
+Name: QTableWidget
+SeeAlso: ???
+
+Feature: DATETIMEEDIT
+Description: Supports editing dates and times.
+Section: Widgets
+Requires: CALENDARWIDGET DATESTRING
+Name: QDateTimeEdit
+SeeAlso: ???
+
+Feature: STACKEDWIDGET
+Description: Supports stacked widgets.
+Section: Widgets
+Requires:
+Name: QStackedWidget
+SeeAlso: ???
+
+Feature: TEXTBROWSER
+Description: Supports HTML document browsing.
+Section: Widgets
+Requires: TEXTEDIT
+Name: QTextBrowser
+SeeAlso: ???
+
+Feature: SPLASHSCREEN
+Description: Supports splash screens that can be shown during application startup.
+Section: Widgets
+Requires:
+Name: Splash screen widget
+SeeAlso: ???
+
+Feature: SPLITTER
+Description: Supports user controlled splitter widgets.
+Section: Widgets
+Requires: RUBBERBAND
+Name: QSplitter
+SeeAlso: ???
+
+Feature: LCDNUMBER
+Description: Supports LCD-like digits.
+Section: Widgets
+Requires:
+Name: QLCDNumber
+SeeAlso: ???
+
+Feature: MENU
+Description: Supports popup-menus.
+Section: Widgets
+Requires: ACTION
+Name: QMenu
+SeeAlso: ???
+
+Feature: LINEEDIT
+Description: Supports single-line edits.
+Section: Widgets
+Requires:
+Name: QLineEdit
+SeeAlso: ???
+
+Feature: SPINBOX
+Description: Supports spin boxes handling integers and discrete sets of values.
+Section: Widgets
+Requires: SPINWIDGET LINEEDIT VALIDATOR
+Name: QSpinBox
+SeeAlso: ???
+
+Feature: TABBAR
+Description: Supports tab bars, e.g. for use in tabbed dialogs.
+Section: Widgets
+Requires: TOOLBUTTON
+Name: QTabBar
+SeeAlso: ???
+
+Feature: TABWIDGET
+Description: Supports stacking tabbed widgets.
+Section: Widgets
+Requires: TABBAR STACKEDWIDGET
+Name: QTabWidget
+SeeAlso: ???
+
+Feature: COMBOBOX
+Description: Supports comboboxes presenting a list of options to the user.
+Section: Widgets
+Requires: LINEEDIT STANDARDITEMMODEL LISTVIEW
+Name: QComboBox
+SeeAlso: ???
+
+Feature: FONTCOMBOBOX
+Description: Supports a combobox that lets the user select a font family.
+Section: Widgets
+Requires: COMBOBOX STRINGLISTMODEL
+Name: QFontComboBox
+SeeAlso: ???
+
+Feature: TOOLBUTTON
+Description: Supports quick-access buttons to commands and options.
+Section: Widgets
+Requires: ACTION
+Name: QToolButton
+SeeAlso: ???
+
+Feature: TOOLBAR
+Description: Supports movable panels containing a set of controls.
+Section: Widgets
+Requires: MAINWINDOW
+Name: QToolBar
+SeeAlso: ???
+
+Feature: TOOLBOX
+Description: Supports columns of tabbed widget items.
+Section: Widgets
+Requires: TOOLBUTTON SCROLLAREA
+Name: QToolBox
+SeeAlso: ???
+
+Feature: GROUPBOX
+Description: Supports group box frames.
+Section: Widgets
+Requires:
+Name: QGroupBox
+SeeAlso: ???
+
+Feature: BUTTONGROUP
+Description: Supports organizing groups of button widgets.
+Section: Widgets
+Requires: GROUPBOX
+Name: QButtonGroup
+SeeAlso: ???
+
+Feature: MAINWINDOW
+Description: Supports main application windows.
+Section: Widgets
+Requires: MENU RESIZEHANDLER TOOLBUTTON
+Name: QMainWindow
+SeeAlso: ???
+
+Feature: DOCKWIDGET
+Description: Supports docking widgets inside a QMainWindow or floated as
+a top-level window on the desktop.
+Section: Widgets
+Requires: RUBBERBAND MAINWINDOW
+Name: QDockwidget
+SeeAlso: ???
+
+Feature: WORKSPACE
+Description: Supports workspace windows, e.g. used in an MDI application.
+Section: Widgets
+Requires: SCROLLBAR MAINWINDOW MENUBAR
+Name: QWorkSpace
+SeeAlso: ???
+
+Feature: MDIAREA
+Description: Provides an area in which MDI windows are displayed.
+Section: Widgets
+Requires: SCROLLAREA
+Name: QMdiArea
+SeeAlso: ???
+
+Feature: RESIZEHANDLER
+Description: Supports an internal resize handler.
+Section: Widgets
+Requires:
+Name: Resize Handler
+SeeAlso: ???
+
+Feature: STATUSBAR
+Description: Supports presentation of status information.
+Section: Widgets
+Requires:
+Name: QStatusBar
+SeeAlso: ???
+
+Feature: MENUBAR
+Description: Supports pull-down menu items.
+Section: Widgets
+Requires: MENU TOOLBUTTON
+Name: QMenuBar
+SeeAlso: ???
+
+Feature: CONTEXTMENU
+Description: Supports pop-up menus on right mouse click
+Section: Widgets
+Requires: MENU
+Name: Context menu
+SeeeAlso: ???
+
+Feature: PROGRESSBAR
+Description: Supports presentation of operation progress.
+Section: Widgets
+Requires:
+Name: QProgressBar
+SeeAlso: ???
+
+Feature: SLIDER
+Description: Supports sliders controlling a bounded value.
+Section: Widgets
+Requires:
+Name: QSlider
+SeeAlso: ???
+
+Feature: SCROLLBAR
+Description: Supports scrollbars allowing the user access parts of a
+document that is larger than the widget used to display it.
+Section: Widgets
+Requires: SLIDER
+Name: QScrollBar
+SeeAlso: ???
+
+Feature: DIAL
+Description: Supports rounded range control, e.g. like a speedometer.
+Section: Widgets
+Requires: SLIDER
+Name: QDial
+SeeAlso: ???
+
+Feature: SCROLLAREA
+Description: Supports scrolling views onto widgets.
+Section: Widgets
+Requires: SCROLLBAR
+Name: QScrollArea
+SeeAlso: ???
+
+Feature: GRAPHICSVIEW
+Description: Supports the graphicsview classes.
+Section: Widgets
+Requires: SCROLLAREA
+Name: QGraphicsView
+SeeAlso: ???
+
+Feature: GRAPHICSEFFECT
+Description: Supports the graphicseffect classes.
+Section: Widgets
+Requires: GRAPHICSVIEW
+Name: QGraphicsEffect
+SeeAlso: ???
+
+Feature: SPINWIDGET
+Description: Supports spinbox control widgets.
+Section: Widgets
+Requires:
+Name: Spin Widget
+SeeAlso: ???
+
+Feature: TEXTEDIT
+Description: Supports rich text editing.
+Section: Widgets
+Requires: SCROLLAREA PROPERTIES
+Name: QTextEdit
+SeeAlso: ???
+
+Feature: SYNTAXHIGHLIGHTER
+Description: Supports custom syntax highlighting.
+Section: Widgets
+Requires: TEXTEDIT
+Name: QSyntaxHighlighter
+SeeAlso: ???
+
+Feature: RUBBERBAND
+Description: Supports using rubberbands to indicate selections and boundaries.
+Section: Widgets
+Requires:
+Name: QRubberBand
+SeeAlso: ???
+
+Feature: TOOLTIP
+Description: Supports presentation of tooltips.
+Section: Widgets
+Requires:
+Name: QToolTip
+SeeAlso: ???
+
+Feature: STATUSTIP
+Description: Supports status tip functionality and events.
+Section: Widgets
+Requires:
+Name: Status Tip
+SeeAlso: ???
+
+Feature: SIGNALMAPPER
+Description: Supports bundling of signals from identifiable senders.
+Section: Widgets
+Requires:
+Name: QSignalMapper
+SeeAlso: ???
+
+Feature: WHATSTHIS
+Description: Supports displaying "What's this" help.
+Section: Widgets
+Requires: TOOLBUTTON
+Name: QWhatsThis
+SeeAlso: ???
+
+Feature: VALIDATOR
+Description: Supports validation of input text.
+Section: Widgets
+Requires:
+Name: QValidator
+SeeAlso: ???
+
+Feature: SIZEGRIP
+Description: Supports corner-grips for resizing a top-level windows.
+Section: Widgets
+Requires:
+Name: QSizeGrip
+SeeAlso: ???
+
+Feature: CALENDARWIDGET
+Description: Provides a monthly based calendar widget allowing the user to select
+a date.
+Section: Widgets
+Requires: TABLEVIEW MENU TEXTDATE SPINBOX TOOLBUTTON
+Name: QCalendarWidget
+SeeAlso: ???
+
+Feature: PRINTPREVIEWWIDGET
+Description: Provides a widget for previewing page layouts for printer output.
+a date.
+Section: Widgets
+Requires: GRAPHICSVIEW PRINTER MAINWINDOW
+Name: QPrintPreviewWidget
+SeeAlso: ???
+
+# Dialogs
+
+Feature: MESSAGEBOX
+Description: Supports message boxes displaying
+informative messages and simple questions.
+Section: Dialogs
+Requires:
+Name: QMessageBox
+SeeAlso: ???
+
+Feature: COLORDIALOG
+Description: Supports a dialog widget for specifying colors.
+Section: Dialogs
+Requires: SPINBOX
+Name: QColorDialog
+SeeAlso: ???
+
+Feature: FILEDIALOG
+Description: Supports a dialog widget for selecting files or directories.
+Section: Dialogs
+Requires: DIRMODEL TREEVIEW COMBOBOX TOOLBUTTON BUTTONGROUP TOOLTIP SPLITTER STACKEDWIDGET PROXYMODEL
+Name: QFileDialog
+SeeAlso: ???
+
+Feature: FONTDIALOG
+Description: Supports a dialog widget for selecting fonts.
+Section: Dialogs
+Requires: STRINGLISTMODEL COMBOBOX VALIDATOR GROUPBOX
+Name: QFontDialog
+SeeAlso: ???
+
+Feature: PRINTDIALOG
+Description: Supports a dialog widget for specifying printer configuration.
+Section: Dialogs
+Requires: PRINTER COMBOBOX BUTTONGROUP SPINBOX TREEVIEW TABWIDGET
+Name: QPrintDialog
+SeeAlso: ???
+
+Feature: PRINTPREVIEWDIALOG
+Description: Provides a dialog for previewing and configuring page layouts for printer output.
+Section: Dialogs
+Requires: PRINTPREVIEWWIDGET PRINTDIALOG TOOLBAR
+Name: QPrintPreviewDialog
+SeeAlso: ???
+
+Feature: PROGRESSDIALOG
+Description: Supports feedback on the progress of a slow operation.
+Section: Dialogs
+Requires: PROGRESSBAR
+Name: QProgressDialog
+SeeAlso: ???
+
+Feature: INPUTDIALOG
+Description: Supports a simple convenience dialog to get a single value from the user.
+Section: Dialogs
+Requires: COMBOBOX SPINBOX STACKEDWIDGET
+Name: QInputDialog
+SeeAlso: ???
+
+Feature: TABDIALOG
+Description: Supports a stack of tabbed widgets.
+Section: Dialogs
+Requires: TABBAR
+Name: Q3TabDialog
+SeeAlso: ???
+
+Feature: ERRORMESSAGE
+Description: Supports an error message display dialog.
+Section: Dialogs
+Requires: TEXTEDIT
+Name: QErrorMessage
+SeeAlso: ???
+
+Feature: WIZARD
+Description: Provides a framework for wizards.
+Section: Dialogs
+Requires: PROPERTIES
+Name: QWizard
+SeeAlso: ???
+
+# ItemViews
+
+Feature: ITEMVIEWS
+Description: Supports the model/view architecture managing the relationship
+between data and the way it is presented to the user.
+Section: ItemViews
+Requires: RUBBERBAND SCROLLAREA
+Name: The Model/View Framework
+SeeAlso: ???
+
+Feature: DIRMODEL
+Description: Supports a data model for the local filesystem.
+Section: ItemViews
+Requires: ITEMVIEWS FILESYSTEMMODEL
+Name: QDirModel
+SeeAlso: ???
+
+Feature: STANDARDITEMMODEL
+Description: Supports a generic model for storing custom data.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QStandardItemModel
+SeeAlso: ???
+
+Feature: PROXYMODEL
+Description: Supports processing of data passed between another model and a view.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QAbstractProxyModel
+SeeAlso: ???
+
+Feature: SORTFILTERPROXYMODEL
+Description: Supports sorting and filtering of data passed between
+another model and a view.
+Section: ItemViews
+Requires: PROXYMODEL
+Name: QSortFilterProxyModel
+SeeAlso: ???
+
+Feature: STRINGLISTMODEL
+Description: Supports a model that supplies strings to views.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QStringListModel
+SeeAlso: ???
+
+Feature: LISTVIEW
+Description: Supports a list or icon view onto a model.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QListView
+SeeAlso: ???
+
+Feature: TABLEVIEW
+Description: Supports a default model/view implementation of a table view.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QTableView
+SeeAlso: ???
+
+Feature: TREEVIEW
+Description: Supports a default model/view implementation of a tree view.
+Section: ItemViews
+Requires: ITEMVIEWS
+Name: QTreeView
+SeeAlso: ???
+
+Feature: DATAWIDGETMAPPER
+Description: Provides mapping between a section of a data model to widgets.
+Section: ItemViews
+Requires: ITEMVIEWS PROPERTIES
+Name: QDataWidgetMapper
+SeeAlso: ???
+
+Feature: COLUMNVIEW
+Description: Provides a model/view implementation of a column view.
+Section: ItemViews
+Requires: LISTVIEW
+Name: QColumnView
+SeeAlso: ???
+
+# Styles
+
+Feature: STYLE_WINDOWS
+Description: Supports a Microsoft Windows-like look and feel.
+Section: Styles
+Requires:
+Name: QWindowsStyle
+SeeAlso: ???
+
+Feature: STYLE_MOTIF
+Description: Supports a Motif look and feel.
+Section: Styles
+Requires:
+Name: QMotifStyle
+SeeAlso: ???
+
+Feature: STYLE_CDE
+Description: Supports a CDE look and feel.
+Section: Styles
+Requires: STYLE_MOTIF
+Name: QCDEStyle
+SeeAlso: ???
+
+Feature: STYLE_PLASTIQUE
+Description: Supports a widget style similar to the Plastik style available in KDE.
+Section: Styles
+Requires: STYLE_WINDOWS IMAGEFORMAT_XPM
+Name: QPlastiqueStyle
+SeeAlso: ???
+
+Feature: STYLE_WINDOWSXP
+Description: Supports a Microsoft WindowsXP-like look and feel.
+Section: Styles
+Requires: STYLE_WINDOWS
+Name: QWindowsXPStyle
+SeeAlso: ???
+
+Feature: STYLE_WINDOWSVISTA
+Description: Supports a Microsoft WindowsVista-like look and feel.
+Section: Styles
+Requires: STYLE_WINDOWSXP
+Name: QWindowsVistaStyle
+SeeAlso: ???
+
+Feature: STYLE_CLEANLOOKS
+Description: Supports a Gnome CleanLooks-like look and feel.
+Section: Styles
+Requires: STYLE_WINDOWS IMAGEFORMAT_XPM
+Name: QCleanLooksStyle
+SeeAlso: ???
+
+Feature: STYLE_WINDOWSCE
+Description: WindowsCE look and feel
+Section: Styles
+Requires: STYLE_WINDOWS IMAGEFORMAT_XPM
+Name: QWindowsCEStyle
+SeeAlso: ???
+
+Feature: STYLE_WINDOWSMOBILE
+Description: WindowsMobile look and feel
+Section: Styles
+Requires: STYLE_WINDOWS IMAGEFORMAT_XPM
+Name: QWindowsMobileStyle
+SeeAlso: ???
+
+Feature: STYLE_STYLESHEET
+Description:
+Section: Styles
+Requires: STYLE_WINDOWS PROPERTIES CSSPARSER
+Name: QStyleSheetStyle
+SeeAlso: ???
+
+# Images
+
+Feature: IMAGEFORMATPLUGIN
+Description: Supports writing an image format plugin.
+Section: Images
+Requires:
+Name: QImageIOPlugin
+SeeAlso: ???
+
+Feature: MOVIE
+Description: Supports animated images.
+Section: Images
+Requires:
+Name: QMovie
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_BMP
+Description: Supports Microsoft's Bitmap image file format.
+Section: Images
+Requires:
+Name: BMP Image Format
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_PPM
+Description: Supports the Portable Pixmap image file format.
+Section: Images
+Requires:
+Name: PPM Image Format
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_XBM
+Description: Supports the X11 Bitmap image file format.
+Section: Images
+Requires:
+Name: XBM Image Format
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_XPM
+Description: Supports the X11 Pixmap image file format.
+Section: Images
+Requires: TEXTSTREAM
+Name: XPM Image Format
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_PNG
+Description: Supports the Portable Network Graphics image file format.
+Section: Images
+Requires:
+Name: PNG Image Format
+SeeAlso: ???
+
+Feature: IMAGEFORMAT_JPEG
+Description: Supports the Joint Photographic Experts Group image file format.
+Section: Images
+Requires:
+Name: JPEG Image Format
+SeeAlso: ???
+
+Feature: IMAGE_HEURISTIC_MASK
+Description: Supports creating a 1-bpp heuristic mask for images.
+Section: Images
+Requires:
+Name: QImage::createHeuristicMask()
+SeeAlso: ???
+
+Feature: IMAGE_TEXT
+Description: Supports image file text strings.
+Section: Images
+Requires:
+Name: Image Text
+SeeAlso: ???
+
+# Painting
+
+Feature: DIRECTPAINTER
+Description: Supports direct access to the video hardware.
+Section: Painting
+Requires:
+Name: QDirectPainter
+SeeAlso: ???
+
+Feature: PICTURE
+Description: Supports recording and replaying QPainter commands.
+Section: Painting
+Requires:
+Name: QPicture
+SeeAlso: ???
+
+Feature: COLORNAMES
+Description: Supports color names such as "red", used by QColor
+and by some HTML documents.
+Section: Painting
+Requires:
+Name: Color Names
+SeeAlso: ???
+
+Feature: PRINTER
+Description: Supports printing
+Section: Painting
+Requires: TEXTSTREAM PICTURE TEMPORARYFILE
+Name: QPrinter
+SeeAlso: ???
+
+Feature: CUPS
+Description Supports the Common UNIX Printing System
+Section: Painting
+Requires: PRINTER LIBRARY
+Name: Common UNIX Printing System
+SeeAlso: ???
+
+Feature: PAINTONSCREEN
+Description: Supports the Qt::WA_PaintOnScreen widget attribute.
+Section: Painting
+Requires:
+Name: Qt::WA_PaintOnScreen
+SeeAlso: ???
+
+Feature: PAINT_DEBUG
+Description: Debug painting with the environment variables QT_FLUSH_UPDATE and QT_FLUSH_PAINT
+Section: Painting
+Requires:
+Name: Painting Debug Utilities
+SeeAlso: ???
+
+Feature: RASTERCALLBACKS
+Description: Supports subclassing the QPaintEngineRaster with callback functions.
+Section: Painting
+Requires:
+Name: Raster Paint Engine callback functions
+SeeAlso: ???
+
+# Fonts
+
+Feature: FREETYPE
+Description: Supports the FreeType 2 font engine (and its supported font formats).
+Section: Fonts
+Requires:
+Name: Freetype Font Engine
+SeeAlso: ???
+
+Feature: QWS_QPF
+Description: Supports Qt's pre-rendered fonts, a light-weight non-scalable font format
+specific to Qt for Embedded Linux.
+Section: Fonts
+Requires:
+Name: Qt Prerendered Font Format
+SeeAlso: ???
+
+Feature: QWS_QPF2
+Description: Supports Qt's second generation of pre-rendered fonts, a light-weight
+non-scalable font format specific to Qt for Embedded Linux.
+Section: Fonts
+Requires:
+Name: Qt Prerendered Font Format 2
+SeeAlso: ???
+
+# Internationalization
+
+Feature: TEXTCODECPLUGIN
+Description: Supports custom text codecs that can be loaded dynamically into applications.
+Section: Internationalization
+Requires: TEXTCODEC LIBRARY
+Name: QTextCodecPlugin
+SeeAlso: ???
+
+Feature: TRANSLATION
+Description: Supports translations using QObject::tr().
+Section: Internationalization
+Requires:
+Name: Translation
+SeeAlso: ???
+
+Feature: TRANSLATION_UTF8
+Description: Supports translations using QObject::trUtf8().
+Section: Internationalization
+Requires: TRANSLATION TEXTCODEC
+Name: Translation (UTF-8 representation)
+SeeAlso: ???
+
+Feature: TEXTCODEC
+Description: Supports conversions between text encodings.
+Section: Internationalization
+Requires:
+Name: QTextCodec
+SeeAlso: ???
+
+Feature: CODECS
+Description: Supports non-unicode text conversions.
+Section: Internationalization
+Requires: TEXTCODEC
+Name: Codecs
+SeeAlso: ???
+
+Feature: BIG_CODECS
+Description: Supports big codecs, e.g. CJK.
+Section: Internationalization
+Requires:
+Name: Big Codecs
+SeeAlso: ???
+
+Feature: QWS_INPUTMETHODS
+Description: Supports international input methods.
+Section: Internationalization
+Requires: IM
+Name: QWSInputMethod
+SeeAlso: ???
+
+# Networking
+
+Feature: URLINFO
+Description: Supports storage of URL information.
+Section: Networking
+Requires:
+Name: QUrlInfo
+SeeAlso: ???
+
+Feature: HOSTINFO
+Description: Supports host name lookups.
+Section: Networking
+Requires: TEXTSTREAM
+Name: QHostInfo
+SeeAlso: ???
+
+Feature: FTP
+Description: Supports FTP file access.
+Section: Networking
+Requires: URLINFO TEXTDATE
+Name: File Transfer Protocol
+SeeAlso: ???
+
+Feature: HTTP
+Description: Supports HTTP file access.
+Section: Networking
+Requires: HOSTINFO
+Name: Hyper Text Transfer Protocol
+SeeAlso: ???
+
+Feature: UDPSOCKET
+Description: Supports User Datagram Protocol sockets.
+Section: Networking
+Requires:
+Name: QUdpSocket
+SeeAlso: ???
+
+Feature: NETWORKPROXY
+Description: Supports configuring network layer proxy support to the Qt network classes.
+Section: Networking
+Requires:
+Name: QNetworkProxy
+SeeAlso: ???
+
+Feature: SOCKS5
+Description: Supports SOCKS v5 network proxy.
+Section: Networking
+Requires: NETWORKPROXY
+Name: SOCKS5
+SeeAlso: ???
+
+Feature: COP
+Description: Supports the QCOP protocol, which is a many-to-many
+communication protocol for transferring messages on various
+channels, and Inter Process Communications (IPC).
+Section: Networking
+Requires:
+Name: QCopChannel
+SeeAlso: ???
+
+Feature: NETWORKINTERFACE
+Description: Supports listing the host's IP addresses and network interfaces
+Section: Networking
+Requires:
+Name: QNetworkInterface
+SeeAlso: ???
+
+Feature: NETWORKDISKCACHE
+Description: Supports a disk cache for network resources
+Section: Networking
+Requires: TEMPORARYFILE
+Name: QNetworkDiskCache
+SeeAlso: ???
+
+Feature: BEARERMANAGEMENT
+Description: Provides bearer management support
+Section: Networking
+Requires: LIBRARY
+Name: Bearer Management
+SeeAlso: ???
+
+
+# Utilities
+
+Feature: COMPLETER
+Description: Provides completions based on an item model.
+Section: Utilities
+Requires: PROXYMODEL
+Name: QCompleter
+SeeAlso: ???
+
+Feature: FSCOMPLETER
+Description: Provides completions based on an item model.
+Section: Utilities
+Requires: FILESYSTEMMODEL COMPLETER
+Name: QCompleter
+SeeAlso: ???
+
+Feature: DESKTOPSERVICES
+Description: Provides methods for accessing common desktop services.
+Section: Utilities
+Requires:
+Name: QDesktopServices
+SeeAlso: ???
+
+Feature: SYSTEMTRAYICON
+Description: Provides an icon for an application in the system tray.
+Section: Utilities
+Requires:
+Name: QSystemTrayIcon
+SeeAlso: ???
+
+Feature: UNDOCOMMAND
+Description: Applies (redo or) undo of a single change in a document.
+Section: Utilities
+Requires:
+Name: QUndoCommand
+SeeAlso: ???
+
+Feature: UNDOSTACK
+Description: Provides the ability to (redo or) undo a list of changes in a document.
+Section: Utilities
+Requires: UNDOCOMMAND
+Name: QUndoStack
+SeeAlso: ???
+
+Feature: UNDOGROUP
+Description:
+Section: Utilities
+Requires: UNDOSTACK
+Name: QUndoGroup
+SeeAlso: ???
+
+Feature: UNDOVIEW
+Description: A widget which shows the contents of an undo stack.
+Section: Utilities
+Requires: UNDOSTACK LISTVIEW
+Name: QUndoView
+SeeAlso: ???
+
+Feature: ACCESSIBILITY
+Description: Provides accessibility support.
+Section: Utilities
+Requires: PROPERTIES MENUBAR
+Name: Accessibility
+SeeAlso: ???
+
+Feature: ANIMATION
+Description: Provides a framework for animations.
+Section: Utilities
+Requires: PROPERTIES
+Name: Animation
+SeeAlso: ???
+
+Feature: STATEMACHINE
+Description: Provides hierarchical finite state machines.
+Section: Utilities
+Requires: PROPERTIES
+Name: State machine
+SeeAlso: ???
+
+Feature: GESTURES
+Description: Provides a framework for gestures.
+Section: Utilities
+Requires:
+Name: Gesture
+SeeAlso: ???
+
+# SVG
+
+Feature: SVG
+Description: Provides classes for displaying the contents of SVG files.
+Section: SVG
+Requires: XMLSTREAMREADER CSSPARSER
+Name: QtSvg module
+SeeAlso: ???
+
+Feature: GRAPHICSSVGITEM
+Description: Provides a QGraphicsItem that can be used to render the contents of SVG files.
+Section: SVG
+Requires: SVGRENDERER GRAPHICSVIEW
+Name: QGraphicsSvgItem
+SeeAlso: ???
+
+Feature: SVGGENERATOR
+Description: Provides a paint device that is used to create SVG drawings.
+Section: SVG
+Requires: SVG
+Name: QSvgGenerator
+SeeAlso: ???
+
+Feature: SVGRENDERER
+Description: Provides a class used to draw the contents of SVG files onto paint devices.
+Section: SVG
+Requires: SVG
+Name: QSvgRenderer
+SeeAlso: ???
+
+Feature: SVGWIDGET
+Description: Provides a widget that is used to display the contents of SVG files.
+Section: SVG
+Requires: SVGRENDERER
+Name: QSvgWidget
+SeeAlso: ???
+
+
+# Qt for Embedded Linux
+
+Feature: QWS_SOUNDSERVER
+Description: Supports servers playing sounds.
+Section: Qt for Embedded Linux
+Requires: SOUND HOSTINFO QWS_MULTIPROCESS
+Name: Sound Server
+SeeAlso: ???
+
+Feature: QWS_MULTIPROCESS
+Description: Supports multi-process architecture.
+Section: Qt for Embedded Linux
+Requires:
+Name: Multi-Process
+SeeAlso: ???
+
+Feature: QWS_KEYBOARD
+Description: Supports the console keyboard.
+Section: Qt for Embedded Linux
+Requires:
+Name: Keyboard
+SeeAlso: ???
+
+Feature: QWS_CURSOR
+Description: Supports visible cursors.
+Section: Qt for Embedded Linux
+Requires: CURSOR
+Name: Cursor
+SeeAlso: ???
+
+Feature: QWS_ALPHA_CURSOR
+Description: Supports alpha-blended cursors.
+Section: Qt for Embedded Linux
+Requires:
+Name: Alpha Cursor
+SeeAlso: ???
+
+Feature: QWS_MANAGER
+Description: Supports the window manager.
+Section: Qt for Embedded Linux
+Requires: QWS_DECORATION_DEFAULT
+Name: Manager
+SeeAlso: ???
+
+Feature: QWS_DECORATION_DEFAULT
+Description: Supports default decoration of the top level windows.
+Section: Qt for Embedded Linux
+Requires:
+Name: Decoration
+SeeAlso: ???
+
+Feature: QWS_DECORATION_WINDOWS
+Description: Supports a "Windows" style decoration of the top level windows.
+Section: Qt for Embedded Linux
+Requires: QWS_DECORATION_DEFAULT
+Name: Decoration (Windows Style)
+SeeAlso: ???
+
+Feature: QWS_DECORATION_STYLED
+Description: Supports styled decoration of the top level windows.
+Section: Qt for Embedded Linux
+Requires: QWS_DECORATION_DEFAULT
+Name: Decoration (Styled)
+SeeAlso: ???
+
+Feature: QWS_MOUSE
+Description: Supports mouse drivers.
+Section: Qt for Embedded Linux
+Requires:
+Name: Mouse
+SeeAlso: ???
+
+Feature: QWS_MOUSE_AUTO
+Description: Supports auto-detected mouse drivers.
+Section: Qt for Embedded Linux
+Requires:
+Name: Mouse (Auto)
+SeeAlso: ???
+
+Feature: QWS_MOUSE_MANUAL
+Description: Supports non-autodetected mouse drivers.
+Section: Qt for Embedded Linux
+Requires:
+Name: Mouse (Non-Auto)
+SeeAlso: ???
+
+Feature: QWS_PROPERTIES
+Description: Supports window system properties.
+Section: Qt for Embedded Linux
+Requires:
+Name: Properties
+SeeAlso: ???
+
+Feature: SXE
+Description: Supports Safe Execution Environment (experimental).
+Section: Qt for Embedded Linux
+Requires: QWS_MULTIPROCESS
+Name: SXE
+SeeAlso: ???
+
+Feature: QWSEMBEDWIDGET
+Description: Provides embedding of a top-level window.
+Section: Qt for Embedded Linux
+Requires:
+Name: QWSEmbedWidget
+SeeAlso: ???
+
+Feature: QWS_PROXYSCREEN
+Description: Provides a proxy helper class used by some screen drivers.
+Section: Qt for Embedded Linux
+Requires:
+Name: QProxyScreen
+SeeAlso: ???
+
+Feature: QWS_VNC
+Description: Provides VNC screen driver
+Section: Qt for Embedded Linux
+Requires: QWS_PROXYSCREEN
+Name: QVncScreen
+SeeAlso: ???
+
+Feature: QWS_TRANSFORMED
+Description: Provides Transformed screen driver
+Section: Qt for Embedded Linux
+Requires: QWS_PROXYSCREEN
+Name: QVncTransformed
+SeeAlso: ???
+
+Feature: QWS_DYNAMICSCREENTRANSFORMATION
+Description: Enables dynamic setting of screen transformation/rotation.
+Section: Qt for Embedded Linux
+Requires: QWS_PROXYSCREEN
+Name: Dynamic screen transformation.
+SeeAlso: ???
+
+# Windows
+
+Feature: WIN_ACTIVEQT
+Description: Support for ActiveQt
+Section: Windows
+Requires: PROPERTIES
+Name: ActiveQt
+SeeAlso: ???
+
+# D-Bus
+
+Feature: DBUS
+Description: Provides classes for D-Bus.
+Section: D-Bus
+Requires: PROPERTIES DOM
+Name: QtDBus module
+SeeAlso: ???
+
+# Phonon
+
+Feature: PHONON_PLATFORMPLUGIN
+Description: Support for platform plugin
+Section: Phonon
+Requires: LIBRARY
+Name: Phonon::PlatformPlugin
+SeeAlso: ???
+
+Feature: PHONON_EFFECT
+Description: Support for Audio Effect
+Section: Phonon
+Requires:
+Name: Phonon::Effect
+SeeAlso: ???
+
+Feature: PHONON_AUDIOCAPTURE
+Description: Support for Audio Capture
+Section: Phonon
+Requires:
+Name: Support for Audio Capture
+SeeAlso: ???
+
+Feature: PHONON_EFFECTWIDGET
+Description: Support for Audio Effect Widget
+Section: Phonon
+Requires: PHONON_EFFECT COMBOBOX SPINBOX
+Name: Phonon::EffectWidget
+SeeAlso: ???
+
+Feature: PHONON_VOLUMEFADEREFFECT
+Description: Support for Volume Fader Effect class
+Section: Phonon
+Requires: PHONON_EFFECT
+Name: Phonon::VolumeFaderEffect
+SeeAlso: ???
+
+
+Feature: PHONON_OBJECTDESCRIPTIONMODEL
+Description: Support for Object Description Model
+Section: Phonon
+Requires:
+Name: Phonon::ObjectDescriptionModel
+SeeAlso: ???
+
+Feature: PHONON_VIDEO
+Description: Support for Video
+Section: Phonon
+Requires:
+Name: Phonon::VideoWidget
+SeeAlso: ???
+
+Feature: PHONON_VIDEOPLAYER
+Description: Support for the Video Player class
+Section: Phonon
+Requires: PHONON_VIDEO
+Name: Phonon::VideoPlayer
+SeeAlso: ???
+
+
+Feature: PHONON_SEEKSLIDER
+Description: Support for the Seek Slider class
+Section: Phonon
+Requires: SLIDER
+Name: Phonon::SeekSlider
+SeeAlso: ???
+
+Feature: PHONON_VOLUMESLIDER
+Description: Support for the Volume Slider class
+Section: Phonon
+Requires: SLIDER TOOLBUTTON
+Name: Phonon::VolumeSlider
+SeeAlso: ???
+
+Feature: PHONON_MEDIACONTROLLER
+Description: Support for the MediaController class
+Section: Phonon
+Requires:
+Name: Phonon::MediaController
+SeeAlso: ???
+
+Feature: PHONON_ABSTRACTMEDIASTREAM
+Description: Support for streaming of raw data (QIODevice...)
+Section: Phonon
+Requires:
+Name: Phonon::AbstractMediaStream
+SeeAlso: ???
+
+Feature: PHONON_SETTINGSGROUP
+Description: Phonon settingsgroup
+Section: Phonon
+Requires: SETTINGS
+Name: Phonon::AbstractMediaStream
+SeeAlso: ???
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
new file mode 100644
index 0000000000..a6b9bddcc4
--- /dev/null
+++ b/src/corelib/global/qglobal.cpp
@@ -0,0 +1,3653 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qstring.h"
+#include "qvector.h"
+#include "qlist.h"
+#include "qthreadstorage.h"
+#include "qdir.h"
+#include "qstringlist.h"
+#include "qdatetime.h"
+
+#ifndef QT_NO_QOBJECT
+#include <private/qthread_p.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifndef QT_NO_EXCEPTIONS
+# include <string>
+# include <exception>
+#endif
+
+#if !defined(Q_OS_WINCE)
+# include <errno.h>
+# if defined(Q_CC_MSVC)
+# include <crtdbg.h>
+# endif
+#endif
+
+#if defined(Q_OS_VXWORKS)
+# include <envLib.h>
+#endif
+
+#if defined(Q_OS_MACX) && !defined(QT_NO_CORESERVICES)
+#include <CoreServices/CoreServices.h>
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+#include <e32def.h>
+#include <e32debug.h>
+#include <f32file.h>
+#include <e32math.h>
+# include "private/qcore_symbian_p.h"
+
+_LIT(qt_S60Filter, "Series60v?.*.sis");
+_LIT(qt_symbianSystemInstallDir, "z:\\system\\install\\");
+#endif
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QFlag
+ \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 given \a value.
+*/
+
+/*!
+ \fn QFlag::operator int() const
+
+ Returns the value stored by the QFlag object.
+*/
+
+/*!
+ \class QFlags
+ \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 0, is legal:
+
+ \snippet doc/src/snippets/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 doc/src/snippets/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_FLAGS() macro must
+ be used:
+
+ \snippet doc/src/snippets/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::enum_type
+
+ Typedef for the Enum template type.
+*/
+
+/*!
+ \fn QFlags::QFlags(const QFlags &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QFlags::QFlags(Enum flag)
+
+ Constructs a QFlags object storing the given \a flag.
+*/
+
+/*!
+ \fn QFlags::QFlags(Zero zero)
+
+ Constructs a QFlags object with no flags set. \a zero must be a
+ literal 0 value.
+*/
+
+/*!
+ \fn QFlags::QFlags(QFlag value)
+
+ Constructs a QFlags object initialized with the given integer \a
+ value.
+
+ 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 QFlags &QFlags::operator=(const QFlags &other)
+
+ Assigns \a other to this object and returns a reference to this
+ object.
+*/
+
+/*!
+ \fn QFlags &QFlags::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 QFlags &QFlags::operator&=(uint mask)
+
+ \overload
+*/
+
+/*!
+ \fn QFlags &QFlags::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 QFlags &QFlags::operator|=(Enum other)
+
+ \overload
+*/
+
+/*!
+ \fn QFlags &QFlags::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 QFlags &QFlags::operator^=(Enum other)
+
+ \overload
+*/
+
+/*!
+ \fn QFlags::operator int() const
+
+ Returns the value stored in the QFlags object as an integer.
+*/
+
+/*!
+ \fn QFlags QFlags::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 QFlags QFlags::operator|(Enum other) const
+
+ \overload
+*/
+
+/*!
+ \fn QFlags QFlags::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 QFlags QFlags::operator^(Enum other) const
+
+ \overload
+*/
+
+/*!
+ \fn QFlags QFlags::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 QFlags QFlags::operator&(uint mask) const
+
+ \overload
+*/
+
+/*!
+ \fn QFlags QFlags::operator&(Enum mask) const
+
+ \overload
+*/
+
+/*!
+ \fn QFlags QFlags::operator~() const
+
+ Returns a QFlags object that contains the bitwise negation of
+ this object.
+
+ \sa operator&(), operator|(), operator^()
+*/
+
+/*!
+ \fn bool QFlags::operator!() const
+
+ Returns true if no flag is set (i.e., if the value stored by the
+ QFlags object is 0); otherwise returns false.
+*/
+
+/*!
+ \fn bool QFlags::testFlag(Enum flag) const
+ \since 4.2
+
+ Returns true if the \a flag is set, otherwise false.
+*/
+
+/*!
+ \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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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}.
+*/
+
+/*!
+ \macro Q_DECLARE_FLAGS(Flags, Enum)
+ \relates QFlags
+
+ The Q_DECLARE_FLAGS() macro expands to
+
+ \snippet doc/src/snippets/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()
+*/
+
+/*!
+ \headerfile <QtGlobal>
+ \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, \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;
+ QtMsgHandler is a type definition for a pointer to a function with
+ the signature \c {void myMsgHandler(QtMsgType, const char *)}.
+
+ \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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 3
+
+ <QtGlobal> also contains functions that generate messages from the
+ given string argument: qCritical(), qDebug(), qFatal() and
+ qWarning(). These functions call the message handler with the
+ given message.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 4
+
+ The remaining functions are qRound() and qRound64(), which both
+ accept a \l qreal value as their argument returning the value
+ rounded up to the nearest integer and 64-bit integer respectively,
+ the qInstallMsgHandler() function which installs the given
+ QtMsgHandler, 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_X11 which is defined for the X Window System.
+
+ 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_TRANSLATE_NOOP() and QT_TR_NOOP() macros provide the
+ possibility of marking text for dynamic translation,
+ i.e. translation without changing the stored source text. 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 0. The qPrintable() macro represent an
+ easy way of printing text.
+
+ Finally, the QT_POINTER_SIZE macro expands to the size of a
+ pointer in bytes, and the QT_VERSION and QT_VERSION_STR macros
+ expand to a numeric value or a string, respectively, specifying
+ Qt's version number, i.e the version the application is compiled
+ against.
+
+ \sa <QtAlgorithms>, QSysInfo
+*/
+
+/*!
+ \typedef qreal
+ \relates <QtGlobal>
+
+ Typedef for \c double on all platforms except for those using CPUs with
+ ARM architectures.
+ On ARM-based platforms, \c qreal is a typedef for \c float for performance
+ reasons.
+*/
+
+/*! \typedef uchar
+ \relates <QtGlobal>
+
+ Convenience typedef for \c{unsigned char}.
+*/
+
+/*!
+ \fn qt_set_sequence_auto_mnemonic(bool on)
+ \relates <QtGlobal>
+
+ Enables automatic mnemonics on Mac if \a on is true; otherwise
+ this feature is disabled.
+
+ Note that this function is only available on Mac where mnemonics
+ are disabled by default.
+
+ To access to this function, use an extern declaration:
+ extern void qt_set_sequence_auto_mnemonic(bool b);
+
+ \sa {QShortcut#mnemonic}{QShortcut}
+*/
+
+/*! \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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 6
+
+ \sa Q_UINT64_C(), qint64, qulonglong
+*/
+
+/*!
+ \typedef quintptr
+ \relates <QtGlobal>
+
+ Integral type for representing a pointers (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 QtMsgHandler
+ \relates <QtGlobal>
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7
+
+ \sa QtMsgType, qInstallMsgHandler()
+*/
+
+/*!
+ \enum QtMsgType
+ \relates <QtGlobal>
+
+ This enum describes the messages that can be sent to a message
+ handler (QtMsgHandler). 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 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
+
+
+ \sa QtMsgHandler, qInstallMsgHandler()
+*/
+
+/*! \macro qint64 Q_INT64_C(literal)
+ \relates <QtGlobal>
+
+ Wraps the signed 64-bit integer \a literal in a
+ platform-independent way.
+
+ Example:
+
+ \snippet doc/src/snippets/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 doc/src/snippets/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 const T &qAbs(const T &value)
+ \relates <QtGlobal>
+
+ Compares \a value to the 0 of type T and returns the absolute
+ value. Thus if T is \e {double}, then \a value is compared to
+ \e{(double) 0}.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 10
+*/
+
+/*! \fn int qRound(qreal value)
+ \relates <QtGlobal>
+
+ Rounds \a value to the nearest integer.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 11
+*/
+
+/*! \fn qint64 qRound64(qreal value)
+ \relates <QtGlobal>
+
+ Rounds \a value to the nearest 64-bit integer.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 12
+*/
+
+/*! \fn const T &qMin(const T &value1, const T &value2)
+ \relates <QtGlobal>
+
+ Returns the minimum of \a value1 and \a value2.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 13
+
+ \sa qMax(), qBound()
+*/
+
+/*! \fn const T &qMax(const T &value1, const T &value2)
+ \relates <QtGlobal>
+
+ Returns the maximum of \a value1 and \a value2.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 14
+
+ \sa qMin(), qBound()
+*/
+
+/*! \fn const T &qBound(const T &min, const T &value, const T &max)
+ \relates <QtGlobal>
+
+ Returns \a value bounded by \a min and \a max. This is equivalent
+ to qMax(\a min, qMin(\a value, \a max)).
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 15
+
+ \sa qMin(), qMax()
+*/
+
+/*!
+ \typedef Q_INT8
+ \relates <QtGlobal>
+ \compat
+
+ Use \l qint8 instead.
+*/
+
+/*!
+ \typedef Q_UINT8
+ \relates <QtGlobal>
+ \compat
+
+ Use \l quint8 instead.
+*/
+
+/*!
+ \typedef Q_INT16
+ \relates <QtGlobal>
+ \compat
+
+ Use \l qint16 instead.
+*/
+
+/*!
+ \typedef Q_UINT16
+ \relates <QtGlobal>
+ \compat
+
+ Use \l quint16 instead.
+*/
+
+/*!
+ \typedef Q_INT32
+ \relates <QtGlobal>
+ \compat
+
+ Use \l qint32 instead.
+*/
+
+/*!
+ \typedef Q_UINT32
+ \relates <QtGlobal>
+ \compat
+
+ Use \l quint32 instead.
+*/
+
+/*!
+ \typedef Q_INT64
+ \relates <QtGlobal>
+ \compat
+
+ Use \l qint64 instead.
+*/
+
+/*!
+ \typedef Q_UINT64
+ \relates <QtGlobal>
+ \compat
+
+ Use \l quint64 instead.
+*/
+
+/*!
+ \typedef Q_LLONG
+ \relates <QtGlobal>
+ \compat
+
+ Use \l qint64 instead.
+*/
+
+/*!
+ \typedef Q_ULLONG
+ \relates <QtGlobal>
+ \compat
+
+ Use \l quint64 instead.
+*/
+
+/*!
+ \typedef Q_LONG
+ \relates <QtGlobal>
+ \compat
+
+ Use \c{void *} instead.
+*/
+
+/*!
+ \typedef Q_ULONG
+ \relates <QtGlobal>
+ \compat
+
+ Use \c{void *} instead.
+*/
+
+/*! \fn bool qSysInfo(int *wordSize, bool *bigEndian)
+ \relates <QtGlobal>
+
+ Use QSysInfo::WordSize and QSysInfo::ByteOrder instead.
+*/
+
+/*!
+ \fn bool qt_winUnicode()
+ \relates <QtGlobal>
+
+ This function always returns true.
+
+ \sa QSysInfo
+*/
+
+/*!
+ \fn int qWinVersion()
+ \relates <QtGlobal>
+
+ Use QSysInfo::WindowsVersion instead.
+
+ \sa QSysInfo
+*/
+
+/*!
+ \fn int qMacVersion()
+ \relates <QtGlobal>
+
+ Use QSysInfo::MacintoshVersion instead.
+
+ \sa QSysInfo
+*/
+
+/*!
+ \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.
+
+ \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 doc/src/snippets/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
+*/
+
+const char *qVersion()
+{
+ return QT_VERSION_STR;
+}
+
+bool qSharedBuild()
+{
+#ifdef QT_SHARED
+ return true;
+#else
+ return false;
+#endif
+}
+
+/*****************************************************************************
+ System detection routines
+ *****************************************************************************/
+
+/*!
+ \class QSysInfo
+ \brief The QSysInfo class provides information about the system.
+
+ \list
+ \o \l WordSize specifies the size of a pointer for the platform
+ on which the application is compiled.
+ \o \l ByteOrder specifies whether the platform is big-endian or
+ little-endian.
+ \o \l WindowsVersion specifies the version of the Windows operating
+ system on which the application is run (Windows only)
+ \o \l MacintoshVersion specifies the version of the Macintosh
+ operating system on which the application is run (Mac only).
+ \endlist
+
+ Some constants are defined only on certain platforms. You can use
+ the preprocessor symbols Q_WS_WIN and Q_WS_MAC to test that
+ the application is compiled under Windows or Mac.
+
+ \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).
+*/
+
+/*!
+ \variable QSysInfo::WindowsVersion
+ \brief the version of the Windows operating system on which the
+ application is run (Windows only)
+*/
+
+/*!
+ \fn QSysInfo::WindowsVersion QSysInfo::windowsVersion()
+ \since 4.4
+
+ Returns the version of the Windows operating system on which the
+ application is run (Windows only).
+*/
+
+/*!
+ \variable QSysInfo::MacintoshVersion
+ \brief the version of the Macintosh operating system on which
+ the application is run (Mac only).
+*/
+
+/*!
+ \fn QSysInfo::SymbianVersion QSysInfo::symbianVersion()
+ \since 4.6
+
+ Returns the version of the Symbian operating system on which the
+ application is run (Symbian only).
+*/
+
+/*!
+ \fn QSysInfo::S60Version QSysInfo::s60Version()
+ \since 4.6
+
+ Returns the version of the S60 SDK system on which the
+ application is run (S60 only).
+*/
+
+/*!
+ \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.
+*/
+
+/*!
+ \enum QSysInfo::WinVersion
+
+ 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)
+
+ 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
+
+ CE-based versions:
+
+ \value WV_CE Windows CE
+ \value WV_CENET Windows CE .NET
+ \value WV_CE_5 Windows CE 5.x
+ \value WV_CE_6 Windows CE 6.x
+
+ The following masks can be used for testing whether a Windows
+ version is MS-DOS-based, NT-based, or CE-based:
+
+ \value WV_DOS_based MS-DOS-based version of Windows
+ \value WV_NT_based NT-based version of Windows
+ \value WV_CE_based CE-based version of Windows
+
+ \sa MacVersion, SymbianVersion
+*/
+
+/*!
+ \enum QSysInfo::MacVersion
+
+ This enum provides symbolic names for the various versions of the
+ Macintosh operating system. On Mac, the
+ QSysInfo::MacintoshVersion variable gives the version of the
+ system on which the application is run.
+
+ \value MV_9 Mac OS 9 (unsupported)
+ \value MV_10_0 Mac OS X 10.0 (unsupported)
+ \value MV_10_1 Mac OS X 10.1 (unsupported)
+ \value MV_10_2 Mac OS X 10.2 (unsupported)
+ \value MV_10_3 Mac OS X 10.3
+ \value MV_10_4 Mac OS X 10.4
+ \value MV_10_5 Mac OS X 10.5
+ \value MV_10_6 Mac OS X 10.6
+ \value MV_10_7 Mac OS X 10.7
+ \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
+
+ \sa WinVersion, SymbianVersion
+*/
+
+/*!
+ \enum QSysInfo::SymbianVersion
+
+ This enum provides symbolic names for the various versions of the
+ Symbian operating system. On Symbian, the
+ QSysInfo::symbianVersion() function gives the version of the
+ system on which the application is run.
+
+ \value SV_9_2 Symbian OS v9.2
+ \value SV_9_3 Symbian OS v9.3
+ \value SV_9_4 Symbian OS v9.4
+ \value SV_SF_1 S60 5th Edition (Symbian^1)
+ \value SV_SF_2 Symbian^2
+ \value SV_SF_3 Symbian^3 or Symbian Anna
+ \value SV_SF_4 \e{This enum value is deprecated.}
+ \value SV_API_5_3 Symbian/S60 API version 5.3 release
+ \value SV_API_5_4 Symbian/S60 API version 5.4 release
+ \value SV_Unknown An unknown and currently unsupported platform
+
+ \sa S60Version, WinVersion, MacVersion
+*/
+
+/*!
+ \enum QSysInfo::S60Version
+
+ This enum provides symbolic names for the various versions of the
+ S60 SDK. On S60, the
+ QSysInfo::s60Version() function gives the version of the
+ SDK on which the application is run.
+
+ \value SV_S60_3_1 S60 3rd Edition Feature Pack 1
+ \value SV_S60_3_2 S60 3rd Edition Feature Pack 2
+ \value SV_S60_5_0 S60 5th Edition
+ \value SV_S60_5_1 \e{This enum value is deprecated.}
+ \value SV_S60_5_2 Symbian^3 and Symbian Anna
+ \value SV_S60_5_3 Symbian/S60 API version 5.3 release
+ \value SV_S60_5_4 Symbian/S60 API version 5.4 release
+ \value SV_S60_Unknown An unknown and currently unsupported platform
+ \omitvalue SV_S60_None
+
+ \sa SymbianVersion, WinVersion, MacVersion
+*/
+
+/*!
+ \macro Q_WS_MAC
+ \relates <QtGlobal>
+
+ Defined on Mac OS X.
+
+ \sa Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60
+*/
+
+/*!
+ \macro Q_WS_WIN
+ \relates <QtGlobal>
+
+ Defined on Windows.
+
+ \sa Q_WS_MAC, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60
+*/
+
+/*!
+ \macro Q_WS_X11
+ \relates <QtGlobal>
+
+ Defined on X11.
+
+ \sa Q_WS_MAC, Q_WS_WIN, Q_WS_QWS, Q_WS_QPA, Q_WS_S60
+*/
+
+/*!
+ \macro Q_WS_QWS
+ \relates <QtGlobal>
+
+ Defined on Qt for Embedded Linux.
+
+ \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QPA, Q_WS_S60
+*/
+
+/*!
+ \macro Q_WS_QPA
+ \relates <QtGlobal>
+
+ Defined on Qt for Embedded Linux, Lite version.
+
+ \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_S60
+*/
+
+/*!
+ \macro Q_OS_DARWIN
+ \relates <QtGlobal>
+
+ Defined on Darwin OS (synonym for Q_OS_MAC).
+*/
+
+/*!
+ \macro Q_OS_MSDOS
+ \relates <QtGlobal>
+
+ Defined on MS-DOS and Windows.
+*/
+
+/*!
+ \macro Q_OS_OS2
+ \relates <QtGlobal>
+
+ Defined on OS/2.
+*/
+
+/*!
+ \macro Q_OS_OS2EMX
+ \relates <QtGlobal>
+
+ Defined on XFree86 on OS/2 (not PM).
+*/
+
+/*!
+ \macro Q_OS_WIN32
+ \relates <QtGlobal>
+
+ Defined on all supported versions of Windows.
+*/
+
+/*!
+ \macro Q_OS_WINCE
+ \relates <QtGlobal>
+
+ Defined on Windows CE.
+*/
+
+/*!
+ \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_ULTRIX
+ \relates <QtGlobal>
+
+ Defined on DEC Ultrix.
+*/
+
+/*!
+ \macro Q_OS_LINUX
+ \relates <QtGlobal>
+
+ Defined on Linux.
+*/
+
+/*!
+ \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_BSDI
+ \relates <QtGlobal>
+
+ Defined on BSD/OS.
+*/
+
+/*!
+ \macro Q_OS_IRIX
+ \relates <QtGlobal>
+
+ Defined on SGI Irix.
+*/
+
+/*!
+ \macro Q_OS_OSF
+ \relates <QtGlobal>
+
+ Defined on HP Tru64 UNIX.
+*/
+
+/*!
+ \macro Q_OS_SCO
+ \relates <QtGlobal>
+
+ Defined on SCO OpenServer 5.
+*/
+
+/*!
+ \macro Q_OS_UNIXWARE
+ \relates <QtGlobal>
+
+ Defined on UnixWare 7, Open UNIX 8.
+*/
+
+/*!
+ \macro Q_OS_AIX
+ \relates <QtGlobal>
+
+ Defined on AIX.
+*/
+
+/*!
+ \macro Q_OS_HURD
+ \relates <QtGlobal>
+
+ Defined on GNU Hurd.
+*/
+
+/*!
+ \macro Q_OS_DGUX
+ \relates <QtGlobal>
+
+ Defined on DG/UX.
+*/
+
+/*!
+ \macro Q_OS_RELIANT
+ \relates <QtGlobal>
+
+ Defined on Reliant UNIX.
+*/
+
+/*!
+ \macro Q_OS_DYNIX
+ \relates <QtGlobal>
+
+ Defined on DYNIX/ptx.
+*/
+
+/*!
+ \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_CC_SYM
+ \relates <QtGlobal>
+
+ Defined if the application is compiled using Digital Mars C/C++
+ (used to be Symantec C++).
+*/
+
+/*!
+ \macro Q_CC_MWERKS
+ \relates <QtGlobal>
+
+ Defined if the application is compiled using Metrowerks
+ CodeWarrior.
+*/
+
+/*!
+ \macro Q_CC_MSVC
+ \relates <QtGlobal>
+
+ Defined if the application is compiled using Microsoft Visual
+ C/C++, Intel C++ for Windows.
+*/
+
+/*!
+ \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_OS_MAC
+ \relates <QtGlobal>
+
+ Defined on MAC OS (synonym for Darwin).
+ */
+
+/*!
+ \macro Q_OS_SYMBIAN
+ \relates <QtGlobal>
+
+ Defined on Symbian.
+ */
+
+/*!
+ \macro Q_WS_S60
+ \relates <QtGlobal>
+
+ Defined on S60 with the Avkon UI framework.
+
+ \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS
+ */
+
+#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(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "private/qcore_mac_p.h"
+#include "qnamespace.h"
+QT_END_INCLUDE_NAMESPACE
+
+Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
+{
+ return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0);
+}
+
+// Don't use this function, it won't work in 10.5 (Leopard) and up
+Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec)
+{
+ FSRef fsref;
+ OSErr ret = qt_mac_create_fsref(file, &fsref);
+ if (ret == noErr)
+ ret = FSGetCatalogInfo(&fsref, kFSCatInfoNone, 0, 0, spec, 0);
+ return ret;
+}
+
+Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1)
+{
+ if(len == -1)
+ len = s.length();
+#if 0
+ UnicodeMapping mapping;
+ mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+ kTextEncodingDefaultVariant,
+ kUnicode16BitFormat);
+ mapping.otherEncoding = (encoding ? encoding : );
+ mapping.mappingVersion = kUnicodeUseLatestMapping;
+
+ UnicodeToTextInfo info;
+ OSStatus err = CreateUnicodeToTextInfo(&mapping, &info);
+ if(err != noErr) {
+ qDebug("Qt: internal: Unable to create pascal string '%s'::%d [%ld]",
+ s.left(len).latin1(), (int)encoding, err);
+ return;
+ }
+ const int unilen = len * 2;
+ const UniChar *unibuf = (UniChar *)s.unicode();
+ ConvertFromUnicodeToPString(info, unilen, unibuf, str);
+ DisposeUnicodeToTextInfo(&info);
+#else
+ Q_UNUSED(encoding);
+ CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding());
+#endif
+}
+
+Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) {
+ return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding()));
+}
+#endif //!defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+
+#if !defined(QWS) && defined(Q_OS_MAC)
+
+static QSysInfo::MacVersion macVersion()
+{
+#ifndef QT_NO_CORESERVICES
+ SInt32 gestalt_version;
+ if (Gestalt(gestaltSystemVersion, &gestalt_version) == noErr) {
+ return QSysInfo::MacVersion(((gestalt_version & 0x00F0) >> 4) + 2);
+ }
+#endif
+ return QSysInfo::MV_Unknown;
+}
+const QSysInfo::MacVersion QSysInfo::MacintoshVersion = macVersion();
+
+#elif defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINCE)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qt_windows.h"
+QT_END_INCLUDE_NAMESPACE
+
+QSysInfo::WinVersion QSysInfo::windowsVersion()
+{
+#ifndef VER_PLATFORM_WIN32s
+#define VER_PLATFORM_WIN32s 0
+#endif
+#ifndef VER_PLATFORM_WIN32_WINDOWS
+#define VER_PLATFORM_WIN32_WINDOWS 1
+#endif
+#ifndef VER_PLATFORM_WIN32_NT
+#define VER_PLATFORM_WIN32_NT 2
+#endif
+#ifndef VER_PLATFORM_WIN32_CE
+#define VER_PLATFORM_WIN32_CE 3
+#endif
+
+ static QSysInfo::WinVersion winver;
+ if (winver)
+ return winver;
+ winver = QSysInfo::WV_NT;
+ OSVERSIONINFO osver;
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ GetVersionEx(&osver);
+#ifdef Q_OS_WINCE
+ DWORD qt_cever = 0;
+ qt_cever = osver.dwMajorVersion * 100;
+ qt_cever += osver.dwMinorVersion * 10;
+#endif
+ switch (osver.dwPlatformId) {
+ case VER_PLATFORM_WIN32s:
+ winver = QSysInfo::WV_32s;
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ // We treat Windows Me (minor 90) the same as Windows 98
+ if (osver.dwMinorVersion == 90)
+ winver = QSysInfo::WV_Me;
+ else if (osver.dwMinorVersion == 10)
+ winver = QSysInfo::WV_98;
+ else
+ winver = QSysInfo::WV_95;
+ break;
+#ifdef Q_OS_WINCE
+ case VER_PLATFORM_WIN32_CE:
+ if (qt_cever >= 600)
+ winver = QSysInfo::WV_CE_6;
+ if (qt_cever >= 500)
+ winver = QSysInfo::WV_CE_5;
+ else if (qt_cever >= 400)
+ winver = QSysInfo::WV_CENET;
+ else
+ winver = QSysInfo::WV_CE;
+ break;
+#endif
+ default: // VER_PLATFORM_WIN32_NT
+ if (osver.dwMajorVersion < 5) {
+ winver = QSysInfo::WV_NT;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0) {
+ winver = QSysInfo::WV_2000;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1) {
+ winver = QSysInfo::WV_XP;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2) {
+ winver = QSysInfo::WV_2003;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0) {
+ winver = QSysInfo::WV_VISTA;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1) {
+ winver = QSysInfo::WV_WINDOWS7;
+ } else {
+ qWarning("Qt: Untested Windows version %d.%d detected!",
+ int(osver.dwMajorVersion), int(osver.dwMinorVersion));
+ winver = QSysInfo::WV_NT_based;
+ }
+ }
+
+#ifdef QT_DEBUG
+ {
+ QByteArray override = qgetenv("QT_WINVER_OVERRIDE");
+ if (override.isEmpty())
+ return winver;
+
+ if (override == "Me")
+ winver = QSysInfo::WV_Me;
+ if (override == "95")
+ winver = QSysInfo::WV_95;
+ else if (override == "98")
+ winver = QSysInfo::WV_98;
+ else if (override == "NT")
+ winver = QSysInfo::WV_NT;
+ else if (override == "2000")
+ winver = QSysInfo::WV_2000;
+ else if (override == "2003")
+ winver = QSysInfo::WV_2003;
+ else if (override == "XP")
+ winver = QSysInfo::WV_XP;
+ else if (override == "VISTA")
+ winver = QSysInfo::WV_VISTA;
+ else if (override == "WINDOWS7")
+ winver = QSysInfo::WV_WINDOWS7;
+ }
+#endif
+
+ return winver;
+}
+
+const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
+
+#endif
+
+#ifdef Q_OS_SYMBIAN
+static QSysInfo::SymbianVersion cachedSymbianVersion = QSysInfo::SymbianVersion(-1);
+static QSysInfo::S60Version cachedS60Version = QSysInfo::S60Version(-1);
+
+static void symbianInitVersions()
+{
+ // Use pure Symbian code, because if done using QDir, there will be a call back
+ // to this method, resulting doing this expensive operation twice before the cache kicks in.
+ // Pure Symbian code also makes this method ~10x faster, speeding up the application launch.
+ RFs rfs = qt_s60GetRFs();
+ TFindFile fileFinder(rfs);
+ CDir* contents;
+
+ // Check for platform version
+ TInt err = fileFinder.FindWildByDir(qt_S60Filter, qt_symbianSystemInstallDir, contents);
+ if (err == KErrNone) {
+ QScopedPointer<CDir> contentsDeleter(contents);
+ err = contents->Sort(EDescending|ESortByName);
+ if (err == KErrNone && contents->Count() > 0 && (*contents)[0].iName.Length() >= 12) {
+ TInt major = (*contents)[0].iName[9] - '0';
+ TInt minor = (*contents)[0].iName[11] - '0';
+ if (major == 3) {
+ if (minor == 1) {
+ cachedS60Version = QSysInfo::SV_S60_3_1;
+ cachedSymbianVersion = QSysInfo::SV_9_2;
+ } else if (minor == 2) {
+ cachedS60Version = QSysInfo::SV_S60_3_2;
+ cachedSymbianVersion = QSysInfo::SV_9_3;
+ }
+ } else if (major == 5) {
+ if (minor == 0) {
+ cachedS60Version = QSysInfo::SV_S60_5_0;
+ cachedSymbianVersion = QSysInfo::SV_9_4;
+ } else if (minor == 1) {
+ cachedS60Version = QSysInfo::SV_S60_5_1;
+ cachedSymbianVersion = QSysInfo::SV_SF_2;
+ } else if (minor == 2) {
+ cachedS60Version = QSysInfo::SV_S60_5_2;
+ cachedSymbianVersion = QSysInfo::SV_SF_3;
+ } else if (minor == 3) {
+ cachedS60Version = QSysInfo::SV_S60_5_3;
+ cachedSymbianVersion = QSysInfo::SV_API_5_3;
+ } else if (minor >= 4) {
+ cachedS60Version = QSysInfo::SV_S60_5_4;
+ cachedSymbianVersion = QSysInfo::SV_API_5_4;
+ }
+ }
+ }
+ }
+
+# ifdef Q_CC_NOKIAX86
+ if (cachedS60Version == -1) {
+ // Some emulator environments may not contain the version specific .sis files, so
+ // simply hardcode the version on those environments. Note that can't use
+ // S60_VERSION_* defines for S60 3.x/5.0 platforms, as they do not define them
+ // right anyway in case .sis files are not found.
+# if defined(__SERIES60_31__)
+ cachedS60Version = QSysInfo::SV_S60_3_1;
+ cachedSymbianVersion = QSysInfo::SV_9_2;
+# elif defined(__S60_32__)
+ cachedS60Version = QSysInfo::SV_S60_3_2;
+ cachedSymbianVersion = QSysInfo::SV_9_3;
+# elif defined(__S60_50__)
+ cachedS60Version = QSysInfo::SV_S60_5_0;
+ cachedSymbianVersion = QSysInfo::SV_9_4;
+# elif defined(S60_VERSION_5_2)
+ cachedS60Version = QSysInfo::SV_S60_5_2;
+ cachedSymbianVersion = QSysInfo::SV_SF_3;
+# elif defined(S60_VERSION_5_3)
+ cachedS60Version = QSysInfo::SV_S60_5_3;
+ cachedSymbianVersion = QSysInfo::SV_API_5_3;
+# elif defined(S60_VERSION_5_4)
+ cachedS60Version = QSysInfo::SV_S60_5_4;
+ cachedSymbianVersion = QSysInfo::SV_API_5_4;
+# endif
+ }
+# endif
+
+ if (cachedS60Version == -1) {
+ //If reaching here, it was not possible to determine the version
+ cachedS60Version = QSysInfo::SV_S60_Unknown;
+ cachedSymbianVersion = QSysInfo::SV_Unknown;
+ }
+}
+
+QSysInfo::SymbianVersion QSysInfo::symbianVersion()
+{
+ if (cachedSymbianVersion == -1)
+ symbianInitVersions();
+
+ return cachedSymbianVersion;
+}
+
+QSysInfo::S60Version QSysInfo::s60Version()
+{
+ if (cachedS60Version == -1)
+ symbianInitVersions();
+
+ return cachedS60Version;
+}
+#endif // ifdef Q_OS_SYMBIAN
+
+/*!
+ \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 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 doc/src/snippets/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 doc/src/snippets/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 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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 20
+
+ \sa Q_ASSERT(), qFatal(), {Debugging Techniques}
+*/
+
+/*!
+ \macro void Q_CHECK_PTR(void *pointer)
+ \relates <QtGlobal>
+
+ If \a pointer is 0, prints a warning message containing the source
+ code's file name and line number, saying that the program ran out
+ of memory.
+
+ Q_CHECK_PTR does nothing if \c QT_NO_DEBUG was defined during
+ compilation.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 21
+
+ \sa qWarning(), {Debugging Techniques}
+*/
+
+/*!
+ \fn T *q_check_ptr(T *pointer)
+ \relates <QtGlobal>
+
+ Users Q_CHECK_PTR on \a pointer, then returns \a pointer.
+
+ 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 doc/src/snippets/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.
+ */
+
+/*
+ The Q_CHECK_PTR macro calls this function if an allocation check
+ fails.
+*/
+void qt_check_pointer(const char *n, int l)
+{
+ qFatal("In file %s, line %d: Out of memory", n, l);
+}
+
+/* \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());
+}
+
+/*
+ The Q_ASSERT macro calls this function when the test fails.
+*/
+void qt_assert(const char *assertion, const char *file, int line)
+{
+ qFatal("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)
+{
+ qFatal("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
+*/
+Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n)
+{
+ // n must be in the range 0...UINT_MAX/2-1
+ 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;
+ while (q <= n)
+ q <<= 2;
+ while (q != 1) {
+ q >>= 2;
+ h= p + q;
+ p >>= 1;
+ if (r >= h) {
+ p += q;
+ r -= h;
+ }
+ }
+ return p;
+}
+
+#if defined(qMemCopy)
+# undef qMemCopy
+#endif
+#if defined(qMemSet)
+# undef qMemSet
+#endif
+
+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); }
+
+static QtMsgHandler handler = 0; // pointer to debug handler
+
+#if defined(Q_CC_MWERKS) && defined(Q_OS_MACX)
+extern bool qt_is_gui_used;
+static void mac_default_handler(const char *msg)
+{
+ if (qt_is_gui_used) {
+ Str255 pmsg;
+ qt_mac_to_pascal_string(msg, pmsg);
+ DebugStr(pmsg);
+ } else {
+ fprintf(stderr, msg);
+ }
+}
+#endif // Q_CC_MWERKS && Q_OS_MACX
+
+#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
+ defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
+namespace {
+ // There are two incompatible versions of strerror_r:
+ // a) the XSI/POSIX.1 version, which returns an int,
+ // indicating success or not
+ // b) the GNU version, which returns a char*, which may or may not
+ // be the beginning of the buffer we used
+ // The GNU libc manpage for strerror_r says you should use the the XSI
+ // 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 QString fromstrerror_helper(int, const QByteArray &buf)
+ {
+ return QString::fromLocal8Bit(buf);
+ }
+ static inline QString fromstrerror_helper(const char *str, const QByteArray &)
+ {
+ return QString::fromLocal8Bit(str);
+ }
+}
+#endif
+
+QString qt_error_string(int errorCode)
+{
+ const char *s = 0;
+ QString ret;
+ if (errorCode == -1) {
+#if defined(Q_OS_WIN)
+ errorCode = GetLastError();
+#else
+ errorCode = errno;
+#endif
+ }
+ switch (errorCode) {
+ case 0:
+ break;
+ case EACCES:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
+ break;
+ case EMFILE:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
+ break;
+ case ENOENT:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
+ break;
+ case ENOSPC:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
+ break;
+ default: {
+#ifdef Q_OS_WIN
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string,
+ 0,
+ NULL);
+ ret = QString::fromWCharArray(string);
+ LocalFree((HLOCAL)string);
+
+ if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
+ ret = QString::fromLatin1("The specified module could not be found.");
+#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
+ QByteArray buf(1024, '\0');
+ ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
+#else
+ ret = QString::fromLocal8Bit(strerror(errorCode));
+#endif
+ break; }
+ }
+ if (s)
+ // ######## this breaks moc build currently
+// ret = QCoreApplication::translate("QIODevice", s);
+ ret = QString::fromLatin1(s);
+ return ret.trimmed();
+}
+
+
+/*!
+ \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler)
+ \relates <QtGlobal>
+
+ Installs a Qt message \a handler which has been defined
+ previously. Returns a pointer to the previous message handler
+ (which may be 0).
+
+ 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 qInstallMsgHandler(0).
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23
+
+ \sa qDebug(), qWarning(), qCritical(), qFatal(), QtMsgType,
+ {Debugging Techniques}
+*/
+#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
+extern bool usingWinMain;
+extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str);
+#endif
+
+QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
+{
+ QtMsgHandler old = handler;
+ handler = h;
+#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
+ if (!handler && usingWinMain)
+ handler = qWinMsgHandler;
+#endif
+ return old;
+}
+
+/*!
+ \internal
+*/
+void qt_message_output(QtMsgType msgType, const char *buf)
+{
+ if (handler) {
+ (*handler)(msgType, buf);
+ } else {
+#if defined(Q_CC_MWERKS) && defined(Q_OS_MACX)
+ mac_default_handler(buf);
+#elif defined(Q_OS_WINCE)
+ QString fstr = QString::fromLatin1(buf);
+ fstr += QLatin1Char('\n');
+ OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
+#elif defined(Q_OS_SYMBIAN)
+ // RDebug::Print has a cap of 256 characters so break it up
+ _LIT(format, "[Qt Message] %S");
+ const int maxBlockSize = 256 - ((const TDesC &)format).Length();
+ const TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf));
+ HBufC* hbuffer = HBufC::New(qMin(maxBlockSize, ptr.Length()));
+ Q_CHECK_PTR(hbuffer);
+ for (int i = 0; i < ptr.Length(); i += hbuffer->Length()) {
+ hbuffer->Des().Copy(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i)));
+ RDebug::Print(format, hbuffer);
+ }
+ delete hbuffer;
+#else
+ fprintf(stderr, "%s\n", buf);
+ fflush(stderr);
+#endif
+ }
+
+ if (msgType == QtFatalMsg
+ || (msgType == QtWarningMsg
+ && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) {
+
+#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
+ // get the current report mode
+ int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
+ _CrtSetReportMode(_CRT_ERROR, reportMode);
+#if !defined(Q_OS_WINCE)
+ int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, buf);
+#else
+ int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__),
+ __LINE__, _CRT_WIDE(QT_VERSION_STR), reinterpret_cast<const wchar_t *> (QString::fromLatin1(buf).utf16()));
+#endif
+ if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
+ return; // ignore
+ else if (ret == 1)
+ _CrtDbgBreak();
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+ __DEBUGGER(); // on the emulator, get the debugger to kick in if there's one around
+ TBuf<256> tmp;
+ TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf));
+ TInt len = Min(tmp.MaxLength(), ptr.Length());
+ tmp.Copy(ptr.Left(len));
+ // Panic the current thread. We don't use real panic codes, so 0 has no special meaning.
+ User::Panic(tmp, 0);
+#elif (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
+ abort(); // trap; generates core dump
+#else
+ exit(1); // goodbye cruel world
+#endif
+ }
+}
+
+#if !defined(QT_NO_EXCEPTIONS)
+/*!
+ \internal
+ Uses a local buffer to output the message. Not locale safe + cuts off
+ everything after character 255, but will work in out of memory situations.
+*/
+static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
+{
+ char emergency_buf[256] = { '\0' };
+ emergency_buf[255] = '\0';
+ if (msg)
+ qvsnprintf(emergency_buf, 255, msg, ap);
+ qt_message_output(msgType, emergency_buf);
+}
+#endif
+
+/*!
+ \internal
+*/
+static void qt_message(QtMsgType msgType, const char *msg, va_list ap)
+{
+#if !defined(QT_NO_EXCEPTIONS)
+ if (std::uncaught_exception()) {
+ qEmergencyOut(msgType, msg, ap);
+ return;
+ }
+#endif
+ QByteArray buf;
+ if (msg) {
+ QT_TRY {
+ buf = QString().vsprintf(msg, ap).toLocal8Bit();
+ } QT_CATCH(const std::bad_alloc &) {
+#if !defined(QT_NO_EXCEPTIONS)
+ qEmergencyOut(msgType, msg, ap);
+ // don't rethrow - we use qWarning and friends in destructors.
+ return;
+#endif
+ }
+ }
+ qt_message_output(msgType, buf.constData());
+}
+
+#undef qDebug
+/*!
+ \relates <QtGlobal>
+
+ Calls the message handler with the debug message \a msg. 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. 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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 24
+
+ If you include \c <QtDebug>, a more convenient syntax is also
+ available:
+
+ \snippet doc/src/snippets/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 qInstallMsgHandler().
+
+ \sa qWarning(), qCritical(), qFatal(), qInstallMsgHandler(),
+ {Debugging Techniques}
+*/
+void qDebug(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtDebugMsg, msg, ap);
+ va_end(ap);
+}
+
+#undef qWarning
+/*!
+ \relates <QtGlobal>
+
+ Calls the message handler with the warning message \a msg. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger. This
+ function does nothing if \c QT_NO_WARNING_OUTPUT was defined
+ during compilation; it exits if the environment variable \c
+ QT_FATAL_WARNINGS is defined.
+
+ 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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 26
+
+ If you include <QtDebug>, a more convenient syntax is
+ also available:
+
+ \snippet doc/src/snippets/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 qInstallMsgHandler().
+
+ \sa qDebug(), qCritical(), qFatal(), qInstallMsgHandler(),
+ {Debugging Techniques}
+*/
+void qWarning(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtWarningMsg, msg, ap);
+ va_end(ap);
+}
+
+/*!
+ \relates <QtGlobal>
+
+ Calls the message handler with the critical message \a msg. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger.
+
+ 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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 28
+
+ If you include <QtDebug>, a more convenient syntax is
+ also available:
+
+ \snippet doc/src/snippets/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 qInstallMsgHandler().
+
+ \sa qDebug(), qWarning(), qFatal(), qInstallMsgHandler(),
+ {Debugging Techniques}
+*/
+void qCritical(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtCriticalMsg, msg, ap);
+ va_end(ap);
+}
+
+#ifdef QT3_SUPPORT
+void qSystemWarning(const char *msg, int code)
+ { qCritical("%s (%s)", msg, qt_error_string(code).toLocal8Bit().constData()); }
+#endif // QT3_SUPPORT
+
+void qErrnoWarning(const char *msg, ...)
+{
+ // qt_error_string() will allocate anyway, so we don't have
+ // to be careful here (like we do in plain qWarning())
+ QString buf;
+ va_list ap;
+ va_start(ap, msg);
+ if (msg)
+ buf.vsprintf(msg, ap);
+ va_end(ap);
+
+ qCritical("%s (%s)", buf.toLocal8Bit().constData(), qt_error_string(-1).toLocal8Bit().constData());
+}
+
+void qErrnoWarning(int code, const char *msg, ...)
+{
+ // qt_error_string() will allocate anyway, so we don't have
+ // to be careful here (like we do in plain qWarning())
+ QString buf;
+ va_list ap;
+ va_start(ap, msg);
+ if (msg)
+ buf.vsprintf(msg, ap);
+ va_end(ap);
+
+ qCritical("%s (%s)", buf.toLocal8Bit().constData(), qt_error_string(code).toLocal8Bit().constData());
+}
+
+/*!
+ \relates <QtGlobal>
+
+ Calls the message handler with the fatal message \a msg. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger.
+
+ If you are using the \bold{default message handler} this function will
+ abort on Unix systems 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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 30
+
+ To suppress the output at runtime, install your own message handler
+ with qInstallMsgHandler().
+
+ \sa qDebug(), qCritical(), qWarning(), qInstallMsgHandler(),
+ {Debugging Techniques}
+*/
+void qFatal(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtFatalMsg, msg, ap);
+ va_end(ap);
+}
+
+// getenv is declared as deprecated in VS2005. This function
+// makes use of the new secure getenv function.
+/*!
+ \relates <QtGlobal>
+
+ Returns the value of the environment variable with name \a
+ varName. To get the variable string, use QByteArray::constData().
+
+ \note qgetenv() was introduced because getenv() from the standard
+ C library was deprecated in VC2005 (and later versions). qgetenv()
+ uses the new replacement function in VC, and calls the standard C
+ library's implementation on all other platforms.
+
+ \sa qputenv()
+*/
+QByteArray qgetenv(const char *varName)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ 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
+}
+
+/*!
+ \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.
+
+ \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()
+*/
+bool qputenv(const char *varName, const QByteArray& value)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return _putenv_s(varName, value.constData()) == 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
+}
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_THREAD)
+
+# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500)
+// older versions of INTEGRITY used a long instead of a uint for the seed.
+typedef long SeedStorageType;
+# else
+typedef uint SeedStorageType;
+# endif
+
+typedef QThreadStorage<SeedStorageType *> SeedStorage;
+Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
+
+#endif
+
+/*!
+ \relates <QtGlobal>
+ \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 calls qrand(), the threads will get
+ the same random number sequence.
+
+ \sa qrand()
+*/
+void qsrand(uint seed)
+{
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_THREAD)
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed)
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = seed;
+ } else {
+ //global static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to srand(seed)
+ srand(seed);
+ }
+#else
+ // On Windows and Symbian srand() and rand() already use Thread-Local-Storage
+ // to store the seed between calls
+ // this is also valid for QT_NO_THREAD
+ srand(seed);
+#endif
+}
+
+/*!
+ \relates <QtGlobal>
+ \since 4.2
+
+ Thread-safe version of the standard C++ \c rand() function.
+
+ 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.
+
+ Use \c qsrand() to initialize the pseudo-random number generator with
+ a seed value.
+
+ \sa qsrand()
+*/
+int qrand()
+{
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_THREAD)
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed) {
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = 1;
+ }
+ return rand_r(pseed);
+ } else {
+ //global static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to rand()
+ return rand();
+ }
+#else
+ // On Windows and Symbian srand() and rand() already use Thread-Local-Storage
+ // to store the seed between calls
+ // this is also valid for QT_NO_THREAD
+ return rand();
+#endif
+}
+
+/*!
+ \macro forever
+ \relates <QtGlobal>
+
+ This macro is provided for convenience for writing infinite
+ loops.
+
+ Example:
+
+ \snippet doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 33
+
+ \sa Q_FOREACH()
+*/
+
+/*!
+ \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.
+
+ \sa foreach()
+*/
+
+/*!
+ \macro QT_TR_NOOP(sourceText)
+ \relates <QtGlobal>
+
+ Marks the string literal \a sourceText for dynamic translation in
+ the current context (class), i.e the stored \a sourceText will not
+ be altered.
+
+ The macro expands to \a sourceText.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 34
+
+ The macro QT_TR_NOOP_UTF8() is identical except that it tells lupdate
+ that the source string is encoded in UTF-8. Corresponding variants
+ exist in the QT_TRANSLATE_NOOP() family of macros, too. Note that
+ using these macros is not required if \c CODECFORTR is already set to
+ UTF-8 in the qmake project file.
+
+ \sa QT_TRANSLATE_NOOP(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_NOOP(context, sourceText)
+ \relates <QtGlobal>
+
+ Marks the string literal \a sourceText for dynamic translation in
+ the given \a context; i.e, the stored \a sourceText will not be
+ altered. The \a context is typically a class and also needs to
+ be specified as string literal.
+
+ The macro expands to \a sourceText.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 35
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP3(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_NOOP3(context, sourceText, comment)
+ \relates <QtGlobal>
+ \since 4.4
+
+ Marks the string literal \a sourceText for dynamic translation in the
+ given \a context and with \a comment, i.e the stored \a sourceText will
+ not be altered. The \a context is typically a class and also needs to
+ be specified as string literal. The string literal \a comment
+ will be available for translators using e.g. Qt Linguist.
+
+ The macro expands to anonymous struct of the two string
+ literals passed as \a sourceText and \a comment.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 36
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), {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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_global_qglobal.cpp qttrid_noop
+
+ \sa qtTrId(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro Q_LIKELY(expr)
+ \relates <QtGlobal>
+ \since 4.8
+
+ \brief Hints the compiler that the enclosed condition is likely to evaluate
+ to \c true.
+
+ Use of this macro can help the compiler to optimize the code.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp qlikely
+
+ \sa Q_UNLIKELY()
+*/
+
+/*!
+ \macro Q_UNLIKELY(expr)
+ \relates <QtGlobal>
+ \since 4.8
+
+ \brief Hints the compiler that the enclosed condition is likely to evaluate
+ to \c false.
+
+ Use of this macro can help the compiler to optimize the code.
+
+ Example:
+
+ \snippet doc/src/snippets/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 TRUE
+ \relates <QtGlobal>
+ \obsolete
+
+ Synonym for \c true.
+
+ \sa FALSE
+*/
+
+/*!
+ \macro FALSE
+ \relates <QtGlobal>
+ \obsolete
+
+ Synonym for \c false.
+
+ \sa TRUE
+*/
+
+/*!
+ \macro QABS(n)
+ \relates <QtGlobal>
+ \obsolete
+
+ Use qAbs(\a n) instead.
+
+ \sa QMIN(), QMAX()
+*/
+
+/*!
+ \macro QMIN(x, y)
+ \relates <QtGlobal>
+ \obsolete
+
+ Use qMin(\a x, \a y) instead.
+
+ \sa QMAX(), QABS()
+*/
+
+/*!
+ \macro QMAX(x, y)
+ \relates <QtGlobal>
+ \obsolete
+
+ Use qMax(\a x, \a y) instead.
+
+ \sa QMIN(), QABS()
+*/
+
+/*!
+ \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
+ toLocal8Bit() will fall out of scope.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 37
+
+
+ \sa qDebug(), 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
+ \o \c Q_PRIMITIVE_TYPE specifies that \a Type is a POD (plain old
+ data) type with no constructor or destructor.
+ \o \c Q_MOVABLE_TYPE specifies that \a Type has a constructor
+ and/or a destructor but can be moved in memory using \c
+ memcpy().
+ \o \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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 38
+
+ Example of a movable type:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 39
+*/
+
+/*!
+ \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.
+*/
+
+#if defined(QT3_SUPPORT) && !defined(QT_NO_SETTINGS)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <qlibraryinfo.h>
+QT_END_INCLUDE_NAMESPACE
+
+static const char *qInstallLocation(QLibraryInfo::LibraryLocation loc)
+{
+ static QByteArray ret;
+ ret = QLibraryInfo::location(loc).toLatin1();
+ return ret.constData();
+}
+const char *qInstallPath()
+{
+ return qInstallLocation(QLibraryInfo::PrefixPath);
+}
+const char *qInstallPathDocs()
+{
+ return qInstallLocation(QLibraryInfo::DocumentationPath);
+}
+const char *qInstallPathHeaders()
+{
+ return qInstallLocation(QLibraryInfo::HeadersPath);
+}
+const char *qInstallPathLibs()
+{
+ return qInstallLocation(QLibraryInfo::LibrariesPath);
+}
+const char *qInstallPathBins()
+{
+ return qInstallLocation(QLibraryInfo::BinariesPath);
+}
+const char *qInstallPathPlugins()
+{
+ return qInstallLocation(QLibraryInfo::PluginsPath);
+}
+const char *qInstallPathData()
+{
+ return qInstallLocation(QLibraryInfo::DataPath);
+}
+const char *qInstallPathTranslations()
+{
+ return qInstallLocation(QLibraryInfo::TranslationsPath);
+}
+const char *qInstallPathSysconf()
+{
+ return qInstallLocation(QLibraryInfo::SettingsPath);
+}
+#endif
+
+struct QInternal_CallBackTable {
+ QVector<QList<qInternalCallback> > callbacks;
+};
+
+Q_GLOBAL_STATIC(QInternal_CallBackTable, global_callback_table)
+
+bool QInternal::registerCallback(Callback cb, qInternalCallback callback)
+{
+ if (cb >= 0 && cb < QInternal::LastCallback) {
+ QInternal_CallBackTable *cbt = global_callback_table();
+ cbt->callbacks.resize(cb + 1);
+ cbt->callbacks[cb].append(callback);
+ return true;
+ }
+ return false;
+}
+
+bool QInternal::unregisterCallback(Callback cb, qInternalCallback callback)
+{
+ if (cb >= 0 && cb < QInternal::LastCallback) {
+ QInternal_CallBackTable *cbt = global_callback_table();
+ return (bool) cbt->callbacks[cb].removeAll(callback);
+ }
+ return false;
+}
+
+bool QInternal::activateCallbacks(Callback cb, void **parameters)
+{
+ Q_ASSERT_X(cb >= 0, "QInternal::activateCallback()", "Callback id must be a valid id");
+
+ QInternal_CallBackTable *cbt = global_callback_table();
+ if (cbt && cb < cbt->callbacks.size()) {
+ QList<qInternalCallback> callbacks = cbt->callbacks[cb];
+ bool ret = false;
+ for (int i=0; i<callbacks.size(); ++i)
+ ret |= (callbacks.at(i))(parameters);
+ return ret;
+ }
+ return false;
+}
+
+extern void qt_set_current_thread_to_main_thread();
+
+bool QInternal::callFunction(InternalFunction func, void **args)
+{
+ Q_ASSERT_X(func >= 0,
+ "QInternal::callFunction()", "Callback id must be a valid id");
+#ifndef QT_NO_QOBJECT
+ switch (func) {
+#ifndef QT_NO_THREAD
+ case QInternal::CreateThreadForAdoption:
+ *args = QAdoptedThread::createThreadForAdoption();
+ return true;
+#endif
+ case QInternal::RefAdoptedThread:
+ QThreadData::get2((QThread *) *args)->ref();
+ return true;
+ case QInternal::DerefAdoptedThread:
+ QThreadData::get2((QThread *) *args)->deref();
+ return true;
+ case QInternal::SetCurrentThreadToMainThread:
+ qt_set_current_thread_to_main_thread();
+ return true;
+ case QInternal::SetQObjectSender: {
+ QObject *receiver = (QObject *) args[0];
+ QObjectPrivate::Sender *sender = new QObjectPrivate::Sender;
+ sender->sender = (QObject *) args[1];
+ sender->signal = *(int *) args[2];
+ sender->ref = 1;
+
+ // Store the old sender as "return value"
+ args[3] = QObjectPrivate::setCurrentSender(receiver, sender);
+ args[4] = sender;
+ return true;
+ }
+ case QInternal::GetQObjectSender: {
+ QObject *receiver = (QObject *) args[0];
+ QObjectPrivate *d = QObjectPrivate::get(receiver);
+ args[1] = d->currentSender ? d->currentSender->sender : 0;
+ return true;
+ }
+ case QInternal::ResetQObjectSender: {
+ QObject *receiver = (QObject *) args[0];
+ QObjectPrivate::Sender *oldSender = (QObjectPrivate::Sender *) args[1];
+ QObjectPrivate::Sender *sender = (QObjectPrivate::Sender *) args[2];
+ QObjectPrivate::resetCurrentSender(receiver, sender, oldSender);
+ delete sender;
+ return true;
+ }
+
+ default:
+ break;
+ }
+#else
+ Q_UNUSED(args);
+ Q_UNUSED(func);
+#endif
+
+ return false;
+}
+
+/*!
+ \macro Q_BYTE_ORDER
+ \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.
+
+ Use this macro as in the following examples.
+
+ \snippet doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_global_qglobal.cpp 42
+
+ \sa Q_BYTE_ORDER, Q_LITTLE_ENDIAN
+*/
+
+/*!
+ \macro Q_GLOBAL_STATIC(type, name)
+ \internal
+
+ Declares a global static variable with the given \a type and \a name.
+
+ Use this macro to instantiate an object in a thread-safe way, creating
+ a global pointer that can be used to refer to it.
+
+ \warning This macro is subject to a race condition that can cause the object
+ to be constructed twice. However, if this occurs, the second instance will
+ be immediately deleted.
+
+ See also
+ \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"}
+ by Scott Meyers and Andrei Alexandrescu.
+*/
+
+/*!
+ \macro Q_GLOBAL_STATIC_WITH_ARGS(type, name, arguments)
+ \internal
+
+ Declares a global static variable with the specified \a type and \a name.
+
+ Use this macro to instantiate an object using the \a arguments specified
+ in a thread-safe way, creating a global pointer that can be used to refer
+ to it.
+
+ \warning This macro is subject to a race condition that can cause the object
+ to be constructed twice. However, if this occurs, the second instance will
+ be immediately deleted.
+
+ See also
+ \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"}
+ by Scott Meyers and Andrei Alexandrescu.
+*/
+
+/*!
+ \macro QT_NAMESPACE
+ \internal
+
+ If this macro is defined to \c ns all Qt classes are put in a namespace
+ called \c ns. Also, moc will output code putting metaobjects etc.
+ into namespace \c ns.
+
+ \sa QT_BEGIN_NAMESPACE, QT_END_NAMESPACE,
+ QT_PREPEND_NAMESPACE, QT_USE_NAMESPACE,
+ QT_BEGIN_INCLUDE_NAMESPACE, QT_END_INCLUDE_NAMESPACE,
+ QT_BEGIN_MOC_NAMESPACE, QT_END_MOC_NAMESPACE,
+*/
+
+/*!
+ \macro QT_PREPEND_NAMESPACE(identifier)
+ \internal
+
+ This macro qualifies \a identifier with the full namespace.
+ It expands to \c{::QT_NAMESPACE::identifier} if \c QT_NAMESPACE is defined
+ and only \a identifier otherwise.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_USE_NAMESPACE
+ \internal
+
+ This macro expands to using QT_NAMESPACE if QT_NAMESPACE is defined
+ and nothing otherwise.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_BEGIN_NAMESPACE
+ \internal
+
+ This macro expands to
+
+ \snippet snippets/code/src_corelib_global_qglobal.cpp begin namespace macro
+
+ if \c QT_NAMESPACE is defined and nothing otherwise. If should always
+ appear in the file-level scope and be followed by \c QT_END_NAMESPACE
+ at the same logical level with respect to preprocessor conditionals
+ in the same file.
+
+ As a rule of thumb, \c QT_BEGIN_NAMESPACE should appear in all Qt header
+ and Qt source files after the last \c{#include} line and before the first
+ declaration. In Qt headers using \c QT_BEGIN_HEADER, \c QT_BEGIN_NAMESPACE
+ follows \c QT_BEGIN_HEADER immediately.
+
+ If that rule can't be followed because, e.g., \c{#include} lines and
+ declarations are wildly mixed, place \c QT_BEGIN_NAMESPACE before
+ the first declaration and wrap the \c{#include} lines in
+ \c QT_BEGIN_INCLUDE_NAMESPACE and \c QT_END_INCLUDE_NAMESPACE.
+
+ When using the \c QT_NAMESPACE feature in user code
+ (e.g., when building plugins statically linked to Qt) where
+ the user code is not intended to go into the \c QT_NAMESPACE
+ namespace, all forward declarations of Qt classes need to
+ be wrapped in \c QT_BEGIN_NAMESPACE and \c QT_END_NAMESPACE.
+ After that, a \c QT_USE_NAMESPACE should follow.
+ No further changes should be needed.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_END_NAMESPACE
+ \internal
+
+ This macro expands to
+
+ \snippet snippets/code/src_corelib_global_qglobal.cpp end namespace macro
+
+ if \c QT_NAMESPACE is defined and nothing otherwise. It is used to cancel
+ the effect of \c QT_BEGIN_NAMESPACE.
+
+ If a source file ends with a \c{#include} directive that includes a moc file,
+ \c QT_END_NAMESPACE should be placed before that \c{#include}.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_BEGIN_INCLUDE_NAMESPACE
+ \internal
+
+ This macro is equivalent to \c QT_END_NAMESPACE.
+ It only serves as syntactic sugar and is intended
+ to be used before #include lines within a
+ \c QT_BEGIN_NAMESPACE ... \c QT_END_NAMESPACE block.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_END_INCLUDE_NAMESPACE
+ \internal
+
+ This macro is equivalent to \c QT_BEGIN_NAMESPACE.
+ It only serves as syntactic sugar and is intended
+ to be used after #include lines within a
+ \c QT_BEGIN_NAMESPACE ... \c QT_END_NAMESPACE block.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_BEGIN_MOC_NAMESPACE
+ \internal
+
+ This macro is output by moc at the beginning of
+ moc files. It is equivalent to \c QT_USE_NAMESPACE.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \macro QT_END_MOC_NAMESPACE
+ \internal
+
+ This macro is output by moc at the beginning of
+ moc files. It expands to nothing.
+
+ \sa QT_NAMESPACE
+*/
+
+/*!
+ \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.
+ The solution to this is to compare against values greater than or equal to 1.0.
+
+ \snippet doc/src/snippets/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.
+ */
+
+/*!
+ \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 doc/src/snippets/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
+*/
+
+#if defined(Q_OS_SYMBIAN)
+
+#include <typeinfo>
+
+/*! \macro QT_TRAP_THROWING(function)
+ \relates <QtGlobal>
+ \ingroup qts60
+
+ TRAP leaves from Symbian \a function and throws an appropriate
+ standard C++ exception instead.
+ This must be used when calling Symbian OS leaving functions
+ from inside Qt or standard C++ code, so that the code can respond
+ correctly to the exception.
+
+ \warning This macro is only available on Symbian.
+
+ Example:
+
+ \code
+ // A Symbian leaving function is being called within a Qt function.
+ // Any leave must be converted to an exception
+ CAknTitlePane* titlePane = S60->titlePane();
+ if (titlePane) {
+ TPtrC captionPtr(qt_QString2TPtrC(caption));
+ QT_TRAP_THROWING(titlePane->SetTextL(captionPtr));
+ }
+ \endcode
+
+ \sa QT_TRYCATCH_ERROR(), QT_TRYCATCH_LEAVING()
+*/
+
+/*! \macro QT_TRYCATCH_ERROR(error, function)
+ \relates <QtGlobal>
+ \ingroup qts60
+
+ Catch standard C++ exceptions from a \a function and convert them to a Symbian OS
+ \a error code, or \c KErrNone if there is no exception.
+ This must be used inside Qt or standard C++ code when using exception throwing
+ code (practically anything) and returning an error code to Symbian OS.
+
+ \warning This macro is only available on Symbian.
+
+ Example:
+
+ \code
+ // An exception might be thrown in this Symbian TInt error returning function.
+ // It is caught and translated to an error code
+ TInt QServerApp::Connect(const QString &serverName)
+ {
+ TPtrC name;
+ TInt err;
+ QT_TRYCATCH_ERROR(err, name.Set(qt_QString2TPtrC(serverName)));
+ if (err != KErrNone)
+ return err;
+ return iServer.Connect(name);
+ }
+ \endcode
+}
+
+ \sa QT_TRYCATCH_LEAVING(), QT_TRAP_THROWING()
+*/
+
+/*! \macro QT_TRYCATCH_LEAVING(function)
+ \relates <QtGlobal>
+ \ingroup qts60
+
+ Catch standard C++ exceptions from \a function and convert them to Symbian OS
+ leaves. This must be used inside Qt or standard C++ code when using exception
+ throwing code (practically anything) and returning to Symbian OS from a leaving function.
+ For example inside a Symbian active object's \c RunL function implemented with Qt code.
+
+ \warning This macro is only available on Symbian.
+
+ Example:
+
+ \code
+ // This active object signals Qt code
+ // Exceptions from the Qt code must be converted to Symbian OS leaves for the active scheduler
+ void QWakeUpActiveObject::RunL()
+ {
+ iStatus = KRequestPending;
+ SetActive();
+ QT_TRYCATCH_LEAVING(m_dispatcher->wakeUpWasCalled());
+ }
+ \endcode
+
+ \sa QT_TRAP_THROWING(), QT_TRYCATCH_ERROR()
+*/
+
+#include <stdexcept>
+
+class QSymbianLeaveException : public std::exception
+{
+public:
+ inline QSymbianLeaveException(int err) : error(err) {}
+ inline const char* what() const throw() { return "Symbian leave exception"; }
+
+public:
+ int error;
+};
+
+/*! \relates <QtGlobal>
+ \ingroup qts60
+
+ Throws an exception if the \a error parameter is a symbian error code.
+ This is the exception throwing equivalent of Symbian's User::LeaveIfError.
+
+ \warning This function is only available on Symbian.
+
+ \sa qt_symbian_exception2LeaveL(), qt_symbian_exception2Error()
+*/
+void qt_symbian_throwIfError(int error)
+{
+ if (error >= KErrNone)
+ return; // do nothing - not an exception
+ switch (error) {
+ case KErrNoMemory:
+ throw std::bad_alloc();
+ case KErrArgument:
+ throw std::invalid_argument("from Symbian error");
+ case KErrOverflow:
+ throw std::overflow_error("from Symbian error");
+ case KErrUnderflow:
+ throw std::underflow_error("from Symbian error");
+ default:
+ throw QSymbianLeaveException(error);
+ }
+}
+
+/*! \relates <QtGlobal>
+ \ingroup qts60
+
+ Convert a caught standard C++ exception \a aThrow to a Symbian leave
+
+ \warning This function is only available on Symbian.
+
+ \sa qt_symbian_throwIfError(), qt_symbian_exception2Error()
+*/
+void qt_symbian_exception2LeaveL(const std::exception& aThrow)
+{
+ User::Leave(qt_symbian_exception2Error(aThrow));
+}
+
+/*! \relates <QtGlobal>
+ \ingroup qts60
+
+ Convert a caught standard C++ exception \a aThrow to a Symbian error code
+
+ \warning This function is only available on Symbian.
+
+ \sa qt_symbian_throwIfError(), qt_symbian_exception2LeaveL()
+*/
+int qt_symbian_exception2Error(const std::exception& aThrow)
+{
+ const std::type_info& atype = typeid(aThrow);
+ int err = KErrGeneral;
+
+ if(atype == typeid (std::bad_alloc))
+ err = KErrNoMemory;
+ else if(atype == typeid(QSymbianLeaveException))
+ err = static_cast<const QSymbianLeaveException&>(aThrow).error;
+ else {
+ if(atype == typeid(std::invalid_argument))
+ err = KErrArgument;
+ else if(atype == typeid(std::out_of_range))
+ // std::out_of_range is of type logic_error which by definition means that it is
+ // "presumably detectable before the program executes".
+ // std::out_of_range is used to report an argument is not within the expected range.
+ // The description of KErrArgument says an argument is out of range. Hence the mapping.
+ err = KErrArgument;
+ else if(atype == typeid(std::overflow_error))
+ err = KErrOverflow;
+ else if(atype == typeid(std::underflow_error))
+ err = KErrUnderflow;
+ qWarning("translation from std exception \"%s\" to %d", aThrow.what(), err);
+ }
+
+ return err;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
new file mode 100644
index 0000000000..9434eb29f7
--- /dev/null
+++ b/src/corelib/global/qglobal.h
@@ -0,0 +1,2767 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLOBAL_H
+#define QGLOBAL_H
+
+#include <stddef.h>
+
+#define QT_VERSION_STR "4.8.0"
+/*
+ QT_VERSION is (major << 16) + (minor << 8) + patch.
+*/
+#define QT_VERSION 0x040800
+/*
+ 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))
+
+#define QT_PACKAGEDATE_STR "YYYY-MM-DD"
+
+#define QT_PACKAGE_TAG ""
+
+#if !defined(QT_BUILD_MOC)
+#include <QtCore/qconfig.h>
+#endif
+
+#ifdef __cplusplus
+
+#ifndef QT_NO_STL
+#include <algorithm>
+#endif
+
+#ifndef QT_NAMESPACE /* 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_BEGIN_MOC_NAMESPACE
+# define QT_END_MOC_NAMESPACE
+# 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 {
+# define QT_BEGIN_MOC_NAMESPACE QT_USE_NAMESPACE
+# define QT_END_MOC_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);
+
+# 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 */
+
+#if defined(Q_OS_MAC) && !defined(Q_CC_INTEL)
+#define QT_BEGIN_HEADER extern "C++" {
+#define QT_END_HEADER }
+#define QT_BEGIN_INCLUDE_HEADER }
+#define QT_END_INCLUDE_HEADER extern "C++" {
+#else
+#define QT_BEGIN_HEADER
+#define QT_END_HEADER
+#define QT_BEGIN_INCLUDE_HEADER
+#define QT_END_INCLUDE_HEADER extern "C++"
+#endif
+
+/*
+ The operating system, must be one of: (Q_OS_x)
+
+ DARWIN - Darwin OS (synonym for Q_OS_MAC)
+ SYMBIAN - Symbian
+ MSDOS - MS-DOS and Windows
+ OS2 - OS/2
+ OS2EMX - XFree86 on OS/2 (not PM)
+ WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
+ WINCE - WinCE (Windows CE 5.0)
+ CYGWIN - Cygwin
+ SOLARIS - Sun Solaris
+ HPUX - HP-UX
+ ULTRIX - DEC Ultrix
+ LINUX - Linux
+ FREEBSD - FreeBSD
+ NETBSD - NetBSD
+ OPENBSD - OpenBSD
+ BSDI - BSD/OS
+ IRIX - SGI Irix
+ OSF - HP Tru64 UNIX
+ SCO - SCO OpenServer 5
+ UNIXWARE - UnixWare 7, Open UNIX 8
+ AIX - AIX
+ HURD - GNU Hurd
+ DGUX - DG/UX
+ RELIANT - Reliant UNIX
+ DYNIX - DYNIX/ptx
+ QNX - QNX
+ QNX6 - QNX RTP 6.1
+ LYNX - LynxOS
+ BSD4 - Any BSD 4.4 system
+ UNIX - Any UNIX BSD/SYSV system
+*/
+
+#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
+# define Q_OS_DARWIN
+# define Q_OS_BSD4
+# ifdef __LP64__
+# define Q_OS_DARWIN64
+# else
+# define Q_OS_DARWIN32
+# endif
+#elif defined(__SYMBIAN32__) || defined(SYMBIAN)
+# define Q_OS_SYMBIAN
+# define Q_NO_POSIX_SIGNALS
+# define QT_NO_GETIFADDRS
+#elif defined(__CYGWIN__)
+# define Q_OS_CYGWIN
+#elif defined(MSDOS) || defined(_MSDOS)
+# define Q_OS_MSDOS
+#elif defined(__OS2__)
+# if defined(__EMX__)
+# define Q_OS_OS2EMX
+# else
+# define Q_OS_OS2
+# endif
+#elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
+# define Q_OS_WIN32
+# define Q_OS_WIN64
+#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
+# if defined(WINCE) || defined(_WIN32_WCE)
+# define Q_OS_WINCE
+# else
+# define Q_OS_WIN32
+# endif
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define Q_OS_WIN32
+#elif defined(__sun) || defined(sun)
+# define Q_OS_SOLARIS
+#elif defined(hpux) || defined(__hpux)
+# define Q_OS_HPUX
+#elif defined(__ultrix) || defined(ultrix)
+# define Q_OS_ULTRIX
+#elif defined(sinix)
+# define Q_OS_RELIANT
+#elif defined(__native_client__)
+# define Q_OS_NACL
+#elif defined(__linux__) || defined(__linux)
+# define Q_OS_LINUX
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+# define Q_OS_FREEBSD
+# define Q_OS_BSD4
+#elif defined(__NetBSD__)
+# define Q_OS_NETBSD
+# define Q_OS_BSD4
+#elif defined(__OpenBSD__)
+# define Q_OS_OPENBSD
+# define Q_OS_BSD4
+#elif defined(__bsdi__)
+# define Q_OS_BSDI
+# define Q_OS_BSD4
+#elif defined(__sgi)
+# define Q_OS_IRIX
+#elif defined(__osf__)
+# define Q_OS_OSF
+#elif defined(_AIX)
+# define Q_OS_AIX
+#elif defined(__Lynx__)
+# define Q_OS_LYNX
+#elif defined(__GNU__)
+# define Q_OS_HURD
+#elif defined(__DGUX__)
+# define Q_OS_DGUX
+#elif defined(__QNXNTO__)
+# define Q_OS_QNX
+#elif defined(_SEQUENT_)
+# define Q_OS_DYNIX
+#elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */
+# define Q_OS_SCO
+#elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */
+# define Q_OS_UNIXWARE
+#elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */
+# define Q_OS_UNIXWARE
+#elif defined(__INTEGRITY)
+# define Q_OS_INTEGRITY
+#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */
+# define Q_OS_VXWORKS
+#elif defined(__MAKEDEPEND__)
+#else
+# error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com"
+#endif
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE)
+# define Q_OS_WIN
+#endif
+
+#if defined(Q_OS_DARWIN)
+# define Q_OS_MAC /* Q_OS_MAC is mostly for compatibility, but also more clear */
+# define Q_OS_MACX /* Q_OS_MACX is only for compatibility.*/
+# if defined(Q_OS_DARWIN64)
+# define Q_OS_MAC64
+# elif defined(Q_OS_DARWIN32)
+# define Q_OS_MAC32
+# endif
+#endif
+
+#ifdef QT_AUTODETECT_COCOA
+# ifdef Q_OS_MAC64
+# define QT_MAC_USE_COCOA 1
+# define QT_BUILD_KEY QT_BUILD_KEY_COCOA
+# else
+# define QT_BUILD_KEY QT_BUILD_KEY_CARBON
+# endif
+#endif
+
+#if defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) && !defined(QT_BOOTSTRAPPED)
+#error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration."
+#endif
+
+#if defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN)
+# undef Q_OS_UNIX
+#elif !defined(Q_OS_UNIX)
+# define Q_OS_UNIX
+#endif
+
+#if defined(Q_OS_DARWIN) && !defined(QT_LARGEFILE_SUPPORT)
+# define QT_LARGEFILE_SUPPORT 64
+#endif
+
+#ifdef Q_OS_DARWIN
+# ifdef MAC_OS_X_VERSION_MIN_REQUIRED
+# undef MAC_OS_X_VERSION_MIN_REQUIRED
+# endif
+# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
+# include <AvailabilityMacros.h>
+# if !defined(MAC_OS_X_VERSION_10_3)
+# define MAC_OS_X_VERSION_10_3 MAC_OS_X_VERSION_10_2 + 1
+# endif
+# if !defined(MAC_OS_X_VERSION_10_4)
+# define MAC_OS_X_VERSION_10_4 MAC_OS_X_VERSION_10_3 + 1
+# endif
+# if !defined(MAC_OS_X_VERSION_10_5)
+# define MAC_OS_X_VERSION_10_5 MAC_OS_X_VERSION_10_4 + 1
+# endif
+# if !defined(MAC_OS_X_VERSION_10_6)
+# define MAC_OS_X_VERSION_10_6 MAC_OS_X_VERSION_10_5 + 1
+# endif
+# if !defined(MAC_OS_X_VERSION_10_7)
+# define MAC_OS_X_VERSION_10_7 MAC_OS_X_VERSION_10_6 + 1
+# endif
+# if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7)
+# warning "This version of Mac OS X is unsupported"
+# endif
+#endif
+
+#ifdef __LSB_VERSION__
+# if __LSB_VERSION__ < 40
+# error "This version of the Linux Standard Base is unsupported"
+# endif
+#ifndef QT_LINUXBASE
+# define QT_LINUXBASE
+#endif
+#endif
+
+/*
+ The compiler, must be one of: (Q_CC_x)
+
+ SYM - Digital Mars C/C++ (used to be Symantec C++)
+ MWERKS - Metrowerks CodeWarrior
+ MSVC - Microsoft Visual C/C++, Intel C++ for Windows
+ BOR - Borland/Turbo C++
+ WAT - Watcom C++
+ GNU - GNU C++
+ COMEAU - Comeau C++
+ EDG - Edison Design Group C++
+ OC - CenterLine C++
+ SUN - Forte Developer, or Sun Studio C++
+ MIPS - MIPSpro C++
+ DEC - DEC C++
+ HPACC - HP aC++
+ USLC - SCO OUDK and UDK
+ CDS - Reliant C++
+ KAI - KAI C++
+ INTEL - Intel C++ for Linux, Intel C++ for Windows
+ HIGHC - MetaWare High C/C++
+ PGI - Portland Group C++
+ GHS - Green Hills Optimizing C++ Compilers
+ GCCE - GCCE (Symbian GCCE builds)
+ RVCT - ARM Realview Compiler Suite
+ NOKIAX86 - Nokia x86 (Symbian WINSCW builds)
+ CLANG - C++ front-end for the LLVM compiler
+
+
+ Should be sorted most to least authoritative.
+*/
+
+#if defined(__ghs)
+# define Q_OUTOFLINE_TEMPLATE inline
+
+/* the following are necessary because the GHS C++ name mangling relies on __*/
+# define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
+ static const int AFUNC ## _init_variable_ = AFUNC();
+# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
+# define Q_DESTRUCTOR_FUNCTION0(AFUNC) \
+ class AFUNC ## _dest_class_ { \
+ public: \
+ inline AFUNC ## _dest_class_() { } \
+ inline ~ AFUNC ## _dest_class_() { AFUNC(); } \
+ } AFUNC ## _dest_instance_;
+# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
+
+#endif
+
+/* Symantec C++ is now Digital Mars */
+#if defined(__DMC__) || defined(__SC__)
+# define Q_CC_SYM
+/* "explicit" semantics implemented in 8.1e but keyword recognized since 7.5 */
+# if defined(__SC__) && __SC__ < 0x750
+# define Q_NO_EXPLICIT_KEYWORD
+# endif
+# define Q_NO_USING_KEYWORD
+
+#elif defined(__MWERKS__)
+# define Q_CC_MWERKS
+# if defined(__EMU_SYMBIAN_OS__)
+# define Q_CC_NOKIAX86
+# endif
+/* "explicit" recognized since 4.0d1 */
+
+#elif defined(_MSC_VER)
+# define Q_CC_MSVC
+# define Q_CC_MSVC_NET
+# define Q_CANNOT_DELETE_CONSTANT
+# define Q_OUTOFLINE_TEMPLATE inline
+# define Q_NO_TEMPLATE_FRIENDS
+# define Q_ALIGNOF(type) __alignof(type)
+# define Q_DECL_ALIGN(n) __declspec(align(n))
+/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
+# if defined(__INTEL_COMPILER)
+# define Q_CC_INTEL
+# endif
+/* MSVC does not support SSE/MMX on x64 */
+# if (defined(Q_CC_MSVC) && defined(_M_X64))
+# undef QT_HAVE_SSE
+# undef QT_HAVE_MMX
+# undef QT_HAVE_3DNOW
+# endif
+
+#if defined(Q_CC_MSVC) && _MSC_VER >= 1600
+# define Q_COMPILER_RVALUE_REFS
+# define Q_COMPILER_INITIALIZER_LISTS
+# define Q_COMPILER_AUTO_TYPE
+# define Q_COMPILER_LAMBDA
+//# define Q_COMPILER_VARIADIC_TEMPLATES
+//# define Q_COMPILER_CLASS_ENUM
+//# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
+//# define Q_COMPILER_UNICODE_STRINGS
+//# define Q_COMPILER_EXTERN_TEMPLATES
+# endif
+
+
+#elif defined(__BORLANDC__) || defined(__TURBOC__)
+# define Q_CC_BOR
+# define Q_INLINE_TEMPLATE
+# if __BORLANDC__ < 0x502
+# define Q_NO_BOOL_TYPE
+# define Q_NO_EXPLICIT_KEYWORD
+# endif
+# define Q_NO_USING_KEYWORD
+
+#elif defined(__WATCOMC__)
+# define Q_CC_WAT
+
+/* Symbian GCCE */
+#elif defined(__GCCE__)
+# define Q_CC_GCCE
+# define QT_VISIBILITY_AVAILABLE
+# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
+# define QT_HAVE_ARMV6
+# endif
+
+/* ARM Realview Compiler Suite
+ RVCT compiler also defines __EDG__ and __GNUC__ (if --gnu flag is given),
+ so check for it before that */
+#elif defined(__ARMCC__) || defined(__CC_ARM)
+# define Q_CC_RVCT
+# if __TARGET_ARCH_ARM >= 6
+# define QT_HAVE_ARMV6
+# endif
+/* work-around for missing compiler intrinsics */
+# define __is_empty(X) false
+# define __is_pod(X) false
+#elif defined(__GNUC__)
+# define Q_CC_GNU
+# define Q_C_CALLBACKS
+# if defined(__MINGW32__)
+# define Q_CC_MINGW
+# endif
+# if defined(__INTEL_COMPILER)
+/* Intel C++ also masquerades as GCC 3.2.0 */
+# define Q_CC_INTEL
+# endif
+# if defined(__clang__)
+/* Clang also masquerades as GCC 4.2.1 */
+# define Q_CC_CLANG
+# endif
+# ifdef __APPLE__
+# define Q_NO_DEPRECATED_CONSTRUCTORS
+# endif
+# if __GNUC__ == 2 && __GNUC_MINOR__ <= 7
+# define Q_FULL_TEMPLATE_INSTANTIATION
+# endif
+/* GCC 2.95 knows "using" but does not support it correctly */
+# if __GNUC__ == 2 && __GNUC_MINOR__ <= 95
+# define Q_NO_USING_KEYWORD
+# define QT_NO_STL_WCHAR
+# endif
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+# define Q_ALIGNOF(type) __alignof__(type)
+# define Q_TYPEOF(expr) __typeof__(expr)
+# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
+# endif
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# define Q_LIKELY(expr) __builtin_expect(!!(expr), true)
+# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
+# endif
+/* GCC 3.1 and GCC 3.2 wrongly define _SB_CTYPE_MACROS on HP-UX */
+# if defined(Q_OS_HPUX) && __GNUC__ == 3 && __GNUC_MINOR__ >= 1
+# define Q_WRONG_SB_CTYPE_MACROS
+# endif
+/* GCC <= 3.3 cannot handle template friends */
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+# define Q_NO_TEMPLATE_FRIENDS
+# endif
+/* Apple's GCC 3.1 chokes on our streaming qDebug() */
+# if defined(Q_OS_DARWIN) && __GNUC__ == 3 && (__GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 3)
+# define Q_BROKEN_DEBUG_STREAM
+# endif
+# if (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_MOC_CPP)
+# define Q_PACKED __attribute__ ((__packed__))
+# define Q_NO_PACKED_REFERENCE
+# ifndef __ARM_EABI__
+# define QT_NO_ARM_EABI
+# endif
+# endif
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
+ /* C++0x features supported in GCC 4.3: */
+# define Q_COMPILER_RVALUE_REFS
+# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
+ /* C++0x features supported in GCC 4.4: */
+# define Q_COMPILER_VARIADIC_TEMPLATES
+# define Q_COMPILER_AUTO_TYPE
+# define Q_COMPILER_EXTERN_TEMPLATES
+# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
+# define Q_COMPILER_CLASS_ENUM
+# define Q_COMPILER_INITIALIZER_LISTS
+# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
+ /* C++0x features supported in GCC 4.5: */
+# define Q_COMPILER_LAMBDA
+# define Q_COMPILER_UNICODE_STRINGS
+# endif
+# endif
+
+/* IBM compiler versions are a bit messy. There are actually two products:
+ the C product, and the C++ product. The C++ compiler is always packaged
+ with the latest version of the C compiler. Version numbers do not always
+ match. This little table (I'm not sure it's accurate) should be helpful:
+
+ C++ product C product
+
+ C Set 3.1 C Compiler 3.0
+ ... ...
+ C++ Compiler 3.6.6 C Compiler 4.3
+ ... ...
+ Visual Age C++ 4.0 ...
+ ... ...
+ Visual Age C++ 5.0 C Compiler 5.0
+ ... ...
+ Visual Age C++ 6.0 C Compiler 6.0
+
+ Now:
+ __xlC__ is the version of the C compiler in hexadecimal notation
+ is only an approximation of the C++ compiler version
+ __IBMCPP__ is the version of the C++ compiler in decimal notation
+ 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
+# define Q_NO_BOOL_TYPE
+# define Q_NO_EXPLICIT_KEYWORD
+# define Q_NO_USING_KEYWORD
+# define Q_TYPENAME
+# define Q_OUTOFLINE_TEMPLATE inline
+# define Q_BROKEN_TEMPLATE_SPECIALIZATION
+# define Q_CANNOT_DELETE_CONSTANT
+# elif __xlC__ >= 0x0600
+# define Q_ALIGNOF(type) __alignof__(type)
+# define Q_TYPEOF(expr) __typeof__(expr)
+# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
+# define Q_PACKED __attribute__((__packed__))
+# endif
+
+/* Older versions of DEC C++ do not define __EDG__ or __EDG - observed
+ on DEC C++ V5.5-004. New versions do define __EDG__ - observed on
+ Compaq C++ V6.3-002.
+ This compiler is different enough from other EDG compilers to handle
+ it separately anyway. */
+#elif defined(__DECCXX) || defined(__DECC)
+# define Q_CC_DEC
+/* Compaq C++ V6 compilers are EDG-based but I'm not sure about older
+ DEC C++ V5 compilers. */
+# if defined(__EDG__)
+# define Q_CC_EDG
+# endif
+/* Compaq have disabled EDG's _BOOL macro and use _BOOL_EXISTS instead
+ - observed on Compaq C++ V6.3-002.
+ In any case versions prior to Compaq C++ V6.0-005 do not have bool. */
+# if !defined(_BOOL_EXISTS)
+# define Q_NO_BOOL_TYPE
+# endif
+/* Spurious (?) error messages observed on Compaq C++ V6.5-014. */
+# define Q_NO_USING_KEYWORD
+/* Apply to all versions prior to Compaq C++ V6.0-000 - observed on
+ DEC C++ V5.5-004. */
+# if __DECCXX_VER < 60060000
+# define Q_TYPENAME
+# define Q_BROKEN_TEMPLATE_SPECIALIZATION
+# define Q_CANNOT_DELETE_CONSTANT
+# endif
+/* avoid undefined symbol problems with out-of-line template members */
+# define Q_OUTOFLINE_TEMPLATE inline
+
+/* The Portland Group C++ compiler is based on EDG and does define __EDG__
+ but the C compiler does not */
+#elif defined(__PGI)
+# define Q_CC_PGI
+# if defined(__EDG__)
+# define Q_CC_EDG
+# endif
+
+/* Compilers with EDG front end are similar. To detect them we test:
+ __EDG documented by SGI, observed on MIPSpro 7.3.1.1 and KAI C++ 4.0b
+ __EDG__ documented in EDG online docs, observed on Compaq C++ V6.3-002
+ and PGI C++ 5.2-4 */
+#elif !defined(Q_OS_HPUX) && (defined(__EDG) || defined(__EDG__))
+# define Q_CC_EDG
+/* From the EDG documentation (does not seem to apply to Compaq C++):
+ _BOOL
+ Defined in C++ mode when bool is a keyword. The name of this
+ predefined macro is specified by a configuration flag. _BOOL
+ is the default.
+ __BOOL_DEFINED
+ Defined in Microsoft C++ mode when bool is a keyword. */
+# if !defined(_BOOL) && !defined(__BOOL_DEFINED)
+# define Q_NO_BOOL_TYPE
+# endif
+
+/* The Comeau compiler is based on EDG and does define __EDG__ */
+# if defined(__COMO__)
+# define Q_CC_COMEAU
+# define Q_C_CALLBACKS
+
+/* The `using' keyword was introduced to avoid KAI C++ warnings
+ but it's now causing KAI C++ errors instead. The standard is
+ unclear about the use of this keyword, and in practice every
+ compiler is using its own set of rules. Forget it. */
+# elif defined(__KCC)
+# define Q_CC_KAI
+# define Q_NO_USING_KEYWORD
+
+/* Using the `using' keyword avoids Intel C++ for Linux warnings */
+# elif defined(__INTEL_COMPILER)
+# define Q_CC_INTEL
+
+/* Uses CFront, make sure to read the manual how to tweak templates. */
+# elif defined(__ghs)
+# define Q_CC_GHS
+
+# elif defined(__DCC__)
+# define Q_CC_DIAB
+# undef Q_NO_BOOL_TYPE
+# if !defined(__bool)
+# define Q_NO_BOOL_TYPE
+# endif
+
+/* The UnixWare 7 UDK compiler is based on EDG and does define __EDG__ */
+# elif defined(__USLC__) && defined(__SCO_VERSION__)
+# define Q_CC_USLC
+/* The latest UDK 7.1.1b does not need this, but previous versions do */
+# if !defined(__SCO_VERSION__) || (__SCO_VERSION__ < 302200010)
+# define Q_OUTOFLINE_TEMPLATE inline
+# endif
+# define Q_NO_USING_KEYWORD /* ### check "using" status */
+
+/* Never tested! */
+# elif defined(CENTERLINE_CLPP) || defined(OBJECTCENTER)
+# define Q_CC_OC
+# define Q_NO_USING_KEYWORD
+
+/* CDS++ defines __EDG__ although this is not documented in the Reliant
+ documentation. It also follows conventions like _BOOL and this documented */
+# elif defined(sinix)
+# define Q_CC_CDS
+# define Q_NO_USING_KEYWORD
+
+/* The MIPSpro compiler defines __EDG */
+# elif defined(__sgi)
+# define Q_CC_MIPS
+# define Q_NO_USING_KEYWORD /* ### check "using" status */
+# 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
+ (see __DCC__ above). This one is for C mode files (__EDG is not defined) */
+#elif defined(_DIAB_TOOL)
+# define Q_CC_DIAB
+
+/* Never tested! */
+#elif defined(__HIGHC__)
+# define Q_CC_HIGHC
+
+#elif defined(__SUNPRO_CC) || defined(__SUNPRO_C)
+# define Q_CC_SUN
+/* 5.0 compiler or better
+ 'bool' is enabled by default but can be disabled using -features=nobool
+ in which case _BOOL is not defined
+ this is the default in 4.2 compatibility mode triggered by -compat=4 */
+# if __SUNPRO_CC >= 0x500
+# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
+ /* see http://developers.sun.com/sunstudio/support/Ccompare.html */
+# if __SUNPRO_CC >= 0x590
+# define Q_ALIGNOF(type) __alignof__(type)
+# define Q_TYPEOF(expr) __typeof__(expr)
+# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
+# endif
+# if __SUNPRO_CC >= 0x550
+# define Q_DECL_EXPORT __global
+# endif
+# if __SUNPRO_CC < 0x5a0
+# define Q_NO_TEMPLATE_FRIENDS
+# endif
+# if !defined(_BOOL)
+# define Q_NO_BOOL_TYPE
+# endif
+# if defined(__SUNPRO_CC_COMPAT) && (__SUNPRO_CC_COMPAT <= 4)
+# define Q_NO_USING_KEYWORD
+# endif
+# define Q_C_CALLBACKS
+/* 4.2 compiler or older */
+# else
+# define Q_NO_BOOL_TYPE
+# define Q_NO_EXPLICIT_KEYWORD
+# define Q_NO_USING_KEYWORD
+# endif
+
+/* CDS++ does not seem to define __EDG__ or __EDG according to Reliant
+ documentation but nevertheless uses EDG conventions like _BOOL */
+#elif defined(sinix)
+# define Q_CC_EDG
+# define Q_CC_CDS
+# if !defined(_BOOL)
+# define Q_NO_BOOL_TYPE
+# 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
+# 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 >= 061200
+# define Q_DECL_ALIGN(n) __attribute__((aligned(n)))
+# 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
+# define Q_CC_HP
+# define Q_NO_BOOL_TYPE
+# define Q_FULL_TEMPLATE_INSTANTIATION
+# define Q_BROKEN_TEMPLATE_SPECIALIZATION
+# define Q_NO_EXPLICIT_KEYWORD
+# endif
+# define Q_NO_USING_KEYWORD /* ### check "using" status */
+
+#elif defined(__WINSCW__) && !defined(Q_CC_NOKIAX86)
+# define Q_CC_NOKIAX86
+
+#else
+# error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com"
+#endif
+
+
+#ifdef Q_CC_INTEL
+# if __INTEL_COMPILER < 1200
+# define Q_NO_TEMPLATE_FRIENDS
+# endif
+# if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
+# if __INTEL_COMPILER >= 1100
+# define Q_COMPILER_RVALUE_REFS
+# define Q_COMPILER_EXTERN_TEMPLATES
+# elif __INTEL_COMPILER >= 1200
+# define Q_COMPILER_VARIADIC_TEMPLATES
+# define Q_COMPILER_AUTO_TYPE
+# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
+# define Q_COMPILER_CLASS_ENUM
+# define Q_COMPILER_LAMBDA
+# endif
+# endif
+#endif
+
+#ifndef Q_PACKED
+# define Q_PACKED
+# undef Q_NO_PACKED_REFERENCE
+#endif
+
+#ifndef Q_LIKELY
+# define Q_LIKELY(x) (x)
+#endif
+#ifndef Q_UNLIKELY
+# define Q_UNLIKELY(x) (x)
+#endif
+
+#ifndef Q_CONSTRUCTOR_FUNCTION
+# define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
+ static const int AFUNC ## __init_variable__ = AFUNC();
+# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
+#endif
+
+#ifndef Q_DESTRUCTOR_FUNCTION
+# define Q_DESTRUCTOR_FUNCTION0(AFUNC) \
+ class AFUNC ## __dest_class__ { \
+ public: \
+ inline AFUNC ## __dest_class__() { } \
+ inline ~ AFUNC ## __dest_class__() { AFUNC(); } \
+ } AFUNC ## __dest_instance__;
+# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
+#endif
+
+#ifndef Q_REQUIRED_RESULT
+# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+# define Q_REQUIRED_RESULT __attribute__ ((warn_unused_result))
+# else
+# define Q_REQUIRED_RESULT
+# endif
+#endif
+
+#ifndef Q_COMPILER_MANGLES_RETURN_TYPE
+# if defined(Q_CC_MSVC)
+# define Q_COMPILER_MANGLES_RETURN_TYPE
+# endif
+#endif
+
+/*
+ The window system, must be one of: (Q_WS_x)
+
+ MACX - Mac OS X
+ MAC9 - Mac OS 9
+ QWS - Qt for Embedded Linux
+ WIN32 - Windows
+ X11 - X Window System
+ S60 - Symbian S60
+ PM - unsupported
+ WIN16 - unsupported
+*/
+
+#if defined(Q_OS_MSDOS)
+# define Q_WS_WIN16
+# error "Qt requires Win32 and does not work with Windows 3.x"
+#elif defined(_WIN32_X11_)
+# define Q_WS_X11
+#elif defined(Q_OS_WIN32)
+# define Q_WS_WIN32
+# if defined(Q_OS_WIN64)
+# define Q_WS_WIN64
+# endif
+#elif defined(Q_OS_WINCE)
+# define Q_WS_WIN32
+# define Q_WS_WINCE
+# if defined(Q_OS_WINCE_WM)
+# define Q_WS_WINCE_WM
+# endif
+#elif defined(Q_OS_OS2)
+# define Q_WS_PM
+# error "Qt does not work with OS/2 Presentation Manager or Workplace Shell"
+#elif defined(Q_OS_UNIX)
+# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
+# define Q_WS_MAC
+# define Q_WS_MACX
+# if defined(Q_OS_MAC64)
+# define Q_WS_MAC64
+# elif defined(Q_OS_MAC32)
+# define Q_WS_MAC32
+# endif
+# elif defined(Q_OS_SYMBIAN)
+# if !defined(QT_NO_S60)
+# define Q_WS_S60
+# endif
+# elif !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
+# define Q_WS_X11
+# endif
+#endif
+
+#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32) || defined(Q_WS_WINCE)
+# define Q_WS_WIN
+#endif
+
+QT_BEGIN_HEADER
+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) && !defined(Q_CC_MWERKS)
+# 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
+# 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 */
+typedef long long qint64; /* 64 bit signed */
+typedef unsigned long long quint64; /* 64 bit unsigned */
+#endif
+
+typedef qint64 qlonglong;
+typedef quint64 qulonglong;
+
+#ifndef QT_POINTER_SIZE
+# if defined(Q_OS_WIN64)
+# define QT_POINTER_SIZE 8
+# elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+# define QT_POINTER_SIZE 4
+# endif
+#endif
+
+#define Q_INIT_RESOURCE_EXTERN(name) \
+ extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) ();
+
+#define Q_INIT_RESOURCE(name) \
+ do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \
+ QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0)
+#define Q_CLEANUP_RESOURCE(name) \
+ do { extern int QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); \
+ QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); } while (0)
+
+#if defined(__cplusplus)
+
+/*
+ quintptr and qptrdiff is guaranteed to be the same size as a pointer, i.e.
+
+ sizeof(void *) == sizeof(quintptr)
+ && sizeof(void *) == sizeof(qptrdiff)
+*/
+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; };
+template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
+typedef QIntegerForSizeof<void*>::Unsigned quintptr;
+typedef QIntegerForSizeof<void*>::Signed qptrdiff;
+
+/*
+ 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(Q_NO_BOOL_TYPE)
+#error "Compiler doesn't support the bool type"
+#endif
+
+/*
+ Constant bool values
+*/
+
+#ifndef QT_LINUXBASE /* the LSB defines TRUE and FALSE for us */
+/* Symbian OS defines TRUE = 1 and FALSE = 0,
+redefine to built-in booleans to make autotests work properly */
+#ifdef Q_OS_SYMBIAN
+ #include <e32def.h> /* Symbian OS defines */
+
+ #undef TRUE
+ #undef FALSE
+#endif
+# ifndef TRUE
+# define TRUE true
+# define FALSE false
+# endif
+#endif
+
+/*
+ Proper for-scoping in MIPSpro CC
+*/
+#ifndef QT_NO_KEYWORDS
+# if defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64))
+# define for if(0){}else for
+# endif
+#endif
+
+/*
+ Workaround for static const members on MSVC++.
+*/
+
+#if defined(Q_CC_MSVC)
+# define QT_STATIC_CONST static
+# define QT_STATIC_CONST_IMPL
+#else
+# define QT_STATIC_CONST static const
+# define QT_STATIC_CONST_IMPL const
+#endif
+
+/*
+ Warnings and errors when using deprecated methods
+*/
+#if defined(Q_MOC_RUN)
+# define Q_DECL_DEPRECATED Q_DECL_DEPRECATED
+#elif (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2))) || defined(Q_CC_RVCT)
+# define Q_DECL_DEPRECATED __attribute__ ((__deprecated__))
+#elif defined(Q_CC_MSVC)
+# define Q_DECL_DEPRECATED __declspec(deprecated)
+# if defined (Q_CC_INTEL)
+# define Q_DECL_VARIABLE_DEPRECATED
+# else
+# endif
+#else
+# define Q_DECL_DEPRECATED
+#endif
+#ifndef Q_DECL_VARIABLE_DEPRECATED
+# define Q_DECL_VARIABLE_DEPRECATED Q_DECL_DEPRECATED
+#endif
+#ifndef Q_DECL_CONSTRUCTOR_DEPRECATED
+# if defined(Q_MOC_RUN)
+# define Q_DECL_CONSTRUCTOR_DEPRECATED Q_DECL_CONSTRUCTOR_DEPRECATED
+# elif defined(Q_NO_DEPRECATED_CONSTRUCTORS)
+# define Q_DECL_CONSTRUCTOR_DEPRECATED
+# else
+# define Q_DECL_CONSTRUCTOR_DEPRECATED Q_DECL_DEPRECATED
+# endif
+#endif
+
+#if defined(QT_NO_DEPRECATED)
+/* disable Qt3 support as well */
+# undef QT3_SUPPORT_WARNINGS
+# undef QT3_SUPPORT
+# undef QT_DEPRECATED
+# undef QT_DEPRECATED_VARIABLE
+# undef QT_DEPRECATED_CONSTRUCTOR
+#elif defined(QT_DEPRECATED_WARNINGS)
+# ifdef QT3_SUPPORT
+/* enable Qt3 support warnings as well */
+# undef QT3_SUPPORT_WARNINGS
+# define QT3_SUPPORT_WARNINGS
+# endif
+# undef QT_DEPRECATED
+# define QT_DEPRECATED Q_DECL_DEPRECATED
+# 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_VARIABLE
+# define QT_DEPRECATED_VARIABLE
+# undef QT_DEPRECATED_CONSTRUCTOR
+# define QT_DEPRECATED_CONSTRUCTOR
+#endif
+
+#if defined(QT3_SUPPORT_WARNINGS)
+# if !defined(QT_COMPAT_WARNINGS) /* also enable compat */
+# define QT_COMPAT_WARNINGS
+# endif
+# undef QT3_SUPPORT
+# define QT3_SUPPORT Q_DECL_DEPRECATED
+# undef QT3_SUPPORT_VARIABLE
+# define QT3_SUPPORT_VARIABLE Q_DECL_VARIABLE_DEPRECATED
+# undef QT3_SUPPORT_CONSTRUCTOR
+# define QT3_SUPPORT_CONSTRUCTOR explicit Q_DECL_CONSTRUCTOR_DEPRECATED
+#elif defined(QT3_SUPPORT) /* define back to nothing */
+# if !defined(QT_COMPAT) /* also enable qt3 support */
+# define QT_COMPAT
+# endif
+# undef QT3_SUPPORT
+# define QT3_SUPPORT
+# undef QT3_SUPPORT_VARIABLE
+# define QT3_SUPPORT_VARIABLE
+# undef QT3_SUPPORT_CONSTRUCTOR
+# define QT3_SUPPORT_CONSTRUCTOR explicit
+#endif
+
+/* moc compats (signals/slots) */
+#ifndef QT_MOC_COMPAT
+# if defined(QT3_SUPPORT)
+# define QT_MOC_COMPAT QT3_SUPPORT
+# else
+# define QT_MOC_COMPAT
+# endif
+#else
+# undef QT_MOC_COMPAT
+# define QT_MOC_COMPAT
+#endif
+
+#ifdef QT_ASCII_CAST_WARNINGS
+# define QT_ASCII_CAST_WARN Q_DECL_DEPRECATED
+# if defined(Q_CC_GNU) && __GNUC__ < 4
+ /* gcc < 4 doesn't like Q_DECL_DEPRECATED in front of constructors */
+# define QT_ASCII_CAST_WARN_CONSTRUCTOR
+# else
+# define QT_ASCII_CAST_WARN_CONSTRUCTOR Q_DECL_CONSTRUCTOR_DEPRECATED
+# endif
+#else
+# define QT_ASCII_CAST_WARN
+# define QT_ASCII_CAST_WARN_CONSTRUCTOR
+#endif
+
+#if defined(__i386__) || defined(_WIN32) || defined(_WIN32_WCE)
+# if defined(Q_CC_GNU)
+#if !defined(Q_CC_INTEL) && ((100*(__GNUC__ - 0) + 10*(__GNUC_MINOR__ - 0) + __GNUC_PATCHLEVEL__) >= 332)
+# define QT_FASTCALL __attribute__((regparm(3)))
+#else
+# define QT_FASTCALL
+#endif
+# elif defined(Q_CC_MSVC)
+# define QT_FASTCALL __fastcall
+# else
+# define QT_FASTCALL
+# endif
+#else
+# define QT_FASTCALL
+#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_WS_WIN)
+# if defined(Q_CC_MINGW)
+# 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;
+
+#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A)
+#define QT_NO_FPU
+#endif
+
+// This logic must match the one in qmetatype.h
+#if defined(QT_COORD_TYPE)
+typedef QT_COORD_TYPE qreal;
+#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
+typedef float qreal;
+#else
+typedef double qreal;
+#endif
+
+/*
+ Utility macros and inline functions
+*/
+
+template <typename T>
+inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
+
+inline int qRound(qreal d)
+{ return d >= qreal(0.0) ? int(d + qreal(0.5)) : int(d - int(d-1) + qreal(0.5)) + int(d-1); }
+
+#if defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
+inline qint64 qRound64(double d)
+{ return d >= 0.0 ? qint64(d + 0.5) : qint64(d - qreal(qint64(d-1)) + 0.5) + qint64(d-1); }
+#else
+inline qint64 qRound64(qreal d)
+{ return d >= qreal(0.0) ? qint64(d + qreal(0.5)) : qint64(d - qreal(qint64(d-1)) + qreal(0.5)) + qint64(d-1); }
+#endif
+
+template <typename T>
+inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; }
+template <typename T>
+inline const T &qMax(const T &a, const T &b) { if (a < b) return b; return a; }
+template <typename T>
+inline const T &qBound(const T &min, const T &val, const T &max)
+{ return qMax(min, qMin(max, val)); }
+
+#ifdef QT3_SUPPORT
+typedef qint8 Q_INT8;
+typedef quint8 Q_UINT8;
+typedef qint16 Q_INT16;
+typedef quint16 Q_UINT16;
+typedef qint32 Q_INT32;
+typedef quint32 Q_UINT32;
+typedef qint64 Q_INT64;
+typedef quint64 Q_UINT64;
+
+typedef qint64 Q_LLONG;
+typedef quint64 Q_ULLONG;
+#if defined(Q_OS_WIN64)
+typedef __int64 Q_LONG; /* word up to 64 bit signed */
+typedef unsigned __int64 Q_ULONG; /* word up to 64 bit unsigned */
+#else
+typedef long Q_LONG; /* word up to 64 bit signed */
+typedef unsigned long Q_ULONG; /* word up to 64 bit unsigned */
+#endif
+
+# define QABS(a) qAbs(a)
+# define QMAX(a, b) qMax((a), (b))
+# define QMIN(a, b) qMin((a), (b))
+#endif
+
+/*
+ Data stream functions are provided by many classes (defined in qdatastream.h)
+*/
+
+class QDataStream;
+
+#ifndef QT_BUILD_KEY
+#define QT_BUILD_KEY "unspecified"
+#endif
+
+#if defined(Q_WS_MAC)
+# ifndef QMAC_QMENUBAR_NO_EVENT
+# define QMAC_QMENUBAR_NO_EVENT
+# endif
+#endif
+
+#if !defined(Q_WS_QWS) && !defined(QT_NO_COP)
+# define QT_NO_COP
+#endif
+
+#if defined(Q_OS_VXWORKS)
+# define QT_NO_CRASHHANDLER // no popen
+# define QT_NO_PROCESS // no exec*, no fork
+# define QT_NO_LPR
+# define QT_NO_SHAREDMEMORY // only POSIX, no SysV and in the end...
+# define QT_NO_SYSTEMSEMAPHORE // not needed at all in a flat address space
+# define QT_NO_QWS_MULTIPROCESS // no processes
+#endif
+
+# include <QtCore/qfeatures.h>
+
+#define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
+
+#if defined(Q_OS_LINUX) && defined(Q_CC_RVCT)
+# define Q_DECL_EXPORT __attribute__((visibility("default")))
+# define Q_DECL_IMPORT __attribute__((visibility("default")))
+# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
+#endif
+
+#ifndef Q_DECL_EXPORT
+# if defined(Q_OS_WIN) || defined(Q_CC_NOKIAX86) || defined(Q_CC_RVCT)
+# define Q_DECL_EXPORT __declspec(dllexport)
+# elif defined(QT_VISIBILITY_AVAILABLE)
+# define Q_DECL_EXPORT __attribute__((visibility("default")))
+# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
+# endif
+# ifndef Q_DECL_EXPORT
+# define Q_DECL_EXPORT
+# endif
+#endif
+#ifndef Q_DECL_IMPORT
+# if defined(Q_OS_WIN) || defined(Q_CC_NOKIAX86) || defined(Q_CC_RVCT)
+# define Q_DECL_IMPORT __declspec(dllimport)
+# else
+# define Q_DECL_IMPORT
+# endif
+#endif
+#ifndef Q_DECL_HIDDEN
+# define Q_DECL_HIDDEN
+#endif
+
+
+/*
+ Create Qt DLL if QT_DLL is defined (Windows and Symbian only)
+*/
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+# if defined(QT_NODLL)
+# undef QT_MAKEDLL
+# undef QT_DLL
+# elif defined(QT_MAKEDLL) /* create a Qt DLL library */
+# if defined(QT_DLL)
+# undef QT_DLL
+# endif
+# if defined(QT_BUILD_CORE_LIB)
+# define Q_CORE_EXPORT Q_DECL_EXPORT
+# else
+# define Q_CORE_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_GUI_LIB)
+# define Q_GUI_EXPORT Q_DECL_EXPORT
+# else
+# define Q_GUI_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SQL_LIB)
+# define Q_SQL_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SQL_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_NETWORK_LIB)
+# define Q_NETWORK_EXPORT Q_DECL_EXPORT
+# else
+# define Q_NETWORK_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SVG_LIB)
+# define Q_SVG_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SVG_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_DECLARATIVE_LIB)
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
+# else
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_OPENGL_LIB)
+# define Q_OPENGL_EXPORT Q_DECL_EXPORT
+# else
+# define Q_OPENGL_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_MULTIMEDIA_LIB)
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_OPENVG_LIB)
+# define Q_OPENVG_EXPORT Q_DECL_EXPORT
+# else
+# define Q_OPENVG_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_XML_LIB)
+# define Q_XML_EXPORT Q_DECL_EXPORT
+# else
+# define Q_XML_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_XMLPATTERNS_LIB)
+# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SCRIPT_LIB)
+# define Q_SCRIPT_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SCRIPT_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SCRIPTTOOLS_LIB)
+# define Q_SCRIPTTOOLS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SCRIPTTOOLS_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_CANVAS_LIB)
+# define Q_CANVAS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_CANVAS_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_COMPAT_LIB)
+# define Q_COMPAT_EXPORT Q_DECL_EXPORT
+# else
+# define Q_COMPAT_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_DBUS_LIB)
+# define Q_DBUS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_DBUS_EXPORT Q_DECL_IMPORT
+# endif
+# define Q_TEMPLATEDLL
+# elif defined(QT_DLL) /* use a Qt DLL library */
+# define Q_CORE_EXPORT Q_DECL_IMPORT
+# define Q_GUI_EXPORT Q_DECL_IMPORT
+# define Q_SQL_EXPORT Q_DECL_IMPORT
+# define Q_NETWORK_EXPORT Q_DECL_IMPORT
+# define Q_SVG_EXPORT Q_DECL_IMPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
+# define Q_CANVAS_EXPORT Q_DECL_IMPORT
+# define Q_OPENGL_EXPORT Q_DECL_IMPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
+# define Q_OPENVG_EXPORT Q_DECL_IMPORT
+# define Q_XML_EXPORT Q_DECL_IMPORT
+# define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT
+# define Q_SCRIPT_EXPORT Q_DECL_IMPORT
+# define Q_SCRIPTTOOLS_EXPORT Q_DECL_IMPORT
+# define Q_COMPAT_EXPORT Q_DECL_IMPORT
+# define Q_DBUS_EXPORT Q_DECL_IMPORT
+# define Q_TEMPLATEDLL
+# endif
+# define Q_NO_DECLARED_NOT_DEFINED
+#else
+# if defined(Q_OS_LINUX) && defined(Q_CC_BOR)
+# define Q_TEMPLATEDLL
+# define Q_NO_DECLARED_NOT_DEFINED
+# endif
+# undef QT_MAKEDLL /* ignore these for other platforms */
+# undef QT_DLL
+#endif
+
+#if !defined(Q_CORE_EXPORT)
+# if defined(QT_SHARED)
+# define Q_CORE_EXPORT Q_DECL_EXPORT
+# define Q_GUI_EXPORT Q_DECL_EXPORT
+# define Q_SQL_EXPORT Q_DECL_EXPORT
+# define Q_NETWORK_EXPORT Q_DECL_EXPORT
+# define Q_SVG_EXPORT Q_DECL_EXPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
+# define Q_OPENGL_EXPORT Q_DECL_EXPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
+# define Q_OPENVG_EXPORT Q_DECL_EXPORT
+# define Q_XML_EXPORT Q_DECL_EXPORT
+# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
+# define Q_SCRIPT_EXPORT Q_DECL_EXPORT
+# define Q_SCRIPTTOOLS_EXPORT Q_DECL_EXPORT
+# define Q_COMPAT_EXPORT Q_DECL_EXPORT
+# define Q_DBUS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_CORE_EXPORT
+# define Q_GUI_EXPORT
+# define Q_SQL_EXPORT
+# define Q_NETWORK_EXPORT
+# define Q_SVG_EXPORT
+# define Q_DECLARATIVE_EXPORT
+# define Q_OPENGL_EXPORT
+# define Q_MULTIMEDIA_EXPORT
+# define Q_XML_EXPORT
+# define Q_XMLPATTERNS_EXPORT
+# define Q_SCRIPT_EXPORT
+# define Q_SCRIPTTOOLS_EXPORT
+# define Q_COMPAT_EXPORT
+# define Q_DBUS_EXPORT
+# endif
+#endif
+
+// Functions marked as Q_GUI_EXPORT_INLINE were exported and inlined by mistake.
+// Compilers like MinGW complain that the import attribute is ignored.
+#if defined(Q_CC_MINGW)
+# if defined(QT_BUILD_CORE_LIB)
+# define Q_CORE_EXPORT_INLINE Q_CORE_EXPORT inline
+# else
+# define Q_CORE_EXPORT_INLINE inline
+# endif
+# if defined(QT_BUILD_GUI_LIB)
+# define Q_GUI_EXPORT_INLINE Q_GUI_EXPORT inline
+# else
+# define Q_GUI_EXPORT_INLINE inline
+# endif
+# if defined(QT_BUILD_COMPAT_LIB)
+# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline
+# else
+# define Q_COMPAT_EXPORT_INLINE inline
+# endif
+#elif defined(Q_CC_RVCT)
+// we force RVCT not to export inlines by passing --visibility_inlines_hidden
+// so we need to just inline it, rather than exporting and inlining
+// note: this affects the contents of the DEF files (ie. these functions do not appear)
+# define Q_CORE_EXPORT_INLINE inline
+# define Q_GUI_EXPORT_INLINE inline
+# define Q_COMPAT_EXPORT_INLINE inline
+#else
+# define Q_CORE_EXPORT_INLINE Q_CORE_EXPORT inline
+# define Q_GUI_EXPORT_INLINE Q_GUI_EXPORT inline
+# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline
+#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.
+*/
+#if defined(QT_BUILD_INTERNAL) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_MAKEDLL)
+# define Q_AUTOTEST_EXPORT Q_DECL_EXPORT
+#elif defined(QT_BUILD_INTERNAL) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_DLL)
+# define Q_AUTOTEST_EXPORT Q_DECL_IMPORT
+#elif defined(QT_BUILD_INTERNAL) && !(defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_SHARED)
+# define Q_AUTOTEST_EXPORT Q_DECL_EXPORT
+#else
+# define Q_AUTOTEST_EXPORT
+#endif
+
+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.
+*/
+
+#ifdef QT_BOOTSTRAPPED
+# define QT_NO_EXCEPTIONS
+#endif
+#if !defined(QT_NO_EXCEPTIONS) && defined(Q_CC_GNU) && !defined (__EXCEPTIONS) && !defined(Q_MOC_RUN)
+# define QT_NO_EXCEPTIONS
+#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()
+#else
+# define QT_TRY try
+# define QT_CATCH(A) catch (A)
+# define QT_THROW(A) throw A
+# define QT_RETHROW throw
+#endif
+
+/*
+ System information
+*/
+
+class QString;
+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 qdoc
+ , ByteOrder = <platform-dependent>
+# elif Q_BYTE_ORDER == Q_BIG_ENDIAN
+ , ByteOrder = BigEndian
+# elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ , ByteOrder = LittleEndian
+# else
+# error "Undefined byte order"
+# endif
+ };
+#else
+# error "Qt not configured correctly, please run configure"
+#endif
+#if defined(Q_WS_WIN) || defined(Q_OS_CYGWIN)
+ enum WinVersion {
+ 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_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_CE = 0x0100,
+ WV_CENET = 0x0200,
+ WV_CE_5 = 0x0300,
+ WV_CE_6 = 0x0400,
+ WV_CE_based = 0x0f00
+ };
+ static const WinVersion WindowsVersion;
+ static WinVersion windowsVersion();
+
+#endif
+#ifdef Q_OS_MAC
+ enum MacVersion {
+ MV_Unknown = 0x0000,
+
+ /* version */
+ MV_9 = 0x0001,
+ MV_10_0 = 0x0002,
+ MV_10_1 = 0x0003,
+ MV_10_2 = 0x0004,
+ MV_10_3 = 0x0005,
+ MV_10_4 = 0x0006,
+ MV_10_5 = 0x0007,
+ MV_10_6 = 0x0008,
+ MV_10_7 = 0x0009,
+
+ /* 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
+ };
+ static const MacVersion MacintoshVersion;
+#endif
+#ifdef Q_OS_SYMBIAN
+ enum SymbianVersion {
+ SV_Unknown = 1000000, // Assume unknown is something newer than what is supported
+ //These are the Symbian Ltd versions 9.2-9.4
+ SV_9_2 = 10,
+ SV_9_3 = 20,
+ SV_9_4 = 30,
+ //Following values are the symbian foundation versions, i.e. Symbian^1 == SV_SF_1
+ SV_SF_1 = SV_9_4,
+ SV_SF_2 = 40,
+ SV_SF_3 = 50,
+ SV_SF_4 = 60, // Deprecated
+ SV_API_5_3 = 70,
+ SV_API_5_4 = 80
+ };
+ static SymbianVersion symbianVersion();
+ enum S60Version {
+ SV_S60_None = 0,
+ SV_S60_Unknown = SV_Unknown,
+ SV_S60_3_1 = SV_9_2,
+ SV_S60_3_2 = SV_9_3,
+ SV_S60_5_0 = SV_9_4,
+ SV_S60_5_1 = SV_SF_2, // Deprecated
+ SV_S60_5_2 = SV_SF_3,
+ SV_S60_5_3 = SV_API_5_3,
+ SV_S60_5_4 = SV_API_5_4
+ };
+ static S60Version s60Version();
+#endif
+};
+
+Q_CORE_EXPORT const char *qVersion();
+Q_CORE_EXPORT bool qSharedBuild();
+
+#if defined(Q_OS_MAC)
+inline int qMacVersion() { return QSysInfo::MacintoshVersion; }
+#endif
+
+#ifdef QT3_SUPPORT
+inline QT3_SUPPORT bool qSysInfo(int *wordSize, bool *bigEndian)
+{
+ *wordSize = QSysInfo::WordSize;
+ *bigEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian);
+ return true;
+}
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_OS_CYGWIN)
+#if defined(QT3_SUPPORT)
+inline QT3_SUPPORT bool qt_winUnicode() { return true; }
+inline QT3_SUPPORT int qWinVersion() { return QSysInfo::WindowsVersion; }
+#endif
+
+// ### Qt 5: remove Win9x support macros QT_WA and QT_WA_INLINE.
+#define QT_WA(unicode, ansi) unicode
+#define QT_WA_INLINE(unicode, ansi) (unicode)
+
+#endif /* Q_WS_WIN */
+
+#ifndef Q_OUTOFLINE_TEMPLATE
+# define Q_OUTOFLINE_TEMPLATE
+#endif
+#ifndef Q_INLINE_TEMPLATE
+# define Q_INLINE_TEMPLATE inline
+#endif
+
+#ifndef Q_TYPENAME
+# define Q_TYPENAME typename
+#endif
+
+/*
+ Avoid "unused parameter" warnings
+*/
+
+#if defined(Q_CC_INTEL) && !defined(Q_OS_WIN) || defined(Q_CC_RVCT)
+template <typename T>
+inline void qUnused(T &x) { (void)x; }
+# define Q_UNUSED(x) qUnused(x);
+#else
+# define Q_UNUSED(x) (void)x;
+#endif
+
+/*
+ Debugging and error handling
+*/
+
+/*
+ On Symbian we do not know beforehand whether we are compiling in
+ release or debug mode, so check the Symbian build define here,
+ and set the QT_NO_DEBUG define appropriately.
+*/
+#if defined(Q_OS_SYMBIAN) && defined(NDEBUG) && !defined(QT_NO_DEBUG)
+# define QT_NO_DEBUG
+#endif
+
+#if !defined(QT_NO_DEBUG) && !defined(QT_DEBUG)
+# define QT_DEBUG
+#endif
+
+#ifndef qPrintable
+# define qPrintable(string) QString(string).toLocal8Bit().constData()
+#endif
+
+Q_CORE_EXPORT void qDebug(const char *, ...) /* print debug message */
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+Q_CORE_EXPORT void qWarning(const char *, ...) /* print warning message */
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+class QString;
+Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
+Q_CORE_EXPORT void qCritical(const char *, ...) /* print critical message */
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+Q_CORE_EXPORT void qFatal(const char *, ...) /* print fatal message and exit */
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+#ifdef QT3_SUPPORT
+Q_CORE_EXPORT QT3_SUPPORT void qSystemWarning(const char *msg, int code = -1);
+#endif /* QT3_SUPPORT */
+Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...);
+Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...);
+
+#if (defined(QT_NO_DEBUG_OUTPUT) || defined(QT_NO_TEXTSTREAM)) && !defined(QT_NO_DEBUG_STREAM)
+#define QT_NO_DEBUG_STREAM
+#endif
+
+/*
+ Forward declarations only.
+
+ In order to use the qDebug() stream, you must #include<QDebug>
+*/
+class QDebug;
+class QNoDebug;
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT_INLINE QDebug qDebug();
+Q_CORE_EXPORT_INLINE QDebug qWarning();
+Q_CORE_EXPORT_INLINE QDebug qCritical();
+#else
+inline QNoDebug qDebug();
+#endif
+
+#define QT_NO_QDEBUG_MACRO while (false) qDebug
+#ifdef QT_NO_DEBUG_OUTPUT
+# define qDebug QT_NO_QDEBUG_MACRO
+#endif
+#define QT_NO_QWARNING_MACRO while (false) qWarning
+#ifdef QT_NO_WARNING_OUTPUT
+# define qWarning QT_NO_QWARNING_MACRO
+#endif
+
+
+Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line);
+
+#if !defined(Q_ASSERT)
+# ifndef QT_NO_DEBUG
+# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+# else
+# define Q_ASSERT(cond) qt_noop()
+# endif
+#endif
+
+#if defined(QT_NO_DEBUG) && !defined(QT_PAINT_DEBUG)
+#define QT_NO_PAINT_DEBUG
+#endif
+
+Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line);
+
+#if !defined(Q_ASSERT_X)
+# ifndef QT_NO_DEBUG
+# define Q_ASSERT_X(cond, where, what) ((!(cond)) ? qt_assert_x(where, what,__FILE__,__LINE__) : qt_noop())
+# else
+# define Q_ASSERT_X(cond, where, what) qt_noop()
+# endif
+#endif
+
+Q_CORE_EXPORT void qt_check_pointer(const char *, int);
+Q_CORE_EXPORT void qBadAlloc();
+
+#ifdef QT_NO_EXCEPTIONS
+# if defined(QT_NO_DEBUG)
+# define Q_CHECK_PTR(p) qt_noop()
+# else
+# define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0)
+# endif
+#else
+# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (0)
+#endif
+
+template <typename T>
+inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; }
+
+#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB)
+# define Q_FUNC_INFO __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+# define Q_FUNC_INFO __FUNCSIG__
+#else
+# if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) || defined(Q_OS_SYMBIAN)
+# define Q_FUNC_INFO __FILE__ "(line number unavailable)"
+# else
+ /* 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)
+# define Q_FUNC_INFO __FILE__ ":" QT_STRINGIFY(__LINE__)
+# endif
+ /* The MIPSpro and RVCT compilers postpones macro expansion,
+ and therefore macros must be in scope when being used. */
+# if !defined(Q_CC_MIPS) && !defined(Q_CC_RVCT) && !defined(Q_CC_NOKIAX86)
+# undef QT_STRINGIFY2
+# undef QT_STRINGIFY
+# endif
+#endif
+
+enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg };
+
+Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf);
+
+typedef void (*QtMsgHandler)(QtMsgType, const char *);
+Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
+
+#ifdef QT3_SUPPORT
+inline QT3_SUPPORT void qSuppressObsoleteWarnings(bool = true) {}
+inline QT3_SUPPORT void qObsolete(const char *, const char * = 0, const char * = 0) {}
+#endif
+
+#if defined(QT_NO_THREAD)
+
+template <typename T>
+class QGlobalStatic
+{
+public:
+ T *pointer;
+ inline QGlobalStatic(T *p) : pointer(p) { }
+ inline ~QGlobalStatic() { pointer = 0; }
+};
+
+#define Q_GLOBAL_STATIC(TYPE, NAME) \
+ static TYPE *NAME() \
+ { \
+ static TYPE thisVariable; \
+ static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \
+ return thisGlobalStatic.pointer; \
+ }
+
+#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
+ static TYPE *NAME() \
+ { \
+ static TYPE thisVariable ARGS; \
+ static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \
+ return thisGlobalStatic.pointer; \
+ }
+
+#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \
+ static TYPE *NAME() \
+ { \
+ static TYPE thisVariable; \
+ static QGlobalStatic<TYPE > thisGlobalStatic(0); \
+ if (!thisGlobalStatic.pointer) { \
+ TYPE *x = thisGlobalStatic.pointer = &thisVariable; \
+ INITIALIZER; \
+ } \
+ return thisGlobalStatic.pointer; \
+ }
+
+#else
+
+// forward declaration, since qatomic.h needs qglobal.h
+template <typename T> class QBasicAtomicPointer;
+
+// POD for Q_GLOBAL_STATIC
+template <typename T>
+class QGlobalStatic
+{
+public:
+ QBasicAtomicPointer<T> pointer;
+ bool destroyed;
+};
+
+// Created as a function-local static to delete a QGlobalStatic<T>
+template <typename T>
+class QGlobalStaticDeleter
+{
+public:
+ QGlobalStatic<T> &globalStatic;
+ QGlobalStaticDeleter(QGlobalStatic<T> &_globalStatic)
+ : globalStatic(_globalStatic)
+ { }
+
+ inline ~QGlobalStaticDeleter()
+ {
+ delete globalStatic.pointer;
+ globalStatic.pointer = 0;
+ globalStatic.destroyed = true;
+ }
+};
+
+#define Q_GLOBAL_STATIC(TYPE, NAME) \
+ static TYPE *NAME() \
+ { \
+ static QGlobalStatic<TYPE > thisGlobalStatic \
+ = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \
+ if (!thisGlobalStatic.pointer && !thisGlobalStatic.destroyed) { \
+ TYPE *x = new TYPE; \
+ if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) \
+ delete x; \
+ else \
+ static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \
+ } \
+ return thisGlobalStatic.pointer; \
+ }
+
+#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
+ static TYPE *NAME() \
+ { \
+ static QGlobalStatic<TYPE > thisGlobalStatic \
+ = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \
+ if (!thisGlobalStatic.pointer && !thisGlobalStatic.destroyed) { \
+ TYPE *x = new TYPE ARGS; \
+ if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) \
+ delete x; \
+ else \
+ static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \
+ } \
+ return thisGlobalStatic.pointer; \
+ }
+
+#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \
+ static TYPE *NAME() \
+ { \
+ static QGlobalStatic<TYPE > thisGlobalStatic \
+ = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \
+ if (!thisGlobalStatic.pointer && !thisGlobalStatic.destroyed) { \
+ QScopedPointer<TYPE > x(new TYPE); \
+ INITIALIZER; \
+ if (thisGlobalStatic.pointer.testAndSetOrdered(0, x.data())) { \
+ static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \
+ x.take(); \
+ } \
+ } \
+ return thisGlobalStatic.pointer; \
+ }
+
+#endif
+
+class QBool
+{
+ bool b;
+
+public:
+ inline explicit QBool(bool B) : b(B) {}
+ inline operator const void *() const
+ { return b ? static_cast<const void *>(this) : static_cast<const void *>(0); }
+};
+
+inline bool operator==(QBool b1, bool b2) { return !b1 == !b2; }
+inline bool operator==(bool b1, QBool b2) { return !b1 == !b2; }
+inline bool operator==(QBool b1, QBool b2) { return !b1 == !b2; }
+inline bool operator!=(QBool b1, bool b2) { return !b1 != !b2; }
+inline bool operator!=(bool b1, QBool b2) { return !b1 != !b2; }
+inline bool operator!=(QBool b1, QBool b2) { return !b1 != !b2; }
+
+static inline bool qFuzzyCompare(double p1, double p2)
+{
+ return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2)));
+}
+
+static inline bool qFuzzyCompare(float p1, float p2)
+{
+ return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+}
+
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(double d)
+{
+ return qAbs(d) <= 0.000000000001;
+}
+
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(float f)
+{
+ return qAbs(f) <= 0.00001f;
+}
+
+/*
+ This function tests a double for a null value. It doesn't
+ check whether the actual value is 0 or close to 0, but whether
+ it is binary 0.
+*/
+static inline bool qIsNull(double d)
+{
+ union U {
+ double d;
+ quint64 u;
+ };
+ U val;
+ val.d = d;
+ return val.u == quint64(0);
+}
+
+/*
+ This function tests a float for a null value. It doesn't
+ check whether the actual value is 0 or close to 0, but whether
+ it is binary 0.
+*/
+static inline bool qIsNull(float f)
+{
+ union U {
+ float f;
+ quint32 u;
+ };
+ U val;
+ val.f = f;
+ return val.u == 0u;
+}
+
+/*
+ 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
+
+
+/*
+ QTypeInfo - type trait functionality
+ qIsDetached - data sharing functionality
+*/
+
+/*
+ The catch-all template.
+*/
+
+template <typename T> inline bool qIsDetached(T &) { return true; }
+
+template <typename T>
+class QTypeInfo
+{
+public:
+ enum {
+ isPointer = false,
+ isComplex = true,
+ isStatic = true,
+ isLarge = (sizeof(T)>sizeof(void*)),
+ isDummy = false
+ };
+};
+
+template <typename T>
+class QTypeInfo<T*>
+{
+public:
+ enum {
+ isPointer = true,
+ isComplex = false,
+ isStatic = false,
+ isLarge = false,
+ isDummy = false
+ };
+};
+
+/*
+ Specialize a specific type with:
+
+ Q_DECLARE_TYPEINFO(type, flags);
+
+ where 'type' is the name of the type to specialize and 'flags' is
+ logically-OR'ed combination of the flags below.
+*/
+enum { /* TYPEINFO flags */
+ Q_COMPLEX_TYPE = 0,
+ Q_PRIMITIVE_TYPE = 0x1,
+ Q_STATIC_TYPE = 0,
+ Q_MOVABLE_TYPE = 0x2,
+ Q_DUMMY_TYPE = 0x4
+};
+
+#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
+class QTypeInfo<TYPE > \
+{ \
+public: \
+ enum { \
+ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \
+ isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \
+ isLarge = (sizeof(TYPE)>sizeof(void*)), \
+ isPointer = false, \
+ isDummy = (((FLAGS) & Q_DUMMY_TYPE) != 0) \
+ }; \
+ static inline const char *name() { return #TYPE; } \
+}
+
+#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
+template<> \
+Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
+
+
+template <typename T>
+inline void qSwap(T &value1, T &value2)
+{
+#ifdef QT_NO_STL
+ const T t = value1;
+ value1 = value2;
+ value2 = t;
+#else
+ using std::swap;
+ swap(value1, value2);
+#endif
+}
+
+/*
+ Specialize a shared type with:
+
+ Q_DECLARE_SHARED(type);
+
+ where 'type' is the name of the type to specialize. NOTE: shared
+ types must declare a 'bool isDetached(void) const;' member for this
+ to work.
+*/
+#ifdef QT_NO_STL
+#define Q_DECLARE_SHARED_STL(TYPE)
+#else
+#define Q_DECLARE_SHARED_STL(TYPE) \
+QT_END_NAMESPACE \
+namespace std { \
+ template<> inline void swap<QT_PREPEND_NAMESPACE(TYPE)>(QT_PREPEND_NAMESPACE(TYPE) &value1, QT_PREPEND_NAMESPACE(TYPE) &value2) \
+ { swap(value1.data_ptr(), value2.data_ptr()); } \
+} \
+QT_BEGIN_NAMESPACE
+#endif
+
+#define Q_DECLARE_SHARED(TYPE) \
+template <> inline bool qIsDetached<TYPE>(TYPE &t) { return t.isDetached(); } \
+template <> inline void qSwap<TYPE>(TYPE &value1, TYPE &value2) \
+{ qSwap(value1.data_ptr(), value2.data_ptr()); } \
+Q_DECLARE_SHARED_STL(TYPE)
+
+/*
+ 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);
+#ifndef Q_OS_DARWIN
+Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
+#endif
+
+/*
+ These functions make it possible to use standard C++ functions with
+ a similar name from Qt header files (especially template classes).
+*/
+Q_CORE_EXPORT void *qMalloc(size_t size);
+Q_CORE_EXPORT void qFree(void *ptr);
+Q_CORE_EXPORT void *qRealloc(void *ptr, size_t size);
+Q_CORE_EXPORT void *qMallocAligned(size_t size, size_t alignment);
+Q_CORE_EXPORT void *qReallocAligned(void *ptr, size_t size, size_t oldsize, size_t alignment);
+Q_CORE_EXPORT void qFreeAligned(void *ptr);
+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);
+
+
+/*
+ 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)
+# pragma warning(disable: 4251) /* class 'A' needs to have dll interface for to be used by clients of class 'B'. */
+# pragma warning(disable: 4244) /* 'conversion' conversion from 'type1' to 'type2', possible loss of data */
+# pragma warning(disable: 4275) /* non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' */
+# pragma warning(disable: 4514) /* unreferenced inline/local function has been removed */
+# pragma warning(disable: 4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */
+# pragma warning(disable: 4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */
+# pragma warning(disable: 4706) /* assignment within conditional expression */
+# pragma warning(disable: 4786) /* truncating debug info after 255 characters */
+# pragma warning(disable: 4660) /* template-class specialization 'identifier' is already instantiated */
+# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
+# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */
+# pragma warning(disable: 4710) /* function not inlined */
+# pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify -GX */
+# 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
+
+class Q_CORE_EXPORT QFlag
+{
+ int i;
+public:
+ inline QFlag(int i);
+ inline operator int() const { return i; }
+};
+
+inline QFlag::QFlag(int ai) : i(ai) {}
+
+class Q_CORE_EXPORT QIncompatibleFlag
+{
+ int i;
+public:
+ inline explicit QIncompatibleFlag(int i);
+ inline operator int() const { return i; }
+};
+
+inline QIncompatibleFlag::QIncompatibleFlag(int ai) : i(ai) {}
+
+
+#ifndef Q_NO_TYPESAFE_FLAGS
+
+template<typename Enum>
+class QFlags
+{
+ typedef void **Zero;
+ int i;
+public:
+ typedef Enum enum_type;
+ inline QFlags(const QFlags &f) : i(f.i) {}
+ inline QFlags(Enum f) : i(f) {}
+ inline QFlags(Zero = 0) : i(0) {}
+ inline QFlags(QFlag f) : i(f) {}
+
+ inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; }
+ inline QFlags &operator&=(int mask) { i &= mask; return *this; }
+ inline QFlags &operator&=(uint mask) { i &= mask; return *this; }
+ inline QFlags &operator|=(QFlags f) { i |= f.i; return *this; }
+ inline QFlags &operator|=(Enum f) { i |= f; return *this; }
+ inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
+ inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
+
+ inline operator int() const { return i; }
+
+ inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; }
+ inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; }
+ inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; }
+ inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; }
+ inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; }
+ inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; }
+ inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; }
+ inline QFlags operator~() const { QFlags g; g.i = ~i; return g; }
+
+ inline bool operator!() const { return !i; }
+
+ inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); }
+};
+
+#define Q_DECLARE_FLAGS(Flags, Enum)\
+typedef QFlags<Enum> Flags;
+
+#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
+inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \
+{ return QIncompatibleFlag(int(f1) | f2); }
+
+#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
+inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
+{ return QFlags<Flags::enum_type>(f1) | f2; } \
+inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
+{ return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags)
+
+
+#else /* Q_NO_TYPESAFE_FLAGS */
+
+#define Q_DECLARE_FLAGS(Flags, Enum)\
+typedef uint Flags;
+#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
+
+#endif /* Q_NO_TYPESAFE_FLAGS */
+
+#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT)
+/* make use of typeof-extension */
+template <typename T>
+class QForeachContainer {
+public:
+ inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
+ const T c;
+ int brk;
+ typename T::const_iterator i, e;
+};
+
+#define Q_FOREACH(variable, container) \
+for (QForeachContainer<__typeof__(container)> _container_(container); \
+ !_container_.brk && _container_.i != _container_.e; \
+ __extension__ ({ ++_container_.brk; ++_container_.i; })) \
+ for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
+
+#else
+
+struct QForeachContainerBase {};
+
+template <typename T>
+class QForeachContainer : public QForeachContainerBase {
+public:
+ inline QForeachContainer(const T& t): c(t), brk(0), i(c.begin()), e(c.end()){};
+ const T c;
+ mutable int brk;
+ mutable typename T::const_iterator i, e;
+ inline bool condition() const { return (!brk++ && i != e); }
+};
+
+template <typename T> inline T *qForeachPointer(const T &) { return 0; }
+
+template <typename T> inline QForeachContainer<T> qForeachContainerNew(const T& t)
+{ return QForeachContainer<T>(t); }
+
+template <typename T>
+inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase *base, const T *)
+{ return static_cast<const QForeachContainer<T> *>(base); }
+
+#if defined(Q_CC_MIPS)
+/*
+ Proper for-scoping in MIPSpro CC
+*/
+# define Q_FOREACH(variable,container) \
+ if(0){}else \
+ for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \
+ qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->condition(); \
+ ++qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i) \
+ for (variable = *qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i; \
+ qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk; \
+ --qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk)
+
+#elif defined(Q_CC_DIAB)
+// VxWorks DIAB generates unresolvable symbols, if container is a function call
+# define Q_FOREACH(variable,container) \
+ if(0){}else \
+ for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \
+ qForeachContainer(&_container_, (__typeof__(container) *) 0)->condition(); \
+ ++qForeachContainer(&_container_, (__typeof__(container) *) 0)->i) \
+ for (variable = *qForeachContainer(&_container_, (__typeof__(container) *) 0)->i; \
+ qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk; \
+ --qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk)
+
+#else
+# define Q_FOREACH(variable, container) \
+ for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \
+ qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->condition(); \
+ ++qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i) \
+ for (variable = *qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i; \
+ qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk; \
+ --qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk)
+#endif // MSVC6 || MIPSpro
+
+#endif
+
+#define Q_FOREVER for(;;)
+#ifndef QT_NO_KEYWORDS
+# ifndef foreach
+# define foreach Q_FOREACH
+# endif
+# ifndef forever
+# define forever Q_FOREVER
+# endif
+#endif
+
+#if 0
+/* tell gcc to use its built-in methods for some common functions */
+#if defined(QT_NO_DEBUG) && defined(Q_CC_GNU)
+# define qMemCopy __builtin_memcpy
+# define qMemSet __builtin_memset
+#endif
+#endif
+
+template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
+template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }
+
+#define Q_DECLARE_PRIVATE(Class) \
+ inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
+ inline const Class##Private* d_func() const { 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() { return reinterpret_cast<Class##Private *>(Dptr); } \
+ inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(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 // ### This should enclose the NOOPs above
+
+// 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
+
+#define QDOC_PROPERTY(text)
+
+/*
+ When RTTI is not available, define this macro to force any uses of
+ dynamic_cast to cause a compile failure.
+*/
+
+#ifdef QT_NO_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
+
+/*
+ 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 &); \
+ Class &operator=(const Class &);
+
+class QByteArray;
+Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
+Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
+
+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
+*/
+Q_CORE_EXPORT void qsrand(uint seed);
+Q_CORE_EXPORT int qrand();
+
+/*
+ Compat functions that were generated by configure
+*/
+#ifdef QT3_SUPPORT
+#ifndef QT_PRODUCT_LICENSEE
+# define QT_PRODUCT_LICENSEE QLibraryInfo::licensee()
+#endif
+#ifndef QT_PRODUCT_LICENSE
+# define QT_PRODUCT_LICENSE QLibraryInfo::licensedProducts()
+#endif
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPath();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathDocs();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathHeaders();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathLibs();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathBins();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathPlugins();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathData();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathTranslations();
+QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+
+#ifdef SYMBIAN_BUILD_GCE
+#define Q_SYMBIAN_SUPPORTS_SURFACES
+//RWsPointerCursor is fixed, so don't use low performance sprites
+#define Q_SYMBIAN_FIXED_POINTER_CURSORS
+#define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
+#define Q_SYMBIAN_WINDOW_SIZE_CACHE
+#define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
+
+//enabling new graphics resources
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+# define QT_SYMBIAN_SUPPORTS_SGIMAGE
+#endif
+
+#ifdef SYMBIAN_GRAPHICS_SET_SURFACE_TRANSPARENCY_AVAILABLE
+# define Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE
+#endif
+
+#ifdef SYMBIAN_GRAPHICS_TRANSITION_EFFECTS_SIGNALING_AVAILABLE
+# define Q_SYMBIAN_TRANSITION_EFFECTS
+#endif
+#endif
+
+#ifdef SYMBIAN_WSERV_AND_CONE_MULTIPLE_SCREENS
+#define Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS
+#endif
+
+#ifdef SYMBIAN_GRAPHICS_FIXNATIVEORIENTATION
+#define Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION
+#endif
+
+//Symbian does not support data imports from a DLL
+#define Q_NO_DATA_RELOCATION
+
+QT_END_NAMESPACE
+// forward declare std::exception
+#ifdef __cplusplus
+namespace std { class exception; }
+#endif
+QT_BEGIN_NAMESPACE
+Q_CORE_EXPORT void qt_symbian_throwIfError(int error);
+Q_CORE_EXPORT void qt_symbian_exception2LeaveL(const std::exception& ex);
+Q_CORE_EXPORT int qt_symbian_exception2Error(const std::exception& ex);
+
+#define QT_TRAP_THROWING(_f) \
+ { \
+ TInt ____error; \
+ TRAP(____error, _f); \
+ qt_symbian_throwIfError(____error); \
+ }
+
+#define QT_TRYCATCH_ERROR(_err, _f) \
+ { \
+ _err = KErrNone; \
+ try { \
+ _f; \
+ } catch (const std::exception &____ex) { \
+ _err = qt_symbian_exception2Error(____ex); \
+ } \
+ }
+
+#define QT_TRYCATCH_LEAVING(_f) \
+ { \
+ TInt ____err; \
+ QT_TRYCATCH_ERROR(____err, _f) \
+ User::LeaveIfError(____err); \
+ }
+#endif
+
+
+/*
+ This gives us the possibility to check which modules the user can
+ use. These are purely compile time checks and will generate no code.
+*/
+
+/* Qt modules */
+#define QT_MODULE_CORE 0x00001
+#define QT_MODULE_GUI 0x00002
+#define QT_MODULE_NETWORK 0x00004
+#define QT_MODULE_OPENGL 0x00008
+#define QT_MODULE_SQL 0x00010
+#define QT_MODULE_XML 0x00020
+#define QT_MODULE_QT3SUPPORTLIGHT 0x00040
+#define QT_MODULE_QT3SUPPORT 0x00080
+#define QT_MODULE_SVG 0x00100
+#define QT_MODULE_ACTIVEQT 0x00200
+#define QT_MODULE_GRAPHICSVIEW 0x00400
+#define QT_MODULE_SCRIPT 0x00800
+#define QT_MODULE_XMLPATTERNS 0x01000
+#define QT_MODULE_HELP 0x02000
+#define QT_MODULE_TEST 0x04000
+#define QT_MODULE_DBUS 0x08000
+#define QT_MODULE_SCRIPTTOOLS 0x10000
+#define QT_MODULE_OPENVG 0x20000
+#define QT_MODULE_MULTIMEDIA 0x40000
+#define QT_MODULE_DECLARATIVE 0x80000
+
+/* Qt editions */
+#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
+ | QT_MODULE_NETWORK \
+ | QT_MODULE_SQL \
+ | QT_MODULE_SCRIPT \
+ | QT_MODULE_MULTIMEDIA \
+ | QT_MODULE_XML \
+ | QT_MODULE_XMLPATTERNS \
+ | QT_MODULE_TEST \
+ | QT_MODULE_DBUS)
+#define QT_EDITION_DESKTOPLIGHT (QT_MODULE_CORE \
+ | QT_MODULE_GUI \
+ | QT_MODULE_QT3SUPPORTLIGHT \
+ | QT_MODULE_TEST \
+ | QT_MODULE_DBUS)
+#define QT_EDITION_OPENSOURCE (QT_MODULE_CORE \
+ | QT_MODULE_GUI \
+ | QT_MODULE_NETWORK \
+ | QT_MODULE_OPENGL \
+ | QT_MODULE_OPENVG \
+ | QT_MODULE_SQL \
+ | QT_MODULE_MULTIMEDIA \
+ | QT_MODULE_XML \
+ | QT_MODULE_XMLPATTERNS \
+ | QT_MODULE_SCRIPT \
+ | QT_MODULE_SCRIPTTOOLS \
+ | QT_MODULE_QT3SUPPORTLIGHT \
+ | QT_MODULE_QT3SUPPORT \
+ | QT_MODULE_SVG \
+ | QT_MODULE_DECLARATIVE \
+ | QT_MODULE_GRAPHICSVIEW \
+ | QT_MODULE_HELP \
+ | QT_MODULE_TEST \
+ | QT_MODULE_DBUS \
+ | QT_MODULE_ACTIVEQT)
+#define QT_EDITION_DESKTOP (QT_EDITION_OPENSOURCE)
+#define QT_EDITION_UNIVERSAL QT_EDITION_DESKTOP
+#define QT_EDITION_ACADEMIC QT_EDITION_DESKTOP
+#define QT_EDITION_EDUCATIONAL QT_EDITION_DESKTOP
+#define QT_EDITION_EVALUATION QT_EDITION_DESKTOP
+
+/* Determine which modules can be used */
+#ifndef QT_EDITION
+# ifdef QT_BUILD_QMAKE
+# define QT_EDITION QT_EDITION_DESKTOP
+# else
+# error "Qt not configured correctly, please run configure"
+# endif
+#endif
+
+#define QT_LICENSED_MODULE(x) \
+ enum QtValidLicenseFor##x##Module { Licensed##x = true };
+
+/* qdoc is really unhappy with the following block of preprocessor checks,
+ making it difficult to document classes properly after this point. */
+
+#if (QT_EDITION & QT_MODULE_CORE)
+QT_LICENSED_MODULE(Core)
+#endif
+#if (QT_EDITION & QT_MODULE_GUI)
+QT_LICENSED_MODULE(Gui)
+#endif
+#if (QT_EDITION & QT_MODULE_NETWORK)
+QT_LICENSED_MODULE(Network)
+#endif
+#if (QT_EDITION & QT_MODULE_OPENGL)
+QT_LICENSED_MODULE(OpenGL)
+#endif
+#if (QT_EDITION & QT_MODULE_OPENVG)
+QT_LICENSED_MODULE(OpenVG)
+#endif
+#if (QT_EDITION & QT_MODULE_SQL)
+QT_LICENSED_MODULE(Sql)
+#endif
+#if (QT_EDITION & QT_MODULE_MULTIMEDIA)
+QT_LICENSED_MODULE(Multimedia)
+#endif
+#if (QT_EDITION & QT_MODULE_XML)
+QT_LICENSED_MODULE(Xml)
+#endif
+#if (QT_EDITION & QT_MODULE_XMLPATTERNS)
+QT_LICENSED_MODULE(XmlPatterns)
+#endif
+#if (QT_EDITION & QT_MODULE_HELP)
+QT_LICENSED_MODULE(Help)
+#endif
+#if (QT_EDITION & QT_MODULE_SCRIPT) || defined(QT_BUILD_QMAKE)
+QT_LICENSED_MODULE(Script)
+#endif
+#if (QT_EDITION & QT_MODULE_SCRIPTTOOLS)
+QT_LICENSED_MODULE(ScriptTools)
+#endif
+#if (QT_EDITION & QT_MODULE_QT3SUPPORTLIGHT)
+QT_LICENSED_MODULE(Qt3SupportLight)
+#endif
+#if (QT_EDITION & QT_MODULE_QT3SUPPORT)
+QT_LICENSED_MODULE(Qt3Support)
+#endif
+#if (QT_EDITION & QT_MODULE_SVG)
+QT_LICENSED_MODULE(Svg)
+#endif
+#if (QT_EDITION & QT_MODULE_DECLARATIVE)
+QT_LICENSED_MODULE(Declarative)
+#endif
+#if (QT_EDITION & QT_MODULE_ACTIVEQT)
+QT_LICENSED_MODULE(ActiveQt)
+#endif
+#if (QT_EDITION & QT_MODULE_TEST)
+QT_LICENSED_MODULE(Test)
+#endif
+#if (QT_EDITION & QT_MODULE_DBUS)
+QT_LICENSED_MODULE(DBus)
+#endif
+
+#define QT_MODULE(x) \
+ typedef QtValidLicenseFor##x##Module Qt##x##Module;
+
+#ifdef QT_NO_CONCURRENT
+# define QT_NO_QFUTURE
+#endif
+
+// gcc 3 version has problems with some of the
+// map/filter overloads.
+#if defined(Q_CC_GNU) && (__GNUC__ < 4)
+# define QT_NO_CONCURRENT_MAP
+# define QT_NO_CONCURRENT_FILTER
+#endif
+
+#ifdef Q_OS_QNX
+// QNX doesn't have SYSV style shared memory. Multiprocess QWS apps,
+// shared fonts and QSystemSemaphore + QSharedMemory are not available
+# define QT_NO_QWS_MULTIPROCESS
+# define QT_NO_QWS_SHARE_FONTS
+# define QT_NO_SYSTEMSEMAPHORE
+# define QT_NO_SHAREDMEMORY
+// QNX currently doesn't support forking in a thread, so disable QProcess
+# define QT_NO_PROCESS
+#endif
+
+#if defined (__ELF__)
+# if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX)
+# define Q_OF_ELF
+# endif
+#endif
+
+#if !(defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) \
+ && !(defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)) \
+ && !(defined(Q_WS_X11) && !defined(QT_NO_FREETYPE))
+# define QT_NO_RAWFONT
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif /* __cplusplus */
+
+#endif /* QGLOBAL_H */
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
new file mode 100644
index 0000000000..aca1cb1db6
--- /dev/null
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -0,0 +1,555 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdir.h"
+#include "qfile.h"
+#include "qconfig.h"
+#include "qsettings.h"
+#include "qlibraryinfo.h"
+#include "qscopedpointer.h"
+
+#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED)
+# define BOOTSTRAPPING
+#endif
+
+#ifdef BOOTSTRAPPING
+QT_BEGIN_NAMESPACE
+extern QString qmake_libraryInfoFile();
+QT_END_NAMESPACE
+#else
+# include "qcoreapplication.h"
+#endif
+
+#ifdef Q_OS_MAC
+# include "private/qcore_mac_p.h"
+#endif
+
+#ifdef QLIBRARYINFO_EPOCROOT
+# include "symbian/epocroot_p.h"
+#endif
+
+#include "qconfig.cpp"
+
+QT_BEGIN_NAMESPACE
+
+extern void qDumpCPUFeatures(); // in qsimd.cpp
+
+#ifndef QT_NO_SETTINGS
+
+struct QLibrarySettings
+{
+ QLibrarySettings();
+ QScopedPointer<QSettings> settings;
+};
+Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
+
+class QLibraryInfoPrivate
+{
+public:
+ static QSettings *findConfiguration();
+ static void cleanup()
+ {
+ QLibrarySettings *ls = qt_library_settings();
+ if (ls)
+ ls->settings.reset(0);
+ }
+ static QSettings *configuration()
+ {
+ QLibrarySettings *ls = qt_library_settings();
+ return ls ? ls->settings.data() : 0;
+ }
+};
+
+QLibrarySettings::QLibrarySettings()
+ : settings(QLibraryInfoPrivate::findConfiguration())
+{
+#ifndef BOOTSTRAPPING
+ qAddPostRoutine(QLibraryInfoPrivate::cleanup);
+#endif
+}
+
+QSettings *QLibraryInfoPrivate::findConfiguration()
+{
+ QString qtconfig = QLatin1String(":/qt/etc/qt.conf");
+#ifdef BOOTSTRAPPING
+ if(!QFile::exists(qtconfig))
+ qtconfig = qmake_libraryInfoFile();
+#else
+ if (!QFile::exists(qtconfig) && QCoreApplication::instance()) {
+#ifdef Q_OS_MAC
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
+ QCFString(QLatin1String("qt.conf")),
+ 0,
+ 0);
+ if (urlRef) {
+ QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
+ qtconfig = QDir::cleanPath(path);
+ }
+ }
+ if (qtconfig.isEmpty())
+#endif
+ {
+ QDir pwd(QCoreApplication::applicationDirPath());
+ qtconfig = pwd.filePath(QLatin1String("qt.conf"));
+ }
+ }
+#endif
+ if (QFile::exists(qtconfig))
+ return new QSettings(qtconfig, QSettings::IniFormat);
+ return 0; //no luck
+}
+
+/*!
+ \class QLibraryInfo
+ \brief The QLibraryInfo class provides information about the Qt library.
+
+ Many pieces of information are established when Qt is configured.
+ Installation paths, license information, and even a unique build
+ key. This class provides an abstraction for accessing this
+ information.
+
+ \table
+ \header \o Function \o Return value
+ \row \o buildKey() \o A string that identifies the Qt version and
+ the configuration. This key is used to ensure
+ that \l{plugins} link against the same version
+ of Qt as the application.
+ \row \o location() \o The path to a certain Qt
+ component (e.g., documentation, header files).
+ \row \o licensee(),
+ licensedProducts() \o Licensing information.
+ \endtable
+
+ You can also use a \c qt.conf file to override the hard-coded paths
+ that are compiled into the Qt library. For more information, see
+ the \l {Using qt.conf} documentation.
+
+ \sa QSysInfo, {Using qt.conf}
+*/
+
+/*! \internal
+
+ You cannot create a QLibraryInfo, instead only the static functions are available to query
+ information.
+*/
+
+QLibraryInfo::QLibraryInfo()
+{ }
+
+/*!
+ Returns the person to whom this build of Qt is licensed.
+
+ \sa licensedProducts()
+*/
+
+QString
+QLibraryInfo::licensee()
+{
+ const char *str = QT_CONFIGURE_LICENSEE;
+ return QString::fromLocal8Bit(str);
+}
+
+/*!
+ Returns the products that the license for this build of Qt has access to.
+
+ \sa licensee()
+*/
+
+QString
+QLibraryInfo::licensedProducts()
+{
+ const char *str = QT_CONFIGURE_LICENSED_PRODUCTS;
+ return QString::fromLatin1(str);
+}
+
+/*!
+ Returns a unique key identifying this build of Qt and its
+ configurations. This key is not globally unique, rather only useful
+ for establishing of two configurations are compatible. This can be
+ used to compare with the \c QT_BUILD_KEY preprocessor symbol.
+
+ \sa location()
+*/
+
+QString
+QLibraryInfo::buildKey()
+{
+ return QString::fromLatin1(QT_BUILD_KEY);
+}
+
+/*!
+ \since 4.6
+ Returns the installation date for this build of Qt. The install date will
+ usually be the last time that Qt sources were configured.
+*/
+#ifndef QT_NO_DATESTRING
+QDate
+QLibraryInfo::buildDate()
+{
+ return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate);
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+ Returns the location specified by \a loc.
+
+*/
+
+QString
+QLibraryInfo::location(LibraryLocation loc)
+{
+ QString ret;
+ if(!QLibraryInfoPrivate::configuration()) {
+ const char *path = 0;
+ switch (loc) {
+#ifdef QT_CONFIGURE_PREFIX_PATH
+ case PrefixPath:
+ path = QT_CONFIGURE_PREFIX_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_DOCUMENTATION_PATH
+ case DocumentationPath:
+ path = QT_CONFIGURE_DOCUMENTATION_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_HEADERS_PATH
+ case HeadersPath:
+ path = QT_CONFIGURE_HEADERS_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_LIBRARIES_PATH
+ case LibrariesPath:
+ path = QT_CONFIGURE_LIBRARIES_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_BINARIES_PATH
+ case BinariesPath:
+ path = QT_CONFIGURE_BINARIES_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_PLUGINS_PATH
+ case PluginsPath:
+ path = QT_CONFIGURE_PLUGINS_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_IMPORTS_PATH
+ case ImportsPath:
+ path = QT_CONFIGURE_IMPORTS_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_DATA_PATH
+ case DataPath:
+ path = QT_CONFIGURE_DATA_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_TRANSLATIONS_PATH
+ case TranslationsPath:
+ path = QT_CONFIGURE_TRANSLATIONS_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_SETTINGS_PATH
+ case SettingsPath:
+ path = QT_CONFIGURE_SETTINGS_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_EXAMPLES_PATH
+ case ExamplesPath:
+ path = QT_CONFIGURE_EXAMPLES_PATH;
+ break;
+#endif
+#ifdef QT_CONFIGURE_DEMOS_PATH
+ case DemosPath:
+ path = QT_CONFIGURE_DEMOS_PATH;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (path)
+ ret = QString::fromLocal8Bit(path);
+ } else {
+ QString key;
+ QString defaultValue;
+ switch(loc) {
+ case PrefixPath:
+ key = QLatin1String("Prefix");
+ break;
+ case DocumentationPath:
+ key = QLatin1String("Documentation");
+ defaultValue = QLatin1String("doc");
+ break;
+ case HeadersPath:
+ key = QLatin1String("Headers");
+ defaultValue = QLatin1String("include");
+ break;
+ case LibrariesPath:
+ key = QLatin1String("Libraries");
+ defaultValue = QLatin1String("lib");
+ break;
+ case BinariesPath:
+ key = QLatin1String("Binaries");
+ defaultValue = QLatin1String("bin");
+ break;
+ case PluginsPath:
+ key = QLatin1String("Plugins");
+ defaultValue = QLatin1String("plugins");
+ break;
+ case ImportsPath:
+ key = QLatin1String("Imports");
+ defaultValue = QLatin1String("imports");
+ break;
+ case DataPath:
+ key = QLatin1String("Data");
+ break;
+ case TranslationsPath:
+ key = QLatin1String("Translations");
+ defaultValue = QLatin1String("translations");
+ break;
+ case SettingsPath:
+ key = QLatin1String("Settings");
+ break;
+ case ExamplesPath:
+ key = QLatin1String("Examples");
+ break;
+ case DemosPath:
+ key = QLatin1String("Demos");
+ break;
+ default:
+ break;
+ }
+
+ if(!key.isNull()) {
+ QSettings *config = QLibraryInfoPrivate::configuration();
+ config->beginGroup(QLatin1String("Paths"));
+
+ QString subKey;
+ {
+ /*
+ find the child group whose version number is closest
+ to the library version. for example and we have the
+ following groups:
+
+ Paths
+ Paths/4.0
+ Paths/4.1.2
+ Paths/4.2.5
+ Paths/5
+
+ if QT_VERSION is 4.0.1, then we use 'Paths/4.0'
+ if QT_VERSION is 4.1.5, then we use 'Paths/4.1.2'
+ if QT_VERSION is 4.6.3, then we use 'Paths/4.2.5'
+ if QT_VERSION is 6.0.2, then we use 'Paths/5'
+
+ note: any of the trailing version numbers may be
+ omitted (in which case, they default to zero),
+ i.e. 4 == 4.0.0, 4.1 == 4.1.0, and so on
+ */
+ enum {
+ QT_MAJOR = ((QT_VERSION >> 16) & 0xFF),
+ QT_MINOR = ((QT_VERSION >> 8) & 0xFF),
+ QT_PATCH = (QT_VERSION & 0xFF)
+ };
+ int maj = 0, min = 0, pat = 0;
+ QStringList children = config->childGroups();
+ for(int child = 0; child < children.size(); ++child) {
+ QString cver = children.at(child);
+ QStringList cver_list = cver.split(QLatin1Char('.'));
+ if(cver_list.size() > 0 && cver_list.size() < 4) {
+ bool ok;
+ int cmaj = -1, cmin = -1, cpat = -1;
+ cmaj = cver_list[0].toInt(&ok);
+ if(!ok || cmaj < 0)
+ continue;
+ if(cver_list.size() >= 2) {
+ cmin = cver_list[1].toInt(&ok);
+ if(!ok)
+ continue;
+ if(cmin < 0)
+ cmin = -1;
+ }
+ if(cver_list.size() >= 3) {
+ cpat = cver_list[2].toInt(&ok);
+ if(!ok)
+ continue;
+ if(cpat < 0)
+ cpat = -1;
+ }
+ if((cmaj >= maj && cmaj <= QT_MAJOR) &&
+ (cmin == -1 || (cmin >= min && cmin <= QT_MINOR)) &&
+ (cpat == -1 || (cpat >= pat && cpat <= QT_PATCH)) &&
+ config->contains(cver + QLatin1Char('/') + key)) {
+ subKey = cver + QLatin1Char('/');
+ maj = cmaj;
+ min = cmin;
+ pat = cpat;
+ }
+ }
+ }
+ }
+ ret = config->value(subKey + key, defaultValue).toString();
+ // expand environment variables in the form $(ENVVAR)
+ int rep;
+ QRegExp reg_var(QLatin1String("\\$\\(.*\\)"));
+ reg_var.setMinimal(true);
+ while((rep = reg_var.indexIn(ret)) != -1) {
+ ret.replace(rep, reg_var.matchedLength(),
+ QString::fromLocal8Bit(qgetenv(ret.mid(rep + 2,
+ reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
+ }
+
+#ifdef QLIBRARYINFO_EPOCROOT
+ // $${EPOCROOT} is a special case, resolve it similarly to qmake.
+ QRegExp epocrootMatcher(QLatin1String("\\$\\$\\{EPOCROOT\\}"));
+ if ((rep = epocrootMatcher.indexIn(ret)) != -1)
+ ret.replace(rep, epocrootMatcher.matchedLength(), qt_epocRoot());
+#endif
+
+ config->endGroup();
+ }
+ }
+
+ if (QDir::isRelativePath(ret)) {
+ if (loc == PrefixPath) {
+ // we make the prefix path absolute to the executable's directory
+#ifdef BOOTSTRAPPING
+ return QFileInfo(qmake_libraryInfoFile()).absolutePath();
+#else
+ if (QCoreApplication::instance()) {
+#ifdef Q_OS_MAC
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
+ if (urlRef) {
+ QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
+ return QDir::cleanPath(QString(path) + QLatin1String("/Contents/") + ret);
+ }
+ }
+#endif
+ return QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(ret);
+ } else {
+ return QDir::current().absoluteFilePath(ret);
+ }
+#endif
+ } else {
+ // we make any other path absolute to the prefix directory
+ return QDir(location(PrefixPath)).absoluteFilePath(ret);
+ }
+ }
+ return ret;
+}
+
+/*!
+ \enum QLibraryInfo::LibraryLocation
+
+ \keyword library location
+
+ This enum type is used to specify a specific location
+ specifier:
+
+ \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 BinariesPath The location of installed Qt binaries (tools and applications).
+ \value PluginsPath The location of installed Qt plugins.
+ \value ImportsPath The location of installed QML extensions to import.
+ \value DataPath The location of general Qt data.
+ \value TranslationsPath The location of translation information for Qt strings.
+ \value SettingsPath The location for Qt settings.
+ \value ExamplesPath The location for examples upon install.
+ \value DemosPath The location for demos upon install.
+
+ \sa location()
+*/
+
+#endif // QT_NO_SETTINGS
+
+QT_END_NAMESPACE
+
+#if defined(Q_CC_GNU) && defined(ELF_INTERPRETER)
+# include <stdio.h>
+# include <stdlib.h>
+
+extern const char qt_core_interpreter[] __attribute__((section(".interp")))
+ = ELF_INTERPRETER;
+
+extern "C" void qt_core_boilerplate();
+void qt_core_boilerplate()
+{
+ printf("This is the QtCore library version " QT_VERSION_STR "\n"
+ "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
+ "Contact: Nokia Corporation (qt-info@nokia.com)\n"
+ "\n"
+ "Build key: " QT_BUILD_KEY "\n"
+ "Compat build key: "
+#ifdef QT_BUILD_KEY_COMPAT
+ "| " QT_BUILD_KEY_COMPAT " "
+#endif
+#ifdef QT_BUILD_KEY_COMPAT2
+ "| " QT_BUILD_KEY_COMPAT2 " "
+#endif
+#ifdef QT_BUILD_KEY_COMPAT3
+ "| " QT_BUILD_KEY_COMPAT3 " "
+#endif
+ "|\n"
+ "Build date: %s\n"
+ "Installation prefix: %s\n"
+ "Library path: %s\n"
+ "Include path: %s\n",
+ qt_configure_installation + 12,
+ qt_configure_prefix_path_str + 12,
+ qt_configure_libraries_path_str + 12,
+ qt_configure_headers_path_str + 12);
+
+ QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
+
+#ifdef QT_EVAL
+ extern void qt_core_eval_init(uint);
+ qt_core_eval_init(1);
+#endif
+
+ exit(0);
+}
+
+#endif
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
new file mode 100644
index 0000000000..8ed64affad
--- /dev/null
+++ b/src/corelib/global/qlibraryinfo.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIBRARYINFO_H
+#define QLIBRARYINFO_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/QDate>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SETTINGS
+
+class Q_CORE_EXPORT QLibraryInfo
+{
+public:
+ static QString licensee();
+ static QString licensedProducts();
+
+ static QString buildKey();
+#ifndef QT_NO_DATESTRING
+ static QDate buildDate();
+#endif //QT_NO_DATESTRING
+
+ enum LibraryLocation
+ {
+ PrefixPath,
+ DocumentationPath,
+ HeadersPath,
+ LibrariesPath,
+ BinariesPath,
+ PluginsPath,
+ DataPath,
+ TranslationsPath,
+ SettingsPath,
+ DemosPath,
+ ExamplesPath,
+ ImportsPath
+ };
+ static QString location(LibraryLocation); // ### Qt 5: consider renaming it to path()
+
+private:
+ QLibraryInfo();
+};
+
+#endif /* QT_NO_SETTINGS */
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLIBRARYINFO_H
diff --git a/src/corelib/global/qmalloc.cpp b/src/corelib/global/qmalloc.cpp
new file mode 100644
index 0000000000..a12b0ba242
--- /dev/null
+++ b/src/corelib/global/qmalloc.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include <stdlib.h>
+
+/*
+ Define the container allocation functions in a separate file, so that our
+ users can easily override them.
+*/
+
+QT_BEGIN_NAMESPACE
+
+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(0, size, 0, alignment);
+}
+
+void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
+{
+ // fake an aligned allocation
+ Q_UNUSED(oldsize);
+
+ void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : 0;
+ if (alignment <= sizeof(void*)) {
+ // special, fast case
+ void **newptr = static_cast<void **>(qRealloc(actualptr, newsize + sizeof(void*)));
+ if (!newptr)
+ return 0;
+ if (newptr == actualptr) {
+ // realloc succeeded without reallocating
+ return oldptr;
+ }
+
+ *newptr = newptr;
+ return newptr + 1;
+ }
+
+ // qMalloc returns pointers aligned at least at sizeof(size_t) boundaries
+ // but usually more (8- or 16-byte boundaries).
+ // So we overallocate by alignment-sizeof(size_t) bytes, so we're guaranteed to find a
+ // somewhere within the first alignment-sizeof(size_t) that is properly aligned.
+
+ // However, we need to store the actual pointer, so we need to allocate actually size +
+ // alignment anyway.
+
+ void *real = qRealloc(actualptr, newsize + alignment);
+ if (!real)
+ return 0;
+
+ quintptr faked = reinterpret_cast<quintptr>(real) + alignment;
+ faked &= ~(alignment - 1);
+
+ void **faked_ptr = reinterpret_cast<void **>(faked);
+
+ // now save the value of the real pointer at faked-sizeof(void*)
+ // by construction, alignment > sizeof(void*) and is a power of 2, so
+ // faked-sizeof(void*) is properly aligned for a pointer
+ faked_ptr[-1] = real;
+
+ return faked_ptr;
+}
+
+void qFreeAligned(void *ptr)
+{
+ if (!ptr)
+ return;
+ void **ptr2 = static_cast<void **>(ptr);
+ free(ptr2[-1]);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
new file mode 100644
index 0000000000..75ce68afbf
--- /dev/null
+++ b/src/corelib/global/qnamespace.h
@@ -0,0 +1,1882 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNAMESPACE_H
+#define QNAMESPACE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef Q_MOC_RUN
+namespace
+#else
+class Q_CORE_EXPORT
+#endif
+Qt {
+
+#if defined(Q_MOC_RUN)
+ Q_OBJECT
+#endif
+
+#if (defined(Q_MOC_RUN) || defined(QT_JAMBI_RUN))
+ // NOTE: Generally, do not add Q_ENUMS if a corresponding Q_FLAGS exists.
+ Q_ENUMS(ScrollBarPolicy FocusPolicy ContextMenuPolicy)
+ Q_ENUMS(ArrowType ToolButtonStyle PenStyle PenCapStyle PenJoinStyle BrushStyle)
+ Q_ENUMS(FillRule MaskMode BGMode ClipOperation SizeMode)
+ Q_ENUMS(BackgroundMode) // Qt3
+ Q_ENUMS(Axis Corner LayoutDirection SizeHint Orientation DropAction)
+ Q_FLAGS(Alignment Orientations DropActions)
+ Q_FLAGS(DockWidgetAreas ToolBarAreas)
+ Q_ENUMS(DockWidgetArea ToolBarArea)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(TextElideMode)
+ Q_ENUMS(DateFormat TimeSpec DayOfWeek)
+ Q_ENUMS(CursorShape GlobalColor)
+ Q_ENUMS(AspectRatioMode TransformationMode)
+ Q_FLAGS(ImageConversionFlags)
+ Q_ENUMS(Key ShortcutContext)
+ Q_ENUMS(TextInteractionFlag)
+ Q_FLAGS(TextInteractionFlags)
+ Q_ENUMS(ItemSelectionMode)
+ Q_FLAGS(ItemFlags)
+ Q_ENUMS(CheckState)
+ Q_ENUMS(SortOrder CaseSensitivity)
+ Q_FLAGS(MatchFlags)
+ Q_FLAGS(KeyboardModifiers MouseButtons)
+ Q_ENUMS(WindowType WindowState WindowModality WidgetAttribute ApplicationAttribute)
+ Q_ENUMS(InputMethodHint)
+ Q_FLAGS(WindowFlags WindowStates InputMethodHints)
+ Q_ENUMS(ConnectionType)
+#ifndef QT_NO_GESTURES
+ Q_ENUMS(GestureState)
+ Q_ENUMS(GestureType)
+#endif
+#endif // (defined(Q_MOC_RUN) || defined(QT_JAMBI_RUN))
+
+#if defined(Q_MOC_RUN)
+public:
+#endif
+
+ enum GlobalColor {
+ color0,
+ color1,
+ black,
+ white,
+ darkGray,
+ gray,
+ lightGray,
+ red,
+ green,
+ blue,
+ cyan,
+ magenta,
+ yellow,
+ darkRed,
+ darkGreen,
+ darkBlue,
+ darkCyan,
+ darkMagenta,
+ darkYellow,
+ 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)
+
+ //shorter names for shortcuts
+ enum Modifier {
+ META = Qt::MetaModifier,
+ SHIFT = Qt::ShiftModifier,
+ CTRL = Qt::ControlModifier,
+ ALT = Qt::AltModifier,
+ MODIFIER_MASK = KeyboardModifierMask,
+ UNICODE_ACCEL = 0x00000000
+ };
+
+ enum MouseButton {
+ NoButton = 0x00000000,
+ LeftButton = 0x00000001,
+ RightButton = 0x00000002,
+ MidButton = 0x00000004, // ### Qt 5: remove me
+ MiddleButton = MidButton,
+ XButton1 = 0x00000008,
+ XButton2 = 0x00000010,
+ MouseButtonMask = 0x000000ff
+ };
+ Q_DECLARE_FLAGS(MouseButtons, MouseButton)
+
+#ifdef QT3_SUPPORT
+ enum ButtonState_enum {
+ ShiftButton = Qt::ShiftModifier,
+ ControlButton = Qt::ControlModifier,
+ AltButton = Qt::AltModifier,
+ MetaButton = Qt::MetaModifier,
+ Keypad = Qt::KeypadModifier,
+ KeyButtonMask = Qt::KeyboardModifierMask
+ };
+ typedef int ButtonState;
+#endif
+
+ enum Orientation {
+ Horizontal = 0x1,
+ Vertical = 0x2
+ };
+
+ Q_DECLARE_FLAGS(Orientations, Orientation)
+
+ enum FocusPolicy {
+ NoFocus = 0,
+ TabFocus = 0x1,
+ ClickFocus = 0x2,
+ StrongFocus = TabFocus | ClickFocus | 0x8,
+ WheelFocus = StrongFocus | 0x4
+ };
+
+ enum SortOrder {
+ AscendingOrder,
+ DescendingOrder
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ ,Ascending = AscendingOrder,
+ Descending = DescendingOrder
+#endif
+ };
+
+ enum TileRule {
+ StretchTile,
+ RepeatTile,
+ RoundTile
+ };
+
+ // Text formatting flags for QPainter::drawText and QLabel.
+ // The following two enums can be combined to one integer which
+ // is passed as 'flags' to drawText and qt_format_text.
+
+ enum AlignmentFlag {
+ AlignLeft = 0x0001,
+ AlignLeading = AlignLeft,
+ AlignRight = 0x0002,
+ AlignTrailing = AlignRight,
+ AlignHCenter = 0x0004,
+ AlignJustify = 0x0008,
+ AlignAbsolute = 0x0010,
+ AlignHorizontal_Mask = AlignLeft | AlignRight | AlignHCenter | AlignJustify | AlignAbsolute,
+
+ AlignTop = 0x0020,
+ AlignBottom = 0x0040,
+ AlignVCenter = 0x0080,
+ AlignVertical_Mask = AlignTop | AlignBottom | AlignVCenter,
+
+ AlignCenter = AlignVCenter | AlignHCenter
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ , AlignAuto = AlignLeft
+#endif
+ };
+
+ Q_DECLARE_FLAGS(Alignment, AlignmentFlag)
+
+ enum TextFlag {
+ TextSingleLine = 0x0100,
+ TextDontClip = 0x0200,
+ TextExpandTabs = 0x0400,
+ TextShowMnemonic = 0x0800,
+ TextWordWrap = 0x1000,
+ TextWrapAnywhere = 0x2000,
+ TextDontPrint = 0x4000,
+ TextIncludeTrailingSpaces = 0x08000000,
+ TextHideMnemonic = 0x8000,
+ TextJustificationForced = 0x10000,
+ TextForceLeftToRight = 0x20000,
+ TextForceRightToLeft = 0x40000,
+ TextLongestVariant = 0x80000,
+ TextBypassShaping = 0x100000
+
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ ,SingleLine = TextSingleLine,
+ DontClip = TextDontClip,
+ ExpandTabs = TextExpandTabs,
+ ShowPrefix = TextShowMnemonic,
+ WordBreak = TextWordWrap,
+ BreakAnywhere = TextWrapAnywhere,
+ DontPrint = TextDontPrint,
+ IncludeTrailingSpaces = TextIncludeTrailingSpaces,
+ NoAccel = TextHideMnemonic
+#endif
+ };
+#ifdef QT3_SUPPORT
+ typedef TextFlag TextFlags;
+#endif
+
+ enum TextElideMode {
+ ElideLeft,
+ ElideRight,
+ ElideMiddle,
+ ElideNone
+ };
+
+ enum WindowType {
+ Widget = 0x00000000,
+ Window = 0x00000001,
+ Dialog = 0x00000002 | Window,
+ Sheet = 0x00000004 | Window,
+ Drawer = 0x00000006 | Window,
+ Popup = 0x00000008 | Window,
+ Tool = 0x0000000a | Window,
+ ToolTip = 0x0000000c | Window,
+ SplashScreen = 0x0000000e | Window,
+ Desktop = 0x00000010 | Window,
+ SubWindow = 0x00000012,
+
+ WindowType_Mask = 0x000000ff,
+ MSWindowsFixedSizeDialogHint = 0x00000100,
+ MSWindowsOwnDC = 0x00000200,
+ X11BypassWindowManagerHint = 0x00000400,
+ FramelessWindowHint = 0x00000800,
+ WindowTitleHint = 0x00001000,
+ WindowSystemMenuHint = 0x00002000,
+ WindowMinimizeButtonHint = 0x00004000,
+ WindowMaximizeButtonHint = 0x00008000,
+ WindowMinMaxButtonsHint = WindowMinimizeButtonHint | WindowMaximizeButtonHint,
+ WindowContextHelpButtonHint = 0x00010000,
+ WindowShadeButtonHint = 0x00020000,
+ WindowStaysOnTopHint = 0x00040000,
+ // reserved for Qt3Support:
+ // WMouseNoMask = 0x00080000,
+ // WDestructiveClose = 0x00100000,
+ // WStaticContents = 0x00200000,
+ // WGroupLeader = 0x00400000,
+ // WShowModal = 0x00800000,
+ // WNoMousePropagation = 0x01000000,
+ CustomizeWindowHint = 0x02000000,
+ WindowStaysOnBottomHint = 0x04000000,
+ WindowCloseButtonHint = 0x08000000,
+ MacWindowToolBarButtonHint = 0x10000000,
+ BypassGraphicsProxyWidget = 0x20000000,
+ WindowOkButtonHint = 0x00080000,
+ WindowCancelButtonHint = 0x00100000,
+ WindowSoftkeysVisibleHint = 0x40000000,
+ WindowSoftkeysRespondHint = 0x80000000
+
+#ifdef QT3_SUPPORT
+ ,
+ WMouseNoMask = 0x00080000,
+ WDestructiveClose = 0x00100000,
+ WStaticContents = 0x00200000,
+ WGroupLeader = 0x00400000,
+ WShowModal = 0x00800000,
+ WNoMousePropagation = 0x01000000,
+
+ WType_TopLevel = Window,
+ WType_Dialog = Dialog,
+ WType_Popup = Popup,
+ WType_Desktop = Desktop,
+ WType_Mask = WindowType_Mask,
+
+ WStyle_Customize = 0,
+ WStyle_NormalBorder = 0,
+ WStyle_DialogBorder = MSWindowsFixedSizeDialogHint,
+ WStyle_NoBorder = FramelessWindowHint,
+ WStyle_Title = WindowTitleHint,
+ WStyle_SysMenu = WindowSystemMenuHint,
+ WStyle_Minimize = WindowMinimizeButtonHint,
+ WStyle_Maximize = WindowMaximizeButtonHint,
+ WStyle_MinMax = WStyle_Minimize | WStyle_Maximize,
+ WStyle_Tool = Tool,
+ WStyle_StaysOnTop = WindowStaysOnTopHint,
+ WStyle_ContextHelp = WindowContextHelpButtonHint,
+
+ // misc flags
+ WPaintDesktop = 0,
+ WPaintClever = 0,
+
+ WX11BypassWM = X11BypassWindowManagerHint,
+ WWinOwnDC = MSWindowsOwnDC,
+ WMacSheet = Sheet,
+ WMacDrawer = Drawer,
+
+ WStyle_Splash = SplashScreen,
+
+ WNoAutoErase = 0,
+ WRepaintNoErase = 0,
+ WNorthWestGravity = WStaticContents,
+ WType_Modal = Dialog | WShowModal,
+ WStyle_Dialog = Dialog,
+ WStyle_NoBorderEx = FramelessWindowHint,
+ WResizeNoErase = 0,
+ WMacNoSheet = 0
+#endif
+
+ };
+
+ Q_DECLARE_FLAGS(WindowFlags, WindowType)
+
+ enum WindowState {
+ WindowNoState = 0x00000000,
+ WindowMinimized = 0x00000001,
+ WindowMaximized = 0x00000002,
+ WindowFullScreen = 0x00000004,
+ WindowActive = 0x00000008
+ };
+
+ Q_DECLARE_FLAGS(WindowStates, WindowState)
+
+ enum WidgetAttribute {
+ WA_Disabled = 0,
+ WA_UnderMouse = 1,
+ WA_MouseTracking = 2,
+ WA_ContentsPropagated = 3, // ## deprecated
+ WA_OpaquePaintEvent = 4,
+ WA_NoBackground = WA_OpaquePaintEvent, // ## deprecated
+ WA_StaticContents = 5,
+ WA_LaidOut = 7,
+ WA_PaintOnScreen = 8,
+ WA_NoSystemBackground = 9,
+ WA_UpdatesDisabled = 10,
+ WA_Mapped = 11,
+ WA_MacNoClickThrough = 12, // Mac only
+ WA_PaintOutsidePaintEvent = 13,
+ WA_InputMethodEnabled = 14,
+ WA_WState_Visible = 15,
+ WA_WState_Hidden = 16,
+
+ WA_ForceDisabled = 32,
+ WA_KeyCompression = 33,
+ WA_PendingMoveEvent = 34,
+ WA_PendingResizeEvent = 35,
+ WA_SetPalette = 36,
+ WA_SetFont = 37,
+ WA_SetCursor = 38,
+ WA_NoChildEventsFromChildren = 39,
+ WA_WindowModified = 41,
+ WA_Resized = 42,
+ WA_Moved = 43,
+ WA_PendingUpdate = 44,
+ WA_InvalidSize = 45,
+ WA_MacBrushedMetal = 46, // Mac only
+ WA_MacMetalStyle = WA_MacBrushedMetal, // obsolete
+ WA_CustomWhatsThis = 47,
+ WA_LayoutOnEntireRect = 48,
+ WA_OutsideWSRange = 49,
+ WA_GrabbedShortcut = 50,
+ WA_TransparentForMouseEvents = 51,
+ WA_PaintUnclipped = 52,
+ WA_SetWindowIcon = 53,
+ WA_NoMouseReplay = 54,
+ WA_DeleteOnClose = 55,
+ WA_RightToLeft = 56,
+ WA_SetLayoutDirection = 57,
+ WA_NoChildEventsForParent = 58,
+ WA_ForceUpdatesDisabled = 59,
+
+ WA_WState_Created = 60,
+ WA_WState_CompressKeys = 61,
+ WA_WState_InPaintEvent = 62,
+ WA_WState_Reparented = 63,
+ WA_WState_ConfigPending = 64,
+ WA_WState_Polished = 66,
+ WA_WState_DND = 67, // ## deprecated
+ WA_WState_OwnSizePolicy = 68,
+ WA_WState_ExplicitShowHide = 69,
+
+ WA_ShowModal = 70, // ## deprecated
+ WA_MouseNoMask = 71,
+ WA_GroupLeader = 72, // ## deprecated
+ 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,
+
+ WA_KeyboardFocusChange = 77,
+
+ WA_AcceptDrops = 78,
+ WA_DropSiteRegistered = 79, // internal
+ WA_ForceAcceptDrops = WA_DropSiteRegistered, // ## deprecated
+
+ WA_WindowPropagation = 80,
+
+ WA_NoX11EventCompression = 81,
+ WA_TintedBackground = 82,
+ WA_X11OpenGLOverlay = 83,
+ WA_AlwaysShowToolTips = 84,
+ WA_MacOpaqueSizeGrip = 85,
+ WA_SetStyle = 86,
+
+ WA_SetLocale = 87,
+ WA_MacShowFocusRect = 88,
+
+ WA_MacNormalSize = 89, // Mac only
+ WA_MacSmallSize = 90, // Mac only
+ WA_MacMiniSize = 91, // Mac only
+
+ WA_LayoutUsesWidgetRect = 92,
+ WA_StyledBackground = 93, // internal
+ WA_MSWindowsUseDirect3D = 94, // Win only
+ WA_CanHostQMdiSubWindowTitleBar = 95, // Internal
+
+ WA_MacAlwaysShowToolWindow = 96, // Mac only
+
+ WA_StyleSheet = 97, // internal
+
+ WA_ShowWithoutActivating = 98,
+
+ WA_X11BypassTransientForHint = 99,
+
+ WA_NativeWindow = 100,
+ WA_DontCreateNativeAncestors = 101,
+
+ WA_MacVariableSize = 102, // Mac only
+
+ WA_DontShowOnScreen = 103,
+
+ // window types from http://standards.freedesktop.org/wm-spec/
+ WA_X11NetWmWindowTypeDesktop = 104,
+ WA_X11NetWmWindowTypeDock = 105,
+ WA_X11NetWmWindowTypeToolBar = 106,
+ WA_X11NetWmWindowTypeMenu = 107,
+ WA_X11NetWmWindowTypeUtility = 108,
+ WA_X11NetWmWindowTypeSplash = 109,
+ WA_X11NetWmWindowTypeDialog = 110,
+ WA_X11NetWmWindowTypeDropDownMenu = 111,
+ WA_X11NetWmWindowTypePopupMenu = 112,
+ WA_X11NetWmWindowTypeToolTip = 113,
+ WA_X11NetWmWindowTypeNotification = 114,
+ WA_X11NetWmWindowTypeCombo = 115,
+ WA_X11NetWmWindowTypeDND = 116,
+
+ WA_MacFrameworkScaled = 117,
+
+ WA_SetWindowModality = 118,
+ WA_WState_WindowOpacitySet = 119, // internal
+ WA_TranslucentBackground = 120,
+
+ WA_AcceptTouchEvents = 121,
+ WA_WState_AcceptedTouchBeginEvent = 122,
+ WA_TouchPadAcceptSingleTouchEvents = 123,
+
+ WA_MergeSoftkeys = 124,
+ WA_MergeSoftkeysRecursively = 125,
+
+#if 0 // these values are reserved for Maemo5 - do not re-use them
+ WA_Maemo5NonComposited = 126,
+ WA_Maemo5StackedWindow = 127,
+#endif
+
+ WA_LockPortraitOrientation = 128,
+ WA_LockLandscapeOrientation = 129,
+ WA_AutoOrientation = 130,
+
+#if 0 // these values are reserved for Maemo5 - do not re-use them
+ WA_Maemo5PortraitOrientation = WA_LockPortraitOrientation,
+ WA_Maemo5LandscapeOrientation = WA_LockLandscapeOrientation,
+ WA_Maemo5AutoOrientation = WA_AutoOrientation,
+ WA_Maemo5ShowProgressIndicator = 131,
+#endif
+
+ WA_X11DoNotAcceptFocus = 132,
+ WA_SymbianNoSystemRotation = 133,
+ WA_MacNoShadow = 134,
+
+ // Add new attributes before this line
+ WA_AttributeCount
+ };
+
+ enum ApplicationAttribute
+ {
+ AA_ImmediateWidgetCreation = 0,
+ AA_MSWindowsUseDirect3DByDefault = 1, // Win only
+ AA_DontShowIconsInMenus = 2,
+ AA_NativeWindows = 3,
+ AA_DontCreateNativeWidgetSiblings = 4,
+ AA_MacPluginApplication = 5,
+ AA_DontUseNativeMenuBar = 6,
+ AA_MacDontSwapCtrlAndMeta = 7,
+ AA_S60DontConstructApplicationPanes = 8,
+ AA_S60DisablePartialScreenInputMode = 9,
+ AA_X11InitThreads = 10,
+
+ // Add new attributes before this line
+ AA_AttributeCount
+ };
+
+
+ // Image conversion flags. The unusual ordering is caused by
+ // compatibility and default requirements.
+
+ enum ImageConversionFlag {
+ ColorMode_Mask = 0x00000003,
+ AutoColor = 0x00000000,
+ ColorOnly = 0x00000003,
+ MonoOnly = 0x00000002,
+ // Reserved = 0x00000001,
+
+ AlphaDither_Mask = 0x0000000c,
+ ThresholdAlphaDither = 0x00000000,
+ OrderedAlphaDither = 0x00000004,
+ DiffuseAlphaDither = 0x00000008,
+ NoAlpha = 0x0000000c, // Not supported
+
+ Dither_Mask = 0x00000030,
+ DiffuseDither = 0x00000000,
+ OrderedDither = 0x00000010,
+ ThresholdDither = 0x00000020,
+ // ReservedDither = 0x00000030,
+
+ DitherMode_Mask = 0x000000c0,
+ AutoDither = 0x00000000,
+ PreferDither = 0x00000040,
+ AvoidDither = 0x00000080,
+
+ NoOpaqueDetection = 0x00000100,
+ NoFormatConversion = 0x00000200
+ };
+ Q_DECLARE_FLAGS(ImageConversionFlags, ImageConversionFlag)
+
+ enum BGMode {
+ TransparentMode,
+ OpaqueMode
+ };
+
+#ifdef QT3_SUPPORT
+ enum PaintUnit { // paint unit
+ PixelUnit,
+ LoMetricUnit, // obsolete
+ HiMetricUnit, // obsolete
+ LoEnglishUnit, // obsolete
+ HiEnglishUnit, // obsolete
+ TwipsUnit // obsolete
+ };
+
+ enum GUIStyle {
+ MacStyle,
+ WindowsStyle,
+ Win3Style,
+ PMStyle,
+ MotifStyle
+ };
+#endif
+
+ enum Key {
+ Key_Escape = 0x01000000, // misc keys
+ Key_Tab = 0x01000001,
+ Key_Backtab = 0x01000002,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_BackTab = Key_Backtab,
+#endif
+ Key_Backspace = 0x01000003,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_BackSpace = Key_Backspace,
+#endif
+ Key_Return = 0x01000004,
+ Key_Enter = 0x01000005,
+ Key_Insert = 0x01000006,
+ Key_Delete = 0x01000007,
+ Key_Pause = 0x01000008,
+ Key_Print = 0x01000009,
+ 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,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_Prior = Key_PageUp,
+#endif
+ Key_PageDown = 0x01000017,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_Next = Key_PageDown,
+#endif
+ 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
+ Key_Any = Key_Space,
+ Key_Exclam = 0x21,
+ Key_QuoteDbl = 0x22,
+ Key_NumberSign = 0x23,
+ Key_Dollar = 0x24,
+ Key_Percent = 0x25,
+ Key_Ampersand = 0x26,
+ Key_Apostrophe = 0x27,
+ Key_ParenLeft = 0x28,
+ Key_ParenRight = 0x29,
+ Key_Asterisk = 0x2a,
+ Key_Plus = 0x2b,
+ Key_Comma = 0x2c,
+ Key_Minus = 0x2d,
+ Key_Period = 0x2e,
+ Key_Slash = 0x2f,
+ Key_0 = 0x30,
+ Key_1 = 0x31,
+ Key_2 = 0x32,
+ Key_3 = 0x33,
+ Key_4 = 0x34,
+ Key_5 = 0x35,
+ Key_6 = 0x36,
+ Key_7 = 0x37,
+ Key_8 = 0x38,
+ Key_9 = 0x39,
+ Key_Colon = 0x3a,
+ Key_Semicolon = 0x3b,
+ Key_Less = 0x3c,
+ Key_Equal = 0x3d,
+ Key_Greater = 0x3e,
+ Key_Question = 0x3f,
+ Key_At = 0x40,
+ Key_A = 0x41,
+ Key_B = 0x42,
+ Key_C = 0x43,
+ Key_D = 0x44,
+ Key_E = 0x45,
+ Key_F = 0x46,
+ Key_G = 0x47,
+ Key_H = 0x48,
+ Key_I = 0x49,
+ Key_J = 0x4a,
+ Key_K = 0x4b,
+ Key_L = 0x4c,
+ Key_M = 0x4d,
+ Key_N = 0x4e,
+ Key_O = 0x4f,
+ Key_P = 0x50,
+ Key_Q = 0x51,
+ Key_R = 0x52,
+ Key_S = 0x53,
+ Key_T = 0x54,
+ Key_U = 0x55,
+ Key_V = 0x56,
+ Key_W = 0x57,
+ Key_X = 0x58,
+ Key_Y = 0x59,
+ Key_Z = 0x5a,
+ Key_BracketLeft = 0x5b,
+ Key_Backslash = 0x5c,
+ Key_BracketRight = 0x5d,
+ Key_AsciiCircum = 0x5e,
+ Key_Underscore = 0x5f,
+ Key_QuoteLeft = 0x60,
+ Key_BraceLeft = 0x7b,
+ Key_Bar = 0x7c,
+ Key_BraceRight = 0x7d,
+ Key_AsciiTilde = 0x7e,
+
+ Key_nobreakspace = 0x0a0,
+ Key_exclamdown = 0x0a1,
+ Key_cent = 0x0a2,
+ Key_sterling = 0x0a3,
+ Key_currency = 0x0a4,
+ Key_yen = 0x0a5,
+ Key_brokenbar = 0x0a6,
+ Key_section = 0x0a7,
+ Key_diaeresis = 0x0a8,
+ Key_copyright = 0x0a9,
+ Key_ordfeminine = 0x0aa,
+ Key_guillemotleft = 0x0ab, // left angle quotation mark
+ Key_notsign = 0x0ac,
+ Key_hyphen = 0x0ad,
+ Key_registered = 0x0ae,
+ Key_macron = 0x0af,
+ Key_degree = 0x0b0,
+ Key_plusminus = 0x0b1,
+ Key_twosuperior = 0x0b2,
+ Key_threesuperior = 0x0b3,
+ Key_acute = 0x0b4,
+ Key_mu = 0x0b5,
+ Key_paragraph = 0x0b6,
+ Key_periodcentered = 0x0b7,
+ Key_cedilla = 0x0b8,
+ Key_onesuperior = 0x0b9,
+ Key_masculine = 0x0ba,
+ Key_guillemotright = 0x0bb, // right angle quotation mark
+ Key_onequarter = 0x0bc,
+ Key_onehalf = 0x0bd,
+ Key_threequarters = 0x0be,
+ Key_questiondown = 0x0bf,
+ Key_Agrave = 0x0c0,
+ Key_Aacute = 0x0c1,
+ Key_Acircumflex = 0x0c2,
+ Key_Atilde = 0x0c3,
+ Key_Adiaeresis = 0x0c4,
+ Key_Aring = 0x0c5,
+ Key_AE = 0x0c6,
+ Key_Ccedilla = 0x0c7,
+ Key_Egrave = 0x0c8,
+ Key_Eacute = 0x0c9,
+ Key_Ecircumflex = 0x0ca,
+ Key_Ediaeresis = 0x0cb,
+ Key_Igrave = 0x0cc,
+ Key_Iacute = 0x0cd,
+ Key_Icircumflex = 0x0ce,
+ Key_Idiaeresis = 0x0cf,
+ Key_ETH = 0x0d0,
+ Key_Ntilde = 0x0d1,
+ Key_Ograve = 0x0d2,
+ Key_Oacute = 0x0d3,
+ Key_Ocircumflex = 0x0d4,
+ Key_Otilde = 0x0d5,
+ Key_Odiaeresis = 0x0d6,
+ Key_multiply = 0x0d7,
+ Key_Ooblique = 0x0d8,
+ Key_Ugrave = 0x0d9,
+ Key_Uacute = 0x0da,
+ Key_Ucircumflex = 0x0db,
+ Key_Udiaeresis = 0x0dc,
+ Key_Yacute = 0x0dd,
+ Key_THORN = 0x0de,
+ Key_ssharp = 0x0df,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_agrave = Key_Agrave,
+ Key_aacute = Key_Aacute,
+ Key_acircumflex = Key_Acircumflex,
+ Key_atilde = Key_Atilde,
+ Key_adiaeresis = Key_Adiaeresis,
+ Key_aring = Key_Aring,
+ Key_ae = Key_AE,
+ Key_ccedilla = Key_Ccedilla,
+ Key_egrave = Key_Egrave,
+ Key_eacute = Key_Eacute,
+ Key_ecircumflex = Key_Ecircumflex,
+ Key_ediaeresis = Key_Ediaeresis,
+ Key_igrave = Key_Igrave,
+ Key_iacute = Key_Iacute,
+ Key_icircumflex = Key_Icircumflex,
+ Key_idiaeresis = Key_Idiaeresis,
+ Key_eth = Key_ETH,
+ Key_ntilde = Key_Ntilde,
+ Key_ograve = Key_Ograve,
+ Key_oacute = Key_Oacute,
+ Key_ocircumflex = Key_Ocircumflex,
+ Key_otilde = Key_Otilde,
+ Key_odiaeresis = Key_Odiaeresis,
+#endif
+ Key_division = 0x0f7,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_oslash = Key_Ooblique,
+ Key_ugrave = Key_Ugrave,
+ Key_uacute = Key_Uacute,
+ Key_ucircumflex = Key_Ucircumflex,
+ Key_udiaeresis = Key_Udiaeresis,
+ Key_yacute = Key_Yacute,
+ Key_thorn = Key_THORN,
+#endif
+ Key_ydiaeresis = 0x0ff,
+
+ // 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
+
+ // International & multi-key character composition
+ Key_AltGr = 0x01001103,
+ Key_Multi_key = 0x01001120, // Multi-key character compose
+ Key_Codeinput = 0x01001137,
+ Key_SingleCandidate = 0x0100113c,
+ Key_MultipleCandidate = 0x0100113d,
+ Key_PreviousCandidate = 0x0100113e,
+
+ // Misc Functions
+ Key_Mode_switch = 0x0100117e, // Character set switch
+ //Key_script_switch = 0x0100117e, // Alias for mode_switch
+
+ // Japanese keyboard support
+ Key_Kanji = 0x01001121, // Kanji, Kanji convert
+ Key_Muhenkan = 0x01001122, // Cancel Conversion
+ //Key_Henkan_Mode = 0x01001123, // Start/Stop Conversion
+ Key_Henkan = 0x01001123, // Alias for Henkan_Mode
+ Key_Romaji = 0x01001124, // to Romaji
+ Key_Hiragana = 0x01001125, // to Hiragana
+ Key_Katakana = 0x01001126, // to Katakana
+ Key_Hiragana_Katakana = 0x01001127, // Hiragana/Katakana toggle
+ Key_Zenkaku = 0x01001128, // to Zenkaku
+ Key_Hankaku = 0x01001129, // to Hankaku
+ Key_Zenkaku_Hankaku = 0x0100112a, // Zenkaku/Hankaku toggle
+ Key_Touroku = 0x0100112b, // Add to Dictionary
+ Key_Massyo = 0x0100112c, // Delete from Dictionary
+ Key_Kana_Lock = 0x0100112d, // Kana Lock
+ Key_Kana_Shift = 0x0100112e, // Kana Shift
+ Key_Eisu_Shift = 0x0100112f, // Alphanumeric Shift
+ Key_Eisu_toggle = 0x01001130, // Alphanumeric toggle
+ //Key_Kanji_Bangou = 0x01001137, // Codeinput
+ //Key_Zen_Koho = 0x0100113d, // Multiple/All Candidate(s)
+ //Key_Mae_Koho = 0x0100113e, // Previous Candidate
+
+ // Korean keyboard support
+ //
+ // In fact, many Korean users need only 2 keys, Key_Hangul and
+ // Key_Hangul_Hanja. But rest of the keys are good for future.
+
+ Key_Hangul = 0x01001131, // Hangul start/stop(toggle)
+ Key_Hangul_Start = 0x01001132, // Hangul start
+ Key_Hangul_End = 0x01001133, // Hangul end, English start
+ Key_Hangul_Hanja = 0x01001134, // Start Hangul->Hanja Conversion
+ Key_Hangul_Jamo = 0x01001135, // Hangul Jamo mode
+ Key_Hangul_Romaja = 0x01001136, // Hangul Romaja mode
+ //Key_Hangul_Codeinput = 0x01001137, // Hangul code input mode
+ Key_Hangul_Jeonja = 0x01001138, // Jeonja mode
+ Key_Hangul_Banja = 0x01001139, // Banja mode
+ Key_Hangul_PreHanja = 0x0100113a, // Pre Hanja conversion
+ Key_Hangul_PostHanja = 0x0100113b, // Post Hanja conversion
+ //Key_Hangul_SingleCandidate = 0x0100113c, // Single candidate
+ //Key_Hangul_MultipleCandidate = 0x0100113d, // Multiple candidate
+ //Key_Hangul_PreviousCandidate = 0x0100113e, // Previous candidate
+ Key_Hangul_Special = 0x0100113f, // Special symbols
+ //Key_Hangul_switch = 0x0100117e, // Alias for mode_switch
+
+ // dead keys (X keycode - 0xED00 to avoid the conflict)
+ Key_Dead_Grave = 0x01001250,
+ Key_Dead_Acute = 0x01001251,
+ Key_Dead_Circumflex = 0x01001252,
+ Key_Dead_Tilde = 0x01001253,
+ Key_Dead_Macron = 0x01001254,
+ Key_Dead_Breve = 0x01001255,
+ Key_Dead_Abovedot = 0x01001256,
+ Key_Dead_Diaeresis = 0x01001257,
+ Key_Dead_Abovering = 0x01001258,
+ Key_Dead_Doubleacute = 0x01001259,
+ Key_Dead_Caron = 0x0100125a,
+ Key_Dead_Cedilla = 0x0100125b,
+ Key_Dead_Ogonek = 0x0100125c,
+ Key_Dead_Iota = 0x0100125d,
+ Key_Dead_Voiced_Sound = 0x0100125e,
+ Key_Dead_Semivoiced_Sound = 0x0100125f,
+ Key_Dead_Belowdot = 0x01001260,
+ Key_Dead_Hook = 0x01001261,
+ Key_Dead_Horn = 0x01001262,
+
+ // multimedia/internet keys - ignored by default - see QKeyEvent c'tor
+ Key_Back = 0x01000061,
+ Key_Forward = 0x01000062,
+ Key_Stop = 0x01000063,
+ Key_Refresh = 0x01000064,
+ Key_VolumeDown = 0x01000070,
+ Key_VolumeMute = 0x01000071,
+ Key_VolumeUp = 0x01000072,
+ Key_BassBoost = 0x01000073,
+ Key_BassUp = 0x01000074,
+ Key_BassDown = 0x01000075,
+ Key_TrebleUp = 0x01000076,
+ Key_TrebleDown = 0x01000077,
+ Key_MediaPlay = 0x01000080,
+ Key_MediaStop = 0x01000081,
+ Key_MediaPrevious = 0x01000082,
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ Key_MediaPrev = Key_MediaPrevious,
+#endif
+ Key_MediaNext = 0x01000083,
+ Key_MediaRecord = 0x01000084,
+ Key_MediaPause = 0x1000085,
+ Key_MediaTogglePlayPause = 0x1000086,
+ Key_HomePage = 0x01000090,
+ Key_Favorites = 0x01000091,
+ Key_Search = 0x01000092,
+ Key_Standby = 0x01000093,
+ Key_OpenUrl = 0x01000094,
+ Key_LaunchMail = 0x010000a0,
+ Key_LaunchMedia = 0x010000a1,
+ Key_Launch0 = 0x010000a2,
+ Key_Launch1 = 0x010000a3,
+ Key_Launch2 = 0x010000a4,
+ Key_Launch3 = 0x010000a5,
+ Key_Launch4 = 0x010000a6,
+ Key_Launch5 = 0x010000a7,
+ Key_Launch6 = 0x010000a8,
+ Key_Launch7 = 0x010000a9,
+ Key_Launch8 = 0x010000aa,
+ Key_Launch9 = 0x010000ab,
+ Key_LaunchA = 0x010000ac,
+ Key_LaunchB = 0x010000ad,
+ Key_LaunchC = 0x010000ae,
+ Key_LaunchD = 0x010000af,
+ Key_LaunchE = 0x010000b0,
+ Key_LaunchF = 0x010000b1,
+ Key_MonBrightnessUp = 0x010000b2,
+ Key_MonBrightnessDown = 0x010000b3,
+ Key_KeyboardLightOnOff = 0x010000b4,
+ Key_KeyboardBrightnessUp = 0x010000b5,
+ Key_KeyboardBrightnessDown = 0x010000b6,
+ Key_PowerOff = 0x010000b7,
+ Key_WakeUp = 0x010000b8,
+ Key_Eject = 0x010000b9,
+ Key_ScreenSaver = 0x010000ba,
+ Key_WWW = 0x010000bb,
+ Key_Memo = 0x010000bc,
+ Key_LightBulb = 0x010000bd,
+ Key_Shop = 0x010000be,
+ Key_History = 0x010000bf,
+ Key_AddFavorite = 0x010000c0,
+ Key_HotLinks = 0x010000c1,
+ Key_BrightnessAdjust = 0x010000c2,
+ Key_Finance = 0x010000c3,
+ Key_Community = 0x010000c4,
+ Key_AudioRewind = 0x010000c5,
+ Key_BackForward = 0x010000c6,
+ Key_ApplicationLeft = 0x010000c7,
+ Key_ApplicationRight = 0x010000c8,
+ Key_Book = 0x010000c9,
+ Key_CD = 0x010000ca,
+ Key_Calculator = 0x010000cb,
+ Key_ToDoList = 0x010000cc,
+ Key_ClearGrab = 0x010000cd,
+ Key_Close = 0x010000ce,
+ Key_Copy = 0x010000cf,
+ Key_Cut = 0x010000d0,
+ Key_Display = 0x010000d1,
+ Key_DOS = 0x010000d2,
+ Key_Documents = 0x010000d3,
+ Key_Excel = 0x010000d4,
+ Key_Explorer = 0x010000d5,
+ Key_Game = 0x010000d6,
+ Key_Go = 0x010000d7,
+ Key_iTouch = 0x010000d8,
+ Key_LogOff = 0x010000d9,
+ Key_Market = 0x010000da,
+ Key_Meeting = 0x010000db,
+ Key_MenuKB = 0x010000dc,
+ Key_MenuPB = 0x010000dd,
+ Key_MySites = 0x010000de,
+ Key_News = 0x010000df,
+ Key_OfficeHome = 0x010000e0,
+ Key_Option = 0x010000e1,
+ Key_Paste = 0x010000e2,
+ Key_Phone = 0x010000e3,
+ Key_Calendar = 0x010000e4,
+ Key_Reply = 0x010000e5,
+ Key_Reload = 0x010000e6,
+ Key_RotateWindows = 0x010000e7,
+ Key_RotationPB = 0x010000e8,
+ Key_RotationKB = 0x010000e9,
+ Key_Save = 0x010000ea,
+ Key_Send = 0x010000eb,
+ Key_Spell = 0x010000ec,
+ Key_SplitScreen = 0x010000ed,
+ Key_Support = 0x010000ee,
+ Key_TaskPane = 0x010000ef,
+ Key_Terminal = 0x010000f0,
+ Key_Tools = 0x010000f1,
+ Key_Travel = 0x010000f2,
+ Key_Video = 0x010000f3,
+ Key_Word = 0x010000f4,
+ Key_Xfer = 0x010000f5,
+ Key_ZoomIn = 0x010000f6,
+ Key_ZoomOut = 0x010000f7,
+ Key_Away = 0x010000f8,
+ Key_Messenger = 0x010000f9,
+ Key_WebCam = 0x010000fa,
+ Key_MailForward = 0x010000fb,
+ Key_Pictures = 0x010000fc,
+ Key_Music = 0x010000fd,
+ Key_Battery = 0x010000fe,
+ Key_Bluetooth = 0x010000ff,
+ Key_WLAN = 0x01000100,
+ Key_UWB = 0x01000101,
+ Key_AudioForward = 0x01000102,
+ Key_AudioRepeat = 0x01000103,
+ Key_AudioRandomPlay = 0x01000104,
+ Key_Subtitle = 0x01000105,
+ Key_AudioCycleTrack = 0x01000106,
+ Key_Time = 0x01000107,
+ Key_Hibernate = 0x01000108,
+ Key_View = 0x01000109,
+ Key_TopMenu = 0x0100010a,
+ Key_PowerDown = 0x0100010b,
+ Key_Suspend = 0x0100010c,
+ Key_ContrastAdjust = 0x0100010d,
+
+ Key_LaunchG = 0x0100010e,
+ Key_LaunchH = 0x0100010f,
+
+ Key_MediaLast = 0x0100ffff,
+
+ // Keypad navigation keys
+ Key_Select = 0x01010000,
+ Key_Yes = 0x01010001,
+ Key_No = 0x01010002,
+
+ // Newer misc keys
+ Key_Cancel = 0x01020001,
+ Key_Printer = 0x01020002,
+ Key_Execute = 0x01020003,
+ Key_Sleep = 0x01020004,
+ Key_Play = 0x01020005, // Not the same as Key_MediaPlay
+ Key_Zoom = 0x01020006,
+ //Key_Jisho = 0x01020007, // IME: Dictionary key
+ //Key_Oyayubi_Left = 0x01020008, // IME: Left Oyayubi key
+ //Key_Oyayubi_Right = 0x01020009, // IME: Right Oyayubi key
+
+ // Device keys
+ Key_Context1 = 0x01100000,
+ Key_Context2 = 0x01100001,
+ Key_Context3 = 0x01100002,
+ Key_Context4 = 0x01100003,
+ Key_Call = 0x01100004, // set absolute state to in a call (do not toggle state)
+ Key_Hangup = 0x01100005, // set absolute state to hang up (do not toggle state)
+ Key_Flip = 0x01100006,
+ Key_ToggleCallHangup = 0x01100007, // a toggle key for answering, or hanging up, based on current call state
+ Key_VoiceDial = 0x01100008,
+ Key_LastNumberRedial = 0x01100009,
+
+ Key_Camera = 0x01100020,
+ Key_CameraFocus = 0x01100021,
+
+ Key_unknown = 0x01ffffff
+ };
+
+ enum ArrowType {
+ NoArrow,
+ UpArrow,
+ DownArrow,
+ LeftArrow,
+ RightArrow
+ };
+
+ enum PenStyle { // pen style
+ NoPen,
+ SolidLine,
+ DashLine,
+ DotLine,
+ DashDotLine,
+ DashDotDotLine,
+ CustomDashLine
+#ifndef Q_MOC_RUN
+ , MPenStyle = 0x0f
+#endif
+ };
+
+ enum PenCapStyle { // line endcap style
+ FlatCap = 0x00,
+ SquareCap = 0x10,
+ RoundCap = 0x20,
+ MPenCapStyle = 0x30
+ };
+
+ enum PenJoinStyle { // line join style
+ MiterJoin = 0x00,
+ BevelJoin = 0x40,
+ RoundJoin = 0x80,
+ SvgMiterJoin = 0x100,
+ MPenJoinStyle = 0x1c0
+ };
+
+ enum BrushStyle { // brush style
+ NoBrush,
+ SolidPattern,
+ Dense1Pattern,
+ Dense2Pattern,
+ Dense3Pattern,
+ Dense4Pattern,
+ Dense5Pattern,
+ Dense6Pattern,
+ Dense7Pattern,
+ HorPattern,
+ VerPattern,
+ CrossPattern,
+ BDiagPattern,
+ FDiagPattern,
+ DiagCrossPattern,
+ LinearGradientPattern,
+ RadialGradientPattern,
+ ConicalGradientPattern,
+ TexturePattern = 24
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ , CustomPattern = TexturePattern
+#endif
+ };
+
+ enum SizeMode {
+ AbsoluteSize,
+ RelativeSize
+ };
+
+#if defined(QT3_SUPPORT)
+#if defined(Q_OS_MAC)
+#ifndef qdoc
+ typedef int MacintoshVersion;
+
+ enum
+#else
+ enum MacintoshVersion
+#endif
+ {
+ //Unknown
+ MV_Unknown = 0x0000,
+
+ //Version numbers
+ MV_9 = QSysInfo::MV_9,
+ MV_10_DOT_0 = QSysInfo::MV_10_0,
+ MV_10_DOT_1 = QSysInfo::MV_10_1,
+ MV_10_DOT_2 = QSysInfo::MV_10_2,
+ MV_10_DOT_3 = QSysInfo::MV_10_3,
+ MV_10_DOT_4 = QSysInfo::MV_10_4,
+
+ //Code names
+ MV_CHEETAH = QSysInfo::MV_CHEETAH,
+ MV_PUMA = QSysInfo::MV_PUMA,
+ MV_JAGUAR = QSysInfo::MV_JAGUAR,
+ MV_PANTHER = QSysInfo::MV_PANTHER,
+ MV_TIGER = QSysInfo::MV_TIGER
+ };
+#endif // Q_OS_MAC
+
+#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
+#ifndef qdoc
+ typedef int WindowsVersion;
+
+ enum
+#else
+ enum WindowsVersion
+#endif
+ {
+ WV_32s = QSysInfo::WV_32s,
+ WV_95 = QSysInfo::WV_95,
+ WV_98 = QSysInfo::WV_98,
+ WV_Me = QSysInfo::WV_Me,
+ WV_DOS_based= QSysInfo::WV_DOS_based,
+
+ WV_NT = QSysInfo::WV_NT,
+ WV_2000 = QSysInfo::WV_2000,
+ WV_XP = QSysInfo::WV_XP,
+ WV_2003 = QSysInfo::WV_2003,
+ WV_NT_based = QSysInfo::WV_NT_based,
+
+ WV_CE = QSysInfo::WV_CE,
+ WV_CENET = QSysInfo::WV_CENET,
+ WV_CE_5 = QSysInfo::WV_CE_5,
+ WV_CE_6 = QSysInfo::WV_CE_6,
+ WV_CE_based = QSysInfo::WV_CE_based
+ };
+#endif // Q_OS_WIN
+#endif // QT3_SUPPORT
+
+ enum UIEffect {
+ UI_General,
+ UI_AnimateMenu,
+ UI_FadeMenu,
+ UI_AnimateCombo,
+ UI_AnimateTooltip,
+ UI_FadeTooltip,
+ UI_AnimateToolBox
+ };
+
+ enum CursorShape {
+ ArrowCursor,
+ UpArrowCursor,
+ CrossCursor,
+ WaitCursor,
+ IBeamCursor,
+ SizeVerCursor,
+ SizeHorCursor,
+ SizeBDiagCursor,
+ SizeFDiagCursor,
+ SizeAllCursor,
+ BlankCursor,
+ SplitVCursor,
+ SplitHCursor,
+ PointingHandCursor,
+ ForbiddenCursor,
+ WhatsThisCursor,
+ BusyCursor,
+ OpenHandCursor,
+ ClosedHandCursor,
+ DragCopyCursor,
+ DragMoveCursor,
+ DragLinkCursor,
+ LastCursor = DragLinkCursor,
+ BitmapCursor = 24,
+ CustomCursor = 25
+
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ ,
+ arrowCursor = ArrowCursor,
+ upArrowCursor = UpArrowCursor,
+ crossCursor = CrossCursor,
+ waitCursor = WaitCursor,
+ ibeamCursor = IBeamCursor,
+ sizeVerCursor = SizeVerCursor,
+ sizeHorCursor = SizeHorCursor,
+ sizeBDiagCursor = SizeBDiagCursor,
+ sizeFDiagCursor = SizeFDiagCursor,
+ sizeAllCursor = SizeAllCursor,
+ blankCursor = BlankCursor,
+ splitVCursor = SplitVCursor,
+ splitHCursor = SplitHCursor,
+ pointingHandCursor = PointingHandCursor,
+ forbiddenCursor = ForbiddenCursor,
+ whatsThisCursor = WhatsThisCursor
+#endif
+ };
+
+ enum TextFormat {
+ PlainText,
+ RichText,
+ AutoText,
+ LogText
+ };
+
+ enum AspectRatioMode {
+ IgnoreAspectRatio,
+ KeepAspectRatio,
+ KeepAspectRatioByExpanding
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ , ScaleFree = IgnoreAspectRatio,
+ ScaleMin = KeepAspectRatio,
+ ScaleMax = KeepAspectRatioByExpanding
+#endif
+ };
+#ifdef QT3_SUPPORT
+ typedef AspectRatioMode ScaleMode;
+#endif
+
+ // This is for Q3TextEdit only, actually.
+ enum AnchorAttribute {
+ AnchorName,
+ AnchorHref
+ };
+
+ enum DockWidgetArea {
+ LeftDockWidgetArea = 0x1,
+ RightDockWidgetArea = 0x2,
+ TopDockWidgetArea = 0x4,
+ BottomDockWidgetArea = 0x8,
+
+ DockWidgetArea_Mask = 0xf,
+ AllDockWidgetAreas = DockWidgetArea_Mask,
+ NoDockWidgetArea = 0
+ };
+ enum DockWidgetAreaSizes {
+ NDockWidgetAreas = 4
+ };
+
+ Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
+
+ enum ToolBarArea {
+ LeftToolBarArea = 0x1,
+ RightToolBarArea = 0x2,
+ TopToolBarArea = 0x4,
+ BottomToolBarArea = 0x8,
+
+ ToolBarArea_Mask = 0xf,
+ AllToolBarAreas = ToolBarArea_Mask,
+ NoToolBarArea = 0
+ };
+
+ enum ToolBarAreaSizes {
+ NToolBarAreas = 4
+ };
+
+ Q_DECLARE_FLAGS(ToolBarAreas, ToolBarArea)
+
+#ifdef QT3_SUPPORT
+ enum Dock {
+ DockUnmanaged,
+ DockTornOff,
+ DockTop,
+ DockBottom,
+ DockRight,
+ DockLeft,
+ DockMinimized
+ ,
+ Unmanaged = DockUnmanaged,
+ TornOff = DockTornOff,
+ Top = DockTop,
+ Bottom = DockBottom,
+ Right = DockRight,
+ Left = DockLeft,
+ Minimized = DockMinimized
+ };
+ // compatibility
+ typedef Dock ToolBarDock;
+#endif
+
+ enum DateFormat {
+ TextDate, // default Qt
+ ISODate, // ISO 8601
+ SystemLocaleDate, // deprecated
+ LocalDate = SystemLocaleDate, // deprecated
+ LocaleDate, // deprecated
+ SystemLocaleShortDate,
+ SystemLocaleLongDate,
+ DefaultLocaleShortDate,
+ DefaultLocaleLongDate
+ };
+
+ enum TimeSpec {
+ LocalTime,
+ UTC,
+ OffsetFromUTC
+ };
+
+ enum DayOfWeek {
+ Monday = 1,
+ Tuesday = 2,
+ Wednesday = 3,
+ Thursday = 4,
+ Friday = 5,
+ Saturday = 6,
+ Sunday = 7
+ };
+
+ enum ScrollBarPolicy {
+ ScrollBarAsNeeded,
+ ScrollBarAlwaysOff,
+ ScrollBarAlwaysOn
+ };
+
+#ifdef QT3_SUPPORT
+ enum BackgroundMode {
+ FixedColor,
+ FixedPixmap,
+ NoBackground,
+ PaletteForeground,
+ PaletteButton,
+ PaletteLight,
+ PaletteMidlight,
+ PaletteDark,
+ PaletteMid,
+ PaletteText,
+ PaletteBrightText,
+ PaletteBase,
+ PaletteBackground,
+ PaletteShadow,
+ PaletteHighlight,
+ PaletteHighlightedText,
+ PaletteButtonText,
+ PaletteLink,
+ PaletteLinkVisited,
+ X11ParentRelative
+ };
+#endif
+
+ enum CaseSensitivity {
+ CaseInsensitive,
+ CaseSensitive
+ };
+
+ enum Corner {
+ TopLeftCorner = 0x00000,
+ TopRightCorner = 0x00001,
+ BottomLeftCorner = 0x00002,
+ BottomRightCorner = 0x00003
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ ,TopLeft = TopLeftCorner,
+ TopRight = TopRightCorner,
+ BottomLeft = BottomLeftCorner,
+ BottomRight = BottomRightCorner
+#endif
+ };
+
+ enum ConnectionType {
+ AutoConnection,
+ DirectConnection,
+ QueuedConnection,
+ AutoCompatConnection,
+ BlockingQueuedConnection,
+ UniqueConnection = 0x80
+ };
+
+ enum ShortcutContext {
+ WidgetShortcut,
+ WindowShortcut,
+ ApplicationShortcut,
+ WidgetWithChildrenShortcut
+ };
+
+ enum FillRule {
+ OddEvenFill,
+ WindingFill
+ };
+
+ enum MaskMode {
+ MaskInColor,
+ MaskOutColor
+ };
+
+ enum ClipOperation {
+ NoClip,
+ ReplaceClip,
+ IntersectClip,
+ UniteClip
+ };
+
+ // Shape = 0x1, BoundingRect = 0x2
+ enum ItemSelectionMode {
+ ContainsItemShape = 0x0,
+ IntersectsItemShape = 0x1,
+ ContainsItemBoundingRect = 0x2,
+ IntersectsItemBoundingRect = 0x3
+ };
+
+ enum TransformationMode {
+ FastTransformation,
+ SmoothTransformation
+ };
+
+ enum Axis {
+ XAxis,
+ YAxis,
+ ZAxis
+ };
+
+ enum FocusReason {
+ MouseFocusReason,
+ TabFocusReason,
+ BacktabFocusReason,
+ ActiveWindowFocusReason,
+ PopupFocusReason,
+ ShortcutFocusReason,
+ MenuBarFocusReason,
+ OtherFocusReason,
+ NoFocusReason
+ };
+
+ enum ContextMenuPolicy {
+ NoContextMenu,
+ DefaultContextMenu,
+ ActionsContextMenu,
+ CustomContextMenu,
+ PreventContextMenu
+ };
+
+ enum InputMethodQuery {
+ ImMicroFocus,
+ ImFont,
+ ImCursorPosition,
+ ImSurroundingText,
+ ImCurrentSelection,
+ ImMaximumTextLength,
+ ImAnchorPosition
+ };
+
+ enum InputMethodHint {
+ ImhNone = 0x0,
+ ImhHiddenText = 0x1,
+ ImhNoAutoUppercase = 0x2,
+ ImhPreferNumbers = 0x4,
+ ImhPreferUppercase = 0x8,
+ ImhPreferLowercase = 0x10,
+ ImhNoPredictiveText = 0x20,
+
+ ImhDigitsOnly = 0x10000,
+ ImhFormattedNumbersOnly = 0x20000,
+ ImhUppercaseOnly = 0x40000,
+ ImhLowercaseOnly = 0x80000,
+ ImhDialableCharactersOnly = 0x100000,
+ ImhEmailCharactersOnly = 0x200000,
+ ImhUrlCharactersOnly = 0x400000,
+
+ ImhExclusiveInputMask = 0xffff0000
+ };
+ Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint)
+
+ enum ToolButtonStyle {
+ ToolButtonIconOnly,
+ ToolButtonTextOnly,
+ ToolButtonTextBesideIcon,
+ ToolButtonTextUnderIcon,
+ ToolButtonFollowStyle
+ };
+
+ enum LayoutDirection {
+ LeftToRight,
+ RightToLeft,
+ LayoutDirectionAuto
+ };
+
+ enum AnchorPoint {
+ AnchorLeft = 0,
+ AnchorHorizontalCenter,
+ AnchorRight,
+ AnchorTop,
+ AnchorVerticalCenter,
+ AnchorBottom
+ };
+
+
+
+ enum DropAction {
+ CopyAction = 0x1,
+ MoveAction = 0x2,
+ LinkAction = 0x4,
+ ActionMask = 0xff,
+ TargetMoveAction = 0x8002,
+ IgnoreAction = 0x0
+ };
+ Q_DECLARE_FLAGS(DropActions, DropAction)
+
+ enum CheckState {
+ Unchecked,
+ PartiallyChecked,
+ Checked
+ };
+
+ enum ItemDataRole {
+ DisplayRole = 0,
+ DecorationRole = 1,
+ EditRole = 2,
+ ToolTipRole = 3,
+ StatusTipRole = 4,
+ WhatsThisRole = 5,
+ // Metadata
+ FontRole = 6,
+ TextAlignmentRole = 7,
+ BackgroundColorRole = 8,
+ BackgroundRole = 8,
+ TextColorRole = 9,
+ ForegroundRole = 9,
+ CheckStateRole = 10,
+ // Accessibility
+ AccessibleTextRole = 11,
+ AccessibleDescriptionRole = 12,
+ // More general purpose
+ SizeHintRole = 13,
+ InitialSortOrderRole = 14,
+ // Internal UiLib roles. Start worrying when public roles go that high.
+ DisplayPropertyRole = 27,
+ DecorationPropertyRole = 28,
+ ToolTipPropertyRole = 29,
+ StatusTipPropertyRole = 30,
+ WhatsThisPropertyRole = 31,
+ // Reserved
+ UserRole = 32
+ };
+
+ enum ItemFlag {
+ NoItemFlags = 0,
+ ItemIsSelectable = 1,
+ ItemIsEditable = 2,
+ ItemIsDragEnabled = 4,
+ ItemIsDropEnabled = 8,
+ ItemIsUserCheckable = 16,
+ ItemIsEnabled = 32,
+ ItemIsTristate = 64
+ };
+ Q_DECLARE_FLAGS(ItemFlags, ItemFlag)
+
+ enum MatchFlag {
+ MatchExactly = 0,
+ MatchContains = 1,
+ MatchStartsWith = 2,
+ MatchEndsWith = 3,
+ MatchRegExp = 4,
+ MatchWildcard = 5,
+ MatchFixedString = 8,
+ MatchCaseSensitive = 16,
+ MatchWrap = 32,
+ MatchRecursive = 64
+ };
+ Q_DECLARE_FLAGS(MatchFlags, MatchFlag)
+
+#if defined(Q_WS_MAC)
+ typedef void * HANDLE;
+#elif defined(Q_WS_WIN)
+ typedef void *HANDLE;
+#elif defined(Q_WS_X11)
+ typedef unsigned long HANDLE;
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ typedef void * HANDLE;
+#elif defined(Q_OS_SYMBIAN)
+ typedef unsigned long int HANDLE; // equivalent to TUint32
+#endif
+ typedef WindowFlags WFlags;
+
+ enum WindowModality {
+ NonModal,
+ WindowModal,
+ ApplicationModal
+ };
+
+ enum TextInteractionFlag {
+ NoTextInteraction = 0,
+ TextSelectableByMouse = 1,
+ TextSelectableByKeyboard = 2,
+ LinksAccessibleByMouse = 4,
+ LinksAccessibleByKeyboard = 8,
+ TextEditable = 16,
+
+ TextEditorInteraction = TextSelectableByMouse | TextSelectableByKeyboard | TextEditable,
+ TextBrowserInteraction = TextSelectableByMouse | LinksAccessibleByMouse | LinksAccessibleByKeyboard
+ };
+ Q_DECLARE_FLAGS(TextInteractionFlags, TextInteractionFlag)
+
+ enum EventPriority {
+ HighEventPriority = 1,
+ NormalEventPriority = 0,
+ LowEventPriority = -1
+ };
+
+ enum SizeHint {
+ MinimumSize,
+ PreferredSize,
+ MaximumSize,
+ MinimumDescent,
+ NSizeHints
+ };
+
+ enum WindowFrameSection {
+ NoSection,
+ LeftSection, // For resize
+ TopLeftSection,
+ TopSection,
+ TopRightSection,
+ RightSection,
+ BottomRightSection,
+ BottomSection,
+ BottomLeftSection,
+ TitleBarArea // For move
+ };
+
+ enum Initialization {
+ Uninitialized
+ };
+
+ enum CoordinateSystem {
+ DeviceCoordinates,
+ LogicalCoordinates
+ };
+
+ enum TouchPointState {
+ TouchPointPressed = 0x01,
+ TouchPointMoved = 0x02,
+ TouchPointStationary = 0x04,
+ TouchPointReleased = 0x08,
+ TouchPointStateMask = 0x0f,
+
+ TouchPointPrimary = 0x10
+ };
+ Q_DECLARE_FLAGS(TouchPointStates, TouchPointState)
+
+#ifndef QT_NO_GESTURES
+ enum GestureState
+ {
+ NoGesture,
+ GestureStarted = 1,
+ GestureUpdated = 2,
+ GestureFinished = 3,
+ GestureCanceled = 4
+ };
+
+ enum GestureType
+ {
+ TapGesture = 1,
+ TapAndHoldGesture = 2,
+ PanGesture = 3,
+ PinchGesture = 4,
+ SwipeGesture = 5,
+
+ CustomGesture = 0x0100,
+
+ LastGestureType = ~0u
+ };
+
+ enum GestureFlag
+ {
+ DontStartGestureOnChildren = 0x01,
+ ReceivePartialGestures = 0x02,
+ IgnoredGesturesPropagateToParent = 0x04
+ };
+ Q_DECLARE_FLAGS(GestureFlags, GestureFlag)
+#endif // QT_NO_GESTURES
+
+ enum NavigationMode
+ {
+ NavigationModeNone,
+ NavigationModeKeypadTabOrder,
+ NavigationModeKeypadDirectional,
+ NavigationModeCursorAuto,
+ NavigationModeCursorForceVisible
+ };
+}
+#ifdef Q_MOC_RUN
+ ;
+#endif
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseButtons)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Orientations)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::KeyboardModifiers)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Alignment)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ImageConversionFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DockWidgetAreas)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ToolBarAreas)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowStates)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DropActions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ItemFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates)
+#ifndef QT_NO_GESTURES
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::GestureFlags)
+#endif
+
+typedef bool (*qInternalCallback)(void **);
+
+class Q_CORE_EXPORT QInternal {
+public:
+ enum PaintDeviceFlags {
+ UnknownDevice = 0x00,
+ Widget = 0x01,
+ Pixmap = 0x02,
+ Image = 0x03,
+ Printer = 0x04,
+ Picture = 0x05,
+ Pbuffer = 0x06, // GL pbuffer
+ FramebufferObject = 0x07, // GL framebuffer object
+ CustomRaster = 0x08,
+ MacQuartz = 0x09,
+ PaintBuffer = 0x0a,
+ OpenGL = 0x0b
+ };
+ enum RelayoutType {
+ RelayoutNormal,
+ RelayoutDragging,
+ RelayoutDropped
+ };
+
+
+ enum Callback {
+ ConnectCallback,
+ DisconnectCallback,
+ AdoptCurrentThread,
+ EventNotifyCallback,
+ LastCallback
+ };
+
+ enum InternalFunction {
+ CreateThreadForAdoption,
+ RefAdoptedThread,
+ DerefAdoptedThread,
+ SetCurrentThreadToMainThread,
+ SetQObjectSender,
+ GetQObjectSender,
+ ResetQObjectSender,
+ LastInternalFunction
+ };
+
+ enum DockPosition {
+ LeftDock,
+ RightDock,
+ TopDock,
+ BottomDock,
+ DockCount
+ };
+
+ static bool registerCallback(Callback, qInternalCallback);
+ static bool unregisterCallback(Callback, qInternalCallback);
+
+ static bool activateCallbacks(Callback, void **);
+ static bool callFunction(InternalFunction func, void **);
+};
+
+#ifdef QT3_SUPPORT
+typedef qint32 QCOORD; // coordinate type
+enum {
+ QCOORD_MAX = 2147483647,
+ QCOORD_MIN = -QCOORD_MAX - 1
+};
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QNAMESPACE_H
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
new file mode 100644
index 0000000000..7cc0814e9c
--- /dev/null
+++ b/src/corelib/global/qnamespace.qdoc
@@ -0,0 +1,3008 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \namespace Qt
+ \inmodule QtCore
+ \target Qt Namespace
+
+ \brief The Qt namespace contains miscellaneous identifiers
+ used throughout the Qt library.
+*/
+
+/*!
+ \enum Qt::Orientation
+
+ This type is used to signify an object's orientation.
+
+ \value Horizontal
+ \value Vertical
+
+ Orientation is used with QScrollBar for example.
+*/
+
+/*!
+ \enum Qt::AlignmentFlag
+
+ This enum type is used to describe alignment. It contains
+ horizontal and vertical flags that can be combined to produce
+ the required effect.
+
+ The \l{TextElideMode} enum can also be used in many situations
+ to fine-tune the appearance of aligned text.
+
+ The horizontal flags are:
+
+ \value AlignLeft Aligns with the left edge.
+ \value AlignRight Aligns with the right edge.
+ \value AlignHCenter Centers horizontally in the available space.
+ \value AlignJustify Justifies the text in the available space.
+ \omitvalue AlignAuto
+
+ The vertical flags are:
+
+ \value AlignTop Aligns with the top.
+ \value AlignBottom Aligns with the bottom.
+ \value AlignVCenter Centers vertically in the available space.
+
+ You can use only one of the horizontal flags at a time. There is
+ one two-dimensional flag:
+
+ \value AlignCenter Centers in both dimensions.
+
+ You can use at most one horizontal and one vertical flag at a
+ time. Qt::AlignCenter counts as both horizontal and vertical.
+
+ Three enum values are useful in applications that can be run in
+ right-to-left mode:
+
+ \value AlignAbsolute If the widget's layout direction is
+ Qt::RightToLeft (instead of Qt::LeftToRight, the default),
+ Qt::AlignLeft refers to the \e right edge and Qt::AlignRight
+ to the \e left edge. This is normally the desired behavior.
+ If you want Qt::AlignLeft to always mean "left" and
+ Qt::AlignRight to always mean "right", combine the flag with
+ Qt::AlignAbsolute.
+ \value AlignLeading Synonym for Qt::AlignLeft.
+ \value AlignTrailing Synonym for Qt::AlignRight.
+
+ Masks:
+
+ \value AlignHorizontal_Mask
+ \value AlignVertical_Mask
+
+ Conflicting combinations of flags have undefined meanings.
+*/
+
+/*!
+ \enum Qt::ApplicationAttribute
+
+ This enum describes attributes that change the behavior of
+ application-wide features. These are enabled and disabled using
+ QCoreApplication::setAttribute(), and can be tested for with
+ QCoreApplication::testAttribute().
+
+ \value AA_ImmediateWidgetCreation Ensures that widgets are created
+ as soon as they are constructed. By default, resources for
+ widgets are allocated on demand to improve efficiency and
+ minimize resource usage. Setting or clearing this attribute
+ affects widgets constructed after the change. Setting it
+ tells Qt to create toplevel windows immediately.
+ Therefore, if it is important to minimize resource
+ consumption, do not set this attribute.
+
+ \value AA_MSWindowsUseDirect3DByDefault This value is obsolete and
+ has no effect.
+
+ \value AA_DontShowIconsInMenus Actions with the Icon property won't be
+ shown in any menus unless specifically set by the
+ QAction::iconVisibleInMenu property.
+ Menus that are currently open or menus already created in the native
+ Mac OS X menubar \e{may not} pick up a change in this attribute. Changes
+ in the QAction::iconVisibleInMenu property will always be picked up.
+
+ \value AA_NativeWindows Ensures that widgets have native windows.
+
+ \value AA_DontCreateNativeWidgetSiblings Ensures that siblings of native
+ widgets stay non-native unless specifically set by the
+ Qt::WA_NativeWindow attribute.
+
+ \value AA_MacPluginApplication Stops the Qt mac application from doing
+ specific initializations that do not necessarily make sense when using Qt
+ to author a plugin. This includes avoiding loading our nib for the main
+ menu and not taking possession of the native menu bar. When setting this
+ attribute to true will also set the AA_DontUseNativeMenuBar attribute
+ to true.
+
+ \value AA_DontUseNativeMenuBar All menubars created while this attribute is
+ set to true won't be used as a native menubar (e.g, the menubar at
+ the top of the main screen on Mac OS X or at the bottom in Windows CE).
+
+ \value AA_MacDontSwapCtrlAndMeta On Mac OS X 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. QKeySequence::StandardShortcuts
+ 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(QKeySequence::PortableText) will be different).
+
+ \value AA_S60DontConstructApplicationPanes Stops Qt from initializing the S60 status
+ pane and softkey pane on Symbian. This is useful to save memory and reduce
+ startup time for applications that will run in fullscreen mode during their
+ whole lifetime. This attribute must be set before QApplication is
+ constructed.
+
+ \omitvalue AA_S60DisablePartialScreenInputMode By default in Symbian^3,
+ a separate editing window is opened on top of an application. This is exactly
+ like editing on previous versions of Symbian behave. When this attribute
+ is true, a virtual keyboard window is shown on top of application and it
+ is ensured that the focused text widget is visible. This is only supported in
+ Symbian^3. (internal)
+
+ \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication
+ construction in order to make Xlib calls thread-safe. This
+ attribute must be set before QApplication is constructed.
+
+ \omitvalue AA_AttributeCount
+*/
+
+/*!
+ \enum Qt::MouseButton
+
+ This enum type describes the different mouse buttons.
+
+ \value NoButton The button state does not refer to any
+ button (see QMouseEvent::button()).
+ \value LeftButton The left button is pressed, or an event refers
+ 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 XButton1 The first X button.
+ \value XButton2 The second X button.
+
+ \omitvalue MouseButtonMask
+
+ \sa KeyboardModifier Modifier
+*/
+
+/*!
+ \enum Qt::KeyboardModifier
+
+ This enum describes the modifier keys.
+
+ \value NoModifier No modifier key is pressed.
+ \value ShiftModifier A Shift key on the keyboard is pressed.
+ \value ControlModifier A Ctrl key on the keyboard is pressed.
+ \value AltModifier An Alt key on the keyboard is pressed.
+ \value MetaModifier A Meta key on the keyboard is pressed.
+ \value KeypadModifier A keypad button is pressed.
+ \value GroupSwitchModifier X11 only. A Mode_switch key on the keyboard is pressed.
+
+ \omitvalue KeyboardModifierMask
+
+ \note On Mac OS X, the \c ControlModifier value corresponds to
+ the Command keys on the Macintosh keyboard, and the \c MetaModifier value
+ corresponds to the Control keys. The \c KeypadModifier value will also be set
+ when an arrow key is pressed as the arrow keys are considered part of the
+ keypad.
+
+ \note On Windows Keyboards, Qt::MetaModifier and Qt::Key_Meta are mapped
+ to the Windows key.
+
+ \sa MouseButton Modifier
+*/
+
+/*!
+ \enum Qt::Modifier
+
+ This enum provides shorter names for the keyboard modifier keys
+ supported by Qt.
+
+ \bold{Note:} On Mac OS X, the \c CTRL value corresponds to
+ the Command keys on the Macintosh keyboard, and the \c META value
+ corresponds to the Control keys.
+
+ \value SHIFT The Shift keys provided on all standard keyboards.
+ \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
+*/
+
+/*!
+ \enum Qt::GlobalColor
+
+ Qt's predefined QColor objects:
+
+ \value white \span {id="color-white"} {White (#ffffff) }
+ \value black \span {id="color-black"} {Black (#000000) }
+ \value red \span {id="color-red"} {Red (#ff0000) }
+ \value darkRed \span {id="color-darkRed"} {Dark red (#800000) }
+ \value green \span {id="color-green"} {Green (#00ff00) }
+ \value darkGreen \span {id="color-darkGreen"} {Dark green (#008000) }
+ \value blue \span {id="color-blue"} {Blue (#0000ff) }
+ \value darkBlue \span {id="color-darkBlue"} {Dark blue (#000080) }
+ \value cyan \span {id="color-cyan"} {Cyan (#00ffff) }
+ \value darkCyan \span {id="color-darkCyan"} {Dark cyan (#008080) }
+ \value magenta \span {id="color-magenta"} {Magenta (#ff00ff) }
+ \value darkMagenta \span {id="color-darkMagenta"} {Dark magenta (#800080) }
+ \value yellow \span {id="color-yellow"} {Yellow (#ffff00) }
+ \value darkYellow \span {id="color-darkYellow"} {Dark yellow (#808000) }
+ \value gray \span {id="color-gray"} {Gray (#a0a0a4) }
+ \value darkGray \span {id="color-darkGray"} {Dark gray (#808080) }
+ \value lightGray \span {id="color-lightGray"} {Light gray (#c0c0c0) }
+ \value transparent a transparent black value (i.e., QColor(0, 0, 0, 0))
+ \value color0 0 pixel value (for bitmaps)
+ \value color1 1 pixel value (for bitmaps)
+
+ \sa QColor
+
+*/
+
+/*!
+ \enum Qt::PenStyle
+
+ This enum type defines the pen styles that can be drawn using
+ QPainter. The styles are:
+
+ \table
+ \row
+ \o \inlineimage qpen-solid.png
+ \o \inlineimage qpen-dash.png
+ \o \inlineimage qpen-dot.png
+ \row
+ \o Qt::SolidLine
+ \o Qt::DashLine
+ \o Qt::DotLine
+ \row
+ \o \inlineimage qpen-dashdot.png
+ \o \inlineimage qpen-dashdotdot.png
+ \o \inlineimage qpen-custom.png
+ \row
+ \o Qt::DashDotLine
+ \o Qt::DashDotDotLine
+ \o Qt::CustomDashLine
+ \endtable
+
+ \value NoPen no line at all. For example, QPainter::drawRect()
+ fills but does not draw any boundary line.
+
+ \value SolidLine A plain line.
+ \value DashLine Dashes separated by a few pixels.
+ \value DotLine Dots separated by a few pixels.
+ \value DashDotLine Alternate dots and dashes.
+ \value DashDotDotLine One dash, two dots, one dash, two dots.
+ \value CustomDashLine A custom pattern defined using
+ QPainterPathStroker::setDashPattern().
+
+ \omitvalue MPenStyle
+
+ \sa QPen
+*/
+
+/*!
+ \enum Qt::PenCapStyle
+
+ This enum type defines the pen cap styles supported by Qt, i.e.
+ the line end caps that can be drawn using QPainter.
+
+ \table
+ \row
+ \o \inlineimage qpen-square.png
+ \o \inlineimage qpen-flat.png
+ \o \inlineimage qpen-roundcap.png
+ \row
+ \o Qt::SquareCap
+ \o Qt::FlatCap
+ \o Qt::RoundCap
+ \endtable
+
+ \value FlatCap a square line end that does not cover the end
+ point of the line.
+ \value SquareCap a square line end that covers the end point and
+ extends beyond it by half the line width.
+ \value RoundCap a rounded line end.
+ \omitvalue MPenCapStyle
+
+ \sa QPen
+*/
+
+/*!
+ \enum Qt::PenJoinStyle
+
+ This enum type defines the pen join styles supported by Qt, i.e.
+ which joins between two connected lines can be drawn using
+ QPainter.
+
+ \table
+ \row
+ \o \inlineimage qpen-bevel.png
+ \o \inlineimage qpen-miter.png
+ \o \inlineimage qpen-roundjoin.png
+ \row
+ \o Qt::BevelJoin
+ \o Qt::MiterJoin
+ \o Qt::RoundJoin
+ \endtable
+
+ \value MiterJoin The outer edges of the lines are extended to
+ meet at an angle, and this area is filled.
+ \value BevelJoin The triangular notch between the two lines is filled.
+ \value RoundJoin A circular arc between the two lines is filled.
+ \value SvgMiterJoin A miter join corresponding to the definition of
+ a miter join in the \l{SVG 1.2 Tiny} specification.
+ \omitvalue MPenJoinStyle
+
+ \sa QPen
+*/
+
+/*!
+ \enum Qt::BrushStyle
+
+ This enum type defines the brush styles supported by Qt, i.e. the
+ fill pattern of shapes drawn using QPainter.
+
+ \image brush-styles.png Brush Styles
+
+ \value NoBrush No brush pattern.
+ \value SolidPattern Uniform color.
+ \value Dense1Pattern Extremely dense brush pattern.
+ \value Dense2Pattern Very dense brush pattern.
+ \value Dense3Pattern Somewhat dense brush pattern.
+ \value Dense4Pattern Half dense brush pattern.
+ \value Dense5Pattern Somewhat sparse brush pattern.
+ \value Dense6Pattern Very sparse brush pattern.
+ \value Dense7Pattern Extremely sparse brush pattern.
+ \value HorPattern Horizontal lines.
+ \value VerPattern Vertical lines.
+ \value CrossPattern Crossing horizontal and vertical lines.
+ \value BDiagPattern Backward diagonal lines.
+ \value FDiagPattern Forward diagonal lines.
+ \value DiagCrossPattern Crossing diagonal lines.
+ \value LinearGradientPattern Linear gradient (set using a dedicated QBrush constructor).
+ \value ConicalGradientPattern Conical gradient (set using a dedicated QBrush constructor).
+ \value RadialGradientPattern Radial gradient (set using a dedicated QBrush constructor).
+ \value TexturePattern Custom pattern (see QBrush::setTexture()).
+
+ \omitvalue CustomPattern
+
+ \sa QBrush
+*/
+
+/*!
+ \enum Qt::TextFlag
+
+ This enum type is used to define some modifier flags. Some of
+ these flags only make sense in the context of printing:
+
+ \value TextSingleLine Treats all whitespace as spaces and prints just
+ one line.
+ \value TextDontClip If it's impossible to stay within the given bounds,
+ it prints outside.
+ \value TextExpandTabs Makes the U+0009 (ASCII tab) character move to
+ the next tab stop.
+ \value TextShowMnemonic Displays the string "\&P" as \underline{P}
+ (see QButton for an example). For an ampersand, use "\&\&".
+ \value TextWordWrap Breaks lines at appropriate points, e.g. at word
+ boundaries.
+ \value TextWrapAnywhere Breaks lines anywhere, even within words.
+ \value TextHideMnemonic Same as Qt::TextShowMnemonic but doesn't draw
+ the underlines.
+ \value TextDontPrint Treat this text as "hidden" and don't print it.
+ \value IncludeTrailingSpaces When this option is set,
+ QTextLine::naturalTextWidth() and naturalTextRect() will
+ return a value that includes the width of trailing spaces in the
+ text; otherwise this width is excluded.
+ \value TextIncludeTrailingSpaces Same as IncludeTrailingSpaces
+ \value TextJustificationForced Ensures that text lines are justified.
+
+ \omitvalue TextLongestVariant Ensures that the longest variant is always used
+ when computing the size of a multi-variant string. (Internal)
+ \omitvalue TextBypassShaping
+ \omitvalue BreakAnywhere
+ \omitvalue DontClip
+ \omitvalue DontPrint
+ \omitvalue ExpandTabs
+ \omitvalue IncludeTrailingSpaces
+ \omitvalue NoAccel
+ \omitvalue ShowPrefix
+ \omitvalue SingleLine
+ \omitvalue WordBreak
+ \omitvalue TextForceLeftToRight
+ \omitvalue TextForceRightToLeft
+
+ You can use as many modifier flags as you want, except that
+ Qt::TextSingleLine and Qt::TextWordWrap cannot be combined.
+
+ Flags that are inappropriate for a given use are generally
+ ignored.
+*/
+
+/*!
+ \enum Qt::BGMode
+
+ Background mode:
+
+ \value TransparentMode
+ \value OpaqueMode
+*/
+
+/*!
+ \enum Qt::ConnectionType
+
+ This enum describes the types of connection that can be used
+ between signals and slots. In particular, it determines whether a
+ particular signal is delivered to a slot immediately or queued for
+ delivery at a later time.
+
+ \value AutoConnection
+ (default) If the signal is emitted from a different thread than the
+ receiving object, the signal is queued, behaving as
+ Qt::QueuedConnection. Otherwise, the slot is invoked directly,
+ behaving as Qt::DirectConnection. The type of connection is
+ determined when the signal is emitted.
+
+ \value DirectConnection
+ The slot is invoked immediately, when the signal is
+ emitted.
+
+ \value QueuedConnection
+ The slot is invoked when control returns to the event loop
+ of the receiver's thread. The slot is executed in the
+ receiver's thread.
+
+ \value BlockingQueuedConnection
+ Same as QueuedConnection, except the current thread blocks
+ until the slot returns. This connection type should only be
+ used where the emitter and receiver are in different
+ threads. \note Violating this rule can cause your
+ application to deadlock.
+
+ \value UniqueConnection
+ Same as AutoConnection, but the connection is made only if
+ it does not duplicate an existing connection. i.e., if the
+ same signal is already connected to the same slot for the
+ same pair of objects, then the connection will fail. This
+ connection type was introduced in Qt 4.6.
+
+ \value AutoCompatConnection
+ The default type when Qt 3 support is enabled. Same as
+ AutoConnection but will also cause warnings to be output in
+ certain situations. See \l{Porting to Qt 4#Compatibility
+ Signals and Slots}{Compatibility Signals and Slots} for
+ further information.
+
+ With queued connections, 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 scenes. If you try
+ to use a queued connection and get the error message:
+
+ \snippet doc/src/snippets/code/doc_src_qnamespace.qdoc 0
+
+ Call qRegisterMetaType() to register the data type before you
+ establish the connection.
+
+ When using signals and slots with multiple threads, see \l{Signals and Slots Across Threads}.
+
+ \sa {Thread Support in Qt}, QObject::connect(), qRegisterMetaType()
+*/
+
+/*!
+ \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}, \c{YYYY-MM-DDTHH:MM:SSTZD} (e.g., 1997-07-16T19:20:30+01:00)
+ for combined dates and times.
+
+ \value SystemLocaleShortDate The \l{QLocale::ShortFormat}{short format} used
+ by the \l{QLocale::system()}{operating system}.
+
+ \value SystemLocaleLongDate The \l{QLocale::LongFormat}{long format} used
+ by the \l{QLocale::system()}{operating system}.
+
+ \value DefaultLocaleShortDate The \l{QLocale::ShortFormat}{short format} specified
+ by the \l{QLocale::setDefault()}{application's locale}.
+
+ \value DefaultLocaleLongDate The \l{QLocale::LongFormat}{long format} used
+ by the \l{QLocale::setDefault()}{application's locale}.
+
+ \value SystemLocaleDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
+ instead (or Qt::SystemLocaleLongDate if you want long dates).
+
+ \value LocaleDate \e{This enum value is deprecated.} Use Qt::DefaultLocaleShortDate
+ instead (or Qt::DefaultLocaleLongDate if you want long dates).
+
+ \value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
+ instead (or Qt::SystemLocaleLongDate if you want long dates).
+
+ \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, 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.
+*/
+
+
+/*!
+ \enum Qt::TimeSpec
+
+ \value LocalTime Locale dependent time (Timezones and Daylight Savings Time).
+ \value UTC Coordinated Universal Time, replaces Greenwich Mean Time.
+ \value OffsetFromUTC An offset in seconds from Coordinated Universal Time.
+*/
+
+/*!
+ \enum Qt::DayOfWeek
+
+ \value Monday
+ \value Tuesday
+ \value Wednesday
+ \value Thursday
+ \value Friday
+ \value Saturday
+ \value Sunday
+*/
+
+/*!
+ \enum Qt::CaseSensitivity
+
+ \value CaseInsensitive
+ \value CaseSensitive
+*/
+
+/*!
+ \enum Qt::ToolBarArea
+
+ \value LeftToolBarArea
+ \value RightToolBarArea
+ \value TopToolBarArea
+ \value BottomToolBarArea
+ \value AllToolBarAreas
+ \value NoToolBarArea
+
+ \omitvalue ToolBarArea_Mask
+*/
+
+/*!
+ \enum Qt::DockWidgetArea
+
+ \value LeftDockWidgetArea
+ \value RightDockWidgetArea
+ \value TopDockWidgetArea
+ \value BottomDockWidgetArea
+ \value AllDockWidgetAreas
+ \value NoDockWidgetArea
+
+ \omitvalue DockWidgetArea_Mask
+*/
+
+/*!
+ \enum Qt::BackgroundMode
+
+ \compat
+
+ \value FixedColor
+ \value FixedPixmap
+ \value NoBackground
+ \value PaletteForeground
+ \value PaletteButton
+ \value PaletteLight
+ \value PaletteMidlight
+ \value PaletteDark
+ \value PaletteMid
+ \value PaletteText
+ \value PaletteBrightText
+ \value PaletteBase
+ \value PaletteBackground
+ \value PaletteShadow
+ \value PaletteHighlight
+ \value PaletteHighlightedText
+ \value PaletteButtonText
+ \value PaletteLink
+ \value PaletteLinkVisited
+ \value X11ParentRelative
+*/
+
+/*!
+ \enum Qt::ImageConversionFlag
+
+ The options marked "(default)" are set if no other values from
+ the list are included (since the defaults are zero):
+
+ Color/Mono preference (ignored for QBitmap):
+
+ \value AutoColor (default) - If the image has \link
+ QImage::depth() depth\endlink 1 and contains only
+ black and white pixels, the pixmap becomes monochrome.
+ \value ColorOnly The pixmap is dithered/converted to the
+ \link QPixmap::defaultDepth() native display depth\endlink.
+ \value MonoOnly The pixmap becomes monochrome. If necessary,
+ it is dithered using the chosen dithering algorithm.
+
+ Dithering mode preference for RGB channels:
+
+ \value DiffuseDither (default) - A high-quality dither.
+ \value OrderedDither A faster, more ordered dither.
+ \value ThresholdDither No dithering; closest color is used.
+
+ Dithering mode preference for alpha channel:
+
+ \value ThresholdAlphaDither (default) - No dithering.
+ \value OrderedAlphaDither A faster, more ordered dither.
+ \value DiffuseAlphaDither A high-quality dither.
+ \omitvalue NoAlpha
+
+ Color matching versus dithering preference:
+
+ \value PreferDither (default when converting to a pixmap) - Always dither
+ 32-bit images when the image is converted to 8 bits.
+ \value AvoidDither (default when converting for the purpose of saving to
+ file) - Dither 32-bit images only if the image has more than 256
+ colors and it is being converted to 8 bits.
+ \omitvalue AutoDither
+
+ \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
+ until a non-opaque pixel is found, or if you want the pixmap to
+ retain an alpha channel for some other reason. If the image has no
+ alpha channel this flag has no effect.
+
+ \omitvalue NoFormatConversion Don't do any format conversions on the image.
+ Can be useful when converting a QImage to a QPixmap for a one-time
+ rendering operation for example.
+*/
+
+/*! \enum Qt::GUIStyle
+
+ \compat
+
+ \value WindowsStyle
+ \value MotifStyle
+ \value MacStyle
+ \value Win3Style
+ \value PMStyle
+*/
+
+/*!
+ \enum Qt::UIEffect
+
+ This enum describes the available UI effects.
+
+ By default, Qt will try to use the platform specific desktop
+ settings for each effect. Use the
+ QApplication::setDesktopSettingsAware() function (passing \c false
+ as argument) to prevent this, and the
+ QApplication::setEffectEnabled() to enable or disable a particular
+ effect.
+
+ Note that all effects are disabled on screens running at less than
+ 16-bit color depth.
+
+ \omitvalue UI_General
+
+ \value UI_AnimateMenu Show animated menus.
+ \value UI_FadeMenu Show faded menus.
+ \value UI_AnimateCombo Show animated comboboxes.
+ \value UI_AnimateTooltip Show tooltip animations.
+ \value UI_FadeTooltip Show tooltip fading effects.
+ \value UI_AnimateToolBox Reserved
+
+ \sa QApplication::setEffectEnabled(), QApplication::setDesktopSettingsAware()
+*/
+
+/*! \enum Qt::AspectRatioMode
+
+ This enum type defines what happens to the aspect ratio when
+ scaling an rectangle.
+
+ \image qimage-scaling.png
+
+ \value IgnoreAspectRatio The size is scaled freely. The aspect
+ ratio is not preserved.
+ \value KeepAspectRatio The size is scaled to a rectangle as
+ large as possible inside a given
+ rectangle, preserving the aspect ratio.
+ \value KeepAspectRatioByExpanding The size is scaled to a
+ rectangle as small as possible
+ outside a given rectangle,
+ preserving the aspect ratio.
+
+ \omitvalue ScaleFree
+ \omitvalue ScaleMin
+ \omitvalue ScaleMax
+
+ \sa QSize::scale(), QImage::scaled()
+*/
+
+/*! \typedef Qt::ScaleMode
+ \compat
+
+ Use Qt::AspectRatioMode instead.
+
+ The enum values have been renamed as follows:
+
+ \table
+ \row \i Old enum value \i New enum value
+ \row \i Qt::ScaleFree \i Qt::IgnoreAspectRatio
+ \row \i Qt::ScaleMin \i Qt::KeepAspectRatio
+ \row \i Qt::ScaleMax \i Qt::KeepAspectRatioByExpanding
+ \endtable
+*/
+
+/*! \enum Qt::TransformationMode
+
+ This enum type defines whether image transformations (e.g.,
+ scaling) should be smooth or not.
+
+ \value FastTransformation The transformation is performed
+ quickly, with no smoothing.
+ \value SmoothTransformation The resulting image is transformed
+ using bilinear filtering.
+
+ \sa QImage::scaled()
+*/
+
+/*! \enum Qt::Axis
+
+ This enum type defines three values to represent the three
+ axes in the cartesian coordinate system.
+
+ \value XAxis The X axis.
+ \value YAxis The Y axis.
+ \value ZAxis The Z axis.
+
+ \sa QTransform::rotate(), QTransform::rotateRadians()
+ */
+
+/*!
+ \enum Qt::WidgetAttribute
+
+ \keyword widget attributes
+
+ This enum type is used to specify various widget attributes.
+ Attributes are set and cleared with QWidget::setAttribute(), and
+ queried with QWidget::testAttribute(), although some have special
+ convenience functions which are mentioned below.
+
+ \value WA_AcceptDrops Allows data from drag and drop operations
+ to be dropped onto the widget (see QWidget::setAcceptDrops()).
+
+ \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.
+
+ \value WA_DeleteOnClose Makes Qt delete this widget when the
+ widget has accepted the close event (see QWidget::closeEvent()).
+
+ \value WA_Disabled Indicates that the widget is disabled, i.e.
+ it does not receive any mouse or keyboard events. There is also a
+ getter functions QWidget::isEnabled(). This is set/cleared by the
+ Qt kernel.
+
+ \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
+ WA_Disabled. This is set/cleared by QWidget::setEnabled() and
+ QWidget::setDisabled().
+
+ \value WA_ForceUpdatesDisabled Indicates that updates are
+ explicitly disabled for the widget; i.e. it will remain disabled
+ even when all its ancestors are set to the updates-enabled state.
+ 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.
+
+ \value WA_InputMethodEnabled Enables input methods for Asian languages.
+ Must be set when creating custom text editing widgets.
+ On Windows CE and Symbian this flag can be used in addition to
+ QApplication::autoSipEnabled to automatically display the SIP when
+ entering a widget.
+
+ \value WA_KeyboardFocusChange Set on a toplevel window when
+ the users changes focus with the keyboard (tab, backtab, or shortcut).
+
+ \value WA_KeyCompression Enables key event compression if set,
+ and disables it if not set. By default key compression is off, so
+ widgets receive one key press event for each key press (or more,
+ since autorepeat is usually on). If you turn it on and your
+ program doesn't keep up with key input, Qt may try to compress key
+ events so that more than one character can be processed in each
+ event.
+ For example, a word processor widget might receive 2, 3 or more
+ characters in each QKeyEvent::text(), if the layout recalculation
+ takes too long for the CPU.
+ If a widget supports multiple character unicode input, it is
+ always safe to turn the compression on.
+ Qt performs key event compression only for printable characters.
+ Qt::Modifier keys, cursor movement keys, function keys and
+ miscellaneous action keys (e.g. Escape, Enter, Backspace,
+ PrintScreen) will stop key event compression, even if there are
+ more compressible key events available.
+ Platforms other than Mac and X11 do not support this compression,
+ in which case turning it on will have no effect.
+ This is set/cleared by the widget's author.
+
+ \value WA_LayoutOnEntireRect Indicates that the widget
+ wants QLayout to operate on the entire QWidget::rect(), not only
+ on QWidget::contentsRect(). This is set by the widget's author.
+
+ \value WA_LayoutUsesWidgetRect Ignore the layout item rect from the style
+ when laying out this widget with QLayout. This makes a difference in
+ QMacStyle and QPlastiqueStyle for some widgets.
+
+ \value WA_MacNoClickThrough When a widget that has this attribute set
+ is clicked, and its window is inactive, the click will make the window
+ active but won't be seen by the widget. Typical use of this attribute
+ is on widgets with "destructive" actions, such as a "Delete" button.
+ WA_MacNoClickThrough also applies to all child widgets of the widget
+ that has it set.
+
+ \value WA_MacOpaqueSizeGrip Indicates that the native Carbon size grip
+ should be opaque instead of transparent (the default). This attribute
+ is only applicable to Mac OS X and is set by the widget's author.
+
+ \value WA_MacShowFocusRect Indicates that this widget should get a
+ QFocusFrame around it. Some widgets draw their own focus halo
+ regardless of this attribute. Not that the QWidget::focusPolicy
+ also plays the main role in whether something is given focus or
+ not, this only controls whether or not this gets the focus
+ frame. This attribute is only applicable to Mac OS X.
+
+ \value WA_MacNormalSize Indicates the widget should have the
+ normal size for widgets in Mac OS X. This attribute is only
+ applicable to Mac OS X.
+
+ \value WA_MacSmallSize Indicates the widget should have the small
+ size for widgets in Mac OS X. This attribute is only applicable to
+ Mac OS X.
+
+ \value WA_MacMiniSize Indicates the widget should have the mini
+ size for widgets in Mac OS X. This attribute is only applicable to
+ Mac OS X.
+
+ \value WA_MacVariableSize Indicates the widget can choose between
+ alternative sizes for widgets to avoid clipping.
+ This attribute is only applicable to Mac OS X.
+
+ \value WA_MacBrushedMetal Indicates the widget should be drawn in
+ the brushed metal style as supported by the windowing system. This
+ attribute is only applicable to Mac OS X.
+
+ \omitvalue WA_MacMetalStyle
+
+ \value WA_Mapped Indicates that the widget is mapped on screen.
+ This is set/cleared by the Qt kernel.
+
+ \value WA_MouseNoMask Makes the widget receive mouse events for
+ the entire widget regardless of the currently set mask,
+ overriding QWidget::setMask(). This is not applicable for
+ top-level windows.
+
+ \value WA_MouseTracking Indicates that the widget has mouse
+ tracking enabled. See QWidget::mouseTracking.
+
+ \value WA_Moved Indicates that the widget has an explicit
+ 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
+ insertion widgets like splitters and layouts. This is set by a
+ widget's author.
+
+ \value WA_NoChildEventsFromChildren Indicates that the widget does
+ not want to receive ChildAdded or ChildRemoved events sent from its
+ children. This is set by a widget's author.
+
+ \value WA_NoMouseReplay Used for pop-up widgets. Indicates that the most
+ recent mouse press event should not be replayed when the pop-up widget
+ closes. The flag is set by the widget's author and cleared by the Qt kernel
+ every time the widget receives a new mouse event.
+
+ \value WA_NoMousePropagation Prohibits mouse events from being propagated
+ to the widget's parent. This attribute is disabled by default.
+
+ \value WA_TransparentForMouseEvents When enabled, this attribute disables
+ the delivery of mouse events to the widget and its children. Mouse events
+ are delivered to other widgets as if the widget and its children were not
+ present in the widget hierarchy; mouse clicks and other events effectively
+ "pass through" them. This attribute is disabled by default.
+
+ \value WA_NoSystemBackground Indicates that the widget has no background,
+ i.e. when the widget receives paint events, the background is not
+ automatically repainted. \note Unlike WA_OpaquePaintEvent, newly exposed
+ areas are \bold never filled with the background (e.g., after showing a
+ window for the first time the user can see "through" it until the
+ application processes the paint events). This flag is set or cleared by the
+ widget's author.
+
+ \value WA_OpaquePaintEvent Indicates that the widget paints all its pixels
+ when it receives a paint event. Thus, it is not required for operations
+ like updating, resizing, scrolling and focus changes to erase the widget
+ before generating paint events. The use of WA_OpaquePaintEvent provides a
+ small optimization by helping to reduce flicker on systems that do not
+ support double buffering and avoiding computational cycles necessary to
+ erase the background prior to painting. \note Unlike
+ WA_NoSystemBackground, WA_OpaquePaintEvent makes an effort to avoid
+ transparent window backgrounds. This flag is set or cleared by the widget's
+ author.
+
+ \value WA_OutsideWSRange Indicates that the widget is outside
+ the valid range of the window system's coordinate system. A widget
+ outside the valid range cannot be mapped on screen. This is
+ set/cleared by the Qt kernel.
+
+ \value WA_PaintOnScreen Indicates that the widget wants to draw directly
+ onto the screen. Widgets with this attribute set do not participate in
+ composition management, i.e. they cannot be semi-transparent or shine
+ through semi-transparent overlapping widgets. \note This flag is only
+ supported on X11 and it disables double buffering. On Qt for Embedded
+ Linux, the flag only works when set on a top-level widget and it relies on
+ support from the active screen driver. This flag is set or cleared by the
+ widget's author. To render outside of Qt's paint system, e.g., if you
+ require native painting primitives, you need to reimplement
+ QWidget::paintEngine() to return 0 and set this flag.
+
+ \value WA_PaintOutsidePaintEvent Makes it possible to use QPainter to
+ paint on the widget outside \l{QWidget::paintEvent()}{paintEvent()}. This
+ flag is not supported on Windows, Mac OS X or Embedded Linux. We recommend
+ that you use it only when porting Qt 3 code to Qt 4.
+
+ \value WA_PaintUnclipped Makes all painters operating on this widget
+ unclipped. Children of this widget or other widgets in front of it do not
+ clip the area the painter can paint on. This flag is only supported for
+ widgets with the WA_PaintOnScreen flag set. The preferred way to do this in
+ a cross platform way is to create a transparent widget that lies in front
+ of the other widgets.
+
+ \value WA_PendingMoveEvent Indicates that a move event is pending, e.g.,
+ when a hidden widget was moved. This flag is set or cleared by the Qt
+ kernel.
+
+ \value WA_PendingResizeEvent Indicates that a resize event is pending,
+ 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_Resized Indicates that the widget has an explicit size. This flag
+ is set or cleared by QWidget::resize() and QWidget::setGeometry().
+
+ \value WA_RightToLeft Indicates that the layout direction for the widget
+ is right to left.
+
+ \value WA_SetCursor Indicates that the widget has a cursor of its own. This
+ flag is set or cleared by QWidget::setCursor() and QWidget::unsetCursor().
+
+ \value WA_SetFont Indicates that the widget has a font of its own. This
+ flag is set or cleared by QWidget::setFont().
+
+ \value WA_SetPalette Indicates that the widget has a palette of its own.
+ This flag is set or cleared by QWidget::setPalette().
+
+ \value WA_SetStyle Indicates that the widget has a style of its own. This
+ flag is set or cleared by QWidget::setStyle().
+
+ \value WA_ShowModal \e{This attribute has been deprecated.} Use
+ QWidget::windowModality instead.
+
+ \value WA_StaticContents Indicates that the widget contents are north-west
+ aligned and static. On resize, such a widget will receive paint events only
+ for parts of itself that are newly visible. This flag is set or cleared by
+ the widget's author.
+
+ \value WA_StyleSheet Indicates that the widget is styled using a
+ \l{Qt Style Sheets}{style sheet}.
+
+ \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.
+
+ \value WA_UnderMouse Indicates that the widget is under the mouse cursor.
+ The value is not updated correctly during drag and drop operations. There
+ is also a getter function, QWidget::underMouse(). This flag is set or
+ cleared by the Qt kernel.
+
+ \value WA_UpdatesDisabled Indicates that updates are blocked (including the
+ system background). This flag is set or cleared by the Qt kernel.
+ \warning This flag must \e never be set or cleared by the widget's author.
+
+ \value WA_WindowModified Indicates that the window is marked as modified.
+ On some platforms this flag will do nothing, on others (including Mac OS X
+ and Windows) the window will take a modified appearance. This flag is set
+ or cleared by QWidget::setWindowModified().
+
+ \value WA_WindowPropagation Makes a toplevel window inherit font and
+ palette from its parent.
+
+ \value WA_MacAlwaysShowToolWindow On Mac OS X, show the tool window even
+ when the application is not active. By default, all tool windows are
+ hidden when the application is inactive.
+
+ \value WA_SetLocale Indicates the locale should be taken into consideration
+ in the widget.
+
+ \value WA_StyledBackground Indicates the widget should be drawn using a
+ styled background.
+
+ \value WA_ShowWithoutActivating Show the widget without making it active.
+
+ \value WA_NativeWindow Indicates that a native window is created for the
+ widget. Enabling this flag will also force a native window for the widget's
+ ancestors unless Qt::WA_DontCreateNativeAncestors is set.
+
+ \value WA_DontCreateNativeAncestors Indicates that the widget's ancestors
+ are kept non-native even though the widget itself is native.
+
+ \value WA_X11NetWmWindowTypeDesktop Adds _NET_WM_WINDOW_TYPE_DESKTOP to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms.
+
+ \value WA_X11NetWmWindowTypeDock Adds _NET_WM_WINDOW_TYPE_DOCK to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms.
+
+ \value WA_X11NetWmWindowTypeToolBar Adds _NET_WM_WINDOW_TYPE_TOOLBAR to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automaticaly sets this
+ attribute for QToolBar.
+
+ \value WA_X11NetWmWindowTypeMenu Adds _NET_WM_WINDOW_TYPE_MENU to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for QMenu when torn-off.
+
+ \value WA_X11NetWmWindowTypeUtility Adds _NET_WM_WINDOW_TYPE_UTILITY to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for the Qt::Tool window type.
+
+ \value WA_X11NetWmWindowTypeSplash Adds _NET_WM_WINDOW_TYPE_SPLASH to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for the Qt::SplashScreen window type.
+
+ \value WA_X11NetWmWindowTypeDialog Adds _NET_WM_WINDOW_TYPE_DIALOG
+ to the window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This
+ attribute has no effect on non-X11 platforms. \note Qt automatically sets
+ this attribute for the Qt::Dialog and Qt::Sheet window types.
+
+ \value WA_X11NetWmWindowTypeDropDownMenu Adds
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU to the window's
+ _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This
+ attribute has no effect on non-X11 platforms. \note Qt
+ automatically sets this attribute for QMenus added to a QMenuBar.
+
+ \value WA_X11NetWmWindowTypePopupMenu Adds _NET_WM_WINDOW_TYPE_POPUP_MENU
+ to the window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for QMenu.
+
+ \value WA_X11NetWmWindowTypeToolTip Adds _NET_WM_WINDOW_TYPE_TOOLTIP to the
+ window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for the Qt::ToolTip window type.
+
+ \value WA_X11NetWmWindowTypeNotification Adds
+ _NET_WM_WINDOW_TYPE_NOTIFICATION to the window's _NET_WM_WINDOW_TYPE X11
+ window property. See http://standards.freedesktop.org/wm-spec/ for more
+ details. This attribute has no effect on non-X11 platforms.
+
+ \value WA_X11NetWmWindowTypeCombo Adds _NET_WM_WINDOW_TYPE_COMBO
+ to the window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute for the QComboBox pop-up.
+
+ \value WA_X11NetWmWindowTypeDND Adds _NET_WM_WINDOW_TYPE_DND to
+ the window's _NET_WM_WINDOW_TYPE X11 window property. See
+ http://standards.freedesktop.org/wm-spec/ for more details. This attribute
+ has no effect on non-X11 platforms. \note Qt automatically sets this
+ attribute on the feedback widget used during a drag.
+
+ \value WA_MacFrameworkScaled Enables resolution independence aware mode
+ on Mac when using Carbon. This attribute has no effect on Cocoa.
+ The attribute is off by default and can be enabled on a per-window basis.
+
+ \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
+ touch device will be sent as mouse events.
+
+ \value WA_TouchPadAcceptSingleTouchEvents Allows touchpad single
+ touch events to be sent to the widget.
+
+ \value WA_MergeSoftkeys Allows widget to merge softkeys with parent widget,
+ i.e. widget can set only one softkeys and request softkey implementation
+ to take rest of the softkeys from the parent. Note parents are traversed until
+ WA_MergeSoftkeys is not set. See also Qt::WA_MergeSoftkeysRecursively
+ This attribute currently has effect only on Symbian platforms
+
+ \value WA_MergeSoftkeysRecursively Allows widget to merge softkeys recursively
+ with all parents. If this attribute is set, the widget parents are traversed until
+ window boundary (widget without parent or dialog) is found.
+ This attribute currently has effect only on Symbian platforms
+
+ \value WA_X11DoNotAcceptFocus Asks the window manager to not give focus
+ to this top level window. This attribute has no effect on non-X11
+ platforms.
+
+ \value WA_LockPortraitOrientation Locks the widget to a portrait orientation,
+ ignoring changes to the display's orientation with respect to the user.
+ \value WA_LockLandscapeOrientation Locks the widget to a landscape orientation,
+ ignoring changes to the display's orientation with respect to the user.
+ \value WA_AutoOrientation Causes the widget to change orientation whenever the
+ display changes orientation with respect to the user.
+
+ \value WA_MacNoShadow Since Qt 4.8, this attribute disables drop shadows
+ for this top level window. Only affects Cocoa builds of Qt for Mac OS X.
+
+ \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
+ \omitvalue WA_WState_Visible
+ \omitvalue WA_SetWindowIcon
+ \omitvalue WA_PendingUpdate
+ \omitvalue WA_LaidOut
+ \omitvalue WA_GrabbedShortcut
+ \omitvalue WA_DontShowOnScreen
+ \omitvalue WA_InvalidSize
+ \omitvalue WA_ForceUpdatesDisabled
+ \omitvalue WA_NoX11EventCompression
+ \omitvalue WA_TintedBackground
+ \omitvalue WA_X11OpenGLOverlay
+ \omitvalue WA_CanHostQMdiSubWindowTitleBar
+ \omitvalue WA_AttributeCount
+ \omitvalue WA_StyleSheet
+ \omitvalue WA_X11BypassTransientForHint
+ \omitvalue WA_SetWindowModality
+ \omitvalue WA_WState_WindowOpacitySet
+ \omitvalue WA_WState_AcceptedTouchBeginEvent
+ \omitvalue WA_SymbianNoSystemRotation
+*/
+
+/*! \typedef Qt::HANDLE
+
+ Platform-specific handle type for system objects. This is
+ equivalent to \c{void *} on Mac OS X and embedded Linux,
+ and to \c{unsigned long} on X11. On Windows it is the
+ DWORD returned by the Win32 function getCurrentThreadId().
+
+ \warning Using this type is not portable.
+*/
+
+/*!
+ \enum Qt::Key
+
+ The key names used by Qt.
+
+ \value Key_Escape
+ \value Key_Tab
+ \value Key_Backtab
+ \omitvalue Key_BackTab
+ \value Key_Backspace
+ \omitvalue Key_BackSpace
+ \value Key_Return
+ \value Key_Enter Typically located on the keypad.
+ \value Key_Insert
+ \value Key_Delete
+ \value Key_Pause The Pause/Break key (\note Not anything to do with pausing media)
+ \value Key_Print
+ \value Key_SysReq
+ \value Key_Clear
+ \value Key_Home
+ \value Key_End
+ \value Key_Left
+ \value Key_Up
+ \value Key_Right
+ \value Key_Down
+ \value Key_PageUp
+ \omitvalue Key_Prior
+ \value Key_PageDown
+ \omitvalue Key_Next
+ \value Key_Shift
+ \value Key_Control On Mac OS X, this corresponds to the Command keys.
+ \value Key_Meta On Mac OS X, this corresponds to the Control keys.
+ On Windows keyboards, this key is mapped to the
+ Windows key.
+ \value Key_Alt
+ \value Key_AltGr On Windows, when the KeyDown event for this key is
+ sent, the Ctrl+Alt modifiers are also set.
+ \value Key_CapsLock
+ \value Key_NumLock
+ \value Key_ScrollLock
+ \value Key_F1
+ \value Key_F2
+ \value Key_F3
+ \value Key_F4
+ \value Key_F5
+ \value Key_F6
+ \value Key_F7
+ \value Key_F8
+ \value Key_F9
+ \value Key_F10
+ \value Key_F11
+ \value Key_F12
+ \value Key_F13
+ \value Key_F14
+ \value Key_F15
+ \value Key_F16
+ \value Key_F17
+ \value Key_F18
+ \value Key_F19
+ \value Key_F20
+ \value Key_F21
+ \value Key_F22
+ \value Key_F23
+ \value Key_F24
+ \value Key_F25
+ \value Key_F26
+ \value Key_F27
+ \value Key_F28
+ \value Key_F29
+ \value Key_F30
+ \value Key_F31
+ \value Key_F32
+ \value Key_F33
+ \value Key_F34
+ \value Key_F35
+ \value Key_Super_L
+ \value Key_Super_R
+ \value Key_Menu
+ \value Key_Hyper_L
+ \value Key_Hyper_R
+ \value Key_Help
+ \value Key_Direction_L
+ \value Key_Direction_R
+ \value Key_Space
+ \value Key_Any
+ \value Key_Exclam
+ \value Key_QuoteDbl
+ \value Key_NumberSign
+ \value Key_Dollar
+ \value Key_Percent
+ \value Key_Ampersand
+ \value Key_Apostrophe
+ \value Key_ParenLeft
+ \value Key_ParenRight
+ \value Key_Asterisk
+ \value Key_Plus
+ \value Key_Comma
+ \value Key_Minus
+ \value Key_Period
+ \value Key_Slash
+ \value Key_0
+ \value Key_1
+ \value Key_2
+ \value Key_3
+ \value Key_4
+ \value Key_5
+ \value Key_6
+ \value Key_7
+ \value Key_8
+ \value Key_9
+ \value Key_Colon
+ \value Key_Semicolon
+ \value Key_Less
+ \value Key_Equal
+ \value Key_Greater
+ \value Key_Question
+ \value Key_At
+ \value Key_A
+ \value Key_B
+ \value Key_C
+ \value Key_D
+ \value Key_E
+ \value Key_F
+ \value Key_G
+ \value Key_H
+ \value Key_I
+ \value Key_J
+ \value Key_K
+ \value Key_L
+ \value Key_M
+ \value Key_N
+ \value Key_O
+ \value Key_P
+ \value Key_Q
+ \value Key_R
+ \value Key_S
+ \value Key_T
+ \value Key_U
+ \value Key_V
+ \value Key_W
+ \value Key_X
+ \value Key_Y
+ \value Key_Z
+ \value Key_BracketLeft
+ \value Key_Backslash
+ \value Key_BracketRight
+ \value Key_AsciiCircum
+ \value Key_Underscore
+ \value Key_QuoteLeft
+ \value Key_BraceLeft
+ \value Key_Bar
+ \value Key_BraceRight
+ \value Key_AsciiTilde
+ \value Key_nobreakspace
+ \value Key_exclamdown
+ \value Key_cent
+ \value Key_sterling
+ \value Key_currency
+ \value Key_yen
+ \value Key_brokenbar
+ \value Key_section
+ \value Key_diaeresis
+ \value Key_copyright
+ \value Key_ordfeminine
+ \value Key_guillemotleft
+ \value Key_notsign
+ \value Key_hyphen
+ \value Key_registered
+ \value Key_macron
+ \value Key_degree
+ \value Key_plusminus
+ \value Key_twosuperior
+ \value Key_threesuperior
+ \value Key_acute
+ \value Key_mu
+ \value Key_paragraph
+ \value Key_periodcentered
+ \value Key_cedilla
+ \value Key_onesuperior
+ \value Key_masculine
+ \value Key_guillemotright
+ \value Key_onequarter
+ \value Key_onehalf
+ \value Key_threequarters
+ \value Key_questiondown
+ \value Key_Agrave
+ \value Key_Aacute
+ \value Key_Acircumflex
+ \value Key_Atilde
+ \value Key_Adiaeresis
+ \value Key_Aring
+ \value Key_AE
+ \value Key_Ccedilla
+ \value Key_Egrave
+ \value Key_Eacute
+ \value Key_Ecircumflex
+ \value Key_Ediaeresis
+ \value Key_Igrave
+ \value Key_Iacute
+ \value Key_Icircumflex
+ \value Key_Idiaeresis
+ \value Key_ETH
+ \value Key_Ntilde
+ \value Key_Ograve
+ \value Key_Oacute
+ \value Key_Ocircumflex
+ \value Key_Otilde
+ \value Key_Odiaeresis
+ \value Key_multiply
+ \value Key_Ooblique
+ \value Key_Ugrave
+ \value Key_Uacute
+ \value Key_Ucircumflex
+ \value Key_Udiaeresis
+ \value Key_Yacute
+ \value Key_THORN
+ \value Key_ssharp
+ \omitvalue Key_agrave
+ \omitvalue Key_aacute
+ \omitvalue Key_acircumflex
+ \omitvalue Key_atilde
+ \omitvalue Key_adiaeresis
+ \omitvalue Key_aring
+ \omitvalue Key_ae
+ \omitvalue Key_ccedilla
+ \omitvalue Key_egrave
+ \omitvalue Key_eacute
+ \omitvalue Key_ecircumflex
+ \omitvalue Key_ediaeresis
+ \omitvalue Key_igrave
+ \omitvalue Key_iacute
+ \omitvalue Key_icircumflex
+ \omitvalue Key_idiaeresis
+ \omitvalue Key_eth
+ \omitvalue Key_ntilde
+ \omitvalue Key_ograve
+ \omitvalue Key_oacute
+ \omitvalue Key_ocircumflex
+ \omitvalue Key_otilde
+ \omitvalue Key_odiaeresis
+ \value Key_division
+ \omitvalue Key_oslash
+ \omitvalue Key_ugrave
+ \omitvalue Key_uacute
+ \omitvalue Key_ucircumflex
+ \omitvalue Key_udiaeresis
+ \omitvalue Key_yacute
+ \omitvalue Key_thorn
+ \value Key_ydiaeresis
+ \value Key_Multi_key
+ \value Key_Codeinput
+ \value Key_SingleCandidate
+ \value Key_MultipleCandidate
+ \value Key_PreviousCandidate
+ \value Key_Mode_switch
+ \value Key_Kanji
+ \value Key_Muhenkan
+ \value Key_Henkan
+ \value Key_Romaji
+ \value Key_Hiragana
+ \value Key_Katakana
+ \value Key_Hiragana_Katakana
+ \value Key_Zenkaku
+ \value Key_Hankaku
+ \value Key_Zenkaku_Hankaku
+ \value Key_Touroku
+ \value Key_Massyo
+ \value Key_Kana_Lock
+ \value Key_Kana_Shift
+ \value Key_Eisu_Shift
+ \value Key_Eisu_toggle
+ \value Key_Hangul
+ \value Key_Hangul_Start
+ \value Key_Hangul_End
+ \value Key_Hangul_Hanja
+ \value Key_Hangul_Jamo
+ \value Key_Hangul_Romaja
+ \value Key_Hangul_Jeonja
+ \value Key_Hangul_Banja
+ \value Key_Hangul_PreHanja
+ \value Key_Hangul_PostHanja
+ \value Key_Hangul_Special
+ \value Key_Dead_Grave
+ \value Key_Dead_Acute
+ \value Key_Dead_Circumflex
+ \value Key_Dead_Tilde
+ \value Key_Dead_Macron
+ \value Key_Dead_Breve
+ \value Key_Dead_Abovedot
+ \value Key_Dead_Diaeresis
+ \value Key_Dead_Abovering
+ \value Key_Dead_Doubleacute
+ \value Key_Dead_Caron
+ \value Key_Dead_Cedilla
+ \value Key_Dead_Ogonek
+ \value Key_Dead_Iota
+ \value Key_Dead_Voiced_Sound
+ \value Key_Dead_Semivoiced_Sound
+ \value Key_Dead_Belowdot
+ \value Key_Dead_Hook
+ \value Key_Dead_Horn
+ \value Key_Back
+ \value Key_Forward
+ \value Key_Stop
+ \value Key_Refresh
+ \value Key_VolumeDown
+ \value Key_VolumeMute
+ \value Key_VolumeUp
+ \value Key_BassBoost
+ \value Key_BassUp
+ \value Key_BassDown
+ \value Key_TrebleUp
+ \value Key_TrebleDown
+ \value Key_MediaPlay A key setting the state of the media player to play
+ \value Key_MediaStop A key setting the state of the media player to stop
+ \value Key_MediaPrevious
+ \omitvalue Key_MediaPrev
+ \value Key_MediaNext
+ \value Key_MediaRecord
+ \value Key_MediaPause A key setting the state of the media player to pause (\note not the pause/break key)
+ \value Key_MediaTogglePlayPause A key to toggle the play/pause state in the media player (rather than setting an absolute state)
+ \value Key_HomePage
+ \value Key_Favorites
+ \value Key_Search
+ \value Key_Standby
+ \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_MonBrightnessUp
+ \value Key_MonBrightnessDown
+ \value Key_KeyboardLightOnOff
+ \value Key_KeyboardBrightnessUp
+ \value Key_KeyboardBrightnessDown
+ \value Key_PowerOff
+ \value Key_WakeUp
+ \value Key_Eject
+ \value Key_ScreenSaver
+ \value Key_WWW
+ \value Key_Memo
+ \value Key_LightBulb
+ \value Key_Shop
+ \value Key_History
+ \value Key_AddFavorite
+ \value Key_HotLinks
+ \value Key_BrightnessAdjust
+ \value Key_Finance
+ \value Key_Community
+ \value Key_AudioRewind
+ \value Key_BackForward
+ \value Key_ApplicationLeft
+ \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_ToDoList
+ \value Key_ClearGrab
+ \value Key_Close
+ \value Key_Copy
+ \value Key_Cut
+ \value Key_Display
+ \value Key_DOS
+ \value Key_Documents
+ \value Key_Excel
+ \value Key_Explorer
+ \value Key_Game
+ \value Key_Go
+ \value Key_iTouch
+ \value Key_LogOff
+ \value Key_Market
+ \value Key_Meeting
+ \value Key_MenuKB
+ \value Key_MenuPB
+ \value Key_MySites
+ \value Key_News
+ \value Key_OfficeHome
+ \value Key_Option
+ \value Key_Paste
+ \value Key_Phone
+ \value Key_Calendar
+ \value Key_Reply
+ \value Key_Reload
+ \value Key_RotateWindows
+ \value Key_RotationPB
+ \value Key_RotationKB
+ \value Key_Save
+ \value Key_Send
+ \value Key_Spell
+ \value Key_SplitScreen
+ \value Key_Support
+ \value Key_TaskPane
+ \value Key_Terminal
+ \value Key_Tools
+ \value Key_Travel
+ \value Key_Video
+ \value Key_Word
+ \value Key_Xfer
+ \value Key_ZoomIn
+ \value Key_ZoomOut
+ \value Key_Away
+ \value Key_Messenger
+ \value Key_WebCam
+ \value Key_MailForward
+ \value Key_Pictures
+ \value Key_Music
+ \value Key_Battery
+ \value Key_Bluetooth
+ \value Key_WLAN
+ \value Key_UWB
+ \value Key_AudioForward
+ \value Key_AudioRepeat
+ \value Key_AudioRandomPlay
+ \value Key_Subtitle
+ \value Key_AudioCycleTrack
+ \value Key_Time
+ \value Key_Hibernate
+ \value Key_View
+ \value Key_TopMenu
+ \value Key_PowerDown
+ \value Key_Suspend
+ \value Key_ContrastAdjust
+ \value Key_MediaLast
+ \value Key_unknown
+
+ \value Key_Call A key to answer or initiate a call (see Qt::Key_ToggleCallHangup for a key to toggle current call state)
+ \value Key_Camera A key to activate the camera shutter
+ \value Key_CameraFocus A key to focus the camera
+ \value Key_Context1
+ \value Key_Context2
+ \value Key_Context3
+ \value Key_Context4
+ \value Key_Flip
+ \value Key_Hangup A key to end an ongoing call (see Qt::Key_ToggleCallHangup for a key to toggle current call state)
+ \value Key_No
+ \value Key_Select
+ \value Key_Yes
+ \value Key_ToggleCallHangup A key to toggle the current call state (ie. either answer, or hangup) depending on current call state
+ \value Key_VoiceDial
+ \value Key_LastNumberRedial
+
+ \value Key_Execute
+ \value Key_Printer
+ \value Key_Play
+ \value Key_Sleep
+ \value Key_Zoom
+ \value Key_Cancel
+
+ \sa QKeyEvent::key()
+*/
+
+/*!
+ \enum Qt::HitTestAccuracy
+
+ This enum contains the types of accuracy that can be used by the
+ QTextDocument class when testing for mouse clicks on text documents.
+
+ \value ExactHit The point at which input occurred must coincide
+ exactly with input-sensitive parts of the document.
+ \value FuzzyHit The point at which input occurred can lie close to
+ input-sensitive parts of the document.
+
+ This enum is defined in the \c <QTextDocument> header file.
+*/
+
+/*!
+ \enum Qt::WhiteSpaceMode
+
+ This enum describes the types of whitespace mode that are used by
+ the QTextDocument class to meet the requirements of different kinds
+ of textual information.
+
+ \value WhiteSpaceNormal The whitespace mode used to display
+ normal word wrapped text in paragraphs.
+ \value WhiteSpacePre A preformatted text mode in which
+ whitespace is reproduced exactly.
+ \value WhiteSpaceNoWrap
+
+ \omitvalue WhiteSpaceModeUndefined
+
+ This enum is defined in the \c <QTextDocument> header file.
+*/
+
+/*!
+ \enum Qt::ButtonState_enum
+ \compat
+ \value ShiftButton
+ \value ControlButton
+ \value AltButton
+ \value MetaButton
+ \value Keypad
+ \value KeyButtonMask
+
+ Use Qt::KeyboardModifier instead.
+*/
+
+/*!
+ \typedef Qt::ButtonState
+ \compat
+
+ Use Qt::KeyboardModifier instead.
+*/
+
+/*!
+ \enum Qt::CheckState
+
+ This enum describes the state of checkable items, controls, and widgets.
+
+ \value Unchecked The item is unchecked.
+ \value PartiallyChecked The item is partially checked. Items in hierarchical models
+ may be partially checked if some, but not all, of their
+ children are checked.
+ \value Checked The item is checked.
+
+ \sa QCheckBox, Qt::ItemFlags, Qt::ItemDataRole
+*/
+
+
+/*!
+ \enum Qt::ToolButtonStyle
+
+ The style of the tool button, describing how the button's text and
+ icon should be displayed.
+
+ \value ToolButtonIconOnly Only display the icon.
+ \value ToolButtonTextOnly Only display the text.
+ \value ToolButtonTextBesideIcon The text appears beside the icon.
+ \value ToolButtonTextUnderIcon The text appears under the icon.
+ \value ToolButtonFollowStyle Follow the \l{QStyle::SH_ToolButtonStyle}{style}.
+*/
+
+/*!
+ \enum Qt::Corner
+
+ This enum type specifies a corner in a rectangle:
+
+ \value TopLeftCorner The top-left corner of the rectangle.
+ \value TopRightCorner The top-right corner of the rectangle.
+ \value BottomLeftCorner The bottom-left corner of the rectangle.
+ \value BottomRightCorner The bottom-right corner of the rectangle.
+
+ \omitvalue TopLeft
+ \omitvalue TopRight
+ \omitvalue BottomLeft
+ \omitvalue BottomRight
+*/
+
+/*!
+ \enum Qt::ScrollBarPolicy
+
+ This enum type describes the various modes of QAbstractScrollArea's scroll
+ bars.
+
+ \value ScrollBarAsNeeded QAbstractScrollArea shows a scroll bar when the
+ content is too large to fit and not otherwise. This is the
+ default.
+
+ \value ScrollBarAlwaysOff QAbstractScrollArea never shows a scroll bar.
+
+ \value ScrollBarAlwaysOn QAbstractScrollArea always shows a scroll bar.
+
+ (The modes for the horizontal and vertical scroll bars are
+ independent.)
+*/
+
+/*!
+ \enum Qt::ArrowType
+
+ \value NoArrow
+ \value UpArrow
+ \value DownArrow
+ \value LeftArrow
+ \value RightArrow
+*/
+
+/*!
+ \enum Qt::FocusReason
+
+ This enum specifies why the focus changed. It will be passed
+ through QWidget::setFocus and can be retrieved in the QFocusEvent
+ sent to the widget upon focus change.
+
+ \value MouseFocusReason A mouse action occurred.
+ \value TabFocusReason The Tab key was pressed.
+ \value BacktabFocusReason A Backtab occurred. The input for this may
+ include the Shift or Control keys;
+ e.g. Shift+Tab.
+ \value ActiveWindowFocusReason The window system made this window either
+ active or inactive.
+ \value PopupFocusReason The application opened/closed a pop-up that
+ grabbed/released the keyboard focus.
+ \value ShortcutFocusReason The user typed a label's buddy shortcut
+ \value MenuBarFocusReason The menu bar took focus.
+ \value OtherFocusReason Another reason, usually application-specific.
+
+ \omitvalue NoFocusReason
+
+ \sa {Keyboard Focus}
+*/
+
+/*!
+ \enum Qt::WindowState
+
+ \keyword window state
+
+ This enum type is used to specify the current state of a top-level
+ window.
+
+ The states are
+
+ \value WindowNoState The window has no state set (in normal state).
+ \value WindowMinimized The window is minimized (i.e. iconified).
+ \value WindowMaximized The window is maximized with a frame around it.
+ \value WindowFullScreen The window fills the entire screen without any frame around it.
+ \value WindowActive The window is the active window, i.e. it has keyboard focus.
+
+*/
+
+/*!
+ \enum Qt::ContextMenuPolicy
+
+ This enum type defines the various policies a widget can have with
+ respect to showing a context menu.
+
+ \value NoContextMenu the widget does not feature a context menu,
+ context menu handling is deferred to the widget's parent.
+ \value PreventContextMenu the widget does not feature a context
+ menu, and in contrast to \c NoContextMenu, the handling is \e not
+ deferred to the widget's parent. This means that all right mouse
+ button events are guaranteed to be delivered to the widget itself
+ through mousePressEvent(), and mouseReleaseEvent().
+ \value DefaultContextMenu the widget's QWidget::contextMenuEvent() handler is called.
+ \value ActionsContextMenu the widget displays its QWidget::actions() as context menu.
+ \value CustomContextMenu the widget emits the QWidget::customContextMenuRequested() signal.
+*/
+
+/*!
+ \enum Qt::FocusPolicy
+
+ This enum type defines the various policies a widget can have with
+ respect to acquiring keyboard focus.
+
+ \value TabFocus the widget accepts focus by tabbing.
+ \value ClickFocus the widget accepts focus by clicking.
+ \value StrongFocus the widget accepts focus by both tabbing
+ and clicking. On Mac OS X this will also
+ be indicate that the widget accepts tab focus
+ when in 'Text/List focus mode'.
+ \value WheelFocus like Qt::StrongFocus plus the widget accepts
+ focus by using the mouse wheel.
+ \value NoFocus the widget does not accept focus.
+
+*/
+
+/*!
+ \enum Qt::ShortcutContext
+
+ For a QEvent::Shortcut event to occur, the shortcut's key sequence
+ must be entered by the user in a context where the shortcut is
+ active. The possible contexts are these:
+
+ \value WidgetShortcut The shortcut is active when its
+ parent widget has focus.
+ \value WidgetWithChildrenShortcut The shortcut is active
+ when its parent widget, or any of its children has focus.
+ Children which are top-level widgets, except pop-ups, are
+ not affected by this shortcut context.
+ \value WindowShortcut The shortcut is active when its
+ parent widget is a logical subwidget of the
+ active top-level window.
+ \value ApplicationShortcut The shortcut is active when one of
+ the applications windows are active.
+*/
+
+/*!
+ \typedef Qt::WFlags
+
+ Synonym for Qt::WindowFlags.
+*/
+
+/*!
+ \enum Qt::WindowType
+
+ \keyword window flag
+
+ This enum type is used to specify various window-system properties
+ for the widget. They are fairly unusual but necessary in a few
+ cases. Some of these flags depend on whether the underlying window
+ manager supports them.
+
+ The main types are
+
+ \value Widget This is the default type for QWidget. Widgets of
+ this type are child widgets if they have a parent,
+ and independent windows if they have no parent.
+ See also Qt::Window and Qt::SubWindow.
+
+ \value Window Indicates that the widget is a window, usually
+ with a window system frame and a title bar,
+ irrespective of whether the widget has a parent or
+ not. Note that it is not possible to unset this
+ flag if the widget does not have a parent.
+
+ \value Dialog Indicates that the widget is a window that should
+ be decorated as a dialog (i.e., typically no
+ maximize or minimize buttons in the title bar).
+ This is the default type for QDialog. If you want
+ to use it as a modal dialog, it should be launched
+ from another window, or have a parent and used
+ with the QWidget::windowModality property. If you make
+ it modal, the dialog will prevent other top-level
+ windows in the application from getting any input.
+ We refer to a top-level window that has a parent
+ as a \e secondary window.
+
+ \value Sheet Indicates that the window is a Macintosh sheet. Since
+ using a sheet implies window modality, the recommended
+ way is to use QWidget::setWindowModality(), or
+ QDialog::open(), instead.
+
+ \value Drawer Indicates that the widget is a Macintosh drawer.
+
+ \value Popup Indicates that the widget is a pop-up top-level
+ window, i.e. that it is modal, but has a window
+ system frame appropriate for pop-up menus.
+
+ \value Tool Indicates that the widget is a tool window. A tool
+ window is often a small window with a smaller than
+ usual title bar and decoration, typically used for
+ collections of tool buttons. If there is a parent,
+ the tool window will always be kept on top of it.
+ If there isn't a parent, you may consider using
+ Qt::WindowStaysOnTopHint as well. If the window
+ system supports it, a tool window can be decorated
+ with a somewhat lighter frame. It can also be
+ combined with Qt::FramelessWindowHint.
+ \br
+ \br
+ On Mac OS X, tool windows correspond to the
+ \l{http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_concept/chapter_2_section_2.html}{Floating}
+ class of windows. This means that the window lives on a
+ level above normal windows; it impossible to put a normal
+ window on top of it. By default, tool windows will disappear
+ when the application is inactive. This can be controlled by
+ the Qt::WA_MacAlwaysShowToolWindow attribute.
+
+ \value ToolTip Indicates that the widget is a tooltip. This is
+ used internally to implement
+ \l{QWidget::toolTip}{tooltips}.
+
+ \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.
+
+ \value SubWindow Indicates that this widget is a sub-window, such
+ as a QMdiSubWindow widget.
+
+ There are also a number of flags which you can use to customize
+ the appearance of top-level windows. These have no effect on other
+ windows:
+
+ \value MSWindowsFixedSizeDialogHint Gives the window a thin dialog border on Windows.
+ This style is traditionally used for fixed-size dialogs.
+
+ \value MSWindowsOwnDC Gives the window its own display
+ context on Windows.
+
+ \value X11BypassWindowManagerHint Bypass the window
+ manager completely. This results in a borderless window
+ that is not managed at all (i.e., no keyboard input unless
+ 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
+ ability to understand Motif and/or NETWM hints. Most existing
+ modern window managers can handle this.
+
+ The \c CustomizeWindowHint flag is used to enable customization of
+ the window controls. This flag must be set to allow the \c
+ WindowTitleHint, \c WindowSystemMenuHint, \c
+ WindowMinimizeButtonHint, \c WindowMaximizeButtonHint and \c
+ WindowCloseButtonHint flags to be changed.
+
+ \value CustomizeWindowHint Turns off the default window title hints.
+
+ \value WindowTitleHint Gives the window a title bar.
+
+ \value WindowSystemMenuHint Adds a window system menu, and
+ possibly a close button (for example on Mac). If you need to hide
+ or show a close button, it is more portable to use \c
+ WindowCloseButtonHint.
+
+ \value WindowMinimizeButtonHint Adds a minimize button. On
+ some platforms this implies Qt::WindowSystemMenuHint for it to work.
+
+ \value WindowMaximizeButtonHint Adds a maximize button. On
+ some platforms this implies Qt::WindowSystemMenuHint for it to work.
+
+ \value WindowMinMaxButtonsHint Adds a minimize and a maximize
+ button. On some platforms this implies Qt::WindowSystemMenuHint for it to work.
+
+ \value WindowCloseButtonHint Adds a close button. On
+ some platforms this implies Qt::WindowSystemMenuHint for it
+ to work.
+
+ \value WindowContextHelpButtonHint Adds a context help button to dialogs.
+ On some platforms this implies Qt::WindowSystemMenuHint for it to work.
+
+ \value MacWindowToolBarButtonHint On Mac OS X adds a tool bar button (i.e.,
+ the oblong button that is on the top right of windows that have toolbars).
+
+ \value BypassGraphicsProxyWidget Prevents the window and its children from
+ automatically embedding themselves into a QGraphicsProxyWidget if the
+ parent widget is already embedded. You can set this flag if you
+ want your widget to always be a toplevel widget on the desktop,
+ regardless of whether the parent widget is embedded in a scene or
+ not.
+
+ \value WindowShadeButtonHint
+
+ \value WindowStaysOnTopHint Informs the window system that the
+ window should stay on top of all other windows. Note that
+ on some window managers on X11 you also have to pass
+ Qt::X11BypassWindowManagerHint for this flag to work
+ correctly.
+
+ \value WindowStaysOnBottomHint Informs the window system that the
+ window should stay on bottom of all other windows. Note
+ that on X11 this hint will work only in window managers
+ that support _NET_WM_STATE_BELOW atom. If a window always
+ on the bottom has a parent, the parent will also be left on
+ the bottom. This window hint is currently not implemented
+ for Mac OS X.
+
+ \value WindowOkButtonHint Adds an OK button to the window decoration of a dialog.
+ Only supported for Windows CE.
+
+ \value WindowCancelButtonHint Adds a Cancel button to the window decoration of a dialog.
+ Only supported for Windows CE.
+
+ \value WindowSoftkeysVisibleHint Makes softkeys visible when widget is fullscreen.
+ Only supported for Symbian.
+
+ \value WindowSoftkeysRespondHint Makes softkeys to receive key events even
+ when invisible. With this hint the softkey actions are triggered
+ even the softkeys are invisible i.e. the window is displayed with
+ \c showFullscreen(). Only supported for Symbian.
+
+ \value WindowType_Mask A mask for extracting the window type
+ part of the window flags.
+
+ Obsolete flags:
+
+ \value WMouseNoMask Use Qt::WA_MouseNoMask instead.
+ \value WDestructiveClose Use Qt::WA_DeleteOnClose instead.
+ \value WStaticContents Use Qt::WA_StaticContents instead.
+ \value WGroupLeader No longer needed.
+ \value WShowModal Use QWidget::windowModality instead.
+ \value WNoMousePropagation Use Qt::WA_NoMousePropagation instead.
+ \value WType_TopLevel Use Qt::Window instead.
+ \value WType_Dialog Use Qt::Dialog instead.
+ \value WType_Popup Use Qt::Popup instead.
+ \value WType_Desktop Use Qt::Desktop instead.
+ \value WType_Mask Use Qt::WindowType_Mask instead.
+
+ \value WStyle_Customize No longer needed.
+ \value WStyle_NormalBorder No longer needed.
+ \value WStyle_DialogBorder Use Qt::MSWindowsFixedSizeDialogHint instead.
+ \value WStyle_NoBorder Use Qt::FramelessWindowHint instead.
+ \value WStyle_Title Use Qt::WindowTitleHint instead.
+ \value WStyle_SysMenu Use Qt::WindowSystemMenuHint instead.
+ \value WStyle_Minimize Use Qt::WindowMinimizeButtonHint instead.
+ \value WStyle_Maximize Use Qt::WindowMaximizeButtonHint instead.
+ \value WStyle_MinMax Use Qt::WindowMinMaxButtonsHint instead.
+ \value WStyle_Tool Use Qt::Tool instead.
+ \value WStyle_StaysOnTop Use Qt::WindowStaysOnTopHint instead.
+ \value WStyle_ContextHelp Use Qt::WindowContextHelpButtonHint instead.
+
+ \value WPaintDesktop No longer needed.
+ \value WPaintClever No longer needed.
+
+ \value WX11BypassWM Use Qt::X11BypassWindowManagerHint instead.
+ \value WWinOwnDC Use Qt::MSWindowsOwnDC instead.
+ \value WMacSheet Use Qt::Sheet instead.
+ \value WMacDrawer Use Qt::Drawer instead.
+
+ \value WStyle_Splash Use Qt::SplashScreen instead.
+
+ \value WNoAutoErase No longer needed.
+ \value WRepaintNoErase No longer needed.
+ \value WNorthWestGravity Use Qt::WA_StaticContents instead.
+ \value WType_Modal Use Qt::Dialog and QWidget::windowModality instead.
+ \value WStyle_Dialog Use Qt::Dialog instead.
+ \value WStyle_NoBorderEx Use Qt::FramelessWindowHint instead.
+ \value WResizeNoErase No longer needed.
+ \value WMacNoSheet No longer needed.
+
+ \sa QWidget::windowFlags, {Window Flags Example}
+*/
+
+/*!
+ \enum Qt::DropAction
+
+ \value CopyAction Copy the data to the target.
+ \value MoveAction Move the data from the source to the target.
+ \value LinkAction Create a link from the source to the target.
+ \value ActionMask
+ \value IgnoreAction Ignore the action (do nothing with the data).
+ \value TargetMoveAction On Windows, this value is used when the ownership of the D&D data
+ should be taken over by the target application,
+ i.e., the source application should not delete
+ the data.
+ \br
+ On X11 this value is used to do a move.
+ \br
+ TargetMoveAction is not used on the Mac.
+*/
+
+#if defined(Q_OS_WIN) && defined(QT3_SUPPORT)
+/*!
+ \enum Qt::WindowsVersion
+ \compat
+
+ \value WV_32s
+ \value WV_95
+ \value WV_98
+ \value WV_Me
+ \value WV_DOS_based
+ \value WV_NT
+ \value WV_2000
+ \value WV_XP
+ \value WV_2003
+ \value WV_NT_based
+ \value WV_CE
+ \value WV_CENET
+ \value WV_CE_based
+ \value WV_CE_5
+ \value WV_CE_6
+*/
+#endif
+
+#if defined(Q_OS_MAC) && defined(QT3_SUPPORT)
+/*!
+ \enum Qt::MacintoshVersion
+ \compat
+
+ \value MV_Unknown Use QSysInfo::MV_Unknown instead.
+ \value MV_9 Use QSysInfo::MV_9 instead.
+ \value MV_10_DOT_0 Use QSysInfo::MV_10_0 instead.
+ \value MV_10_DOT_1 Use QSysInfo::MV_10_1 instead.
+ \value MV_10_DOT_2 Use QSysInfo::MV_10_2 instead.
+ \value MV_10_DOT_3 Use QSysInfo::MV_10_3 instead.
+ \value MV_10_DOT_4 Use QSysInfo::MV_10_4 instead.
+
+ \value MV_CHEETAH Use QSysInfo::MV_10_0 instead.
+ \value MV_PUMA Use QSysInfo::MV_10_1 instead.
+ \value MV_JAGUAR Use QSysInfo::MV_10_2 instead.
+ \value MV_PANTHER Use QSysInfo::MV_10_3 instead.
+ \value MV_TIGER Use QSysInfo::MV_10_4 instead.
+
+ \sa QSysInfo::MacVersion
+*/
+#endif
+
+/*! \typedef Qt::ToolBarDock
+ \compat
+
+ Use Qt::Dock instead.
+*/
+
+/*!
+ \enum Qt::Dock
+ \compat
+
+ Each dock window can be in one of the following positions:
+
+ \value DockUnmanaged not managed by a Q3MainWindow.
+
+ \value DockTornOff the dock window floats as its own top level
+ window which always stays on top of the main window.
+
+ \value DockTop above the central widget, below the menu bar.
+
+ \value DockBottom below the central widget, above the status bar.
+
+ \value DockRight to the right of the central widget.
+
+ \value DockLeft to the left of the central widget.
+
+ \value DockMinimized the dock window is not shown (this is
+ effectively a 'hidden' dock area); the handles of all minimized
+ dock windows are drawn in one row below the menu bar.
+
+ \omitvalue Bottom
+ \omitvalue Left
+ \omitvalue Minimized
+ \omitvalue Right
+ \omitvalue Top
+ \omitvalue TornOff
+ \omitvalue Unmanaged
+*/
+
+/*!
+ \enum Qt::AnchorAttribute
+
+ An anchor has one or more of the following attributes:
+
+ \value AnchorName the name attribute of the anchor. This attribute is
+ used when scrolling to an anchor in the document.
+
+ \value AnchorHref the href attribute of the anchor. This attribute is
+ used when a link is clicked to determine what content to load.
+*/
+
+/*!
+ \enum Qt::SortOrder
+
+ This enum describes how the items in a widget are sorted.
+
+ \value AscendingOrder The items are sorted ascending e.g. starts with
+ 'AAA' ends with 'ZZZ' in Latin-1 locales
+
+ \value DescendingOrder The items are sorted descending e.g. starts with
+ 'ZZZ' ends with 'AAA' in Latin-1 locales
+
+ \omitvalue Ascending
+ \omitvalue Descending
+*/
+
+/*!
+ \enum Qt::ClipOperation
+
+ \value NoClip This operation turns clipping off.
+
+ \value ReplaceClip Replaces the current clip path/rect/region with
+ the one supplied in the function call.
+
+ \value IntersectClip Intersects the current clip path/rect/region
+ with the one supplied in the function call.
+
+ \value UniteClip Unites the current clip path/rect/region with the
+ one supplied in the function call.
+*/
+
+/*!
+ \enum Qt::ItemSelectionMode
+
+ This enum is used in QGraphicsItem, QGraphicsScene and QGraphicsView to
+ specify how items are selected, or how to determine if a shapes and items
+ collide.
+
+ \value ContainsItemShape The output list contains only items whose
+ \l{QGraphicsItem::shape()}{shape} is fully contained inside the
+ selection area. Items that intersect with the area's outline are
+ not included.
+
+ \value IntersectsItemShape The output list contains both items whose
+ \l{QGraphicsItem::shape()}{shape} is fully contained inside the
+ selection area, and items that intersect with the area's
+ outline. This is a common mode for rubber band selection.
+
+ \value ContainsItemBoundingRect The output list contains only items whose
+ \l{QGraphicsItem::boundingRect()}{bounding rectangle} is fully
+ contained inside the selection area. Items that intersect with the
+ area's outline are not included.
+
+ \value IntersectsItemBoundingRect The output list contains both items
+ whose \l{QGraphicsItem::boundingRect()}{bounding rectangle} is
+ fully contained inside the selection area, and items that intersect
+ with the area's outline. This method is commonly used for
+ determining areas that need redrawing.
+
+ \sa QGraphicsScene::items(), QGraphicsScene::collidingItems(),
+ QGraphicsView::items(), QGraphicsItem::collidesWithItem(),
+ QGraphicsItem::collidesWithPath()
+*/
+
+/*!
+ \enum Qt::FillRule
+
+ Specifies which method should be used to fill the paths and polygons.
+
+ \value OddEvenFill Specifies that the region is filled using the
+ odd even fill rule. With this rule, we determine whether a point
+ is inside the shape by using the following method.
+ Draw a horizontal line from the point to a location outside the shape,
+ and count the number of intersections. If the number of intersections
+ is an odd number, the point is inside the shape. This mode is the
+ default.
+
+ \value WindingFill Specifies that the region is filled using the
+ non zero winding rule. With this rule, we determine whether a
+ point is inside the shape by using the following method.
+ Draw a horizontal line from the point to a location outside the shape.
+ Determine whether the direction of the line at each intersection point
+ is up or down. The winding number is determined by summing the
+ direction of each intersection. If the number is non zero, the point
+ is inside the shape. This fill mode can also in most cases be considered
+ as the intersection of closed shapes.
+*/
+
+/*!
+ \enum Qt::PaintUnit
+
+ \compat
+
+ \value PixelUnit
+ \value LoMetricUnit Obsolete
+ \value HiMetricUnit Obsolete
+ \value LoEnglishUnit Obsolete
+ \value HiEnglishUnit Obsolete
+ \value TwipsUnit Obsolete
+*/
+
+/*!
+ \enum Qt::TextFormat
+
+ This enum is used in widgets that can display both plain text and
+ rich text, e.g. QLabel. It is used for deciding whether a text
+ string should be interpreted as one or the other. This is normally
+ done by passing one of the enum values to a setTextFormat()
+ function.
+
+ \value PlainText The text string is interpreted as a plain text
+ string.
+
+ \value RichText The text string is interpreted as a rich text
+ string.
+
+ \value AutoText The text string is interpreted as for
+ Qt::RichText if Qt::mightBeRichText() returns true, otherwise
+ as Qt::PlainText.
+
+ \value LogText A special, limited text format which is only used
+ by Q3TextEdit in an optimized mode.
+*/
+
+/*!
+ \enum Qt::CursorShape
+
+ This enum type defines the various cursors that can be used.
+
+ The standard arrow cursor is the default for widgets in a normal state.
+
+ \value ArrowCursor \inlineimage cursor-arrow.png
+ The standard arrow cursor.
+ \value UpArrowCursor \inlineimage cursor-uparrow.png
+ An arrow pointing upwards toward the top of the screen.
+ \value CrossCursor \inlineimage cursor-cross.png
+ A crosshair cursor, typically used to help the
+ user accurately select a point on the screen.
+ \value WaitCursor \inlineimage cursor-wait.png
+ An hourglass or watch cursor, usually shown during
+ operations that prevent the user from interacting with
+ the application.
+ \value IBeamCursor \inlineimage cursor-ibeam.png
+ A caret or ibeam cursor, indicating that a widget can
+ accept and display text input.
+ \value SizeVerCursor \inlineimage cursor-sizev.png
+ A cursor used for elements that are used to vertically
+ resize top-level windows.
+ \value SizeHorCursor \inlineimage cursor-sizeh.png
+ A cursor used for elements that are used to horizontally
+ resize top-level windows.
+ \value SizeBDiagCursor \inlineimage cursor-sizeb.png
+ A cursor used for elements that are used to diagonally
+ resize top-level windows at their top-right and
+ bottom-left corners.
+ \value SizeFDiagCursor \inlineimage cursor-sizef.png
+ A cursor used for elements that are used to diagonally
+ resize top-level windows at their top-left and
+ bottom-right corners.
+ \value SizeAllCursor \inlineimage cursor-sizeall.png
+ A cursor used for elements that are used to resize
+ top-level windows in any direction.
+ \value BlankCursor A blank/invisible cursor, typically used when the cursor
+ shape needs to be hidden.
+ \value SplitVCursor \inlineimage cursor-vsplit.png
+ A cursor used for vertical splitters, indicating that
+ a handle can be dragged horizontally to adjust the use
+ of available space.
+ \value SplitHCursor \inlineimage cursor-hsplit.png
+ A cursor used for horizontal splitters, indicating that
+ a handle can be dragged vertically to adjust the use
+ of available space.
+ \value PointingHandCursor \inlineimage cursor-hand.png
+ A pointing hand cursor that is typically used for
+ clickable elements such as hyperlinks.
+ \value ForbiddenCursor \inlineimage cursor-forbidden.png
+ A slashed circle cursor, typically used during drag
+ and drop operations to indicate that dragged content
+ cannot be dropped on particular widgets or inside
+ certain regions.
+ \value OpenHandCursor \inlineimage cursor-openhand.png
+ A cursor representing an open hand, typically used to
+ indicate that the area under the cursor is the visible
+ part of a canvas that the user can click and drag in
+ order to scroll around.
+ \value ClosedHandCursor \inlineimage cursor-closedhand.png
+ A cursor representing a closed hand, typically used to
+ indicate that a dragging operation is in progress that
+ involves scrolling.
+ \value WhatsThisCursor \inlineimage cursor-whatsthis.png
+ An arrow with a question mark, typically used to indicate
+ the presence of What's This? help for a widget.
+ \value BusyCursor \inlineimage cursor-wait.png
+ An hourglass or watch cursor, usually shown during
+ operations that allow the user to interact with
+ the application while they are performed in the
+ background.
+ \value DragMoveCursor
+ A cursor that is usually used when dragging an item.
+ \value DragCopyCursor
+ A cursor that is usually used when dragging an item
+ to copy it.
+ \value DragLinkCursor
+ A cursor that is usually used when dragging an item
+ to make a link to it.
+
+ \value BitmapCursor
+ \omitvalue LastCursor
+ \omitvalue CustomCursor
+
+ \omitvalue arrowCursor
+ \omitvalue upArrowCursor
+ \omitvalue crossCursor
+ \omitvalue waitCursor
+ \omitvalue ibeamCursor
+ \omitvalue sizeVerCursor
+ \omitvalue sizeHorCursor
+ \omitvalue sizeBDiagCursor
+ \omitvalue sizeFDiagCursor
+ \omitvalue sizeAllCursor
+ \omitvalue blankCursor
+ \omitvalue splitVCursor
+ \omitvalue splitHCursor
+ \omitvalue pointingHandCursor
+ \omitvalue forbiddenCursor
+ \omitvalue whatsThisCursor
+*/
+
+/*!
+ \typedef Qt::TextFlags
+ \compat
+
+ Use Qt::TextFlag instead.
+*/
+
+/*!
+ \enum Qt::LayoutDirection
+
+ Specifies the direction of Qt's layouts and text handling.
+
+ \value LeftToRight Left-to-right layout.
+ \value RightToLeft Right-to-left layout.
+ \value LayoutDirectionAuto Automatic layout.
+
+ Right-to-left layouts are necessary for certain languages,
+ notably Arabic and Hebrew.
+
+ LayoutDirectionAuto serves two purposes. When used in conjunction with widgets and layouts, it
+ will imply to use the layout direction set on the parent widget or QApplication. This
+ has the same effect as QWidget::unsetLayoutDirection().
+
+ When LayoutDirectoinAuto is used in conjunction with text layouting, it will imply that the text
+ directionality is determined from the content of the string to be layouted.
+
+ \sa QApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft()
+*/
+
+/*!
+ \enum Qt::AnchorPoint
+
+ Specifies a side of a layout item that can be anchored. This is used by
+ QGraphicsAnchorLayout.
+
+ \value AnchorLeft The left side of a layout item.
+ \value AnchorHorizontalCenter A "virtual" side that is centered between the left and the
+ right side of a layout item.
+ \value AnchorRight The right side of a layout item.
+ \value AnchorTop The top side of a layout item.
+ \value AnchorVerticalCenter A "virtual" side that is centered between the top and the
+ bottom side of a layout item.
+ \value AnchorBottom The bottom side of a layout item.
+
+ \sa QGraphicsAnchorLayout
+*/
+
+/*!
+ \enum Qt::InputMethodHint
+
+ \value ImhNone No hints.
+
+ Flags that alter the behavior:
+
+ \value ImhHiddenText Characters should be hidden, as is typically used when entering passwords.
+ This is automatically set when setting QLineEdit::echoMode to \c Password.
+ \value ImhNoAutoUppercase The input method should not try to automatically switch to upper case
+ when a sentence ends.
+ \value ImhPreferNumbers Numbers are preferred (but not required).
+ \value ImhPreferUppercase Upper case letters are preferred (but not required).
+ \value ImhPreferLowercase Lower case letters are preferred (but not required).
+ \value ImhNoPredictiveText Do not use predictive text (i.e. dictionary lookup) while typing.
+
+ Flags that restrict input (exclusive flags):
+
+ \value ImhDigitsOnly Only digits are allowed.
+ \value ImhFormattedNumbersOnly Only number input is allowed. This includes decimal point and minus sign.
+ \value ImhUppercaseOnly Only upper case letter input is allowed.
+ \value ImhLowercaseOnly Only lower case letter input is allowed.
+ \value ImhDialableCharactersOnly Only characters suitable for phone dialling are allowed.
+ \value ImhEmailCharactersOnly Only characters suitable for email addresses are allowed.
+ \value ImhUrlCharactersOnly Only characters suitable for URLs are allowed.
+
+ Masks:
+
+ \value ImhExclusiveInputMask This mask yields nonzero if any of the exclusive flags are used.
+
+ \note If several exclusive flags are ORed together, the resulting character set will
+ consist of the union of the specified sets. For instance specifying \c ImhNumbersOnly and
+ \c ImhUppercaseOnly would yield a set consisting of numbers and uppercase letters.
+
+ \sa QGraphicsItem::inputMethodHints()
+*/
+
+/*!
+ \enum Qt::InputMethodQuery
+
+ \value ImMicroFocus 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).
+ \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, QVariant() is returned.
+ \value ImAnchorPosition The position of the selection anchor. This may be less or greater than \c ImCursorPosition, depending on which side of selection the cursor is. If there is no selection, it returns the same as \c ImCursorPosition.
+*/
+
+/*!
+ \enum Qt::ItemDataRole
+
+ Each item in the model has a set of data elements associated with
+ it, each with its own role. The roles are used by the view to indicate
+ to the model which type of data it needs. Custom models should return
+ data in these types.
+
+ The general purpose roles (and the associated types) are:
+
+ \value DisplayRole The key data to be rendered in the form of text. (QString)
+ \value DecorationRole The data to be rendered as a decoration in the form
+ of an icon. (QColor, QIcon or QPixmap)
+ \value EditRole The data in a form suitable for editing in an
+ editor. (QString)
+ \value ToolTipRole The data displayed in the item's tooltip. (QString)
+ \value StatusTipRole The data displayed in the status bar. (QString)
+ \value WhatsThisRole The data displayed for the item in "What's This?"
+ mode. (QString)
+ \value SizeHintRole The size hint for the item that will be supplied
+ to views. (QSize)
+
+ Roles describing appearance and meta data (with associated types):
+
+ \value FontRole The font used for items rendered with the default
+ delegate. (QFont)
+ \value TextAlignmentRole The alignment of the text for items rendered with the
+ default delegate. (Qt::AlignmentFlag)
+ \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.
+
+ Accessibility roles (with associated types):
+
+ \value AccessibleTextRole The text to be used by accessibility
+ extensions and plugins, such as screen
+ readers. (QString)
+ \value AccessibleDescriptionRole A description of the item for accessibility
+ purposes. (QString)
+
+ User roles:
+
+ \value UserRole The first role that can be used for application-specific purposes.
+
+ \omitvalue DisplayPropertyRole
+ \omitvalue DecorationPropertyRole
+ \omitvalue ToolTipPropertyRole
+ \omitvalue StatusTipPropertyRole
+ \omitvalue WhatsThisPropertyRole
+
+ For user roles, it is up to the developer to decide which types to use and ensure that
+ components use the correct types when accessing and setting data.
+*/
+
+/*!
+ \enum Qt::ItemFlag
+
+ This enum describes the properties of an item:
+
+ \value NoItemFlags It does not have any properties set.
+ \value ItemIsSelectable It can be selected.
+ \value ItemIsEditable It can be edited.
+ \value ItemIsDragEnabled It can be dragged.
+ \value ItemIsDropEnabled It can be used as a drop target.
+ \value ItemIsUserCheckable It can be checked or unchecked by the user.
+ \value ItemIsEnabled The user can interact with the item.
+ \value ItemIsTristate The item is checkable with three separate states.
+
+ Note that checkable items need to be given both a suitable set of flags
+ and an initial state, indicating whether the item is checked or not.
+ This is handled automatically for model/view components, but needs
+ to be explicitly set for instances of QListWidgetItem, QTableWidgetItem,
+ and QTreeWidgetItem.
+
+ \sa QAbstractItemModel
+*/
+
+/*!
+ \enum Qt::MatchFlag
+
+ This enum describes the type of matches that can be used when searching
+ for items in a model.
+
+ \value MatchExactly Performs QVariant-based matching.
+ \value MatchFixedString Performs string-based matching.
+ String-based comparisons are case-insensitive unless the
+ \c MatchCaseSensitive flag is also specified.
+ \value MatchContains The search term is contained in the item.
+ \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 Performs string-based matching using a regular
+ expression as the search term.
+ \value MatchWildcard Performs string-based matching using a string with
+ wildcards as the search term.
+ \value MatchWrap Perform a search that wraps around, so that when
+ 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.
+
+ \sa QString::compare(), QRegExp
+*/
+
+/*!
+ \enum Qt::TextElideMode
+
+ This enum specifies where the ellipsis should appear when
+ displaying texts that don't fit:
+
+ \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.
+
+ Qt::ElideMiddle is normally the most appropriate choice for URLs (e.g.,
+ "\l{http://bugreports.qt.nokia.com/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"),
+ whereas Qt::ElideRight is appropriate
+ for other strings (e.g.,
+ "\l{http://qt.nokia.com/doc/qq/qq09-mac-deployment.html}{Deploying Applications on Ma...}").
+
+ \sa QAbstractItemView::textElideMode, QFontMetrics::elidedText(), AlignmentFlag QTabBar::elideMode
+*/
+
+/*!
+ \enum Qt::WindowModality
+
+ \keyword modal
+
+ This enum specifies the behavior of a modal window. A modal window
+ is one that blocks input to other windows. Note that windows that
+ are children of a modal window are not blocked.
+
+ The values are:
+ \value NonModal The window is not modal and does not block input to other windows.
+ \value WindowModal The window is modal to a single window hierarchy and blocks input to its parent window, all grandparent windows, and all siblings of its parent and grandparent windows.
+ \value ApplicationModal The window is modal to the application and blocks input to all windows.
+
+ \sa QWidget::windowModality, QDialog
+*/
+
+/*!
+ \enum Qt::TextInteractionFlag
+
+ This enum specifies how a text displaying widget reacts to user input.
+
+ \value NoTextInteraction No interaction with the text is possible.
+ \value TextSelectableByMouse Text can be selected with the mouse and copied to the clipboard using
+ a context menu or standard keyboard shortcuts.
+ \value TextSelectableByKeyboard Text can be selected with the cursor keys on the keyboard. A text cursor is shown.
+ \value LinksAccessibleByMouse Links can be highlighted and activated with the mouse.
+ \value LinksAccessibleByKeyboard Links can be focused using tab and activated with enter.
+ \value TextEditable The text is fully editable.
+
+ \value TextEditorInteraction The default for a text editor.
+ \value TextBrowserInteraction The default for QTextBrowser.
+*/
+
+/*!
+ \enum Qt::MaskMode
+
+ This enum specifies the behavior of the
+ QPixmap::createMaskFromColor() and QImage::createMaskFromColor()
+ functions.
+
+ \value MaskInColor Creates a mask where all pixels matching the given color are opaque.
+ \value MaskOutColor Creates a mask where all pixels matching the given color are transparent.
+*/
+
+/*!
+ \enum Qt::DockWidgetAreaSizes
+ \internal
+*/
+
+/*!
+ \enum Qt::ToolBarAreaSizes
+ \internal
+*/
+
+/*!
+ \enum Qt::EventPriority
+
+ This enum can be used to specify event priorities.
+
+ \value HighEventPriority Events with this priority are sent before
+ events with NormalEventPriority or LowEventPriority.
+
+ \value NormalEventPriority Events with this priority are sent
+ after events with HighEventPriority, but before events with
+ LowEventPriority.
+
+ \value LowEventPriority Events with this priority are sent after
+ events with HighEventPriority or NormalEventPriority.
+
+ Note that these values are provided purely for convenience, since
+ event priorities can be any value between \c INT_MAX and \c
+ INT_MIN, inclusive. For example, you can define custom priorities
+ as being relative to each other:
+
+ \snippet doc/src/snippets/code/doc_src_qnamespace.cpp 1
+
+ \sa QCoreApplication::postEvent()
+*/
+/*!
+ \enum Qt::SizeHint
+ \since 4.4
+
+ This enum is used by QGraphicsLayoutItem::sizeHint()
+
+ \value MinimumSize is used to specify the minimum size of a graphics layout item.
+ \value PreferredSize is used to specify the preferred size of a graphics layout item.
+ \value MaximumSize is used to specify the maximum size of a graphics layout item.
+ \value MinimumDescent is used to specify the minimum descent of a text string in a graphics layout item.
+ \omitvalue NSizeHints
+
+ \sa QGraphicsLayoutItem::sizeHint()
+*/
+
+/*!
+ \enum Qt::SizeMode
+ \since 4.4
+
+ This enum is used by QPainter::drawRoundedRect() and QPainterPath::addRoundedRect()
+ functions to specify the radii of rectangle corners with respect to the dimensions
+ of the bounding rectangles specified.
+
+ \value AbsoluteSize Specifies the size using absolute measurements.
+ \value RelativeSize Specifies the size relative to the bounding rectangle,
+ typically using percentage measurements.
+*/
+
+/*!
+ \enum Qt::WindowFrameSection
+ \since 4.4
+
+ This enum is used to describe parts of a window frame. It is returned by
+ QGraphicsWidget::windowFrameSectionAt() to describe what section of the window
+ frame is under the mouse.
+
+ \value NoSection
+ \value LeftSection
+ \value TopLeftSection
+ \value TopSection
+ \value TopRightSection
+ \value RightSection
+ \value BottomRightSection
+ \value BottomSection
+ \value BottomLeftSection
+ \value TitleBarArea
+
+ \sa QGraphicsWidget::windowFrameEvent()
+ \sa QGraphicsWidget::paintWindowFrame()
+ \sa QGraphicsWidget::windowFrameSectionAt()
+
+*/
+
+/*!
+ \enum Qt::TileRule
+ \since 4.6
+
+ This enum describes how to repeat or stretch the parts of an image
+ when drawing.
+
+ \value StretchTile Scale the image to fit to the available area.
+
+ \value RepeatTile Repeat the image until there is no more space. May
+ crop the last image.
+
+ \value RoundTile Similar to Repeat, but scales the image down to
+ ensure that the last tile is not cropped.
+*/
+
+/*!
+ \enum Qt::Initialization
+ \internal
+*/
+
+/*!
+ \enum Qt::CoordinateSystem
+ \since 4.6
+
+ This enum specifies the coordinate system.
+
+ \value DeviceCoordinates Coordinates are relative to the upper-left corner
+ of the object's paint device.
+
+ \value LogicalCoordinates Coordinates are relative to the upper-left corner
+ of the object.
+*/
+
+/*!
+ \enum Qt::GestureState
+ \since 4.6
+
+ This enum type describes the state of a gesture.
+
+ \value GestureStarted A continuous gesture has started.
+ \value GestureUpdated A gesture continues.
+ \value GestureFinished A gesture has finished.
+ \value GestureCanceled A gesture was canceled.
+ \omitvalue NoGesture
+
+ \sa QGesture
+*/
+
+/*!
+ \enum Qt::GestureType
+ \since 4.6
+
+ This enum type describes the standard gestures.
+
+ \value TapGesture A Tap gesture.
+ \value TapAndHoldGesture A Tap-And-Hold (Long-Tap) gesture.
+ \value PanGesture A Pan gesture.
+ \value PinchGesture A Pinch gesture.
+ \value SwipeGesture A Swipe gesture.
+ \value CustomGesture A flag that can be used to test if the gesture is a
+ user-defined gesture ID.
+ \omitvalue LastGestureType
+
+ User-defined gestures are registered with the
+ QGestureRecognizer::registerRecognizer() function which generates a custom
+ gesture ID with the Qt::CustomGesture flag set.
+
+ \sa QGesture, QWidget::grabGesture(), QGraphicsObject::grabGesture()
+*/
+
+/*!
+ \enum Qt::GestureFlag
+ \since 4.6
+
+ This enum type describes additional flags that can be used when subscribing
+ to a gesture.
+
+ \value DontStartGestureOnChildren By default gestures can start on the
+ widget or over any of its children. Use this flag to disable this and allow
+ a gesture to start on the widget only.
+
+ \value ReceivePartialGestures Allows any ignored gesture events to be
+ propagated to parent widgets which have specified this hint. By default
+ only gestures that are in the Qt::GestureStarted state are propagated and
+ the widget always gets the full gesture sequence starting with a gesture in
+ 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
+ \l{QGraphicsObject::grabGesture()}{grabbing} a gesture all ignored partial
+ gestures will propagate to their parent items.
+
+ \sa QWidget::grabGesture(), QGraphicsObject::grabGesture()
+*/
+
+/*!
+ \enum Qt::NavigationMode
+ \since 4.6
+
+ This enum type describes the mode for moving focus.
+
+ \value NavigationModeNone Only the touch screen is used.
+ \value NavigationModeKeypadTabOrder Qt::Key_Up and Qt::Key_Down are used to change focus.
+ \value NavigationModeKeypadDirectional Qt::Key_Up, Qt::Key_Down, Qt::Key_Left and Qt::Key_Right are used to change focus.
+ \value NavigationModeCursorAuto The mouse cursor is used to change focus,
+ it is displayed only on non touchscreen devices.
+ The keypad is used to implement a virtual cursor, unless
+ the device has an analog mouse type of input device (e.g. touchpad).
+ This is the recommended setting for an application such as a web browser that
+ needs pointer control on both touch and non-touch devices.
+ \value NavigationModeCursorForceVisible The mouse cursor is used to change focus,
+ it is displayed regardless of device type.
+ The keypad is used to implement a virtual cursor, unless
+ the device has an analog mouse type of input device (e.g. touchpad)
+
+ \note: in 4.6, cursor navigation is only implemented for Symbian OS.
+ On other platforms, it behaves as NavigationModeNone.
+ \sa QApplication::setNavigationMode()
+ \sa QApplication::navigationMode()
+*/
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
new file mode 100644
index 0000000000..b602158d4f
--- /dev/null
+++ b/src/corelib/global/qnumeric.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnumeric.h"
+#include "qnumeric_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Returns true if the double \a {d} is equivalent to infinity.
+*/
+Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
+
+/*!
+ Returns true if the double \a {d} is not a number (NaN).
+*/
+Q_CORE_EXPORT bool qIsNaN(double d) { return qt_is_nan(d); }
+
+/*!
+ Returns true if the double \a {d} is a finite number.
+*/
+Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); }
+
+/*!
+ Returns true if the float \a {f} is equivalent to infinity.
+*/
+Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
+
+/*!
+ Returns true if the float \a {f} is not a number (NaN).
+*/
+Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); }
+
+/*!
+ Returns true if the float \a {f} is a finite number.
+*/
+Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); }
+
+/*!
+ Returns the bit pattern of a signalling NaN as a double.
+*/
+Q_CORE_EXPORT double qSNaN() { return qt_snan(); }
+
+/*!
+ Returns the bit pattern of a quiet NaN as a double.
+*/
+Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
+
+/*!
+ Returns the bit pattern for an infinite number as a double.
+*/
+Q_CORE_EXPORT double qInf() { return qt_inf(); }
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
new file mode 100644
index 0000000000..281fc0107a
--- /dev/null
+++ b/src/corelib/global/qnumeric.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNUMERIC_H
+#define QNUMERIC_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+Q_CORE_EXPORT bool qIsInf(double d);
+Q_CORE_EXPORT bool qIsNaN(double d);
+Q_CORE_EXPORT bool qIsFinite(double d);
+Q_CORE_EXPORT bool qIsInf(float f);
+Q_CORE_EXPORT bool qIsNaN(float f);
+Q_CORE_EXPORT bool qIsFinite(float f);
+Q_CORE_EXPORT double qSNaN();
+Q_CORE_EXPORT double qQNaN();
+Q_CORE_EXPORT double qInf();
+
+#define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)())
+#define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)())
+#define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)())
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QNUMERIC_H
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
new file mode 100644
index 0000000000..d4aa6587f3
--- /dev/null
+++ b/src/corelib/global/qnumeric_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNUMERIC_P_H
+#define QNUMERIC_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
+
+#if !defined(Q_CC_MIPS)
+
+static const union { unsigned char c[8]; double d; } qt_be_inf_bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
+static const union { unsigned char c[8]; double d; } qt_le_inf_bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
+static const union { unsigned char c[8]; double d; } qt_armfpa_inf_bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } };
+static inline double qt_inf()
+{
+#ifdef QT_ARMFPA
+ return qt_armfpa_inf_bytes.d;
+#else
+ return (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_inf_bytes.d
+ : qt_le_inf_bytes.d);
+#endif
+}
+
+// Signaling NAN
+static const union { unsigned char c[8]; double d; } qt_be_snan_bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } };
+static const union { unsigned char c[8]; double d; } qt_le_snan_bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } };
+static const union { unsigned char c[8]; double d; } qt_armfpa_snan_bytes = { { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 } };
+static inline double qt_snan()
+{
+#ifdef QT_ARMFPA
+ return qt_armfpa_snan_bytes.d;
+#else
+ return (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_snan_bytes.d
+ : qt_le_snan_bytes.d);
+#endif
+}
+
+// Quiet NAN
+static const union { unsigned char c[8]; double d; } qt_be_qnan_bytes = { { 0xff, 0xf8, 0, 0, 0, 0, 0, 0 } };
+static const union { unsigned char c[8]; double d; } qt_le_qnan_bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0xff } };
+static const union { unsigned char c[8]; double d; } qt_armfpa_qnan_bytes = { { 0, 0, 0xf8, 0xff, 0, 0, 0, 0 } };
+static inline double qt_qnan()
+{
+#ifdef QT_ARMFPA
+ return qt_armfpa_qnan_bytes.d;
+#else
+ return (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_qnan_bytes.d
+ : qt_le_qnan_bytes.d);
+#endif
+}
+
+#else // Q_CC_MIPS
+
+static const unsigned char qt_be_inf_bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
+static const unsigned char qt_le_inf_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
+static const unsigned char qt_armfpa_inf_bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
+static inline double qt_inf()
+{
+ const unsigned char *bytes;
+#ifdef QT_ARMFPA
+ bytes = qt_armfpa_inf_bytes;
+#else
+ bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_inf_bytes
+ : qt_le_inf_bytes);
+#endif
+
+ union { unsigned char c[8]; double d; } returnValue;
+ qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
+ return returnValue.d;
+}
+
+// Signaling NAN
+static const unsigned char qt_be_snan_bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
+static const unsigned char qt_le_snan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
+static const unsigned char qt_armfpa_snan_bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
+static inline double qt_snan()
+{
+ const unsigned char *bytes;
+#ifdef QT_ARMFPA
+ bytes = qt_armfpa_snan_bytes;
+#else
+ bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_snan_bytes
+ : qt_le_snan_bytes);
+#endif
+
+ union { unsigned char c[8]; double d; } returnValue;
+ qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
+ return returnValue.d;
+}
+
+// Quiet NAN
+static const unsigned char qt_be_qnan_bytes[] = { 0xff, 0xf8, 0, 0, 0, 0, 0, 0 };
+static const unsigned char qt_le_qnan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0xff };
+static const unsigned char qt_armfpa_qnan_bytes[] = { 0, 0, 0xf8, 0xff, 0, 0, 0, 0 };
+static inline double qt_qnan()
+{
+ const unsigned char *bytes;
+#ifdef QT_ARMFPA
+ bytes = qt_armfpa_qnan_bytes;
+#else
+ bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qt_be_qnan_bytes
+ : qt_le_qnan_bytes);
+#endif
+
+ union { unsigned char c[8]; double d; } returnValue;
+ qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
+ return returnValue.d;
+}
+
+#endif // Q_CC_MIPS
+
+static inline bool qt_is_inf(double d)
+{
+ uchar *ch = (uchar *)&d;
+#ifdef QT_ARMFPA
+ return (ch[3] & 0x7f) == 0x7f && ch[2] == 0xf0;
+#else
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) == 0x7f && ch[1] == 0xf0;
+ } else {
+ return (ch[7] & 0x7f) == 0x7f && ch[6] == 0xf0;
+ }
+#endif
+}
+
+static inline bool qt_is_nan(double d)
+{
+ uchar *ch = (uchar *)&d;
+#ifdef QT_ARMFPA
+ return (ch[3] & 0x7f) == 0x7f && ch[2] > 0xf0;
+#else
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) == 0x7f && ch[1] > 0xf0;
+ } else {
+ return (ch[7] & 0x7f) == 0x7f && ch[6] > 0xf0;
+ }
+#endif
+}
+
+static inline bool qt_is_finite(double d)
+{
+ uchar *ch = (uchar *)&d;
+#ifdef QT_ARMFPA
+ return (ch[3] & 0x7f) != 0x7f || (ch[2] & 0xf0) != 0xf0;
+#else
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) != 0x7f || (ch[1] & 0xf0) != 0xf0;
+ } else {
+ return (ch[7] & 0x7f) != 0x7f || (ch[6] & 0xf0) != 0xf0;
+ }
+#endif
+}
+
+static inline bool qt_is_inf(float d)
+{
+ uchar *ch = (uchar *)&d;
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) == 0x7f && ch[1] == 0x80;
+ } else {
+ return (ch[3] & 0x7f) == 0x7f && ch[2] == 0x80;
+ }
+}
+
+static inline bool qt_is_nan(float d)
+{
+ uchar *ch = (uchar *)&d;
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) == 0x7f && ch[1] > 0x80;
+ } else {
+ return (ch[3] & 0x7f) == 0x7f && ch[2] > 0x80;
+ }
+}
+
+static inline bool qt_is_finite(float d)
+{
+ uchar *ch = (uchar *)&d;
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ch[0] & 0x7f) != 0x7f || (ch[1] & 0x80) != 0x80;
+ } else {
+ return (ch[3] & 0x7f) != 0x7f || (ch[2] & 0x80) != 0x80;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QNUMERIC_P_H
diff --git a/src/corelib/global/qt_pch.h b/src/corelib/global/qt_pch.h
new file mode 100644
index 0000000000..8a1004d1cb
--- /dev/null
+++ b/src/corelib/global/qt_pch.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This is a precompiled header file for use in Xcode / Mac GCC /
+ * GCC >= 3.4 / VC to greatly speed the building of Qt. It may also be
+ * of use to people developing their own project, but it is probably
+ * better to define your own header. Use of this header is currently
+ * UNSUPPORTED.
+ */
+
+
+#if defined __cplusplus
+#include <qglobal.h>
+#ifdef Q_WS_WIN
+# define _POSIX_
+# include <limits.h>
+# undef _POSIX_
+#endif
+#include <qcoreapplication.h>
+#include <qlist.h>
+#include <qvariant.h> /* All moc genereated code has this include */
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+#include <stdlib.h>
+#endif
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
new file mode 100644
index 0000000000..ee6a272ed7
--- /dev/null
+++ b/src/corelib/global/qt_windows.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_WINDOWS_H
+#define QT_WINDOWS_H
+
+#if defined(Q_CC_BOR)
+// Borland's windows.h does not set these correctly, resulting in
+// unusable WinSDK standard dialogs
+#ifndef WINVER
+#define WINVER 0x400
+#endif
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x400
+#endif
+#endif
+
+#if defined(Q_CC_MINGW)
+// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation
+#ifndef WINVER
+#define WINVER 0x500
+#endif
+#endif
+
+#include <windows.h>
+
+#ifdef _WIN32_WCE
+#include <ceconfig.h>
+#endif
+
+// already defined when compiled with WINVER >= 0x0500
+#ifndef SPI_SETMENUANIMATION
+#define SPI_SETMENUANIMATION 0x1003
+#endif
+#ifndef SPI_SETMENUFADE
+#define SPI_SETMENUFADE 0x1013
+#endif
+#ifndef SPI_SETCOMBOBOXANIMATION
+#define SPI_SETCOMBOBOXANIMATION 0x1005
+#endif
+#ifndef SPI_SETTOOLTIPANIMATION
+#define SPI_SETTOOLTIPANIMATION 0x1017
+#endif
+#ifndef SPI_SETTOOLTIPFADE
+#define SPI_SETTOOLTIPFADE 0x1019
+#endif
+#ifndef SPI_SETUIEFFECTS
+#define SPI_SETUIEFFECTS 0x103F
+#endif
+#ifndef SPI_GETMENUANIMATION
+#define SPI_GETMENUANIMATION 0x1002
+#endif
+#ifndef SPI_GETMENUFADE
+#define SPI_GETMENUFADE 0x1012
+#endif
+#ifndef SPI_GETCOMBOBOXANIMATION
+#define SPI_GETCOMBOBOXANIMATION 0x1004
+#endif
+#ifndef SPI_GETTOOLTIPANIMATION
+#define SPI_GETTOOLTIPANIMATION 0x1016
+#endif
+#ifndef SPI_GETTOOLTIPFADE
+#define SPI_GETTOOLTIPFADE 0x1018
+#endif
+#ifndef SPI_GETUIEFFECTS
+#define SPI_GETUIEFFECTS 0x103E
+#endif
+#ifndef SPI_GETKEYBOARDCUES
+#define SPI_GETKEYBOARDCUES 0x100A
+#endif
+#ifndef SPI_GETGRADIENTCAPTIONS
+#define SPI_GETGRADIENTCAPTIONS 0x1008
+#endif
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x020A
+#endif
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+#ifndef ETO_PDY
+#define ETO_PDY 0x2000
+#endif
+#ifndef COLOR_GRADIENTACTIVECAPTION
+#define COLOR_GRADIENTACTIVECAPTION 27
+#endif
+#ifndef COLOR_GRADIENTINACTIVECAPTION
+#define COLOR_GRADIENTINACTIVECAPTION 28
+#endif
+
+// already defined when compiled with WINVER >= 0x0600
+#ifndef SPI_GETFLATMENU
+#define SPI_GETFLATMENU 0x1022
+#endif
+#ifndef CS_DROPSHADOW
+#define CS_DROPSHADOW 0x00020000
+#endif
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+
+#ifdef Q_WS_WINCE
+#ifndef LR_DEFAULTSIZE
+#define LR_DEFAULTSIZE 0
+#endif
+#ifndef LR_SHARED
+#define LR_SHARED 0
+#endif
+#endif // Q_WS_WINCE
+
+#endif // QT_WINDOWS_H
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
new file mode 100644
index 0000000000..f67600d750
--- /dev/null
+++ b/src/corelib/io/io.pri
@@ -0,0 +1,119 @@
+# Qt core io module
+
+HEADERS += \
+ io/qabstractfileengine.h \
+ io/qabstractfileengine_p.h \
+ io/qbuffer.h \
+ io/qdatastream.h \
+ io/qdatastream_p.h \
+ io/qdataurl_p.h \
+ io/qdebug.h \
+ io/qdir.h \
+ io/qdir_p.h \
+ io/qdiriterator.h \
+ io/qfile.h \
+ io/qfileinfo.h \
+ io/qfileinfo_p.h \
+ io/qiodevice.h \
+ io/qiodevice_p.h \
+ io/qnoncontiguousbytedevice_p.h \
+ io/qprocess.h \
+ io/qprocess_p.h \
+ io/qtextstream.h \
+ io/qtemporaryfile.h \
+ io/qresource_p.h \
+ io/qresource_iterator_p.h \
+ io/qurl.h \
+ io/qsettings.h \
+ io/qsettings_p.h \
+ io/qfsfileengine.h \
+ io/qfsfileengine_p.h \
+ io/qfsfileengine_iterator_p.h \
+ io/qfilesystemwatcher.h \
+ io/qfilesystemwatcher_p.h \
+ io/qfilesystementry_p.h \
+ io/qfilesystemengine_p.h \
+ io/qfilesystemmetadata_p.h \
+ io/qfilesystemiterator_p.h
+
+SOURCES += \
+ io/qabstractfileengine.cpp \
+ io/qbuffer.cpp \
+ io/qdatastream.cpp \
+ io/qdataurl.cpp \
+ io/qdebug.cpp \
+ io/qdir.cpp \
+ io/qdiriterator.cpp \
+ io/qfile.cpp \
+ io/qfileinfo.cpp \
+ io/qiodevice.cpp \
+ io/qnoncontiguousbytedevice.cpp \
+ io/qprocess.cpp \
+ io/qtextstream.cpp \
+ io/qtemporaryfile.cpp \
+ io/qresource.cpp \
+ io/qresource_iterator.cpp \
+ io/qurl.cpp \
+ io/qsettings.cpp \
+ io/qfsfileengine.cpp \
+ io/qfsfileengine_iterator.cpp \
+ io/qfilesystemwatcher.cpp \
+ io/qfilesystementry.cpp \
+ io/qfilesystemengine.cpp
+
+win32 {
+ SOURCES += io/qsettings_win.cpp
+ SOURCES += io/qprocess_win.cpp
+ SOURCES += io/qfsfileengine_win.cpp
+
+ SOURCES += io/qfilesystemwatcher_win.cpp
+ HEADERS += io/qfilesystemwatcher_win_p.h
+ HEADERS += io/qwindowspipewriter_p.h
+ SOURCES += io/qwindowspipewriter.cpp
+ SOURCES += io/qfilesystemengine_win.cpp
+ SOURCES += io/qfilesystemiterator_win.cpp
+} else:unix {
+ SOURCES += io/qfsfileengine_unix.cpp
+ symbian {
+ SOURCES += io/qfilesystemengine_symbian.cpp
+ SOURCES += io/qprocess_symbian.cpp
+ SOURCES += io/qfilesystemiterator_symbian.cpp
+ } else {
+ SOURCES += io/qfilesystemengine_unix.cpp
+ SOURCES += io/qprocess_unix.cpp
+ SOURCES += io/qfilesystemiterator_unix.cpp
+ }
+ !nacl:macx-*: {
+ HEADERS += io/qfilesystemwatcher_fsevents_p.h
+ SOURCES += io/qfilesystemengine_mac.cpp
+ SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp
+ }
+
+ linux-*:!symbian {
+ SOURCES += \
+ io/qfilesystemwatcher_inotify.cpp \
+ io/qfilesystemwatcher_dnotify.cpp
+
+ HEADERS += \
+ io/qfilesystemwatcher_inotify_p.h \
+ io/qfilesystemwatcher_dnotify_p.h
+ }
+
+ !nacl {
+ freebsd-*|macx-*|darwin-*|openbsd-*:{
+ SOURCES += io/qfilesystemwatcher_kqueue.cpp
+ HEADERS += io/qfilesystemwatcher_kqueue_p.h
+ }
+ }
+
+ symbian {
+ SOURCES += io/qfilesystemwatcher_symbian.cpp
+ HEADERS += io/qfilesystemwatcher_symbian_p.h
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+ LIBS += -lplatformenv -lesock
+ }
+}
+integrity {
+ SOURCES += io/qfsfileengine_unix.cpp \
+ io/qfsfileengine_iterator_unix.cpp
+}
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
new file mode 100644
index 0000000000..0a423c0879
--- /dev/null
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -0,0 +1,1233 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractfileengine.h"
+#include "private/qabstractfileengine_p.h"
+#ifdef QT_BUILD_CORE_LIB
+#include "private/qresource_p.h"
+#endif
+#include "qdatetime.h"
+#include "qreadwritelock.h"
+#include "qvariant.h"
+// built-in handlers
+#include "qfsfileengine.h"
+#include "qdiriterator.h"
+#include "qstringbuilder.h"
+
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+#include <QtCore/private/qfilesystemengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractFileEngineHandler
+ \reentrant
+
+ \brief The QAbstractFileEngineHandler class provides a way to register
+ custom file engines with your application.
+
+ \ingroup io
+ \since 4.1
+
+ QAbstractFileEngineHandler is a factory for creating QAbstractFileEngine
+ objects (file engines), which are used internally by QFile, QFileInfo, and
+ QDir when working with files and directories.
+
+ When you open a file, Qt chooses a suitable file engine by passing the
+ file name from QFile or QDir through an internal list of registered file
+ engine handlers. The first handler to recognize the file name is used to
+ create the engine. Qt provides internal file engines for working with
+ regular files and resources, but you can also register your own
+ QAbstractFileEngine subclasses.
+
+ To install an application-specific file engine, you subclass
+ QAbstractFileEngineHandler and reimplement create(). When you instantiate
+ the handler (e.g. by creating an instance on the stack or on the heap), it
+ will automatically register with Qt. (The latest registered handler takes
+ precedence over existing handlers.)
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qabstractfileengine.cpp 0
+
+ When the handler is destroyed, it is automatically removed from Qt.
+
+ The most common approach to registering a handler is to create an instance
+ as part of the start-up phase of your application. It is also possible to
+ limit the scope of the file engine handler to a particular area of
+ interest (e.g. a special file dialog that needs a custom file engine). By
+ creating the handler inside a local scope, you can precisely control the
+ area in which your engine will be applied without disturbing file
+ operations in other parts of your application.
+
+ \sa QAbstractFileEngine, QAbstractFileEngine::create()
+*/
+
+static bool qt_file_engine_handlers_in_use = 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;
+class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
+{
+public:
+ ~QAbstractFileEngineHandlerList()
+ {
+ QWriteLocker locker(fileEngineHandlerMutex());
+ qt_abstractfileenginehandlerlist_shutDown = true;
+ }
+};
+Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
+
+/*!
+ Constructs a file handler and registers it with Qt. Once created this
+ handler's create() function will be called (along with all the other
+ handlers) for any paths used. The most recently created handler that
+ recognizes the given path (i.e. that returns a QAbstractFileEngine) is
+ used for the new path.
+
+ \sa create()
+ */
+QAbstractFileEngineHandler::QAbstractFileEngineHandler()
+{
+ QWriteLocker locker(fileEngineHandlerMutex());
+ qt_file_engine_handlers_in_use = true;
+ fileEngineHandlers()->prepend(this);
+}
+
+/*!
+ Destroys the file handler. This will automatically unregister the handler
+ from Qt.
+ */
+QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
+{
+ QWriteLocker locker(fileEngineHandlerMutex());
+ // Remove this handler from the handler list only if the list is valid.
+ if (!qt_abstractfileenginehandlerlist_shutDown) {
+ QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
+ handlers->removeOne(this);
+ if (handlers->isEmpty())
+ qt_file_engine_handlers_in_use = false;
+ }
+}
+
+/*
+ \ìnternal
+
+ Handles calls to custom file engine handlers.
+*/
+QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
+{
+ QAbstractFileEngine *engine = 0;
+
+ if (qt_file_engine_handlers_in_use) {
+ 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;
+ }
+ }
+
+ return engine;
+}
+
+/*!
+ \fn 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.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qabstractfileengine.cpp 1
+
+ \sa QAbstractFileEngine::create()
+*/
+
+/*!
+ Creates and returns a QAbstractFileEngine suitable for processing \a
+ fileName.
+
+ You should not need to call this function; use QFile, QFileInfo or
+ QDir directly instead.
+
+ If you reimplemnt this function, it should only return file
+ engines that knows how to handle \a fileName; otherwise, it should
+ return 0.
+
+ \sa QAbstractFileEngineHandler
+*/
+QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
+{
+ QFileSystemEntry entry(fileName);
+ QFileSystemMetaData metaData;
+ QAbstractFileEngine *engine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, metaData);
+
+#ifndef QT_NO_FSFILEENGINE
+ if (!engine)
+ // fall back to regular file engine
+ return new QFSFileEngine(entry.filePath());
+#endif
+
+ return engine;
+}
+
+/*!
+ \class QAbstractFileEngine
+ \reentrant
+
+ \brief The QAbstractFileEngine class provides an abstraction for accessing
+ the filesystem.
+
+ \ingroup io
+ \since 4.1
+
+ The QDir, QFile, and QFileInfo classes all make use of a
+ QAbstractFileEngine internally. If you create your own QAbstractFileEngine
+ subclass (and register it with Qt by creating a QAbstractFileEngineHandler
+ subclass), your file engine will be used when the path is one that your
+ file engine handles.
+
+ A QAbstractFileEngine refers to one file or one directory. If the referent
+ is a file, the setFileName(), rename(), and remove() functions are
+ applicable. If the referent is a directory the mkdir(), rmdir(), and
+ entryList() functions are applicable. In all cases the caseSensitive(),
+ isRelativePath(), fileFlags(), ownerId(), owner(), and fileTime()
+ functions are applicable.
+
+ A QAbstractFileEngine subclass can be created to do synchronous network I/O
+ based file system operations, local file system operations, or to operate
+ as a resource system to access file based resources.
+
+ \sa QAbstractFileEngineHandler
+*/
+
+/*!
+ \enum QAbstractFileEngine::FileName
+
+ These values are used to request a file name in a particular
+ format.
+
+ \value DefaultName The same filename that was passed to the
+ QAbstractFileEngine.
+ \value BaseName The name of the file excluding the path.
+ \value PathName The path to the file excluding the base name.
+ \value AbsoluteName The absolute path to the file (including
+ 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
+ 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 CanonicalPathName Same as CanonicalName, excluding the base name.
+ \value BundleName Returns the name of the bundle implies BundleType is set.
+
+ \omitvalue NFileNames
+
+ \sa fileName(), setFileName()
+*/
+
+/*!
+ \enum QAbstractFileEngine::FileFlag
+
+ The permissions and types of a file, suitable for OR'ing together.
+
+ \value ReadOwnerPerm The owner of the file has permission to read
+ it.
+ \value WriteOwnerPerm The owner of the file has permission to
+ write to it.
+ \value ExeOwnerPerm The owner of the file has permission to
+ execute it.
+ \value ReadUserPerm The current user has permission to read the
+ file.
+ \value WriteUserPerm The current user has permission to write to
+ the file.
+ \value ExeUserPerm The current user has permission to execute the
+ file.
+ \value ReadGroupPerm Members of the current user's group have
+ permission to read the file.
+ \value WriteGroupPerm Members of the current user's group have
+ permission to write to the file.
+ \value ExeGroupPerm Members of the current user's group have
+ permission to execute the file.
+ \value ReadOtherPerm All users have permission to read the file.
+ \value WriteOtherPerm All users have permission to write to the
+ file.
+ \value ExeOtherPerm All users have permission to execute the file.
+
+ \value LinkType The file is a link to another file (or link) in
+ the file system (i.e. not a file or directory).
+ \value FileType The file is a regular file to the file system
+ (i.e. not a link or directory)
+ \value BundleType The file is a Mac OS X bundle implies DirectoryType
+ \value DirectoryType The file is a directory in the file system
+ (i.e. not a link or file).
+
+ \value HiddenFlag The file is hidden.
+ \value ExistsFlag The file actually exists in the file system.
+ \value RootFlag The file or the file pointed to is the root of the filesystem.
+ \value LocalDiskFlag The file resides on the local disk and can be passed to standard file functions.
+ \value Refresh Passing this flag will force the file engine to refresh all flags.
+
+ \omitvalue PermsMask
+ \omitvalue TypesMask
+ \omitvalue FlagsMask
+ \omitvalue FileInfoAll
+
+ \sa fileFlags(), setFileName()
+*/
+
+/*!
+ \enum QAbstractFileEngine::FileTime
+
+ These are used by the fileTime() function.
+
+ \value CreationTime When the file was created.
+ \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.
+ \value OwnerGroup The group who owns the file.
+
+ \sa owner(), ownerId(), setFileName()
+*/
+
+/*!
+ Constructs a new QAbstractFileEngine that does not refer to any file or directory.
+
+ \sa setFileName()
+ */
+QAbstractFileEngine::QAbstractFileEngine() : d_ptr(new QAbstractFileEnginePrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+
+ Constructs a QAbstractFileEngine.
+ */
+QAbstractFileEngine::QAbstractFileEngine(QAbstractFileEnginePrivate &dd) : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys the QAbstractFileEngine.
+ */
+QAbstractFileEngine::~QAbstractFileEngine()
+{
+}
+
+/*!
+ \fn bool QAbstractFileEngine::open(QIODevice::OpenMode mode)
+
+ Opens the file in the specified \a mode. Returns true if the file
+ was successfully opened; otherwise returns false.
+
+ The \a mode is an OR combination of QIODevice::OpenMode and
+ QIODevice::HandlingMode values.
+*/
+bool QAbstractFileEngine::open(QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(openMode);
+ return false;
+}
+
+/*!
+ Closes the file, returning true if successful; otherwise returns false.
+
+ The default implementation always returns false.
+*/
+bool QAbstractFileEngine::close()
+{
+ return false;
+}
+
+/*!
+ Flushes the open file, returning true if successful; otherwise returns
+ false.
+
+ The default implementation always returns false.
+*/
+bool QAbstractFileEngine::flush()
+{
+ return false;
+}
+
+/*!
+ Returns the size of the file.
+*/
+qint64 QAbstractFileEngine::size() const
+{
+ return 0;
+}
+
+/*!
+ Returns the current file position.
+
+ This is the position of the data read/write head of the file.
+*/
+qint64 QAbstractFileEngine::pos() const
+{
+ return 0;
+}
+
+/*!
+ \fn bool QAbstractFileEngine::seek(qint64 offset)
+
+ Sets the file position to the given \a offset. Returns true if
+ the position was successfully set; otherwise returns false.
+
+ The offset is from the beginning of the file, unless the
+ file is sequential.
+
+ \sa isSequential()
+*/
+bool QAbstractFileEngine::seek(qint64 pos)
+{
+ Q_UNUSED(pos);
+ return false;
+}
+
+/*!
+ Returns 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
+ sequential devices.
+*/
+bool QAbstractFileEngine::isSequential() const
+{
+ return false;
+}
+
+/*!
+ 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()
+{
+ return false;
+}
+
+/*!
+ Copies the contents of this file to a file with the name \a newName.
+ Returns true on success; otherwise, false is returned.
+*/
+bool QAbstractFileEngine::copy(const QString &newName)
+{
+ Q_UNUSED(newName);
+ return false;
+}
+
+/*!
+ Requests that the file be renamed to \a newName in the file
+ 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)
+{
+ Q_UNUSED(newName);
+ return false;
+}
+
+/*!
+ 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 false.
+*/
+bool QAbstractFileEngine::link(const QString &newName)
+{
+ Q_UNUSED(newName);
+ return false;
+}
+
+/*!
+ Requests that the directory \a dirName be created. 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.
+
+ \sa setFileName() rmdir() isRelativePath()
+ */
+bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
+{
+ Q_UNUSED(dirName);
+ Q_UNUSED(createParentDirectories);
+ return false;
+}
+
+/*!
+ Requests that the directory \a dirName is deleted from the file
+ system. When \a recurseParentDirectories is true, then any empty
+ parent-directories in \a dirName must also be deleted. If
+ \a recurseParentDirectories is false, only the \a dirName leaf-node
+ should be deleted. In most file systems a directory cannot be deleted
+ 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
+{
+ Q_UNUSED(dirName);
+ Q_UNUSED(recurseParentDirectories);
+ return false;
+}
+
+/*!
+ Requests that the file be set to size \a size. If \a size is larger
+ than the current file then it is filled with 0's, if smaller it is
+ 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)
+{
+ Q_UNUSED(size);
+ return false;
+}
+
+/*!
+ 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
+{
+ return false;
+}
+
+/*!
+ 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
+{
+ return false;
+}
+
+/*!
+ Requests that a list of all the files matching the \a filters
+ list based on the \a filterNames in the file engine's directory
+ are returned.
+
+ Should return an empty list if the file engine refers to a file
+ 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();
+ }
+ return ret;
+}
+
+/*!
+ This function should return the set of OR'd flags that are true
+ for the file engine's file, and that are in the \a type's OR'd
+ members.
+
+ In your reimplementation you can use the \a type argument as an
+ optimization hint and only return the OR'd set of members that are
+ true and that match those in \a type; in other words you can
+ 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
+{
+ Q_UNUSED(type);
+ return 0;
+}
+
+/*!
+ Requests that the file's permissions be set to \a perms. The argument
+ perms will be set to the OR-ed together combination of
+ QAbstractFileEngine::FileInfo, with only the QAbstractFileEngine::PermsMask being
+ 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)
+{
+ Q_UNUSED(perms);
+ return false;
+}
+
+/*!
+ Return the file engine's current file name in the format
+ specified by \a file.
+
+ If you don't handle some \c FileName possibilities, return the
+ 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
+{
+ Q_UNUSED(file);
+ return QString();
+}
+
+/*!
+ If \a owner is \c OwnerUser return the ID of the user who owns
+ 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
+{
+ Q_UNUSED(owner);
+ return 0;
+}
+
+/*!
+ If \a owner is \c OwnerUser return the name of the user who owns
+ the file. If \a owner is \c OwnerGroup return the name of the group
+ 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
+{
+ Q_UNUSED(owner);
+ return QString();
+}
+
+/*!
+ If \a time is \c CreationTime, return when the file was created.
+ If \a time is \c ModificationTime, return when the file was most
+ recently modified. If \a time is \c AccessTime, return when the
+ file was 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
+{
+ Q_UNUSED(time);
+ return QDateTime();
+}
+
+/*!
+ 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)
+{
+ Q_UNUSED(file);
+}
+
+/*!
+ Returns the native file handle for this file engine. This handle must be
+ used with care; its value and type are platform specific, and using it
+ will most likely lead to non-portable code.
+*/
+int QAbstractFileEngine::handle() const
+{
+ return -1;
+}
+
+/*!
+ \since 4.3
+
+ Returns true if the current position is at the end of the file; otherwise,
+ returns false.
+
+ This function bases its behavior on calling extension() with
+ AtEndExtension. If the engine does not support this extension, false is
+ returned.
+
+ \sa extension(), supportsExtension(), QFile::atEnd()
+*/
+bool QAbstractFileEngine::atEnd() const
+{
+ return const_cast<QAbstractFileEngine *>(this)->extension(AtEndExtension);
+}
+
+/*!
+ \since 4.4
+
+ Maps \a size bytes of the file into memory starting at \a offset.
+ Returns a pointer to the memory if successful; otherwise returns false
+ if, for example, an error occurs.
+
+ This function bases its behavior on calling extension() with
+ MapExtensionOption. If the engine does not support this extension, 0 is
+ returned.
+
+ \a flags is currently not used, but could be used in the future.
+
+ \sa unmap(), supportsExtension()
+ */
+
+uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
+{
+ MapExtensionOption option;
+ option.offset = offset;
+ option.size = size;
+ option.flags = flags;
+ MapExtensionReturn r;
+ if (!extension(MapExtension, &option, &r))
+ return 0;
+ return r.address;
+}
+
+/*!
+ \since 4.4
+
+ Unmaps the memory \a address. Returns true if the unmap succeeds; otherwise
+ returns false.
+
+ This function bases its behavior on calling extension() with
+ UnMapExtensionOption. If the engine does not support this extension, false is
+ returned.
+
+ \sa map(), supportsExtension()
+ */
+bool QAbstractFileEngine::unmap(uchar *address)
+{
+ UnMapExtensionOption options;
+ options.address = address;
+ return extension(UnMapExtension, &options);
+}
+
+/*!
+ \since 4.3
+ \class QAbstractFileEngineIterator
+ \brief The QAbstractFileEngineIterator class provides an iterator
+ interface for custom file engines.
+
+ If all you want is to iterate over entries in a directory, see
+ QDirIterator instead. This class is 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.
+
+ You can subclass QAbstractFileEngineIterator to provide an iterator when
+ writing your own file engine. To plug the iterator into your file system,
+ you simply return an instance of this subclass from a reimplementation of
+ QAbstractFileEngine::beginEntryList().
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qabstractfileengine.cpp 2
+
+ QAbstractFileEngineIterator is associated with a path, name filters, and
+ entry filters. The path is the directory that the iterator lists entries
+ in. The name filters and entry filters are provided for file engines that
+ can optimize directory listing at the iterator level (e.g., network file
+ systems that need to minimize network traffic), but they can also be
+ ignored by the iterator subclass; QAbstractFileEngineIterator already
+ provides the required filtering logics in the matchesFilters() function.
+ 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 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 currentFileName() returns the name of the
+ current entry without advancing the iterator. The currentFilePath()
+ function is provided for convenience; it returns the full path of the
+ current entry.
+
+ Here is an example of how to implement an iterator that returns each of
+ three fixed entries in sequence.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qabstractfileengine.cpp 3
+
+ 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.
+*/
+
+/*!
+ \typedef QAbstractFileEngine::Iterator
+ \since 4.3
+ \relates QAbstractFileEngine
+
+ Synonym for QAbstractFileEngineIterator.
+*/
+
+class QAbstractFileEngineIteratorPrivate
+{
+public:
+ QString path;
+ QDir::Filters filters;
+ QStringList nameFilters;
+ QFileInfo fileInfo;
+};
+
+/*!
+ Constructs a QAbstractFileEngineIterator, using the entry filters \a
+ filters, and wildcard name filters \a nameFilters.
+*/
+QAbstractFileEngineIterator::QAbstractFileEngineIterator(QDir::Filters filters,
+ const QStringList &nameFilters)
+ : d(new QAbstractFileEngineIteratorPrivate)
+{
+ d->nameFilters = nameFilters;
+ d->filters = filters;
+}
+
+/*!
+ Destroys the QAbstractFileEngineIterator.
+
+ \sa QDirIterator
+*/
+QAbstractFileEngineIterator::~QAbstractFileEngineIterator()
+{
+}
+
+/*!
+ Returns the path for this iterator. QDirIterator is responsible for
+ assigning this path; it cannot change during the iterator's lifetime.
+
+ \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;
+}
+
+/*!
+ Returns the name filters for this iterator.
+
+ \sa QDir::nameFilters(), filters(), path()
+*/
+QStringList QAbstractFileEngineIterator::nameFilters() const
+{
+ return d->nameFilters;
+}
+
+/*!
+ Returns the entry filters for this iterator.
+
+ \sa QDir::filter(), nameFilters(), path()
+*/
+QDir::Filters QAbstractFileEngineIterator::filters() const
+{
+ return d->filters;
+}
+
+/*!
+ \fn QString QAbstractFileEngineIterator::currentFileName() const = 0
+
+ This pure virtual function returns the name of the current directory
+ entry, excluding the path.
+
+ \sa currentFilePath()
+*/
+
+/*!
+ Returns the path to the current directory entry. It's the same as
+ prepending path() to the return value of currentFileName().
+
+ \sa currentFileName()
+*/
+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;
+}
+
+/*!
+ The virtual function returns a QFileInfo for the current directory
+ entry. This function is provided for convenience. It can also be slightly
+ faster than creating a QFileInfo object yourself, as the object returned
+ by this function might contain cached information that QFileInfo otherwise
+ would have to access through the file engine.
+
+ \sa currentFileName()
+*/
+QFileInfo QAbstractFileEngineIterator::currentFileInfo() const
+{
+ QString path = currentFilePath();
+ if (d->fileInfo.filePath() != path)
+ d->fileInfo.setFile(path);
+
+ // return a shallow copy
+ return d->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
+
+ This pure virtual function advances the iterator to the next directory
+ entry, and returns the file path to the current entry.
+
+ 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
+
+ This pure virtual function returns 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()
+*/
+
+/*!
+ 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)
+{
+ Q_UNUSED(filters);
+ Q_UNUSED(filterNames);
+ return 0;
+}
+
+/*!
+ \internal
+*/
+QAbstractFileEngine::Iterator *QAbstractFileEngine::endEntryList()
+{
+ return 0;
+}
+
+/*!
+ Reads a number of characters from the file into \a data. At most
+ \a maxlen characters will be read.
+
+ Returns -1 if a fatal error occurs, or 0 if there are no bytes to
+ read.
+*/
+qint64 QAbstractFileEngine::read(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ return -1;
+}
+
+/*!
+ Writes \a len bytes from \a data to the file. Returns the number
+ of characters written on success; otherwise returns -1.
+*/
+qint64 QAbstractFileEngine::write(const char *data, qint64 len)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(len);
+ return -1;
+}
+
+/*!
+ This function reads one line, terminated by a '\n' character, from the
+ file info \a data. At most \a maxlen characters will be read. The
+ end-of-line character is included.
+*/
+qint64 QAbstractFileEngine::readLine(char *data, qint64 maxlen)
+{
+ qint64 readSoFar = 0;
+ while (readSoFar < maxlen) {
+ char c;
+ qint64 readResult = read(&c, 1);
+ if (readResult <= 0)
+ return (readSoFar > 0) ? readSoFar : -1;
+ ++readSoFar;
+ *data++ = c;
+ if (c == '\n')
+ return readSoFar;
+ }
+ return readSoFar;
+}
+
+/*!
+ \enum QAbstractFileEngine::Extension
+ \since 4.3
+
+ This enum describes the types of extensions that the file engine can
+ support. Before using these extensions, you must verify that the extension
+ is supported (i.e., call supportsExtension()).
+
+ \value AtEndExtension Whether the current file position is at the end of
+ the file or not. This extension allows file engines that implement local
+ buffering to report end-of-file status without having to check the size of
+ the file. It is also useful for sequential files, where the size of the
+ file cannot be used to determine whether or not you have reached the end.
+ This extension returns true if the file is at the end; otherwise it returns
+ false. The input and output arguments to extension() are ignored.
+
+ \value FastReadLineExtension Whether the file engine provides a
+ fast implementation for readLine() or not. If readLine() remains
+ unimplemented in the file engine, QAbstractFileEngine will provide
+ an implementation based on calling read() repeatedly. If
+ supportsExtension() returns false for this extension, however,
+ 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.
+
+ \value MapExtension Whether the file engine provides the ability to map
+ a file to memory.
+
+ \value UnMapExtension Whether the file engine provides the ability to
+ unmap memory that was previously mapped.
+*/
+
+/*!
+ \class QAbstractFileEngine::ExtensionOption
+ \since 4.3
+ \brief provides an extended input argument to QAbstractFileEngine's
+ extension support.
+
+ \sa QAbstractFileEngine::extension()
+*/
+
+/*!
+ \class QAbstractFileEngine::ExtensionReturn
+ \since 4.3
+ \brief provides an extended output argument to QAbstractFileEngine's
+ extension support.
+
+ \sa QAbstractFileEngine::extension()
+*/
+
+/*!
+ \since 4.3
+
+ This virtual function can be reimplemented in a QAbstractFileEngine
+ subclass to provide support for extensions. The \a option argument is
+ provided as input to the extension, and this function can store output
+ results in \a output.
+
+ The behavior of this function is determined by \a extension; see the
+ Extension documentation for details.
+
+ You can call supportsExtension() to check if an extension is supported by
+ the file engine.
+
+ By default, no extensions are supported, and this function returns false.
+
+ \sa supportsExtension(), Extension
+*/
+bool QAbstractFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
+{
+ Q_UNUSED(extension);
+ Q_UNUSED(option);
+ Q_UNUSED(output);
+ return false;
+}
+
+/*!
+ \since 4.3
+
+ This virtual function returns true if the file engine supports \a
+ extension; otherwise, false is returned. By default, no extensions are
+ supported.
+
+ \sa extension()
+*/
+bool QAbstractFileEngine::supportsExtension(Extension extension) const
+{
+ Q_UNUSED(extension);
+ return false;
+}
+
+/*!
+ Returns the QFile::FileError that resulted from the last failed
+ operation. If QFile::UnspecifiedError is returned, QFile will
+ use its own idea of the error status.
+
+ \sa QFile::FileError, errorString()
+ */
+QFile::FileError QAbstractFileEngine::error() const
+{
+ Q_D(const QAbstractFileEngine);
+ return d->fileError;
+}
+
+/*!
+ Returns the human-readable message appropriate to the current error
+ reported by error(). If no suitable string is available, an
+ empty string is returned.
+
+ \sa error()
+ */
+QString QAbstractFileEngine::errorString() const
+{
+ Q_D(const QAbstractFileEngine);
+ return d->errorString;
+}
+
+/*!
+ Sets the error type to \a error, and the error string to \a errorString.
+ Call this function to set the error values returned by the higher-level
+ classes.
+
+ \sa QFile::error(), QIODevice::errorString(), QIODevice::setErrorString()
+*/
+void QAbstractFileEngine::setError(QFile::FileError error, const QString &errorString)
+{
+ Q_D(QAbstractFileEngine);
+ d->fileError = error;
+ d->errorString = errorString;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qabstractfileengine.h b/src/corelib/io/qabstractfileengine.h
new file mode 100644
index 0000000000..91d3a5ef7e
--- /dev/null
+++ b/src/corelib/io/qabstractfileengine.h
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTFILEENGINE_H
+#define QABSTRACTFILEENGINE_H
+
+#include <QtCore/qdir.h>
+
+#ifdef open
+#error qabstractfileengine.h must be included before any header file that defines open
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QFileExtension;
+class QFileExtensionResult;
+class QVariant;
+class QAbstractFileEngineIterator;
+class QAbstractFileEnginePrivate;
+
+class Q_CORE_EXPORT QAbstractFileEngine
+{
+public:
+ enum FileFlag {
+ //perms (overlaps the QFile::Permission)
+ ReadOwnerPerm = 0x4000, WriteOwnerPerm = 0x2000, ExeOwnerPerm = 0x1000,
+ ReadUserPerm = 0x0400, WriteUserPerm = 0x0200, ExeUserPerm = 0x0100,
+ ReadGroupPerm = 0x0040, WriteGroupPerm = 0x0020, ExeGroupPerm = 0x0010,
+ ReadOtherPerm = 0x0004, WriteOtherPerm = 0x0002, ExeOtherPerm = 0x0001,
+
+ //types
+ LinkType = 0x10000,
+ FileType = 0x20000,
+ DirectoryType = 0x40000,
+ BundleType = 0x80000,
+
+ //flags
+ HiddenFlag = 0x0100000,
+ LocalDiskFlag = 0x0200000,
+ ExistsFlag = 0x0400000,
+ RootFlag = 0x0800000,
+ Refresh = 0x1000000,
+
+ //masks
+ PermsMask = 0x0000FFFF,
+ TypesMask = 0x000F0000,
+ FlagsMask = 0x0FF00000,
+ FileInfoAll = FlagsMask | PermsMask | TypesMask
+ };
+ Q_DECLARE_FLAGS(FileFlags, FileFlag)
+
+ enum FileName {
+ DefaultName,
+ BaseName,
+ PathName,
+ AbsoluteName,
+ AbsolutePathName,
+ LinkName,
+ CanonicalName,
+ CanonicalPathName,
+ BundleName,
+ NFileNames = 9
+ };
+ enum FileOwner {
+ OwnerUser,
+ OwnerGroup
+ };
+ enum FileTime {
+ CreationTime,
+ ModificationTime,
+ AccessTime
+ };
+
+ virtual ~QAbstractFileEngine();
+
+ virtual bool open(QIODevice::OpenMode openMode);
+ virtual bool close();
+ virtual bool flush();
+ virtual qint64 size() const;
+ virtual qint64 pos() const;
+ virtual bool seek(qint64 pos);
+ virtual bool isSequential() const;
+ virtual bool remove();
+ virtual bool copy(const QString &newName);
+ virtual bool rename(const QString &newName);
+ virtual bool link(const QString &newName);
+ virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
+ virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
+ virtual bool setSize(qint64 size);
+ virtual bool caseSensitive() const;
+ virtual bool isRelativePath() const;
+ virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+ virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const;
+ virtual bool setPermissions(uint perms);
+ virtual QString fileName(FileName file=DefaultName) const;
+ virtual uint ownerId(FileOwner) const;
+ virtual QString owner(FileOwner) const;
+ virtual QDateTime fileTime(FileTime time) const;
+ virtual void setFileName(const QString &file);
+ virtual int handle() const;
+ bool atEnd() const;
+ uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
+ bool unmap(uchar *ptr);
+
+ typedef QAbstractFileEngineIterator Iterator;
+ virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
+ virtual Iterator *endEntryList();
+
+ virtual qint64 read(char *data, qint64 maxlen);
+ virtual qint64 readLine(char *data, qint64 maxlen);
+ virtual qint64 write(const char *data, qint64 len);
+
+ QFile::FileError error() const;
+ QString errorString() const;
+
+ enum Extension {
+ AtEndExtension,
+ FastReadLineExtension,
+ MapExtension,
+ UnMapExtension
+ };
+ class ExtensionOption
+ {};
+ class ExtensionReturn
+ {};
+
+ class MapExtensionOption : public ExtensionOption {
+ public:
+ qint64 offset;
+ qint64 size;
+ QFile::MemoryMapFlags flags;
+ };
+ class MapExtensionReturn : public ExtensionReturn {
+ public:
+ uchar *address;
+ };
+
+ class UnMapExtensionOption : public ExtensionOption {
+ public:
+ uchar *address;
+ };
+
+ virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
+ virtual bool supportsExtension(Extension extension) const;
+
+ // Factory
+ static QAbstractFileEngine *create(const QString &fileName);
+
+protected:
+ void setError(QFile::FileError error, const QString &str);
+
+ QAbstractFileEngine();
+ QAbstractFileEngine(QAbstractFileEnginePrivate &);
+
+ QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
+private:
+ Q_DECLARE_PRIVATE(QAbstractFileEngine)
+ Q_DISABLE_COPY(QAbstractFileEngine)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFileEngine::FileFlags)
+
+class Q_CORE_EXPORT QAbstractFileEngineHandler
+{
+public:
+ QAbstractFileEngineHandler();
+ virtual ~QAbstractFileEngineHandler();
+ virtual QAbstractFileEngine *create(const QString &fileName) const = 0;
+};
+
+class QAbstractFileEngineIteratorPrivate;
+class Q_CORE_EXPORT QAbstractFileEngineIterator
+{
+public:
+ QAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters);
+ virtual ~QAbstractFileEngineIterator();
+
+ virtual QString next() = 0;
+ virtual bool hasNext() const = 0;
+
+ QString path() const;
+ QStringList nameFilters() const;
+ QDir::Filters filters() const;
+
+ virtual QString currentFileName() const = 0;
+ virtual QFileInfo currentFileInfo() const;
+ QString currentFilePath() const;
+
+protected:
+ enum EntryInfoType {
+ };
+ virtual QVariant entryInfo(EntryInfoType type) const;
+
+private:
+ Q_DISABLE_COPY(QAbstractFileEngineIterator)
+ friend class QDirIterator;
+ friend class QDirIteratorPrivate;
+ void setPath(const QString &path);
+ QScopedPointer<QAbstractFileEngineIteratorPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTFILEENGINE_H
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
new file mode 100644
index 0000000000..d64eaa56c0
--- /dev/null
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTFILEENGINE_P_H
+#define QABSTRACTFILEENGINE_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/qabstractfileengine.h"
+#include "QtCore/qfile.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractFileEnginePrivate
+{
+public:
+ inline QAbstractFileEnginePrivate()
+ : fileError(QFile::UnspecifiedError)
+ {
+ }
+ inline virtual ~QAbstractFileEnginePrivate() { }
+
+ QFile::FileError fileError;
+ QString errorString;
+
+ QAbstractFileEngine *q_ptr;
+ Q_DECLARE_PUBLIC(QAbstractFileEngine)
+};
+
+QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path);
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTFILEENGINE_P_H
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
new file mode 100644
index 0000000000..c5c21659b9
--- /dev/null
+++ b/src/corelib/io/qbuffer.cpp
@@ -0,0 +1,493 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbuffer.h"
+#include "private/qiodevice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/** QBufferPrivate **/
+class QBufferPrivate : public QIODevicePrivate
+{
+ Q_DECLARE_PUBLIC(QBuffer)
+
+public:
+ QBufferPrivate()
+ : buf(0)
+#ifndef QT_NO_QOBJECT
+ , writtenSinceLastEmit(0), signalConnectionCount(0), signalsEmitted(false)
+#endif
+ { }
+ ~QBufferPrivate() { }
+
+ QByteArray *buf;
+ QByteArray defaultBuf;
+ int ioIndex;
+
+ virtual qint64 peek(char *data, qint64 maxSize);
+ virtual QByteArray peek(qint64 maxSize);
+
+#ifndef QT_NO_QOBJECT
+ // private slots
+ void _q_emitSignals();
+
+ qint64 writtenSinceLastEmit;
+ int signalConnectionCount;
+ bool signalsEmitted;
+#endif
+};
+
+#ifndef QT_NO_QOBJECT
+void QBufferPrivate::_q_emitSignals()
+{
+ Q_Q(QBuffer);
+ emit q->bytesWritten(writtenSinceLastEmit);
+ writtenSinceLastEmit = 0;
+ emit q->readyRead();
+ signalsEmitted = false;
+}
+#endif
+
+qint64 QBufferPrivate::peek(char *data, qint64 maxSize)
+{
+ qint64 readBytes = qMin(maxSize, static_cast<qint64>(buf->size()) - pos);
+ memcpy(data, buf->constData() + pos, readBytes);
+ return readBytes;
+}
+
+QByteArray QBufferPrivate::peek(qint64 maxSize)
+{
+ qint64 readBytes = qMin(maxSize, static_cast<qint64>(buf->size()) - pos);
+ if (pos == 0 && maxSize >= buf->size())
+ return *buf;
+ return QByteArray(buf->constData() + pos, readBytes);
+}
+
+/*!
+ \class QBuffer
+ \reentrant
+ \brief The QBuffer class provides a QIODevice interface for a QByteArray.
+
+ \ingroup io
+
+ QBuffer allows you to access a QByteArray using the QIODevice
+ interface. The QByteArray is treated just as a standard random-accessed
+ file. Example:
+
+ \snippet doc/src/snippets/buffer/buffer.cpp 0
+
+ By default, an internal QByteArray buffer is created for you when
+ you create a QBuffer. You can access this buffer directly by
+ calling buffer(). You can also use QBuffer with an existing
+ QByteArray by calling setBuffer(), or by passing your array to
+ QBuffer's constructor.
+
+ Call open() to open the buffer. Then call write() or
+ putChar() to write to the buffer, and read(), readLine(),
+ readAll(), or getChar() to read from it. size() returns the
+ current size of the buffer, and you can seek to arbitrary
+ positions in the buffer by calling seek(). When you are done with
+ accessing the buffer, call close().
+
+ The following code snippet shows how to write data to a
+ QByteArray using QDataStream and QBuffer:
+
+ \snippet doc/src/snippets/buffer/buffer.cpp 1
+
+ Effectively, we convert the application's QPalette into a byte
+ array. Here's how to read the data from the QByteArray:
+
+ \snippet doc/src/snippets/buffer/buffer.cpp 2
+
+ QTextStream and QDataStream also provide convenience constructors
+ that take a QByteArray and that create a QBuffer behind the
+ scenes.
+
+ QBuffer emits readyRead() when new data has arrived in the
+ buffer. By connecting to this signal, you can use QBuffer to
+ store temporary data before processing it. For example, you can
+ pass the buffer to QFtp when downloading a file from an FTP
+ server. Whenever a new payload of data has been downloaded,
+ readyRead() is emitted, and you can process the data that just
+ arrived. QBuffer also emits bytesWritten() every time new data
+ has been written to the buffer.
+
+ \sa QFile, QDataStream, QTextStream, QByteArray
+*/
+
+#ifdef QT_NO_QOBJECT
+QBuffer::QBuffer()
+ : QIODevice(*new QBufferPrivate)
+{
+ Q_D(QBuffer);
+ d->buf = &d->defaultBuf;
+ d->ioIndex = 0;
+}
+QBuffer::QBuffer(QByteArray *buf)
+ : QIODevice(*new QBufferPrivate)
+{
+ Q_D(QBuffer);
+ d->buf = buf ? buf : &d->defaultBuf;
+ d->ioIndex = 0;
+ d->defaultBuf.clear();
+}
+#else
+/*!
+ Constructs an empty buffer with the given \a parent. You can call
+ setData() to fill the buffer with data, or you can open it in
+ write mode and use write().
+
+ \sa open()
+*/
+QBuffer::QBuffer(QObject *parent)
+ : QIODevice(*new QBufferPrivate, parent)
+{
+ Q_D(QBuffer);
+ d->buf = &d->defaultBuf;
+ d->ioIndex = 0;
+}
+
+/*!
+ Constructs a QBuffer that uses the QByteArray pointed to by \a
+ byteArray as its internal buffer, and with the given \a parent.
+ 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. QBuffer doesn't take ownership of
+ the QByteArray.
+
+ If you open the buffer in write-only mode or read-write mode and
+ write something into the QBuffer, \a byteArray will be modified.
+
+ Example:
+
+ \snippet doc/src/snippets/buffer/buffer.cpp 3
+
+ \sa open(), setBuffer(), setData()
+*/
+QBuffer::QBuffer(QByteArray *byteArray, QObject *parent)
+ : QIODevice(*new QBufferPrivate, parent)
+{
+ Q_D(QBuffer);
+ d->buf = byteArray ? byteArray : &d->defaultBuf;
+ d->defaultBuf.clear();
+ d->ioIndex = 0;
+}
+#endif
+
+/*!
+ Destroys the buffer.
+*/
+
+QBuffer::~QBuffer()
+{
+}
+
+/*!
+ Makes QBuffer uses 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.
+ QBuffer doesn't take ownership of the QByteArray.
+
+ Does nothing if isOpen() is true.
+
+ If you open the buffer in write-only mode or read-write mode and
+ write something into the QBuffer, \a byteArray will be modified.
+
+ Example:
+
+ \snippet doc/src/snippets/buffer/buffer.cpp 4
+
+ If \a byteArray is 0, the buffer creates its own internal
+ QByteArray to work on. This byte array is initially empty.
+
+ \sa buffer(), setData(), open()
+*/
+
+void QBuffer::setBuffer(QByteArray *byteArray)
+{
+ Q_D(QBuffer);
+ if (isOpen()) {
+ qWarning("QBuffer::setBuffer: Buffer is open");
+ return;
+ }
+ if (byteArray) {
+ d->buf = byteArray;
+ } else {
+ d->buf = &d->defaultBuf;
+ }
+ d->defaultBuf.clear();
+ d->ioIndex = 0;
+}
+
+/*!
+ Returns a reference to the QBuffer's internal buffer. You can use
+ it to modify the QByteArray behind the QBuffer's back.
+
+ \sa setBuffer(), data()
+*/
+
+QByteArray &QBuffer::buffer()
+{
+ Q_D(QBuffer);
+ return *d->buf;
+}
+
+/*!
+ \overload
+
+ This is the same as data().
+*/
+
+const QByteArray &QBuffer::buffer() const
+{
+ Q_D(const QBuffer);
+ return *d->buf;
+}
+
+
+/*!
+ Returns the data contained in the buffer.
+
+ This is the same as buffer().
+
+ \sa setData(), setBuffer()
+*/
+
+const QByteArray &QBuffer::data() const
+{
+ Q_D(const QBuffer);
+ return *d->buf;
+}
+
+/*!
+ Sets the contents of the internal buffer to be \a data. This is
+ the same as assigning \a data to buffer().
+
+ Does nothing if isOpen() is true.
+
+ \sa setBuffer()
+*/
+void QBuffer::setData(const QByteArray &data)
+{
+ Q_D(QBuffer);
+ if (isOpen()) {
+ qWarning("QBuffer::setData: Buffer is open");
+ return;
+ }
+ *d->buf = data;
+ d->ioIndex = 0;
+}
+
+/*!
+ \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.
+*/
+
+/*!
+ \reimp
+*/
+bool QBuffer::open(OpenMode flags)
+{
+ Q_D(QBuffer);
+
+ if ((flags & Append) == Append)
+ flags |= WriteOnly;
+ setOpenMode(flags);
+ if (!(isReadable() || isWritable())) {
+ qWarning("QFile::open: File access not specified");
+ return false;
+ }
+
+ if ((flags & QIODevice::Truncate) == QIODevice::Truncate) {
+ d->buf->resize(0);
+ }
+ if ((flags & QIODevice::Append) == QIODevice::Append) // append to end of buffer
+ seek(d->buf->size());
+ else
+ seek(0);
+
+ return true;
+}
+
+/*!
+ \reimp
+*/
+void QBuffer::close()
+{
+ QIODevice::close();
+}
+
+/*!
+ \reimp
+*/
+qint64 QBuffer::pos() const
+{
+ return QIODevice::pos();
+}
+
+/*!
+ \reimp
+*/
+qint64 QBuffer::size() const
+{
+ Q_D(const QBuffer);
+ return qint64(d->buf->size());
+}
+
+/*!
+ \reimp
+*/
+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 {
+ return false;
+ }
+ } else if (pos > d->buf->size() || pos < 0) {
+ qWarning("QBuffer::seek: Invalid pos: %d", int(pos));
+ return false;
+ }
+ d->ioIndex = int(pos);
+ return QIODevice::seek(pos);
+}
+
+/*!
+ \reimp
+*/
+bool QBuffer::atEnd() const
+{
+ return QIODevice::atEnd();
+}
+
+/*!
+ \reimp
+*/
+bool QBuffer::canReadLine() const
+{
+ Q_D(const QBuffer);
+ if (!isOpen())
+ return false;
+
+ return d->buf->indexOf('\n', int(pos())) != -1 || QIODevice::canReadLine();
+}
+
+/*!
+ \reimp
+*/
+qint64 QBuffer::readData(char *data, qint64 len)
+{
+ Q_D(QBuffer);
+ if ((len = qMin(len, qint64(d->buf->size()) - d->ioIndex)) <= 0)
+ return qint64(0);
+ memcpy(data, d->buf->constData() + d->ioIndex, len);
+ d->ioIndex += int(len);
+ return len;
+}
+
+/*!
+ \reimp
+*/
+qint64 QBuffer::writeData(const char *data, qint64 len)
+{
+ Q_D(QBuffer);
+ int extraBytes = d->ioIndex + 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
+ qWarning("QBuffer::writeData: Memory allocation error");
+ return -1;
+ }
+ }
+
+ memcpy(d->buf->data() + d->ioIndex, (uchar *)data, int(len));
+ d->ioIndex += int(len);
+
+#ifndef QT_NO_QOBJECT
+ d->writtenSinceLastEmit += len;
+ if (d->signalConnectionCount && !d->signalsEmitted && !signalsBlocked()) {
+ d->signalsEmitted = true;
+ QMetaObject::invokeMethod(this, "_q_emitSignals", Qt::QueuedConnection);
+ }
+#endif
+ return len;
+}
+
+#ifndef QT_NO_QOBJECT
+/*!
+ \reimp
+ \internal
+*/
+void QBuffer::connectNotify(const char *signal)
+{
+ if (strcmp(signal + 1, "readyRead()") == 0 || strcmp(signal + 1, "bytesWritten(qint64)") == 0)
+ d_func()->signalConnectionCount++;
+}
+
+/*!
+ \reimp
+ \internal
+*/
+void QBuffer::disconnectNotify(const char *signal)
+{
+ if (!signal || strcmp(signal + 1, "readyRead()") == 0 || strcmp(signal + 1, "bytesWritten(qint64)") == 0)
+ d_func()->signalConnectionCount--;
+}
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_QOBJECT
+# include "moc_qbuffer.cpp"
+#endif
+
diff --git a/src/corelib/io/qbuffer.h b/src/corelib/io/qbuffer.h
new file mode 100644
index 0000000000..a6cb87bc3f
--- /dev/null
+++ b/src/corelib/io/qbuffer.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBUFFER_H
+#define QBUFFER_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QObject;
+class QBufferPrivate;
+
+class Q_CORE_EXPORT QBuffer : public QIODevice
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#endif
+
+public:
+#ifndef QT_NO_QOBJECT
+ explicit QBuffer(QObject *parent = 0);
+ QBuffer(QByteArray *buf, QObject *parent = 0);
+#else
+ QBuffer();
+ explicit QBuffer(QByteArray *buf);
+#endif
+ ~QBuffer();
+
+ QByteArray &buffer();
+ const QByteArray &buffer() const;
+ void setBuffer(QByteArray *a);
+
+ void setData(const QByteArray &data);
+ inline void setData(const char *data, int len);
+ const QByteArray &data() const;
+
+ bool open(OpenMode openMode);
+
+ void close();
+ qint64 size() const;
+ qint64 pos() const;
+ bool seek(qint64 off);
+ bool atEnd() const;
+ bool canReadLine() const;
+
+protected:
+#ifndef QT_NO_QOBJECT
+ void connectNotify(const char*);
+ void disconnectNotify(const char*);
+#endif
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
+private:
+ Q_DECLARE_PRIVATE(QBuffer)
+ Q_DISABLE_COPY(QBuffer)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_emitSignals())
+};
+
+inline void QBuffer::setData(const char *adata, int alen)
+{ setData(QByteArray(adata, alen)); }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBUFFER_H
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
new file mode 100644
index 0000000000..0361d180b2
--- /dev/null
+++ b/src/corelib/io/qdatastream.cpp
@@ -0,0 +1,1325 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdatastream.h"
+#include "qdatastream_p.h"
+
+#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+#include "qbuffer.h"
+#include "qstring.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "qendian.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDataStream
+ \reentrant
+ \brief The QDataStream class provides serialization of binary data
+ to a QIODevice.
+
+ \ingroup io
+
+
+ A data stream is a binary stream of encoded information which is
+ 100% independent of the host computer's operating system, CPU or
+ byte order. For example, a data stream that is written by a PC
+ under Windows can be read by a Sun SPARC running Solaris.
+
+ You can also use a data stream to read/write \l{raw}{raw
+ unencoded binary data}. If you want a "parsing" input stream, see
+ QTextStream.
+
+ The QDataStream class implements the serialization of C++'s basic
+ data types, like \c char, \c short, \c int, \c{char *}, etc.
+ Serialization of more complex data is accomplished by breaking up
+ the data into primitive units.
+
+ A data stream cooperates closely with a QIODevice. A QIODevice
+ represents an input/output medium one can read data from and write
+ data to. The QFile class is an example of an I/O device.
+
+ Example (write binary data to a stream):
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 0
+
+ Example (read binary data from a stream):
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 1
+
+ Each item written to the stream is written in a predefined binary
+ format that varies depending on the item's type. Supported Qt
+ types include QBrush, QColor, QDateTime, QFont, QPixmap, QString,
+ QVariant and many others. For the complete list of all Qt types
+ supporting data streaming see \l{Serializing Qt Data Types}.
+
+ For integers it is best to always cast to a Qt integer type for
+ writing, and to read back into the same Qt integer type. This
+ ensures that you get integers of the size you want and insulates
+ you from compiler and platform differences.
+
+ 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 Versioning
+
+ QDataStream's binary format has evolved since Qt 1.0, and is
+ likely to continue evolving to reflect changes done in Qt. When
+ inputting or outputting complex types, it's very important to
+ make sure that the same version of the stream (version()) is used
+ for reading and writing. If you need both forward and backward
+ compatibility, you can hardcode the version number in the
+ application:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 2
+
+ If you are producing a new binary data format, such as a file
+ format for documents created by your application, you could use a
+ QDataStream to write the data in a portable format. Typically, you
+ would write a brief header containing a magic string and a version
+ number to give yourself room for future expansion. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 3
+
+ Then read it in with:
+
+ \snippet doc/src/snippets/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
+ special requirements.
+
+ \target raw
+ \section1 Reading and writing raw binary data
+
+ You may wish to read/write your own raw binary data to/from the
+ data stream directly. Data may be read from the stream into a
+ preallocated \c{char *} using readRawData(). Similarly data can be
+ written to the stream using writeRawData(). Note that any
+ encoding/decoding of the data must be done by you.
+
+ A similar pair of functions is readBytes() and writeBytes(). These
+ differ from their \e raw counterparts as follows: readBytes()
+ reads a quint32 which is taken to be the length of the data to be
+ read, then that number of bytes is read into the preallocated
+ \c{char *}; writeBytes() writes a quint32 containing the length of the
+ data, followed by the data. Note that any encoding/decoding of
+ the data (apart from the length quint32) must be done by you.
+
+ \section1 Reading and writing Qt collection classes
+
+ The Qt container classes can also be serialized to a QDataStream.
+ These include QList, QLinkedList, QVector, QSet, QHash, and QMap.
+ The stream operators are declared as non-members of the classes.
+
+ \target Serializing Qt Classes
+ \section1 Reading and writing other Qt classes.
+
+ In addition to the overloaded stream operators documented here,
+ any Qt classes that you might want to serialize to a QDataStream
+ will have appropriate stream operators declared as non-member of
+ the class:
+
+ \code
+ QDataStream &operator<<(QDataStream &, const QXxx &);
+ QDataStream &operator>>(QDataStream &, QXxx &);
+ \endcode
+
+ For example, here are the stream operators declared as non-members
+ of the QImage class:
+
+ \code
+ QDataStream & operator<< (QDataStream& stream, const QImage& image);
+ QDataStream & operator>> (QDataStream& stream, QImage& image);
+ \endcode
+
+ To see if your favorite Qt class has similar stream operators
+ defined, check the \bold {Related Non-Members} section of the
+ class's documentation page.
+
+ \sa QTextStream QVariant
+*/
+
+/*!
+ \enum QDataStream::ByteOrder
+
+ The byte order used for reading/writing the data.
+
+ \value BigEndian Most significant byte first (the default)
+ \value LittleEndian Least significant byte first
+*/
+
+/*!
+ \enum QDataStream::FloatingPointPrecision
+
+ The precision of floating point numbers used for reading/writing the data. This will only have
+ an effect if the version of the data stream is Qt_4_6 or higher.
+
+ \warning The floating point precision must be set to the same value on the object that writes
+ and the object that reads the data stream.
+
+ \value SinglePrecision All floating point numbers in the data stream have 32-bit precision.
+ \value DoublePrecision All floating point numbers in the data stream have 64-bit precision.
+
+ \sa setFloatingPointPrecision(), floatingPointPrecision()
+*/
+
+/*!
+ \enum QDataStream::Status
+
+ This enum describes the current status of the data stream.
+
+ \value Ok The data stream is operating normally.
+ \value ReadPastEnd The data stream has read past the end of the
+ 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.
+*/
+
+/*****************************************************************************
+ QDataStream member functions
+ *****************************************************************************/
+
+#undef CHECK_STREAM_PRECOND
+#ifndef QT_NO_DEBUG
+#define CHECK_STREAM_PRECOND(retVal) \
+ if (!dev) { \
+ qWarning("QDataStream: No device"); \
+ return retVal; \
+ }
+#else
+#define CHECK_STREAM_PRECOND(retVal) \
+ if (!dev) { \
+ return retVal; \
+ }
+#endif
+
+#define CHECK_STREAM_WRITE_PRECOND(retVal) \
+ CHECK_STREAM_PRECOND(retVal) \
+ if (q_status != Ok) \
+ return retVal;
+
+enum {
+ DefaultStreamVersion = QDataStream::Qt_4_6
+};
+
+// ### 5.0: when streaming invalid QVariants, just the type should
+// be written, no "data" after it
+
+/*!
+ Constructs a data stream that has no I/O device.
+
+ \sa setDevice()
+*/
+
+QDataStream::QDataStream()
+{
+ dev = 0;
+ owndev = false;
+ byteorder = BigEndian;
+ ver = DefaultStreamVersion;
+ noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ q_status = Ok;
+}
+
+/*!
+ Constructs a data stream that uses the I/O device \a d.
+
+ \warning If you use QSocket or QSocketDevice as the I/O device \a d
+ for reading data, you must make sure that enough data is available
+ on the socket for the operation to successfully proceed;
+ QDataStream does not have any means to handle or recover from
+ short-reads.
+
+ \sa setDevice(), device()
+*/
+
+QDataStream::QDataStream(QIODevice *d)
+{
+ dev = d; // set device
+ owndev = false;
+ byteorder = BigEndian; // default byte order
+ ver = DefaultStreamVersion;
+ noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ q_status = Ok;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn QDataStream::QDataStream(QByteArray *array, int mode)
+ \compat
+
+ Constructs a data stream that operates on the given \a array. The
+ \a mode specifies how the byte array is to be used, and is
+ usually either QIODevice::ReadOnly or QIODevice::WriteOnly.
+*/
+QDataStream::QDataStream(QByteArray *a, int mode)
+{
+ QBuffer *buf = new QBuffer(a);
+#ifndef QT_NO_QOBJECT
+ buf->blockSignals(true);
+#endif
+ buf->open(QIODevice::OpenMode(mode));
+ dev = buf;
+ owndev = true;
+ byteorder = BigEndian;
+ ver = DefaultStreamVersion;
+ noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ q_status = Ok;
+}
+#endif
+
+/*!
+ \fn QDataStream::QDataStream(QByteArray *a, QIODevice::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.
+
+ Alternatively, you can use QDataStream(const QByteArray &) if you
+ just want to read from a byte array.
+
+ Since QByteArray is not a QIODevice subclass, internally a QBuffer
+ is created to wrap the byte array.
+*/
+
+QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
+{
+ QBuffer *buf = new QBuffer(a);
+#ifndef QT_NO_QOBJECT
+ buf->blockSignals(true);
+#endif
+ buf->open(flags);
+ dev = buf;
+ owndev = true;
+ byteorder = BigEndian;
+ ver = DefaultStreamVersion;
+ noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ q_status = Ok;
+}
+
+/*!
+ Constructs a read-only data stream that operates on byte array \a a.
+ Use QDataStream(QByteArray*, int) if you want to write to a byte
+ array.
+
+ Since QByteArray is not a QIODevice subclass, internally a QBuffer
+ is created to wrap the byte array.
+*/
+QDataStream::QDataStream(const QByteArray &a)
+{
+ QBuffer *buf = new QBuffer;
+#ifndef QT_NO_QOBJECT
+ buf->blockSignals(true);
+#endif
+ buf->setData(a);
+ buf->open(QIODevice::ReadOnly);
+ dev = buf;
+ owndev = true;
+ byteorder = BigEndian;
+ ver = DefaultStreamVersion;
+ noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ q_status = Ok;
+}
+
+/*!
+ Destroys the data stream.
+
+ The destructor will not affect the current I/O device, unless it is
+ an internal I/O device (e.g. a QBuffer) processing a QByteArray
+ passed in the \e constructor, in which case the internal I/O device
+ is destroyed.
+*/
+
+QDataStream::~QDataStream()
+{
+ if (owndev)
+ delete dev;
+}
+
+
+/*!
+ \fn QIODevice *QDataStream::device() const
+
+ Returns the I/O device currently set, or 0 if no
+ device is currently set.
+
+ \sa setDevice()
+*/
+
+/*!
+ void QDataStream::setDevice(QIODevice *d)
+
+ Sets the I/O device to \a d, which can be 0
+ to unset to current I/O device.
+
+ \sa device()
+*/
+
+void QDataStream::setDevice(QIODevice *d)
+{
+ if (owndev) {
+ delete dev;
+ owndev = false;
+ }
+ dev = d;
+}
+
+/*!
+ \obsolete
+ Unsets the I/O device.
+ Use setDevice(0) instead.
+*/
+
+void QDataStream::unsetDevice()
+{
+ setDevice(0);
+}
+
+
+/*!
+ \fn bool QDataStream::atEnd() const
+
+ Returns true if the I/O device has reached the end position (end of
+ the stream or file) or if there is no I/O device set; otherwise
+ returns false.
+
+ \sa QIODevice::atEnd()
+*/
+
+bool QDataStream::atEnd() const
+{
+ return dev ? dev->atEnd() : true;
+}
+
+/*!
+ Returns the floating point precision of the data stream.
+
+ \since 4.6
+
+ \sa FloatingPointPrecision setFloatingPointPrecision()
+*/
+QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
+{
+ return d == 0 ? QDataStream::DoublePrecision : d->floatingPointPrecision;
+}
+
+/*!
+ Sets the floating point precision of the data stream to \a precision. If the floating point precision is
+ DoublePrecision and the version of the data stream is Qt_4_6 or higher, all floating point
+ numbers will be written and read with 64-bit precision. If the floating point precision is
+ SinglePrecision and the version is Qt_4_6 or higher, all floating point numbers will be written
+ and read with 32-bit precision.
+
+ For versions prior to Qt_4_6, the precision of floating point numbers in the data stream depends
+ on the stream operator called.
+
+ The default is DoublePrecision.
+
+ \warning This property must be set to the same value on the object that writes and the object
+ that reads the data stream.
+
+ \since 4.6
+*/
+void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
+{
+ if (d == 0)
+ d.reset(new QDataStreamPrivate());
+ d->floatingPointPrecision = precision;
+}
+
+/*!
+ 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.
+
+ \sa Status status() setStatus()
+*/
+void QDataStream::resetStatus()
+{
+ q_status = Ok;
+}
+
+/*!
+ Sets the status of the data stream to the \a status given.
+
+ Subsequent calls to setStatus() are ignored until resetStatus()
+ is called.
+
+ \sa Status status() resetStatus()
+*/
+void QDataStream::setStatus(Status status)
+{
+ if (q_status == Ok)
+ q_status = status;
+}
+
+/*!\fn bool QDataStream::eof() const
+
+ Use atEnd() instead.
+*/
+
+/*!
+ \fn int QDataStream::byteOrder() const
+
+ Returns the current byte order setting -- either BigEndian or
+ LittleEndian.
+
+ \sa setByteOrder()
+*/
+
+/*!
+ Sets the serialization byte order to \a bo.
+
+ The \a bo parameter can be QDataStream::BigEndian or
+ QDataStream::LittleEndian.
+
+ The default setting is big endian. We recommend leaving this
+ setting unless you have special requirements.
+
+ \sa byteOrder()
+*/
+
+void QDataStream::setByteOrder(ByteOrder bo)
+{
+ byteorder = bo;
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ noswap = (byteorder == BigEndian);
+ else
+ noswap = (byteorder == LittleEndian);
+}
+
+
+/*!
+ \fn bool QDataStream::isPrintableData() const
+
+ In Qt 4, this function always returns false.
+
+ \sa setPrintableData()
+*/
+
+/*!
+ \fn void QDataStream::setPrintableData(bool enable)
+
+ In Qt 3, this function enabled output in a human-readable
+ format if \a enable was false.
+
+ In Qt 4, QDataStream no longer provides a human-readable output.
+ This function does nothing.
+*/
+
+/*!
+ \enum QDataStream::Version
+
+ This enum provides symbolic synonyms for the data serialization
+ format version numbers.
+
+ \value Qt_1_0 Version 1 (Qt 1.x)
+ \value Qt_2_0 Version 2 (Qt 2.0)
+ \value Qt_2_1 Version 3 (Qt 2.1, 2.2, 2.3)
+ \value Qt_3_0 Version 4 (Qt 3.0)
+ \value Qt_3_1 Version 5 (Qt 3.1, 3.2)
+ \value Qt_3_3 Version 6 (Qt 3.3)
+ \value Qt_4_0 Version 7 (Qt 4.0, Qt 4.1)
+ \value Qt_4_1 Version 7 (Qt 4.0, Qt 4.1)
+ \value Qt_4_2 Version 8 (Qt 4.2)
+ \value Qt_4_3 Version 9 (Qt 4.3)
+ \value Qt_4_4 Version 10 (Qt 4.4)
+ \value Qt_4_5 Version 11 (Qt 4.5)
+ \value Qt_4_6 Version 12 (Qt 4.6)
+ \value Qt_4_7 Same as Qt_4_6.
+
+ \sa setVersion(), version()
+*/
+
+/*!
+ \fn int QDataStream::version() const
+
+ Returns the version number of the data serialization format.
+
+ \sa setVersion(), Version
+*/
+
+/*!
+ \fn void QDataStream::setVersion(int v)
+
+ Sets the version number of the data serialization format to \a v.
+
+ You don't \e have to set a version if you are using the current
+ version of Qt, but for your own custom binary formats we
+ recommend that you do; see \l{Versioning} in the Detailed
+ Description.
+
+ To accommodate new functionality, the datastream serialization
+ format of some Qt classes has changed in some versions of Qt. If
+ you want to read data that was created by an earlier version of
+ Qt, or write data that can be read by a program that was compiled
+ with an earlier version of Qt, use this function to modify the
+ serialization format used by QDataStream.
+
+ \table
+ \header \i Qt Version \i QDataStream Version
+ \row \i Qt 4.6 \i 12
+ \row \i Qt 4.5 \i 11
+ \row \i Qt 4.4 \i 10
+ \row \i Qt 4.3 \i 9
+ \row \i Qt 4.2 \i 8
+ \row \i Qt 4.0, 4.1 \i 7
+ \row \i Qt 3.3 \i 6
+ \row \i Qt 3.1, 3.2 \i 5
+ \row \i Qt 3.0 \i 4
+ \row \i Qt 2.1, 2.2, 2.3 \i 3
+ \row \i Qt 2.0 \i 2
+ \row \i Qt 1.x \i 1
+ \endtable
+
+ The \l Version enum provides symbolic constants for the different
+ versions of Qt. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 5
+
+ \sa version(), Version
+*/
+
+/*****************************************************************************
+ QDataStream read functions
+ *****************************************************************************/
+
+/*!
+ \fn QDataStream &QDataStream::operator>>(quint8 &i)
+ \overload
+
+ Reads an unsigned byte from the stream into \a i, and returns a
+ reference to the stream.
+*/
+
+/*!
+ Reads a signed byte from the stream into \a i, and returns a
+ reference to the stream.
+*/
+
+QDataStream &QDataStream::operator>>(qint8 &i)
+{
+ i = 0;
+ CHECK_STREAM_PRECOND(*this)
+ char c;
+ if (!dev->getChar(&c))
+ setStatus(ReadPastEnd);
+ else
+ i = qint8(c);
+ return *this;
+}
+
+
+/*!
+ \fn QDataStream &QDataStream::operator>>(quint16 &i)
+ \overload
+
+ Reads an unsigned 16-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 16-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+QDataStream &QDataStream::operator>>(qint16 &i)
+{
+ i = 0;
+ CHECK_STREAM_PRECOND(*this)
+ if (dev->read((char *)&i, 2) != 2) {
+ i = 0;
+ setStatus(ReadPastEnd);
+ } else {
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ }
+ return *this;
+}
+
+
+/*!
+ \fn QDataStream &QDataStream::operator>>(quint32 &i)
+ \overload
+
+ Reads an unsigned 32-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 32-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+QDataStream &QDataStream::operator>>(qint32 &i)
+{
+ i = 0;
+ CHECK_STREAM_PRECOND(*this)
+ if (dev->read((char *)&i, 4) != 4) {
+ i = 0;
+ setStatus(ReadPastEnd);
+ } else {
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ }
+ return *this;
+}
+
+/*!
+ \fn QDataStream &QDataStream::operator>>(quint64 &i)
+ \overload
+
+ Reads an unsigned 64-bit integer from the stream, into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 64-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+QDataStream &QDataStream::operator>>(qint64 &i)
+{
+ i = qint64(0);
+ CHECK_STREAM_PRECOND(*this)
+ if (version() < 6) {
+ quint32 i1, i2;
+ *this >> i2 >> i1;
+ i = ((quint64)i1 << 32) + i2;
+ } else {
+ if (dev->read((char *)&i, 8) != 8) {
+ i = qint64(0);
+ setStatus(ReadPastEnd);
+ } else {
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ }
+ }
+ return *this;
+}
+
+/*!
+ Reads a boolean value from the stream into \a i. Returns a
+ reference to the stream.
+*/
+QDataStream &QDataStream::operator>>(bool &i)
+{
+ qint8 v;
+ *this >> v;
+ i = !!v;
+ return *this;
+}
+
+/*!
+ \overload
+
+ Reads a floating point number from the stream into \a f,
+ using the standard IEEE 754 format. Returns a reference to the
+ stream.
+
+ \sa setFloatingPointPrecision()
+*/
+
+QDataStream &QDataStream::operator>>(float &f)
+{
+ if (version() >= QDataStream::Qt_4_6
+ && floatingPointPrecision() == QDataStream::DoublePrecision) {
+ double d;
+ *this >> d;
+ f = d;
+ return *this;
+ }
+
+ f = 0.0f;
+ CHECK_STREAM_PRECOND(*this)
+ if (dev->read((char *)&f, 4) != 4) {
+ f = 0.0f;
+ setStatus(ReadPastEnd);
+ } else {
+ if (!noswap) {
+ union {
+ float val1;
+ quint32 val2;
+ } x;
+ x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
+ f = x.val1;
+ }
+ }
+ return *this;
+}
+
+#if defined(Q_DOUBLE_FORMAT)
+#define Q_DF(x) Q_DOUBLE_FORMAT[(x)] - '0'
+#endif
+
+/*!
+ \overload
+
+ Reads a floating point number from the stream into \a f,
+ using the standard IEEE 754 format. Returns a reference to the
+ stream.
+
+ \sa setFloatingPointPrecision()
+*/
+
+QDataStream &QDataStream::operator>>(double &f)
+{
+ if (version() >= QDataStream::Qt_4_6
+ && floatingPointPrecision() == QDataStream::SinglePrecision) {
+ float d;
+ *this >> d;
+ f = d;
+ return *this;
+ }
+
+ f = 0.0;
+ CHECK_STREAM_PRECOND(*this)
+#ifndef Q_DOUBLE_FORMAT
+ if (dev->read((char *)&f, 8) != 8) {
+ f = 0.0;
+ setStatus(ReadPastEnd);
+ } else {
+ if (!noswap) {
+ union {
+ double val1;
+ quint64 val2;
+ } x;
+ x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f));
+ f = x.val1;
+ }
+ }
+#else
+ //non-standard floating point format
+ union {
+ double val1;
+ char val2[8];
+ } x;
+ char *p = x.val2;
+ char b[8];
+ if (dev->read(b, 8) == 8) {
+ if (noswap) {
+ *p++ = b[Q_DF(0)];
+ *p++ = b[Q_DF(1)];
+ *p++ = b[Q_DF(2)];
+ *p++ = b[Q_DF(3)];
+ *p++ = b[Q_DF(4)];
+ *p++ = b[Q_DF(5)];
+ *p++ = b[Q_DF(6)];
+ *p = b[Q_DF(7)];
+ } else {
+ *p++ = b[Q_DF(7)];
+ *p++ = b[Q_DF(6)];
+ *p++ = b[Q_DF(5)];
+ *p++ = b[Q_DF(4)];
+ *p++ = b[Q_DF(3)];
+ *p++ = b[Q_DF(2)];
+ *p++ = b[Q_DF(1)];
+ *p = b[Q_DF(0)];
+ }
+ f = x.val1;
+ } else {
+ setStatus(ReadPastEnd);
+ }
+#endif
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Reads the '\0'-terminated string \a s from the stream and returns
+ a reference to the stream.
+
+ Space for the string is allocated using \c new -- the caller must
+ destroy it with \c{delete[]}.
+*/
+
+QDataStream &QDataStream::operator>>(char *&s)
+{
+ uint len = 0;
+ return readBytes(s, len);
+}
+
+
+/*!
+ Reads the buffer \a s from the stream and returns a reference to
+ the stream.
+
+ The buffer \a s is allocated using \c new. Destroy it with the \c
+ delete[] operator.
+
+ 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
+ a null pointer.
+
+ The serialization format is a quint32 length specifier first,
+ then \a l bytes of data.
+
+ \sa readRawData(), writeBytes()
+*/
+
+QDataStream &QDataStream::readBytes(char *&s, uint &l)
+{
+ s = 0;
+ l = 0;
+ CHECK_STREAM_PRECOND(*this)
+
+ quint32 len;
+ *this >> len;
+ if (len == 0)
+ return *this;
+
+ const quint32 Step = 1024 * 1024;
+ quint32 allocated = 0;
+ char *prevBuf = 0;
+ char *curBuf = 0;
+
+ do {
+ int blockSize = qMin(Step, len - allocated);
+ prevBuf = curBuf;
+ curBuf = new char[allocated + blockSize + 1];
+ if (prevBuf) {
+ memcpy(curBuf, prevBuf, allocated);
+ delete [] prevBuf;
+ }
+ if (dev->read(curBuf + allocated, blockSize) != blockSize) {
+ delete [] curBuf;
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+ allocated += blockSize;
+ } while (allocated < len);
+
+ s = curBuf;
+ s[len] = '\0';
+ l = (uint)len;
+ return *this;
+}
+
+/*!
+ Reads at most \a len bytes from the stream into \a s and returns the number of
+ bytes read. If an error occurs, this function returns -1.
+
+ The buffer \a s must be preallocated. The data is \e not encoded.
+
+ \sa readBytes(), QIODevice::read(), writeRawData()
+*/
+
+int QDataStream::readRawData(char *s, int len)
+{
+ CHECK_STREAM_PRECOND(-1)
+ return dev->read(s, len);
+}
+
+
+/*****************************************************************************
+ QDataStream write functions
+ *****************************************************************************/
+
+
+/*!
+ \fn QDataStream &QDataStream::operator<<(quint8 i)
+ \overload
+
+ Writes an unsigned byte, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ Writes a signed byte, \a i, to the stream and returns a reference
+ to the stream.
+*/
+
+QDataStream &QDataStream::operator<<(qint8 i)
+{
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ if (!dev->putChar(i))
+ q_status = WriteFailed;
+ return *this;
+}
+
+
+/*!
+ \fn QDataStream &QDataStream::operator<<(quint16 i)
+ \overload
+
+ Writes an unsigned 16-bit integer, \a i, to the stream and returns
+ a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Writes a signed 16-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+QDataStream &QDataStream::operator<<(qint16 i)
+{
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ if (dev->write((char *)&i, sizeof(qint16)) != sizeof(qint16))
+ q_status = WriteFailed;
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes a signed 32-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+QDataStream &QDataStream::operator<<(qint32 i)
+{
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
+ q_status = WriteFailed;
+ return *this;
+}
+
+/*!
+ \fn QDataStream &QDataStream::operator<<(quint64 i)
+ \overload
+
+ Writes an unsigned 64-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Writes a signed 64-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+QDataStream &QDataStream::operator<<(qint64 i)
+{
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ if (version() < 6) {
+ quint32 i1 = i & 0xffffffff;
+ quint32 i2 = i >> 32;
+ *this << i2 << i1;
+ } else {
+ if (!noswap) {
+ i = qbswap(i);
+ }
+ if (dev->write((char *)&i, sizeof(qint64)) != sizeof(qint64))
+ q_status = WriteFailed;
+ }
+ return *this;
+}
+
+/*!
+ \fn QDataStream &QDataStream::operator<<(quint32 i)
+ \overload
+
+ Writes an unsigned integer, \a i, to the stream as a 32-bit
+ unsigned integer (quint32). Returns a reference to the stream.
+*/
+
+/*!
+ 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
+
+ Writes a floating point number, \a f, to the stream using
+ the standard IEEE 754 format. Returns a reference to the stream.
+
+ \sa setFloatingPointPrecision()
+*/
+
+QDataStream &QDataStream::operator<<(float f)
+{
+ if (version() >= QDataStream::Qt_4_6
+ && floatingPointPrecision() == QDataStream::DoublePrecision) {
+ *this << double(f);
+ return *this;
+ }
+
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ float g = f; // fixes float-on-stack problem
+ if (!noswap) {
+ union {
+ float val1;
+ quint32 val2;
+ } x;
+ x.val1 = g;
+ x.val2 = qbswap(x.val2);
+ g = x.val1;
+ }
+ if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
+ q_status = WriteFailed;
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Writes a floating point number, \a f, to the stream using
+ the standard IEEE 754 format. Returns a reference to the stream.
+
+ \sa setFloatingPointPrecision()
+*/
+
+QDataStream &QDataStream::operator<<(double f)
+{
+ if (version() >= QDataStream::Qt_4_6
+ && floatingPointPrecision() == QDataStream::SinglePrecision) {
+ *this << float(f);
+ return *this;
+ }
+
+ CHECK_STREAM_WRITE_PRECOND(*this)
+#ifndef Q_DOUBLE_FORMAT
+ if (noswap) {
+ if (dev->write((char *)&f, sizeof(double)) != sizeof(double))
+ q_status = WriteFailed;
+ } else {
+ union {
+ double val1;
+ quint64 val2;
+ } x;
+ x.val1 = f;
+ x.val2 = qbswap(x.val2);
+ if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double))
+ q_status = WriteFailed;
+ }
+#else
+ union {
+ double val1;
+ char val2[8];
+ } x;
+ x.val1 = f;
+ char *p = x.val2;
+ char b[8];
+ if (noswap) {
+ b[Q_DF(0)] = *p++;
+ b[Q_DF(1)] = *p++;
+ b[Q_DF(2)] = *p++;
+ b[Q_DF(3)] = *p++;
+ b[Q_DF(4)] = *p++;
+ b[Q_DF(5)] = *p++;
+ b[Q_DF(6)] = *p++;
+ b[Q_DF(7)] = *p;
+ } else {
+ b[Q_DF(7)] = *p++;
+ b[Q_DF(6)] = *p++;
+ b[Q_DF(5)] = *p++;
+ b[Q_DF(4)] = *p++;
+ b[Q_DF(3)] = *p++;
+ b[Q_DF(2)] = *p++;
+ b[Q_DF(1)] = *p++;
+ b[Q_DF(0)] = *p;
+ }
+ if (dev->write(b, 8) != 8)
+ q_status = WriteFailed;
+#endif
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Writes the '\0'-terminated string \a s to the stream and returns a
+ reference to the stream.
+
+ The string is serialized using writeBytes().
+*/
+
+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);
+ return *this;
+}
+
+
+/*!
+ 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.
+
+ \sa writeRawData(), readBytes()
+*/
+
+QDataStream &QDataStream::writeBytes(const char *s, uint len)
+{
+ CHECK_STREAM_WRITE_PRECOND(*this)
+ *this << (quint32)len; // write length specifier
+ if (len)
+ 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.
+ The data is \e not encoded.
+
+ \sa writeBytes(), QIODevice::write(), readRawData()
+*/
+
+int QDataStream::writeRawData(const char *s, int len)
+{
+ CHECK_STREAM_WRITE_PRECOND(-1)
+ int ret = dev->write(s, len);
+ if (ret != len)
+ q_status = WriteFailed;
+ return ret;
+}
+
+/*!
+ \since 4.1
+
+ Skips \a len bytes from the device. Returns the number of bytes
+ actually skipped, or -1 on error.
+
+ This is equivalent to calling readRawData() on a buffer of length
+ \a len and ignoring the buffer.
+
+ \sa QIODevice::seek()
+*/
+int QDataStream::skipRawData(int len)
+{
+ CHECK_STREAM_PRECOND(-1)
+
+ if (dev->isSequential()) {
+ char buf[4096];
+ int sumRead = 0;
+
+ while (len > 0) {
+ int blockSize = qMin(len, (int)sizeof(buf));
+ int n = dev->read(buf, blockSize);
+ if (n == -1)
+ return -1;
+ if (n == 0)
+ return sumRead;
+
+ sumRead += n;
+ len -= blockSize;
+ }
+ return sumRead;
+ } else {
+ qint64 pos = dev->pos();
+ qint64 size = dev->size();
+ if (pos + len > size)
+ len = size - pos;
+ if (!dev->seek(pos + len))
+ return -1;
+ return len;
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn QDataStream &QDataStream::readRawBytes(char *str, uint len)
+
+ Use readRawData() instead.
+*/
+
+/*!
+ \fn QDataStream &QDataStream::writeRawBytes(const char *str, uint len)
+
+ Use writeRawData() instead.
+*/
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DATASTREAM
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
new file mode 100644
index 0000000000..d19fcc5377
--- /dev/null
+++ b/src/corelib/io/qdatastream.h
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATASTREAM_H
+#define QDATASTREAM_H
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qglobal.h>
+
+#ifdef Status
+#error qdatastream.h must be included before any header file that defines Status
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArray;
+class QIODevice;
+
+template <typename T> class QList;
+template <typename T> class QLinkedList;
+template <typename T> class QVector;
+template <typename T> class QSet;
+template <class Key, class T> class QHash;
+template <class Key, class T> class QMap;
+
+#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+class QDataStreamPrivate;
+class Q_CORE_EXPORT QDataStream
+{
+public:
+ enum Version {
+ Qt_1_0 = 1,
+ Qt_2_0 = 2,
+ Qt_2_1 = 3,
+ Qt_3_0 = 4,
+ Qt_3_1 = 5,
+ Qt_3_3 = 6,
+ Qt_4_0 = 7,
+ Qt_4_1 = Qt_4_0,
+ Qt_4_2 = 8,
+ Qt_4_3 = 9,
+ Qt_4_4 = 10,
+ Qt_4_5 = 11,
+ Qt_4_6 = 12,
+ Qt_4_7 = Qt_4_6,
+ Qt_4_8 = Qt_4_7
+#if QT_VERSION >= 0x040900
+#error Add the datastream version for this Qt version
+ Qt_4_9 = Qt_4_8
+#endif
+ };
+
+ enum ByteOrder {
+ BigEndian = QSysInfo::BigEndian,
+ LittleEndian = QSysInfo::LittleEndian
+ };
+
+ enum Status {
+ Ok,
+ ReadPastEnd,
+ ReadCorruptData,
+ WriteFailed
+ };
+
+ enum FloatingPointPrecision {
+ SinglePrecision,
+ DoublePrecision
+ };
+
+ QDataStream();
+ explicit QDataStream(QIODevice *);
+#ifdef QT3_SUPPORT
+ QDataStream(QByteArray *, int mode);
+#endif
+ QDataStream(QByteArray *, QIODevice::OpenMode flags);
+ QDataStream(const QByteArray &);
+ virtual ~QDataStream();
+
+ QIODevice *device() const;
+ void setDevice(QIODevice *);
+ void unsetDevice();
+
+ bool atEnd() const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool eof() const { return atEnd(); }
+#endif
+
+ Status status() const;
+ void setStatus(Status status);
+ void resetStatus();
+
+ FloatingPointPrecision floatingPointPrecision() const;
+ void setFloatingPointPrecision(FloatingPointPrecision precision);
+
+ ByteOrder byteOrder() const;
+ void setByteOrder(ByteOrder);
+
+ int version() const;
+ void setVersion(int);
+
+ QDataStream &operator>>(qint8 &i);
+ QDataStream &operator>>(quint8 &i);
+ QDataStream &operator>>(qint16 &i);
+ QDataStream &operator>>(quint16 &i);
+ QDataStream &operator>>(qint32 &i);
+ QDataStream &operator>>(quint32 &i);
+ QDataStream &operator>>(qint64 &i);
+ QDataStream &operator>>(quint64 &i);
+
+ QDataStream &operator>>(bool &i);
+ QDataStream &operator>>(float &f);
+ QDataStream &operator>>(double &f);
+ QDataStream &operator>>(char *&str);
+
+ QDataStream &operator<<(qint8 i);
+ QDataStream &operator<<(quint8 i);
+ QDataStream &operator<<(qint16 i);
+ QDataStream &operator<<(quint16 i);
+ QDataStream &operator<<(qint32 i);
+ QDataStream &operator<<(quint32 i);
+ QDataStream &operator<<(qint64 i);
+ QDataStream &operator<<(quint64 i);
+ QDataStream &operator<<(bool i);
+ QDataStream &operator<<(float f);
+ QDataStream &operator<<(double f);
+ QDataStream &operator<<(const char *str);
+
+ QDataStream &readBytes(char *&, uint &len);
+ int readRawData(char *, int len);
+
+ QDataStream &writeBytes(const char *, uint len);
+ int writeRawData(const char *, int len);
+
+ int skipRawData(int len);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QDataStream &readRawBytes(char *str, uint len)
+ { readRawData(str, static_cast<int>(len)); return *this; }
+ inline QT3_SUPPORT QDataStream &writeRawBytes(const char *str, uint len)
+ { writeRawData(str, static_cast<int>(len)); return *this; }
+ inline QT3_SUPPORT bool isPrintableData() const { return false; }
+ inline QT3_SUPPORT void setPrintableData(bool) {}
+#endif
+
+private:
+ Q_DISABLE_COPY(QDataStream)
+
+ QScopedPointer<QDataStreamPrivate> d;
+
+ QIODevice *dev;
+ bool owndev;
+ bool noswap;
+ ByteOrder byteorder;
+ int ver;
+ Status q_status;
+};
+
+
+/*****************************************************************************
+ QDataStream inline functions
+ *****************************************************************************/
+
+inline QIODevice *QDataStream::device() const
+{ return dev; }
+
+inline QDataStream::ByteOrder QDataStream::byteOrder() const
+{ return byteorder; }
+
+inline int QDataStream::version() const
+{ return ver; }
+
+inline void QDataStream::setVersion(int v)
+{ ver = v; }
+
+inline QDataStream &QDataStream::operator>>(quint8 &i)
+{ return *this >> reinterpret_cast<qint8&>(i); }
+
+inline QDataStream &QDataStream::operator>>(quint16 &i)
+{ return *this >> reinterpret_cast<qint16&>(i); }
+
+inline QDataStream &QDataStream::operator>>(quint32 &i)
+{ return *this >> reinterpret_cast<qint32&>(i); }
+
+inline QDataStream &QDataStream::operator>>(quint64 &i)
+{ return *this >> reinterpret_cast<qint64&>(i); }
+
+inline QDataStream &QDataStream::operator<<(quint8 i)
+{ return *this << qint8(i); }
+
+inline QDataStream &QDataStream::operator<<(quint16 i)
+{ return *this << qint16(i); }
+
+inline QDataStream &QDataStream::operator<<(quint32 i)
+{ return *this << qint32(i); }
+
+inline QDataStream &QDataStream::operator<<(quint64 i)
+{ return *this << qint64(i); }
+
+template <typename T>
+QDataStream& operator>>(QDataStream& s, QList<T>& l)
+{
+ l.clear();
+ quint32 c;
+ s >> c;
+ l.reserve(c);
+ for(quint32 i = 0; i < c; ++i)
+ {
+ T t;
+ s >> t;
+ l.append(t);
+ if (s.atEnd())
+ break;
+ }
+ return s;
+}
+
+template <typename T>
+QDataStream& operator<<(QDataStream& s, const QList<T>& l)
+{
+ s << quint32(l.size());
+ for (int i = 0; i < l.size(); ++i)
+ s << l.at(i);
+ return s;
+}
+
+template <typename T>
+QDataStream& operator>>(QDataStream& s, QLinkedList<T>& l)
+{
+ l.clear();
+ quint32 c;
+ s >> c;
+ for(quint32 i = 0; i < c; ++i)
+ {
+ T t;
+ s >> t;
+ l.append(t);
+ if (s.atEnd())
+ break;
+ }
+ return s;
+}
+
+template <typename T>
+QDataStream& operator<<(QDataStream& s, const QLinkedList<T>& l)
+{
+ s << quint32(l.size());
+ typename QLinkedList<T>::ConstIterator it = l.constBegin();
+ for(; it != l.constEnd(); ++it)
+ s << *it;
+ return s;
+}
+
+template<typename T>
+QDataStream& operator>>(QDataStream& s, QVector<T>& v)
+{
+ v.clear();
+ quint32 c;
+ s >> c;
+ v.resize(c);
+ for(quint32 i = 0; i < c; ++i) {
+ T t;
+ s >> t;
+ v[i] = t;
+ }
+ return s;
+}
+
+template<typename T>
+QDataStream& operator<<(QDataStream& s, const QVector<T>& v)
+{
+ s << quint32(v.size());
+ for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
+ s << *it;
+ return s;
+}
+
+template <typename T>
+QDataStream &operator>>(QDataStream &in, QSet<T> &set)
+{
+ set.clear();
+ quint32 c;
+ in >> c;
+ for (quint32 i = 0; i < c; ++i) {
+ T t;
+ in >> t;
+ set << t;
+ if (in.atEnd())
+ break;
+ }
+ return in;
+}
+
+template <typename T>
+QDataStream& operator<<(QDataStream &out, const QSet<T> &set)
+{
+ out << quint32(set.size());
+ typename QSet<T>::const_iterator i = set.constBegin();
+ while (i != set.constEnd()) {
+ out << *i;
+ ++i;
+ }
+ return out;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash)
+{
+ QDataStream::Status oldStatus = in.status();
+ in.resetStatus();
+ hash.clear();
+
+ quint32 n;
+ in >> n;
+
+ for (quint32 i = 0; i < n; ++i) {
+ if (in.status() != QDataStream::Ok)
+ break;
+
+ Key k;
+ T t;
+ in >> k >> t;
+ hash.insertMulti(k, t);
+ }
+
+ if (in.status() != QDataStream::Ok)
+ hash.clear();
+ if (oldStatus != QDataStream::Ok)
+ in.setStatus(oldStatus);
+ return in;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
+{
+ out << quint32(hash.size());
+ typename QHash<Key, T>::ConstIterator it = hash.end();
+ typename QHash<Key, T>::ConstIterator begin = hash.begin();
+ while (it != begin) {
+ --it;
+ out << it.key() << it.value();
+ }
+ return out;
+}
+#ifdef qdoc
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
+#else
+template <class aKey, class aT>
+Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &map)
+#endif
+{
+ QDataStream::Status oldStatus = in.status();
+ in.resetStatus();
+ map.clear();
+
+ quint32 n;
+ in >> n;
+
+ map.detach();
+ map.setInsertInOrder(true);
+ for (quint32 i = 0; i < n; ++i) {
+ if (in.status() != QDataStream::Ok)
+ break;
+
+ aKey key;
+ aT value;
+ in >> key >> value;
+ map.insertMulti(key, value);
+ }
+ map.setInsertInOrder(false);
+ if (in.status() != QDataStream::Ok)
+ map.clear();
+ if (oldStatus != QDataStream::Ok)
+ in.setStatus(oldStatus);
+ return in;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
+{
+ out << quint32(map.size());
+ typename QMap<Key, T>::ConstIterator it = map.end();
+ typename QMap<Key, T>::ConstIterator begin = map.begin();
+ while (it != begin) {
+ --it;
+ out << it.key() << it.value();
+ }
+ return out;
+}
+
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDATASTREAM_H
diff --git a/src/corelib/io/qdatastream_p.h b/src/corelib/io/qdatastream_p.h
new file mode 100644
index 0000000000..ec270d2296
--- /dev/null
+++ b/src/corelib/io/qdatastream_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATASTREAM_P_H
+#define QDATASTREAM_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 <qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+class QDataStreamPrivate
+{
+public:
+ QDataStreamPrivate() : floatingPointPrecision(QDataStream::DoublePrecision) { }
+
+ QDataStream::FloatingPointPrecision floatingPointPrecision;
+};
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QDATASTREAM_P_H
diff --git a/src/corelib/io/qdataurl.cpp b/src/corelib/io/qdataurl.cpp
new file mode 100644
index 0000000000..2e6f635886
--- /dev/null
+++ b/src/corelib/io/qdataurl.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qurl.h"
+#include "private/qdataurl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ Decode a data: URL into its mimetype and payload. Returns a null string if
+ the URL could not be decoded.
+*/
+Q_CORE_EXPORT QPair<QString, QByteArray> qDecodeDataUrl(const QUrl &uri)
+{
+ QString mimeType;
+ QByteArray payload;
+
+ if (uri.scheme() == QLatin1String("data") && uri.host().isEmpty()) {
+ mimeType = QLatin1String("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.encodedPath());
+ QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded());
+
+ // remove the data: scheme
+ data.remove(0, 5);
+
+ // parse it:
+ int pos = data.indexOf(',');
+ if (pos != -1) {
+ payload = data.mid(pos + 1);
+ data.truncate(pos);
+ data = data.trimmed();
+
+ // find out if the payload is encoded in Base64
+ if (data.endsWith(";base64")) {
+ payload = QByteArray::fromBase64(payload);
+ data.chop(7);
+ }
+
+ if (data.toLower().startsWith("charset")) {
+ int i = 7; // strlen("charset")
+ while (data.at(i) == ' ')
+ ++i;
+ if (data.at(i) == '=')
+ data.prepend("text/plain;");
+ }
+
+ if (!data.isEmpty())
+ mimeType = QLatin1String(data.trimmed());
+
+ }
+ }
+
+ return QPair<QString,QByteArray>(mimeType,payload);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qdataurl_p.h b/src/corelib/io/qdataurl_p.h
new file mode 100644
index 0000000000..0cde476a5f
--- /dev/null
+++ b/src/corelib/io/qdataurl_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATAURL_P_H
+#define QDATAURL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qDecodeDataUrl. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qurl.h"
+#include "QtCore/qbytearray.h"
+#include "QtCore/qstring.h"
+#include "QtCore/qpair.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT QPair<QString, QByteArray> qDecodeDataUrl(const QUrl &url);
+
+QT_END_NAMESPACE
+
+#endif // QDATAURL_P_H
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
new file mode 100644
index 0000000000..aac0d982aa
--- /dev/null
+++ b/src/corelib/io/qdebug.cpp
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef QT_NO_DEBUG
+#undef QT_NO_DEBUG
+#endif
+#ifdef qDebug
+#undef qDebug
+#endif
+
+#include "qdebug.h"
+
+// This file is needed to force compilation of QDebug into the kernel library.
+
+/*!
+ \class QDebug
+
+ \brief The QDebug class provides an output stream for debugging information.
+
+ QDebug is used whenever the developer needs to write out debugging or tracing
+ information to a device, file, string or console.
+
+ \section1 Basic Use
+
+ In the common case, it is useful to call the qDebug() function to obtain a
+ default QDebug object to use for writing debugging information.
+
+ \snippet doc/src/snippets/qdebug/qdebugsnippet.cpp 1
+
+ This constructs a QDebug object using the constructor that accepts a QtMsgType
+ value of QtDebugMsg. Similarly, the qWarning(), qCritical() and qFatal()
+ functions also return QDebug objects for the corresponding message types.
+
+ The class also provides several constructors for other situations, including
+ a constructor that accepts a QFile or any other QIODevice subclass that is
+ used to write debugging information to files and other devices. The constructor
+ that accepts a QString is used to write to a string for display or serialization.
+
+ \section1 Writing Custom Types to a Stream
+
+ Many standard types can be written to QDebug objects, and Qt provides support for
+ most Qt value types. To add support for custom types, you need to implement a
+ streaming operator, as in the following example:
+
+ \snippet doc/src/snippets/qdebug/qdebugsnippet.cpp 0
+
+ This is described in the \l{Debugging Techniques} and
+ \l{Creating Custom Qt Types#Making the Type Printable}{Creating Custom Qt Types}
+ documents.
+*/
+
+/*!
+ \fn QDebug::QDebug(QIODevice *device)
+
+ Constructs a debug stream that writes to the given \a device.
+*/
+
+/*!
+ \fn QDebug::QDebug(QString *string)
+
+ Constructs a debug stream that writes to the given \a string.
+*/
+
+/*!
+ \fn QDebug::QDebug(QtMsgType type)
+
+ Constructs a debug stream that writes to the handler for the message type specified by \a type.
+*/
+
+/*!
+ \fn QDebug::QDebug(const QDebug &other)
+
+ Constructs a copy of the \a other debug stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator=(const QDebug &other)
+
+ Assigns the \a other debug stream to this stream and returns a reference to
+ this stream.
+*/
+
+/*!
+ \fn QDebug::~QDebug()
+
+ Flushes any pending data to be written and destroys the debug stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::space()
+
+ Writes a space character to the debug stream and returns a reference to
+ the stream.
+
+ The stream will record that the last character sent to the stream was a
+ space.
+
+ \sa nospace(), maybeSpace()
+*/
+
+/*!
+ \fn QDebug &QDebug::nospace()
+
+ Clears the stream's internal flag that records whether the last character
+ was a space and returns a reference to the stream.
+
+ \sa space(), maybeSpace()
+*/
+
+/*!
+ \fn QDebug &QDebug::maybeSpace()
+
+ Writes a space character to the debug stream, depending on the last
+ character sent to the stream, and returns a reference to the stream.
+
+ If the last character was a space character, this function writes a space
+ character to the stream; otherwise, no characters are written to the stream.
+
+ \sa space(), nospace()
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(QChar t)
+
+ Writes the character, \a t, to the stream and returns a reference to the
+ stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(QBool t)
+ \internal
+
+ Writes the boolean value, \a t, to the stream and returns a reference to the
+ stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(bool t)
+
+ Writes the boolean value, \a t, to the stream and returns a reference to the
+ stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(char t)
+
+ Writes the character, \a t, to the stream and returns a reference to the
+ stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(signed short i)
+
+ Writes the signed short integer, \a i, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(unsigned short i)
+
+ Writes then unsigned short integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(signed int i)
+
+ Writes the signed integer, \a i, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(unsigned int i)
+
+ Writes then unsigned integer, \a i, to the stream and returns a reference to
+ the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(signed long l)
+
+ Writes the signed long integer, \a l, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(unsigned long l)
+
+ Writes then unsigned long integer, \a l, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(qint64 i)
+
+ Writes the signed 64-bit integer, \a i, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(quint64 i)
+
+ Writes then unsigned 64-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(float f)
+
+ Writes the 32-bit floating point number, \a f, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(double f)
+
+ Writes the 64-bit floating point number, \a f, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const char *s)
+
+ Writes the '\0'-terminated string, \a s, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const QString &s)
+
+ Writes the string, \a s, to the stream and returns a reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const QStringRef &s)
+
+ Writes the string reference, \a s, to the stream and returns a reference to
+ the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const QLatin1String &s)
+
+ Writes the Latin1-encoded string, \a s, to the stream and returns a reference
+ to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const QByteArray &b)
+
+ Writes the byte array, \a b, to the stream and returns a reference to the
+ stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const void *p)
+
+ Writes a pointer, \a p, to the stream and returns a reference to the stream.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(QTextStreamFunction f)
+ \internal
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(QTextStreamManipulator m)
+ \internal
+*/
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
new file mode 100644
index 0000000000..f463b753fb
--- /dev/null
+++ b/src/corelib/io/qdebug.h
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDEBUG_H
+#define QDEBUG_H
+
+#include <QtCore/qalgorithms.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qset.h>
+#include <QtCore/qcontiguouscache.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QDebug
+{
+ struct Stream {
+ Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
+ Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
+ Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {}
+ QTextStream ts;
+ QString buffer;
+ int ref;
+ QtMsgType type;
+ bool space;
+ bool message_output;
+ } *stream;
+public:
+ inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
+ inline QDebug(QString *string) : stream(new Stream(string)) {}
+ inline QDebug(QtMsgType t) : stream(new Stream(t)) {}
+ inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }
+ inline QDebug &operator=(const QDebug &other);
+ inline ~QDebug() {
+ if (!--stream->ref) {
+ if(stream->message_output) {
+ QT_TRY {
+ qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());
+ } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
+ }
+ delete stream;
+ }
+ }
+ 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 &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
+ inline QDebug &operator<<(QBool t) { stream->ts << (bool(t != 0) ? "true" : "false"); 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(); }
+ 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 << QString::number(t); return maybeSpace(); }
+ inline QDebug &operator<<(quint64 t)
+ { stream->ts << QString::number(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::fromAscii(t); return maybeSpace(); }
+ inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
+ inline QDebug &operator<<(const QLatin1String &t) { stream->ts << '\"' << t.latin1() << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
+ inline QDebug &operator<<(QTextStreamFunction f) {
+ stream->ts << f;
+ return *this;
+ }
+
+ inline QDebug &operator<<(QTextStreamManipulator m)
+ { stream->ts << m; return *this; }
+};
+
+class QNoDebug
+{
+public:
+ inline QNoDebug(){}
+ inline QNoDebug(const QDebug &){}
+ inline ~QNoDebug(){}
+#if !defined( QT_NO_TEXTSTREAM )
+ inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
+ inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
+#endif
+ inline QNoDebug &space() { return *this; }
+ inline QNoDebug &nospace() { return *this; }
+ inline QNoDebug &maybeSpace() { return *this; }
+
+ template<typename T>
+ inline QNoDebug &operator<<(const T &) { return *this; }
+};
+
+Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); }
+
+inline QDebug &QDebug::operator=(const QDebug &other)
+{
+ if (this != &other) {
+ QDebug copy(other);
+ qSwap(stream, copy.stream);
+ }
+ return *this;
+}
+
+#if defined(FORCE_UREF)
+template <class T>
+inline QDebug &operator<<(QDebug debug, const QList<T> &list)
+#else
+template <class T>
+inline QDebug operator<<(QDebug debug, const QList<T> &list)
+#endif
+{
+ debug.nospace() << '(';
+ for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) {
+ if (i)
+ debug << ", ";
+ debug << list.at(i);
+ }
+ debug << ')';
+ return debug.space();
+}
+
+#if defined(FORCE_UREF)
+template <typename T>
+inline QDebug &operator<<(QDebug debug, const QVector<T> &vec)
+#else
+template <typename T>
+inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
+#endif
+{
+ debug.nospace() << "QVector";
+ return operator<<(debug, vec.toList());
+}
+
+#if defined(FORCE_UREF)
+template <class aKey, class aT>
+inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map)
+#else
+template <class aKey, class aT>
+inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
+#endif
+{
+ debug.nospace() << "QMap(";
+ for (typename QMap<aKey, aT>::const_iterator it = map.constBegin();
+ it != map.constEnd(); ++it) {
+ debug << '(' << it.key() << ", " << it.value() << ')';
+ }
+ debug << ')';
+ return debug.space();
+}
+
+#if defined(FORCE_UREF)
+template <class aKey, class aT>
+inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash)
+#else
+template <class aKey, class aT>
+inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
+#endif
+{
+ debug.nospace() << "QHash(";
+ for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin();
+ it != hash.constEnd(); ++it)
+ debug << '(' << it.key() << ", " << it.value() << ')';
+ debug << ')';
+ return debug.space();
+}
+
+#if defined(FORCE_UREF)
+template <class T1, class T2>
+inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair)
+#else
+template <class T1, class T2>
+inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
+#endif
+{
+ debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
+ return debug.space();
+}
+
+template <typename T>
+inline QDebug operator<<(QDebug debug, const QSet<T> &set)
+{
+ debug.nospace() << "QSet";
+ return operator<<(debug, set.toList());
+}
+
+#if defined(FORCE_UREF)
+template <class T>
+inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#else
+template <class T>
+inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#endif
+{
+ debug.nospace() << "QContiguousCache(";
+ for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
+ debug << cache[i];
+ if (i != cache.lastIndex())
+ debug << ", ";
+ }
+ debug << ')';
+ return debug.space();
+}
+
+#if defined(FORCE_UREF)
+template <class T>
+inline QDebug &operator<<(QDebug debug, const QFlags<T> &flags)
+#else
+template <class T>
+inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
+#endif
+{
+ debug.nospace() << "QFlags(";
+ bool needSeparator = false;
+ for (uint i = 0; i < sizeof(T) * 8; ++i) {
+ if (flags.testFlag(T(1 << i))) {
+ if (needSeparator)
+ debug.nospace() << '|';
+ else
+ needSeparator = true;
+ debug.nospace() << "0x" << QByteArray::number(T(1 << i), 16).constData();
+ }
+ }
+ debug << ')';
+ return debug.space();
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }
+
+#else // QT_NO_DEBUG_STREAM
+#undef qDebug
+inline QNoDebug qDebug() { return QNoDebug(); }
+#define qDebug QT_NO_QDEBUG_MACRO
+
+#endif
+
+#if !defined(QT_NO_WARNING_OUTPUT)
+Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }
+#else
+#undef qWarning
+inline QNoDebug qWarning() { return QNoDebug(); }
+#define qWarning QT_NO_QWARNING_MACRO
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDEBUG_H
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
new file mode 100644
index 0000000000..166513a6ff
--- /dev/null
+++ b/src/corelib/io/qdir.cpp
@@ -0,0 +1,2386 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qdir.h"
+#include "qdir_p.h"
+#include "qabstractfileengine.h"
+#ifndef QT_NO_DEBUG_STREAM
+#include "qdebug.h"
+#endif
+#include "qdiriterator.h"
+#include "qfsfileengine.h"
+#include "qdatetime.h"
+#include "qstring.h"
+#include "qregexp.h"
+#include "qvector.h"
+#include "qalgorithms.h"
+#include "qvarlengtharray.h"
+#include "qfilesystementry_p.h"
+#include "qfilesystemmetadata_p.h"
+#include "qfilesystemengine_p.h"
+#include <qstringbuilder.h>
+
+#ifdef QT_BUILD_CORE_LIB
+# include "qresource.h"
+# include "private/qcoreglobaldata_p.h"
+#endif
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+static QString driveSpec(const QString &path)
+{
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (path.size() < 2)
+ return QString();
+ char c = path.at(0).toAscii();
+ if (c < 'a' && c > 'z' && c < 'A' && c > 'Z')
+ return QString();
+ if (path.at(1).toAscii() != ':')
+ return QString();
+ return path.mid(0, 2);
+#else
+ Q_UNUSED(path);
+ return QString();
+#endif
+}
+
+//************* QDirPrivate
+QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_)
+ : QSharedData()
+ , nameFilters(nameFilters_)
+ , sort(sort_)
+ , filters(filters_)
+#ifdef QT3_SUPPORT
+ , filterSepChar(0)
+ , matchAllDirs(false)
+#endif
+ , fileListsInitialized(false)
+{
+ 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;
+ }
+ }
+ }
+ if (empty)
+ nameFilters = QStringList(QString::fromLatin1("*"));
+}
+
+QDirPrivate::QDirPrivate(const QDirPrivate &copy)
+ : QSharedData(copy)
+ , nameFilters(copy.nameFilters)
+ , sort(copy.sort)
+ , filters(copy.filters)
+#ifdef QT3_SUPPORT
+ , filterSepChar(copy.filterSepChar)
+ , matchAllDirs(copy.matchAllDirs)
+#endif
+ , fileListsInitialized(false)
+ , dirEntry(copy.dirEntry)
+ , metaData(copy.metaData)
+{
+}
+
+bool QDirPrivate::exists() const
+{
+ if (fileEngine.isNull()) {
+ QFileSystemEngine::fillMetaData(dirEntry, metaData,
+ QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat
+ return metaData.exists() && metaData.isDirectory();
+ }
+ const QAbstractFileEngine::FileFlags info =
+ fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
+ | QAbstractFileEngine::ExistsFlag
+ | QAbstractFileEngine::Refresh);
+ if (!(info & QAbstractFileEngine::DirectoryType))
+ return false;
+ return info & 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(' '));
+ return sep;
+}
+
+// static
+inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar sep)
+{
+ if (sep == 0)
+ sep = getFilterSepChar(nameFilter);
+ QStringList ret = nameFilter.split(sep);
+ for (int i = 0; i < ret.count(); ++i)
+ ret[i] = ret[i].trimmed();
+ return ret;
+}
+
+inline void QDirPrivate::setPath(const QString &path)
+{
+ QString p = QDir::fromNativeSeparators(path);
+ if (p.endsWith(QLatin1Char('/'))
+ && p.length() > 1
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ && (!(p.length() == 3 && p.at(1).unicode() == ':' && p.at(0).isLetter()))
+#endif
+ ) {
+ p.truncate(p.length() - 1);
+ }
+
+ dirEntry = QFileSystemEntry(p, QFileSystemEntry::FromInternalPath());
+ metaData.clear();
+ initFileEngine();
+ clearFileLists();
+ absoluteDirEntry = QFileSystemEntry();
+}
+
+inline void QDirPrivate::clearFileLists()
+{
+ fileListsInitialized = false;
+ files.clear();
+ fileInfos.clear();
+}
+
+inline void QDirPrivate::resolveAbsoluteEntry() const
+{
+ if (!absoluteDirEntry.isEmpty() || dirEntry.isEmpty())
+ return;
+
+ QString absoluteName;
+ if (fileEngine.isNull()) {
+ if (!dirEntry.isRelative()) {
+ absoluteDirEntry = dirEntry;
+ return;
+ }
+
+ absoluteName = QFileSystemEngine::absoluteName(dirEntry).filePath();
+ } else {
+ absoluteName = fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
+ }
+
+ absoluteDirEntry = QFileSystemEntry(QDir::cleanPath(absoluteName), QFileSystemEntry::FromInternalPath());
+}
+
+/* For sorting */
+struct QDirSortItem
+{
+ mutable QString filename_cache;
+ mutable QString suffix_cache;
+ QFileInfo item;
+};
+
+
+class QDirSortItemComparator
+{
+ int qt_cmp_si_sort_flags;
+public:
+ QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
+ bool operator()(const QDirSortItem &, const QDirSortItem &);
+};
+
+bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2)
+{
+ const QDirSortItem* f1 = &n1;
+ const QDirSortItem* f2 = &n2;
+
+ if ((qt_cmp_si_sort_flags & QDir::DirsFirst) && (f1->item.isDir() != f2->item.isDir()))
+ return f1->item.isDir();
+ if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
+ return !f1->item.isDir();
+
+ int r = 0;
+ int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
+ | (qt_cmp_si_sort_flags & QDir::Type);
+
+ switch (sortBy) {
+ case QDir::Time:
+ r = f1->item.lastModified().secsTo(f2->item.lastModified());
+ break;
+ case QDir::Size:
+ r = int(qBound<qint64>(-1, f2->item.size() - f1->item.size(), 1));
+ 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);
+ }
+ break;
+ default:
+ ;
+ }
+
+ 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();
+ if (f2->filename_cache.isNull())
+ f2->filename_cache = ic ? f2->item.fileName().toLower()
+ : 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);
+ }
+ if (r == 0) // Enforce an order - the order the items appear in the array
+ r = (&n1) - (&n2);
+ if (qt_cmp_si_sort_flags & QDir::Reversed)
+ return r > 0;
+ return r < 0;
+}
+
+inline void QDirPrivate::sortFileList(QDir::SortFlags sort, 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());
+ }
+ } else {
+ QScopedArrayPointer<QDirSortItem> si(new QDirSortItem[n]);
+ for (int i = 0; i < n; ++i)
+ si[i].item = l.at(i);
+ qSort(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);
+ }
+ if (names) {
+ for (int i = 0; i < n; ++i)
+ names->append(si[i].item.fileName());
+ }
+ }
+ }
+}
+inline void QDirPrivate::initFileLists(const QDir &dir) const
+{
+ if (!fileListsInitialized) {
+ QFileInfoList l;
+ QDirIterator it(dir);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
+ sortFileList(sort, l, &files, &fileInfos);
+ fileListsInitialized = true;
+ }
+}
+
+inline void QDirPrivate::initFileEngine()
+{
+ fileEngine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData));
+}
+
+/*!
+ \class QDir
+ \brief The QDir class provides access to directory structures and their contents.
+
+ \ingroup io
+ \ingroup shared
+ \reentrant
+
+
+ A QDir is used to manipulate path names, access information
+ regarding paths and files, and manipulate the underlying file
+ system. It can also be used to access Qt's \l{resource system}.
+
+ Qt uses "/" as a universal directory separator in the same way
+ that "/" is used as a path separator in URLs. If you always use
+ "/" as a directory separator, Qt will translate your paths to
+ conform to the underlying operating system.
+
+ A QDir can point to a file using either a relative or an absolute
+ path. Absolute paths begin with the directory separator
+ (optionally preceded by 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.
+
+ Examples of absolute paths:
+
+ \snippet doc/src/snippets/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.
+
+ Examples of relative paths:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 1
+
+ You can use the isRelative() or isAbsolute() functions to check if
+ a QDir is using a relative or an absolute file path. Call
+ makeAbsolute() to convert a relative QDir to an absolute one.
+
+ \section1 Navigation and Directory Operations
+
+ A directory's path can be obtained with the path() function, and
+ a new path set with the setPath() function. The absolute path to
+ a directory is found by calling absolutePath().
+
+ The name of a directory is found using the dirName() function. This
+ typically returns the last element in the absolute path that specifies
+ the location of the directory. However, it can also return "." if
+ the QDir represents the current directory.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 2
+
+ The path for a directory can also be changed with the cd() and cdUp()
+ functions, both of which operate like familiar shell commands.
+ When cd() is called with the name of an existing directory, the QDir
+ object changes directory so that it represents that directory instead.
+ The cdUp() function changes the directory of the QDir object so that
+ it refers to its parent directory; i.e. cd("..") is equivalent to
+ cdUp().
+
+ Directories can be created with mkdir(), renamed with rename(), and
+ removed with rmdir().
+
+ You can test for the presence of a directory with a given name by
+ using exists(), and the properties of a directory can be tested with
+ isReadable(), isAbsolute(), isRelative(), and isRoot().
+
+ The refresh() function re-reads the directory's data from disk.
+
+ \section1 Files and Directory Contents
+
+ Directories contain a number of entries, representing files,
+ directories, and symbolic links. The number of entries in a
+ directory is returned by count().
+ A string list of the names of all the entries in a directory can be
+ obtained with entryList(). If you need information about each
+ entry, use entryInfoList() to obtain a list of QFileInfo objects.
+
+ Paths to files and directories within a directory can be
+ constructed using filePath() and absoluteFilePath().
+ The filePath() function returns a path to the specified file
+ or directory relative to the path of the QDir object;
+ absoluteFilePath() returns an absolute path to the specified
+ file or directory. Neither of these functions checks for the
+ existence of files or directory; they only construct paths.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 3
+
+ Files can be removed by using the remove() function. Directories
+ cannot be removed in the same way as files; use rmdir() to remove
+ them instead.
+
+ It is possible to reduce the number of entries returned by
+ entryList() and entryInfoList() by applying filters to a QDir object.
+ You can apply a name filter to specify a pattern with wildcards that
+ file names need to match, an attribute filter that selects properties
+ of entries and can distinguish between files and directories, and a
+ sort order.
+
+ Name filters are lists of strings that are passed to setNameFilters().
+ Attribute filters consist of a bitwise OR combination of Filters, and
+ these are specified when calling setFilter().
+ The sort order is specified using setSorting() with a bitwise OR
+ combination of SortFlags.
+
+ You can test to see if a filename matches a filter using the match()
+ function.
+
+ Filter and sort order flags may also be specified when calling
+ entryList() and entryInfoList() in order to override previously defined
+ behavior.
+
+ \section1 The Current Directory and Other Special Paths
+
+ Access to some common directories is provided with a number of static
+ functions that return QDir objects. There are also corresponding functions
+ for these that return strings:
+
+ \table
+ \header \o QDir \o QString \o Return Value
+ \row \o current() \o currentPath() \o The application's working directory
+ \row \o home() \o homePath() \o The user's home directory
+ \row \o root() \o rootPath() \o The root directory
+ \row \o temp() \o tempPath() \o The system's temporary directory
+ \endtable
+
+ The setCurrent() static function can also be used to set the application's
+ working directory.
+
+ If you want to find the directory containing the application's executable,
+ see \l{QCoreApplication::applicationDirPath()}.
+
+ The drives() static function provides a list of root directories for each
+ device that contains a filing system. On Unix systems this returns a list
+ containing a single root directory "/"; on Windows the list will usually
+ contain \c{C:/}, and possibly other drive letters such as \c{D:/}, depending
+ on the configuration of the user's system.
+
+ \section1 Path Manipulation and Strings
+
+ Paths containing "." elements that reference the current directory at that
+ point in the path, ".." elements that reference the parent directory, and
+ symbolic links can be reduced to a canonical form using the canonicalPath()
+ function.
+
+ Paths can also be simplified by using cleanPath() to remove redundant "/"
+ and ".." elements.
+
+ It is sometimes necessary to be able to show a path in the native
+ representation for the user's platform. The static toNativeSeparators()
+ function returns a copy of the specified path in which each directory
+ separator is replaced by the appropriate separator for the underlying
+ operating system.
+
+ \section1 Examples
+
+ Check if a directory exists:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 4
+
+ (We could also use the static convenience function
+ QFile::exists().)
+
+ Traversing directories and reading a file:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 5
+
+ A program that lists all the files in the current directory
+ (excluding symbolic links), sorted by size, smallest first:
+
+ \snippet doc/src/snippets/qdir-listfiles/main.cpp 0
+
+ \sa QFileInfo, QFile, QFileDialog, QApplication::applicationDirPath(), {Find Files Example}
+*/
+
+/*!
+ Constructs a QDir pointing to the given directory \a path. If path
+ is empty the program's working directory, ("."), is used.
+
+ \sa currentPath()
+*/
+QDir::QDir(const QString &path) : d_ptr(new QDirPrivate(path))
+{
+}
+
+/*!
+ Constructs a QDir with path \a path, that filters its entries by
+ name using \a nameFilter and by attributes using \a filters. It
+ also sorts the names using \a sort.
+
+ The default \a nameFilter is an empty string, which excludes
+ nothing; the default \a filters is \l AllEntries, which also means
+ exclude nothing. The default \a sort is \l Name | \l IgnoreCase,
+ i.e. sort by name case-insensitively.
+
+ If \a path is an empty string, QDir uses "." (the current
+ directory). If \a nameFilter is an empty string, QDir uses the
+ name filter "*" (all files).
+
+ Note that \a path need not exist.
+
+ \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting()
+*/
+QDir::QDir(const QString &path, const QString &nameFilter,
+ SortFlags sort, Filters filters)
+ : d_ptr(new QDirPrivate(path, QDir::nameFiltersFromString(nameFilter), sort, filters))
+{
+}
+
+/*!
+ Constructs a QDir object that is a copy of the QDir object for
+ directory \a dir.
+
+ \sa operator=()
+*/
+QDir::QDir(const QDir &dir)
+ : d_ptr(dir.d_ptr)
+{
+}
+
+/*!
+ Destroys the QDir object frees up its resources. This has no
+ effect on the underlying directory in the file system.
+*/
+QDir::~QDir()
+{
+}
+
+/*!
+ Sets the path of the directory to \a path. The path is cleaned of
+ redundant ".", ".." and of multiple separators. No check is made
+ to see whether a directory with this path actually exists; but you
+ can check for yourself using exists().
+
+ The path can be either absolute or relative. Absolute paths begin
+ with the directory separator "/" (optionally preceded by 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. An example of an absolute path is the string
+ "/tmp/quartz", a relative path might look like "src/fatlib".
+
+ \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
+ absoluteFilePath(), isRelative(), makeAbsolute()
+*/
+void QDir::setPath(const QString &path)
+{
+ d_ptr->setPath(path);
+}
+
+/*!
+ Returns the path. This may contain symbolic links, but never
+ contains redundant ".", ".." or multiple separators.
+
+ The returned path can be either absolute or relative (see
+ setPath()).
+
+ \sa setPath(), absolutePath(), exists(), cleanPath(), dirName(),
+ absoluteFilePath(), toNativeSeparators(), makeAbsolute()
+*/
+QString QDir::path() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->dirEntry.filePath();
+}
+
+/*!
+ Returns the absolute path (a path that starts with "/" or with a
+ drive specification), which may contain symbolic links, but never
+ contains redundant ".", ".." or multiple separators.
+
+ \sa setPath(), canonicalPath(), exists(), cleanPath(),
+ dirName(), absoluteFilePath()
+*/
+QString QDir::absolutePath() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ d->resolveAbsoluteEntry();
+ return d->absoluteDirEntry.filePath();
+}
+
+/*!
+ Returns the canonical path, i.e. a path without symbolic links or
+ redundant "." or ".." elements.
+
+ On systems that do not have symbolic links this function will
+ always return the same string that absolutePath() returns. If the
+ canonical path does not exist (normally due to dangling symbolic
+ links) canonicalPath() returns an empty string.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 6
+
+ \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
+ absoluteFilePath()
+*/
+QString QDir::canonicalPath() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ if (d->fileEngine.isNull()) {
+ QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData);
+ return answer.filePath();
+ }
+ return d->fileEngine->fileName(QAbstractFileEngine::CanonicalName);
+}
+
+/*!
+ Returns the name of the directory; this is \e not the same as the
+ path, e.g. a directory with the name "mail", might have the path
+ "/var/spool/mail". If the directory has no name (e.g. it is the
+ root directory) an empty string is returned.
+
+ No check is made to ensure that a directory with this name
+ actually exists; but see exists().
+
+ \sa path(), filePath(), absolutePath(), absoluteFilePath()
+*/
+QString QDir::dirName() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->dirEntry.fileName();
+}
+
+/*!
+ Returns the path name of a file in the directory. Does \e not
+ check if the file actually exists in the directory; but see
+ exists(). If the QDir is relative the returned path name will also
+ be relative. Redundant multiple separators or "." and ".."
+ directories in \a fileName are not removed (see cleanPath()).
+
+ \sa dirName() absoluteFilePath(), isRelative(), canonicalPath()
+*/
+QString QDir::filePath(const QString &fileName) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ if (isAbsolutePath(fileName))
+ return QString(fileName);
+
+ QString ret = d->dirEntry.filePath();
+ if (!fileName.isEmpty()) {
+ if (!ret.isEmpty() && ret[(int)ret.length()-1] != QLatin1Char('/') && fileName[0] != QLatin1Char('/'))
+ ret += QLatin1Char('/');
+ ret += fileName;
+ }
+ return ret;
+}
+
+/*!
+ Returns the absolute path name of a file in the directory. Does \e
+ not check if the file actually exists in the directory; but see
+ exists(). Redundant multiple separators or "." and ".."
+ directories in \a fileName are not removed (see cleanPath()).
+
+ \sa relativeFilePath() filePath() canonicalPath()
+*/
+QString QDir::absoluteFilePath(const QString &fileName) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ if (isAbsolutePath(fileName))
+ return fileName;
+
+ d->resolveAbsoluteEntry();
+ if (fileName.isEmpty())
+ return d->absoluteDirEntry.filePath();
+ if (!d->absoluteDirEntry.isRoot())
+ return d->absoluteDirEntry.filePath() % QLatin1Char('/') % fileName;
+ return d->absoluteDirEntry.filePath() % fileName;
+}
+
+/*!
+ Returns the path to \a fileName relative to the directory.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 7
+
+ \sa absoluteFilePath() filePath() canonicalPath()
+*/
+QString QDir::relativeFilePath(const QString &fileName) const
+{
+ QString dir = cleanPath(absolutePath());
+ QString file = cleanPath(fileName);
+
+ if (isRelativePath(file) || isRelativePath(dir))
+ return file;
+
+ QString dirDrive = driveSpec(dir);
+ QString fileDrive = driveSpec(file);
+
+ bool fileDriveMissing = false;
+ if (fileDrive.isEmpty()) {
+ fileDrive = dirDrive;
+ fileDriveMissing = true;
+ }
+
+#ifdef Q_OS_WIN
+ if (fileDrive.toLower() != dirDrive.toLower()
+ || (file.startsWith(QLatin1String("//"))
+ && !dir.startsWith(QLatin1String("//"))))
+#elif defined(Q_OS_SYMBIAN)
+ if (fileDrive.toLower() != dirDrive.toLower())
+#else
+ if (fileDrive != dirDrive)
+#endif
+ return file;
+
+ dir.remove(0, dirDrive.size());
+ if (!fileDriveMissing)
+ file.remove(0, fileDrive.size());
+
+ QString result;
+ QStringList dirElts = dir.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ QStringList fileElts = file.split(QLatin1Char('/'), QString::SkipEmptyParts);
+
+ int i = 0;
+ while (i < dirElts.size() && i < fileElts.size() &&
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ dirElts.at(i).toLower() == fileElts.at(i).toLower())
+#else
+ dirElts.at(i) == fileElts.at(i))
+#endif
+ ++i;
+
+ for (int j = 0; j < dirElts.size() - i; ++j)
+ result += QLatin1String("../");
+
+ for (int j = i; j < fileElts.size(); ++j) {
+ result += fileElts.at(j);
+ if (j < fileElts.size() - 1)
+ result += QLatin1Char('/');
+ }
+
+ return result;
+}
+
+#ifndef QT_NO_DEPRECATED
+/*!
+ \obsolete
+
+ Use QDir::toNativeSeparators() instead.
+*/
+QString QDir::convertSeparators(const QString &pathName)
+{
+ return toNativeSeparators(pathName);
+}
+#endif
+
+/*!
+ \since 4.2
+
+ Returns \a pathName with the '/' separators converted to
+ separators that are appropriate for the underlying operating
+ system.
+
+ On Windows, toNativeSeparators("c:/winnt/system32") returns
+ "c:\\winnt\\system32".
+
+ The returned string may be the same as the argument on some
+ operating systems, for example on Unix.
+
+ \sa fromNativeSeparators(), separator()
+*/
+QString QDir::toNativeSeparators(const QString &pathName)
+{
+ QString n(pathName);
+#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
+ for (int i = 0; i < (int)n.length(); ++i) {
+ if (n[i] == QLatin1Char('/'))
+ n[i] = QLatin1Char('\\');
+ }
+#endif
+ return n;
+}
+
+/*!
+ \since 4.2
+
+ Returns \a pathName using '/' as file separator. On Windows,
+ for instance, fromNativeSeparators("\c{c:\\winnt\\system32}") returns
+ "c:/winnt/system32".
+
+ The returned string may be the same as the argument on some
+ operating systems, for example on Unix.
+
+ \sa toNativeSeparators(), separator()
+*/
+QString QDir::fromNativeSeparators(const QString &pathName)
+{
+ QString n(pathName);
+#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
+ for (int i = 0; i < (int)n.length(); ++i) {
+ if (n[i] == QLatin1Char('\\'))
+ n[i] = QLatin1Char('/');
+ }
+#endif
+ return n;
+}
+
+/*!
+ Changes the QDir's directory to \a dirName.
+
+ Returns true if the new directory exists and is readable;
+ otherwise returns false. Note that the logical cd() operation is
+ not performed if the new directory does not exist.
+
+ Calling cd("..") is equivalent to calling cdUp().
+
+ \sa cdUp(), isReadable(), exists(), path()
+*/
+bool QDir::cd(const QString &dirName)
+{
+ // Don't detach just yet.
+ const QDirPrivate * const d = d_ptr.constData();
+
+ if (dirName.isEmpty() || dirName == QLatin1String("."))
+ return true;
+ QString newPath;
+ if (isAbsolutePath(dirName)) {
+ newPath = cleanPath(dirName);
+ } else {
+ if (isRoot()) {
+ if (dirName == QLatin1String(".."))
+ return false;
+ newPath = d->dirEntry.filePath();
+ } else {
+ newPath = d->dirEntry.filePath() % QLatin1Char('/');
+ }
+
+ newPath += dirName;
+ if (dirName.indexOf(QLatin1Char('/')) >= 0
+ || dirName == QLatin1String("..")
+ || d->dirEntry.filePath() == QLatin1String(".")) {
+ newPath = cleanPath(newPath);
+ /*
+ If newPath starts with .., we convert it to absolute to
+ avoid infinite looping on
+
+ QDir dir(".");
+ while (dir.cdUp())
+ ;
+ */
+ if (newPath.startsWith(QLatin1String(".."))) {
+ newPath = QFileInfo(newPath).absoluteFilePath();
+ }
+ }
+ }
+
+ QScopedPointer<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData()));
+ dir->setPath(newPath);
+ if (!dir->exists())
+ return false;
+
+ d_ptr = dir.take();
+ return true;
+}
+
+/*!
+ Changes directory by moving one directory up from the QDir's
+ current directory.
+
+ Returns true if the new directory exists and is readable;
+ otherwise returns false. Note that the logical cdUp() operation is
+ not performed if the new directory does not exist.
+
+ \sa cd(), isReadable(), exists(), path()
+*/
+bool QDir::cdUp()
+{
+ return cd(QString::fromLatin1(".."));
+}
+
+/*!
+ Returns the string list set by setNameFilters()
+*/
+QStringList QDir::nameFilters() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->nameFilters;
+}
+
+/*!
+ Sets the name filters used by entryList() and entryInfoList() to the
+ list of filters specified by \a nameFilters.
+
+ Each name filter is a wildcard (globbing) filter that understands
+ \c{*} and \c{?} wildcards. (See \l{QRegExp wildcard matching}.)
+
+ For example, the following code sets three name filters on a QDir
+ to ensure that only files with extensions typically used for C++
+ source files are listed:
+
+ \snippet doc/src/snippets/qdir-namefilters/main.cpp 0
+
+ \sa nameFilters(), setFilter()
+*/
+void QDir::setNameFilters(const QStringList &nameFilters)
+{
+ QDirPrivate* d = d_ptr.data();
+ d->initFileEngine();
+ d->clearFileLists();
+
+ d->nameFilters = nameFilters;
+}
+
+/*!
+ \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 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
+ QResource::addSearchPath(path);
+#else
+ Q_UNUSED(path)
+#endif
+}
+
+#ifdef QT_BUILD_CORE_LIB
+/*!
+ \since 4.3
+
+ Sets or replaces Qt's search paths for file names with the prefix \a prefix
+ to \a searchPaths.
+
+ To specify a prefix for a file name, prepend the prefix followed by a single
+ colon (e.g., "images:undo.png", "xmldocs:books.xml"). \a prefix can only
+ contain letters or numbers (e.g., it cannot contain a colon, nor a slash).
+
+ Qt uses this search path to locate files with a known prefix. The search
+ path entries are tested in order, starting with the first entry.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 8
+
+ File name prefix must be at least 2 characters long to avoid conflicts with
+ Windows drive letters.
+
+ Search paths may contain paths to \l{The Qt Resource System}.
+*/
+void QDir::setSearchPaths(const QString &prefix, const QStringList &searchPaths)
+{
+ if (prefix.length() < 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()) {
+ qWarning("QDir::setSearchPaths: Prefix can only contain letters or numbers");
+ return;
+ }
+ }
+
+ QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
+ QMap<QString, QStringList> &paths = QCoreGlobalData::instance()->dirSearchPaths;
+ if (searchPaths.isEmpty()) {
+ paths.remove(prefix);
+ } else {
+ paths.insert(prefix, searchPaths);
+ }
+}
+
+/*!
+ \since 4.3
+
+ Adds \a path to the search path for \a prefix.
+
+ \sa setSearchPaths()
+*/
+void QDir::addSearchPath(const QString &prefix, const QString &path)
+{
+ if (path.isEmpty())
+ return;
+
+ QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
+ QCoreGlobalData::instance()->dirSearchPaths[prefix] += path;
+}
+
+/*!
+ \since 4.3
+
+ Returns the search paths for \a prefix.
+
+ \sa setSearchPaths(), addSearchPath()
+*/
+QStringList QDir::searchPaths(const QString &prefix)
+{
+ QReadLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
+ return QCoreGlobalData::instance()->dirSearchPaths.value(prefix);
+}
+
+#endif // QT_BUILD_CORE_LIB
+
+/*!
+ Returns the value set by setFilter()
+*/
+QDir::Filters QDir::filter() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->filters;
+}
+
+/*!
+ \enum QDir::Filter
+
+ This enum describes the filtering options available to QDir; e.g.
+ for entryList() and entryInfoList(). The filter value is specified
+ by combining values from the following list using the bitwise OR
+ operator:
+
+ \value Dirs List directories that match the filters.
+ \value AllDirs List all directories; i.e. don't apply the filters
+ to directory names.
+ \value Files List files.
+ \value Drives List disk drives (ignored under Unix).
+ \value NoSymLinks Do not list symbolic links (ignored by operating
+ systems that don't support symbolic links).
+ \value NoDotAndDotDot Do not list the special entries "." and "..".
+ \value NoDot Do not list the special entry ".".
+ \value NoDotDot Do not list the special entry "..".
+ \value AllEntries List directories, files, drives and symlinks (this does not list
+ broken symlinks unless you specify System).
+ \value Readable List files for which the application has read
+ access. The Readable value needs to be combined
+ with Dirs or Files.
+ \value Writable List files for which the application has write
+ access. The Writable value needs to be combined
+ with Dirs or Files.
+ \value Executable List files for which the application has
+ execute access. The Executable value needs to be
+ combined with Dirs or Files.
+ \value Modified Only list files that have been modified (ignored
+ on Unix).
+ \value Hidden List hidden files (on Unix, files starting with a ".").
+ \value System List system files (on Unix, FIFOs, sockets and
+ device files are included; on Windows, \c {.lnk}
+ files are included)
+ \value CaseSensitive The filter should be case sensitive.
+
+ \omitvalue DefaultFilter
+ \omitvalue TypeMask
+ \omitvalue All
+ \omitvalue RWEMask
+ \omitvalue AccessMask
+ \omitvalue PermissionMask
+ \omitvalue NoFilter
+
+ Functions that use Filter enum values to filter lists of files
+ and directories will include symbolic links to files and directories
+ unless you set the NoSymLinks value.
+
+ A default constructed QDir will not filter out files based on
+ their permissions, so entryList() and entryInfoList() will return
+ all files that are readable, writable, executable, or any
+ combination of the three. This makes the default easy to write,
+ and at the same time useful.
+
+ For example, setting the \c Readable, \c Writable, and \c Files
+ flags allows all files to be listed for which the application has read
+ access, write access or both. If the \c Dirs and \c Drives flags are
+ also included in this combination then all drives, directories, all
+ 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
+ entryInfoList() function to get the associated QFileInfo objects
+ and then use the QFileInfo::permissons() to obtain the permissions
+ and ownership for each file.
+*/
+
+/*!
+ Sets the filter used by entryList() and entryInfoList() to \a
+ filters. The filter is used to specify the kind of files that
+ should be returned by entryList() and entryInfoList(). See
+ \l{QDir::Filter}.
+
+ \sa filter(), setNameFilters()
+*/
+void QDir::setFilter(Filters filters)
+{
+ QDirPrivate* d = d_ptr.data();
+ d->initFileEngine();
+ d->clearFileLists();
+
+ d->filters = filters;
+}
+
+/*!
+ Returns the value set by setSorting()
+
+ \sa setSorting() SortFlag
+*/
+QDir::SortFlags QDir::sorting() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->sort;
+}
+
+/*!
+ \enum QDir::SortFlag
+
+ This enum describes the sort options available to QDir, e.g. for
+ entryList() and entryInfoList(). The sort value is specified by
+ OR-ing together values from the following list:
+
+ \value Name Sort by name.
+ \value Time Sort by time (modification time).
+ \value Size Sort by file size.
+ \value Type Sort by file type (extension).
+ \value Unsorted Do not sort.
+ \value NoSort Not sorted by default.
+
+ \value DirsFirst Put the directories first, then the files.
+ \value DirsLast Put the files first, then the directories.
+ \value Reversed Reverse the sort order.
+ \value IgnoreCase Sort case-insensitively.
+ \value LocaleAware Sort items appropriately using the current locale settings.
+
+ \omitvalue SortByMask
+ \omitvalue DefaultSort
+
+ You can only specify one of the first four.
+
+ If you specify both DirsFirst and Reversed, directories are
+ still put first, but in reverse order; the files will be listed
+ after the directories, again in reverse order.
+*/
+
+/*!
+ Sets the sort order used by entryList() and entryInfoList().
+
+ The \a sort is specified by OR-ing values from the enum
+ \l{QDir::SortFlag}.
+
+ \sa sorting() SortFlag
+*/
+void QDir::setSorting(SortFlags sort)
+{
+ QDirPrivate* d = d_ptr.data();
+ d->initFileEngine();
+ d->clearFileLists();
+
+ d->sort = sort;
+}
+
+/*!
+ Returns the total number of directories and files in the directory.
+
+ Equivalent to entryList().count().
+
+ \sa operator[](), entryList()
+*/
+uint QDir::count() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ d->initFileLists(*this);
+ return d->files.count();
+}
+
+/*!
+ Returns the file name at position \a pos in the list of file
+ names. Equivalent to entryList().at(index).
+ \a pos must be a valid index position in the list (i.e., 0 <= pos < count()).
+
+ \sa count(), entryList()
+*/
+QString QDir::operator[](int pos) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ d->initFileLists(*this);
+ return d->files[pos];
+}
+
+/*!
+ \overload
+
+ Returns a list of the names of all the files and directories in
+ the directory, ordered according to the name and attribute filters
+ previously set with setNameFilters() and setFilter(), and sorted according
+ to the flags set with setSorting().
+
+ The attribute filter and sorting specifications can be overridden using the
+ \a filters and \a sort arguments.
+
+ Returns an empty list if the directory is unreadable, does not
+ exist, or if nothing matches the specification.
+
+ \note To list symlinks that point to non existing files, \l System must be
+ passed to the filter.
+
+ \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
+*/
+QStringList QDir::entryList(Filters filters, SortFlags sort) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return entryList(d->nameFilters, filters, sort);
+}
+
+
+/*!
+ \overload
+
+ Returns a list of QFileInfo objects for all the files and directories in
+ the directory, ordered according to the name and attribute filters
+ previously set with setNameFilters() and setFilter(), and sorted according
+ to the flags set with setSorting().
+
+ The attribute filter and sorting specifications can be overridden using the
+ \a filters and \a sort arguments.
+
+ Returns an empty list if the directory is unreadable, does not
+ exist, or if nothing matches the specification.
+
+ \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
+*/
+QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return entryInfoList(d->nameFilters, filters, sort);
+}
+
+/*!
+ Returns a list of the names of all the files and
+ directories in the directory, ordered according to the name
+ and attribute filters previously set with setNameFilters()
+ and setFilter(), and sorted according to the flags set with
+ setSorting().
+
+ The name filter, file attribute filter, and sorting specification
+ can be overridden using the \a nameFilters, \a filters, and \a sort
+ arguments.
+
+ Returns an empty list if the directory is unreadable, does not
+ exist, or if nothing matches the specification.
+
+ \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
+*/
+QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
+ SortFlags sort) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (filters == NoFilter)
+ filters = d->filters;
+#ifdef QT3_SUPPORT
+ if (d->matchAllDirs)
+ filters |= AllDirs;
+#endif
+ if (sort == NoSort)
+ sort = d->sort;
+
+ if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
+ d->initFileLists(*this);
+ return d->files;
+ }
+
+ QFileInfoList l;
+ QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
+ QStringList ret;
+ d->sortFileList(sort, l, &ret, 0);
+ return ret;
+}
+
+/*!
+ Returns a list of QFileInfo objects for all the files and
+ directories in the directory, ordered according to the name
+ and attribute filters previously set with setNameFilters()
+ and setFilter(), and sorted according to the flags set with
+ setSorting().
+
+ The name filter, file attribute filter, and sorting specification
+ can be overridden using the \a nameFilters, \a filters, and \a sort
+ arguments.
+
+ Returns an empty list if the directory is unreadable, does not
+ exist, or if nothing matches the specification.
+
+ \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
+*/
+QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filters,
+ SortFlags sort) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (filters == NoFilter)
+ filters = d->filters;
+#ifdef QT3_SUPPORT
+ if (d->matchAllDirs)
+ filters |= AllDirs;
+#endif
+ if (sort == NoSort)
+ sort = d->sort;
+
+ if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
+ d->initFileLists(*this);
+ return d->fileInfos;
+ }
+
+ QFileInfoList l;
+ QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
+ QFileInfoList ret;
+ d->sortFileList(sort, l, 0, &ret);
+ return ret;
+}
+
+/*!
+ Creates a sub-directory called \a dirName.
+
+ Returns true on success; otherwise returns false.
+
+ If the directory already exists when this function is called, it will return false.
+
+ \sa rmdir()
+*/
+// ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath
+bool QDir::mkdir(const QString &dirName) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (dirName.isEmpty()) {
+ qWarning("QDir::mkdir: Empty or null file name(s)");
+ return false;
+ }
+
+ QString fn = filePath(dirName);
+ if (d->fileEngine.isNull())
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false);
+ return d->fileEngine->mkdir(fn, false);
+}
+
+/*!
+ Removes the directory specified by \a dirName.
+
+ The directory must be empty for rmdir() to succeed.
+
+ Returns true if successful; otherwise returns false.
+
+ \sa mkdir()
+*/
+bool QDir::rmdir(const QString &dirName) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (dirName.isEmpty()) {
+ qWarning("QDir::rmdir: Empty or null file name(s)");
+ return false;
+ }
+
+ QString fn = filePath(dirName);
+ if (d->fileEngine.isNull())
+ return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false);
+
+ return d->fileEngine->rmdir(fn, false);
+}
+
+/*!
+ Creates the directory path \a dirPath.
+
+ The function will create all parent directories necessary to
+ create the directory.
+
+ Returns true if successful; otherwise returns false.
+
+ If the path already exists when this function is called, it will return true.
+
+ \sa rmpath()
+*/
+// ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath
+bool QDir::mkpath(const QString &dirPath) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (dirPath.isEmpty()) {
+ qWarning("QDir::mkpath: Empty or null file name(s)");
+ return false;
+ }
+
+ QString fn = filePath(dirPath);
+ if (d->fileEngine.isNull())
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), true);
+ return d->fileEngine->mkdir(fn, true);
+}
+
+/*!
+ Removes the directory path \a dirPath.
+
+ The function will remove all parent directories in \a dirPath,
+ provided that they are empty. This is the opposite of
+ mkpath(dirPath).
+
+ Returns true if successful; otherwise returns false.
+
+ \sa mkpath()
+*/
+bool QDir::rmpath(const QString &dirPath) const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (dirPath.isEmpty()) {
+ qWarning("QDir::rmpath: Empty or null file name(s)");
+ return false;
+ }
+
+ QString fn = filePath(dirPath);
+ if (d->fileEngine.isNull())
+ return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true);
+ return d->fileEngine->rmdir(fn, true);
+}
+
+/*!
+ Returns true if the directory is readable \e and we can open files
+ by name; otherwise returns false.
+
+ \warning A false value from this function is not a guarantee that
+ files in the directory are not accessible.
+
+ \sa QFileInfo::isReadable()
+*/
+bool QDir::isReadable() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+
+ if (d->fileEngine.isNull()) {
+ if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission))
+ QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission);
+
+ return (d->metaData.permissions() & QFile::ReadUser) != 0;
+ }
+
+ const QAbstractFileEngine::FileFlags info =
+ d->fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
+ | QAbstractFileEngine::PermsMask);
+ if (!(info & QAbstractFileEngine::DirectoryType))
+ return false;
+ return info & QAbstractFileEngine::ReadUserPerm;
+}
+
+/*!
+ \overload
+
+ Returns true if the directory exists; otherwise returns false.
+ (If a file with the same name is found this function will return false).
+
+ The overload of this function that accepts an argument is used to test
+ for the presence of files and directories within a directory.
+
+ \sa QFileInfo::exists(), QFile::exists()
+*/
+bool QDir::exists() const
+{
+ return d_ptr->exists();
+}
+
+/*!
+ Returns true if the directory is the root directory; otherwise
+ returns false.
+
+ Note: If the directory is a symbolic link to the root directory
+ this function returns false. If you want to test for this use
+ canonicalPath(), e.g.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 9
+
+ \sa root(), rootPath()
+*/
+bool QDir::isRoot() const
+{
+ if (d_ptr->fileEngine.isNull())
+ return d_ptr->dirEntry.isRoot();
+ return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag;
+}
+
+/*!
+ \fn bool QDir::isAbsolute() const
+
+ Returns true if the directory's path is absolute; otherwise
+ returns false. See isAbsolutePath().
+
+ \sa isRelative() makeAbsolute() cleanPath()
+*/
+
+/*!
+ \fn bool QDir::isAbsolutePath(const QString &)
+
+ Returns true if \a path is absolute; returns false if it is
+ relative.
+
+ \sa isAbsolute() isRelativePath() makeAbsolute() cleanPath()
+*/
+
+/*!
+ Returns true if the directory path is relative; otherwise returns
+ false. (Under Unix a path is relative if it does not start with a
+ "/").
+
+ \sa makeAbsolute() isAbsolute() isAbsolutePath() cleanPath()
+*/
+bool QDir::isRelative() const
+{
+ if (d_ptr->fileEngine.isNull())
+ return d_ptr->dirEntry.isRelative();
+ return d_ptr->fileEngine->isRelativePath();
+}
+
+
+/*!
+ Converts the directory path to an absolute path. If it is already
+ absolute nothing happens. Returns true if the conversion
+ succeeded; otherwise returns false.
+
+ \sa isAbsolute() isAbsolutePath() isRelative() cleanPath()
+*/
+bool QDir::makeAbsolute()
+{
+ const QDirPrivate *d = d_ptr.constData();
+ QScopedPointer<QDirPrivate> dir;
+ if (!d->fileEngine.isNull()) {
+ QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
+ if (QDir::isRelativePath(absolutePath))
+ return false;
+
+ dir.reset(new QDirPrivate(*d_ptr.constData()));
+ dir->setPath(absolutePath);
+ } else { // native FS
+ d->resolveAbsoluteEntry();
+ dir.reset(new QDirPrivate(*d_ptr.constData()));
+ dir->setPath(d->absoluteDirEntry.filePath());
+ }
+ d_ptr = dir.take(); // actually detach
+ return true;
+}
+
+/*!
+ Returns true if directory \a dir and this directory have the same
+ path and their sort and filter settings are the same; otherwise
+ returns false.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 10
+*/
+bool QDir::operator==(const QDir &dir) const
+{
+ const QDirPrivate *d = d_ptr.constData();
+ const QDirPrivate *other = dir.d_ptr.constData();
+
+ if (d == other)
+ return true;
+ Qt::CaseSensitivity sensitive;
+ if (d->fileEngine.isNull() || other->fileEngine.isNull()) {
+ if (d->fileEngine.data() != other->fileEngine.data()) // one is native, the other is a custom file-engine
+ return false;
+
+ sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ } else {
+ if (d->fileEngine->caseSensitive() != other->fileEngine->caseSensitive())
+ return false;
+ sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ }
+
+ if (d->filters == other->filters
+ && d->sort == other->sort
+ && d->nameFilters == other->nameFilters) {
+ d->resolveAbsoluteEntry();
+ other->resolveAbsoluteEntry();
+ return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0;
+ }
+ return false;
+}
+
+/*!
+ Makes a copy of the \a dir object and assigns it to this QDir
+ object.
+*/
+QDir &QDir::operator=(const QDir &dir)
+{
+ d_ptr = dir.d_ptr;
+ return *this;
+}
+
+/*!
+ \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;
+}
+
+/*!
+ \fn bool QDir::operator!=(const QDir &dir) const
+
+ Returns true if directory \a dir and this directory have different
+ paths or different sort or filter settings; otherwise returns
+ false.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 11
+*/
+
+/*!
+ Removes the file, \a fileName.
+
+ Returns true if the file is removed successfully; otherwise
+ returns false.
+*/
+bool QDir::remove(const QString &fileName)
+{
+ if (fileName.isEmpty()) {
+ qWarning("QDir::remove: Empty or null file name");
+ return false;
+ }
+ return QFile::remove(filePath(fileName));
+}
+
+/*!
+ Renames a file or directory from \a oldName to \a newName, and returns
+ true if successful; otherwise returns false.
+
+ On most file systems, rename() fails only if \a oldName does not
+ exist, if \a newName and \a oldName are not on the same
+ partition or if a file with the new name already exists.
+ However, there are also other reasons why rename() can
+ fail. For example, on at least one file system rename() fails if
+ \a newName points to an open file.
+*/
+bool QDir::rename(const QString &oldName, const QString &newName)
+{
+ if (oldName.isEmpty() || newName.isEmpty()) {
+ qWarning("QDir::rename: Empty or null file name(s)");
+ return false;
+ }
+
+ QFile file(filePath(oldName));
+ if (!file.exists())
+ return false;
+ return file.rename(filePath(newName));
+}
+
+/*!
+ Returns true if the file called \a name exists; otherwise returns
+ false.
+
+ Unless \a name contains an absolute file path, the file name is assumed
+ to be relative to the directory itself, so this function is typically used
+ to check for the presence of files within a directory.
+
+ \sa QFileInfo::exists(), QFile::exists()
+*/
+bool QDir::exists(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QDir::exists: Empty or null file name");
+ return false;
+ }
+ return QFile::exists(filePath(name));
+}
+
+/*!
+ 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
+ just one root directory (i.e. "/").
+
+ \sa root(), rootPath()
+*/
+QFileInfoList QDir::drives()
+{
+#ifdef QT_NO_FSFILEENGINE
+ return QFileInfoList();
+#else
+ return QFSFileEngine::drives();
+#endif
+}
+
+/*!
+ Returns the native directory separator: "/" under Unix (including
+ Mac OS X) and "\\" under Windows.
+
+ You do not need to use this function to build file paths. If you
+ always use "/", Qt will translate your paths to conform to the
+ underlying operating system. If you want to display paths to the
+ user using their operating system's separator use
+ toNativeSeparators().
+*/
+QChar QDir::separator()
+{
+#if defined (Q_FS_FAT) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
+ return QLatin1Char('\\');
+#elif defined(Q_OS_UNIX)
+ return QLatin1Char('/');
+#elif defined (Q_OS_MAC)
+ return QLatin1Char(':');
+#else
+ return QLatin1Char('/');
+#endif
+}
+
+/*!
+ Sets the application's current working directory to \a path.
+ Returns true if the directory was successfully changed; otherwise
+ returns false.
+
+ \sa current(), currentPath(), home(), root(), temp()
+*/
+bool QDir::setCurrent(const QString &path)
+{
+ return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
+}
+
+/*!
+ \fn QDir QDir::current()
+
+ Returns the application's current directory.
+
+ The directory is constructed using the absolute path of the current directory,
+ ensuring that its path() will be the same as its absolutePath().
+
+ \sa currentPath(), setCurrent(), home(), root(), temp()
+*/
+
+/*!
+ Returns the absolute path of the application's current directory.
+
+ \sa current(), setCurrent(), homePath(), rootPath(), tempPath()
+*/
+QString QDir::currentPath()
+{
+ return QFileSystemEngine::currentPath().filePath();
+}
+
+/*!
+ \fn QString QDir::currentDirPath()
+ Returns the absolute path of the application's current directory.
+
+ Use currentPath() instead.
+
+ \sa currentPath(), setCurrent()
+*/
+
+/*!
+ \fn QDir QDir::home()
+
+ Returns the user's home directory.
+
+ The directory is constructed using the absolute path of the home directory,
+ ensuring that its path() will be the same as its absolutePath().
+
+ See homePath() for details.
+
+ \sa drives(), current(), root(), temp()
+*/
+
+/*!
+ Returns the absolute path of the user's home directory.
+
+ Under Windows this function will return the directory of the
+ current user's profile. Typically, this is:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 12
+
+ Use the toNativeSeparators() function to convert the separators to
+ the ones that are appropriate for the underlying operating system.
+
+ If the directory of the current user's profile does not exist or
+ cannot be retrieved, the following alternatives will be checked (in
+ the given order) until an existing and available path is found:
+
+ \list 1
+ \o The path specified by the \c USERPROFILE environment variable.
+ \o The path formed by concatenating the \c HOMEDRIVE and \c HOMEPATH
+ environment variables.
+ \o The path specified by the \c HOME environment variable.
+ \o The path returned by the rootPath() function (which uses the \c SystemDrive
+ environment variable)
+ \o The \c{C:/} directory.
+ \endlist
+
+ Under non-Windows operating systems the \c HOME environment
+ variable is used if it exists, otherwise the path returned by the
+ rootPath(). On Symbian always the same as the path returned by the rootPath().
+
+ \sa home(), currentPath(), rootPath(), tempPath()
+*/
+QString QDir::homePath()
+{
+ return QFileSystemEngine::homePath();
+}
+
+/*!
+ \fn QString QDir::homeDirPath()
+
+ Returns the absolute path of the user's home directory.
+
+ Use homePath() instead.
+
+ \sa homePath()
+*/
+
+/*!
+ \fn QDir QDir::temp()
+
+ Returns the system's temporary directory.
+
+ The directory is constructed using the absolute path of the temporary directory,
+ ensuring that its path() will be the same as its absolutePath().
+
+ See tempPath() for details.
+
+ \sa drives(), current(), home(), root()
+*/
+
+/*!
+ Returns the absolute path of the system's temporary directory.
+
+ On Unix/Linux systems this is the path in the \c TMPDIR environment
+ variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is
+ usually the path in the \c TEMP or \c TMP environment
+ variable. Whether a directory separator is added to the end or
+ not, depends on the operating system.
+
+ \sa temp(), currentPath(), homePath(), rootPath()
+*/
+QString QDir::tempPath()
+{
+ return QFileSystemEngine::tempPath();
+}
+
+/*!
+ \fn QDir QDir::root()
+
+ Returns the root directory.
+
+ The directory is constructed using the absolute path of the root directory,
+ ensuring that its path() will be the same as its absolutePath().
+
+ See rootPath() for details.
+
+ \sa drives(), current(), home(), temp()
+*/
+
+/*!
+ Returns the absolute path of the root directory.
+
+ For Unix operating systems this returns "/". For Windows file
+ systems this normally returns "c:/". On Symbian this typically returns
+ "c:/data", i.e. the same as native PathInfo::PhoneMemoryRootPath().
+
+ \sa root(), drives(), currentPath(), homePath(), tempPath()
+*/
+QString QDir::rootPath()
+{
+ return QFileSystemEngine::rootPath();
+}
+
+/*!
+ \fn QString QDir::rootDirPath()
+
+ Returns the absolute path of the root directory.
+
+ Use rootPath() instead.
+
+ \sa rootPath()
+*/
+
+#ifndef QT_NO_REGEXP
+/*!
+ \overload
+
+ Returns true if the \a fileName matches any of the wildcard (glob)
+ patterns in the list of \a filters; otherwise returns false. The
+ matching is case insensitive.
+
+ \sa {QRegExp wildcard matching}, QRegExp::exactMatch() entryList() entryInfoList()
+*/
+bool QDir::match(const QStringList &filters, const QString &fileName)
+{
+ for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) {
+ QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard);
+ if (rx.exactMatch(fileName))
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Returns true if the \a fileName matches the wildcard (glob)
+ pattern \a filter; otherwise returns false. The \a filter may
+ contain multiple patterns separated by spaces or semicolons.
+ The matching is case insensitive.
+
+ \sa {QRegExp wildcard matching}, QRegExp::exactMatch() entryList() entryInfoList()
+*/
+bool QDir::match(const QString &filter, const QString &fileName)
+{
+ return match(nameFiltersFromString(filter), fileName);
+}
+#endif // QT_NO_REGEXP
+
+/*!
+ Removes all multiple directory separators "/" and resolves any
+ "."s or ".."s found in the path, \a path.
+
+ Symbolic links are kept. This function does not return the
+ canonical path, but rather the simplest version of the input.
+ For example, "./local" becomes "local", "local/../bin" becomes
+ "bin" and "/local/usr/../bin" becomes "/local/bin".
+
+ \sa absolutePath() canonicalPath()
+*/
+QString QDir::cleanPath(const QString &path)
+{
+ if (path.isEmpty())
+ return path;
+ QString name = path;
+ QChar dir_separator = separator();
+ if (dir_separator != QLatin1Char('/'))
+ name.replace(dir_separator, QLatin1Char('/'));
+
+ int used = 0, levels = 0;
+ const int len = name.length();
+ QVarLengthArray<QChar> outVector(len);
+ QChar *out = outVector.data();
+
+ const QChar *p = name.unicode();
+ for (int i = 0, last = -1, iwrite = 0; i < len; ++i) {
+ if (p[i] == QLatin1Char('/')) {
+ while (i < len-1 && p[i+1] == QLatin1Char('/')) {
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
+ if (!i)
+ break;
+#endif
+ i++;
+ }
+ bool eaten = false;
+ if (i < len - 1 && p[i+1] == QLatin1Char('.')) {
+ int dotcount = 1;
+ if (i < len - 2 && p[i+2] == QLatin1Char('.'))
+ dotcount++;
+ if (i == len - dotcount - 1) {
+ if (dotcount == 1) {
+ break;
+ } else if (levels) {
+ if (last == -1) {
+ for (int i2 = iwrite-1; i2 >= 0; i2--) {
+ if (out[i2] == QLatin1Char('/')) {
+ last = i2;
+ break;
+ }
+ }
+ }
+ used -= iwrite - last - 1;
+ break;
+ }
+ } else if (p[i+dotcount+1] == QLatin1Char('/')) {
+ if (dotcount == 2 && levels) {
+ if (last == -1 || iwrite - last == 1) {
+ for (int i2 = (last == -1) ? (iwrite-1) : (last-1); i2 >= 0; i2--) {
+ if (out[i2] == QLatin1Char('/')) {
+ eaten = true;
+ last = i2;
+ break;
+ }
+ }
+ } else {
+ eaten = true;
+ }
+ if (eaten) {
+ levels--;
+ used -= iwrite - last;
+ iwrite = last;
+ last = -1;
+ }
+ } else if (dotcount == 2 && i > 0 && p[i - 1] != QLatin1Char('.')) {
+ eaten = true;
+ used -= iwrite - qMax(0, last);
+ iwrite = qMax(0, last);
+ last = -1;
+ ++i;
+ } else if (dotcount == 1) {
+ eaten = true;
+ }
+ if (eaten)
+ i += dotcount;
+ } else {
+ levels++;
+ }
+ } else if (last != -1 && iwrite - last == 1) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ eaten = (iwrite > 2);
+#else
+ eaten = true;
+#endif
+ last = -1;
+ } else if (last != -1 && i == len-1) {
+ eaten = true;
+ } else {
+ levels++;
+ }
+ if (!eaten)
+ last = i - (i - iwrite);
+ else
+ continue;
+ } else if (!i && p[i] == QLatin1Char('.')) {
+ int dotcount = 1;
+ if (len >= 1 && p[1] == QLatin1Char('.'))
+ dotcount++;
+ if (len >= dotcount && p[dotcount] == QLatin1Char('/')) {
+ if (dotcount == 1) {
+ i++;
+ while (i+1 < len-1 && p[i+1] == QLatin1Char('/'))
+ i++;
+ continue;
+ }
+ }
+ }
+ out[iwrite++] = p[i];
+ used++;
+ }
+
+ QString ret = (used == len ? name : QString(out, used));
+ // Strip away last slash except for root directories
+ if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
+#if defined (Q_OS_WIN) || defined (Q_OS_SYMBIAN)
+ if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
+#endif
+ ret.chop(1);
+ }
+
+ return ret;
+}
+
+/*!
+ Returns true if \a path is relative; returns false if it is
+ absolute.
+
+ \sa isRelative() isAbsolutePath() makeAbsolute()
+*/
+bool QDir::isRelativePath(const QString &path)
+{
+ return QFileInfo(path).isRelative();
+}
+
+/*!
+ Refreshes the directory information.
+*/
+void QDir::refresh() const
+{
+ QDirPrivate *d = const_cast<QDir*>(this)->d_ptr.data();
+ d->metaData.clear();
+ d->initFileEngine();
+ d->clearFileLists();
+}
+
+/*!
+ \internal
+
+ Returns a list of name filters from the given \a nameFilter. (If
+ there is more than one filter, each pair of filters is separated
+ by a space or by a semicolon.)
+*/
+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, Qt 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_io_qdir.cpp 15
+
+ \sa Q_INIT_RESOURCE(), {The Qt Resource System}
+*/
+
+#ifdef QT3_SUPPORT
+
+/*!
+ \fn bool QDir::matchAllDirs() const
+
+ Use filter() & AllDirs instead.
+*/
+bool QDir::matchAllDirs() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return d->matchAllDirs;
+}
+
+
+/*!
+ \fn void QDir::setMatchAllDirs(bool on)
+
+ Use setFilter() instead.
+*/
+void QDir::setMatchAllDirs(bool on)
+{
+ QDirPrivate* d = d_ptr.data();
+ d->initFileEngine();
+ d->clearFileLists();
+
+ d->matchAllDirs = on;
+}
+
+/*!
+ Use nameFilters() instead.
+*/
+QString QDir::nameFilter() const
+{
+ const QDirPrivate* d = d_ptr.constData();
+ return nameFilters().join(QString(d->filterSepChar));
+}
+
+/*!
+ Use setNameFilters() instead.
+
+ The \a nameFilter is a wildcard (globbing) filter that understands
+ "*" and "?" wildcards. (See \l{QRegExp wildcard matching}.) You may
+ specify several filter entries, each separated by spaces or by
+ semicolons.
+
+ For example, if you want entryList() and entryInfoList() to list
+ all files ending with either ".cpp" or ".h", you would use either
+ dir.setNameFilters("*.cpp *.h") or dir.setNameFilters("*.cpp;*.h").
+
+ \oldcode
+ QString filter = "*.cpp *.cxx *.cc";
+ dir.setNameFilter(filter);
+ \newcode
+ QString filter = "*.cpp *.cxx *.cc";
+ dir.setNameFilters(filter.split(' '));
+ \endcode
+*/
+void QDir::setNameFilter(const QString &nameFilter)
+{
+ QDirPrivate* d = d_ptr.data();
+ d->initFileEngine();
+ d->clearFileLists();
+
+ d->filterSepChar = QDirPrivate::getFilterSepChar(nameFilter);
+ d->nameFilters = QDirPrivate::splitFilters(nameFilter, d->filterSepChar);
+}
+
+/*!
+ \fn QString QDir::absPath() const
+
+ Use absolutePath() instead.
+*/
+
+/*!
+ \fn QString QDir::absFilePath(const QString &fileName, bool acceptAbsPath) const
+
+ Use absoluteFilePath(\a fileName) instead.
+
+ The \a acceptAbsPath parameter is ignored.
+*/
+
+/*!
+ \fn bool QDir::mkdir(const QString &dirName, bool acceptAbsPath) const
+
+ Use mkdir(\a dirName) instead.
+
+ The \a acceptAbsPath parameter is ignored.
+*/
+
+/*!
+ \fn bool QDir::rmdir(const QString &dirName, bool acceptAbsPath) const
+
+ Use rmdir(\a dirName) instead.
+
+ The \a acceptAbsPath parameter is ignored.
+*/
+
+/*!
+ \fn QStringList QDir::entryList(const QString &nameFilter, Filters filters,
+ SortFlags sort) const
+ \overload
+
+ Use the overload that takes a name filter string list as first
+ argument instead of a combination of attribute filter flags.
+*/
+
+/*!
+ \fn QFileInfoList QDir::entryInfoList(const QString &nameFilter, Filters filters,
+ SortFlags sort) const
+ \overload
+
+ Use the overload that takes a name filter string list as first
+ argument instead of a combination of attribute filter flags.
+*/
+
+/*!
+ \fn void QDir::convertToAbs()
+
+ Use makeAbsolute() instead.
+*/
+
+/*!
+ \fn QString QDir::cleanDirPath(const QString &name)
+
+ Use cleanPath() instead.
+*/
+
+/*!
+ \typedef QDir::FilterSpec
+
+ Use QDir::Filters instead.
+*/
+
+/*!
+ \typedef QDir::SortSpec
+
+ Use QDir::SortFlags instead.
+*/
+#endif // QT3_SUPPORT
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, QDir::Filters filters)
+{
+ QStringList flags;
+ if (filters == QDir::NoFilter) {
+ flags << QLatin1String("NoFilter");
+ } 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::NoDotAndDotDot) flags << QLatin1String("NoDotAndDotDot"); // ### Qt5: remove (because NoDotAndDotDot=NoDot|NoDotDot)
+ 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");
+ }
+ debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ')';
+ return debug;
+}
+
+static QDebug operator<<(QDebug debug, QDir::SortFlags sorting)
+{
+ if (sorting == QDir::NoSort) {
+ 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");
+
+ 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 << "QDir::SortFlags(" << qPrintable(type)
+ << '|'
+ << qPrintable(flags.join(QLatin1String("|"))) << ')';
+ }
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const QDir &dir)
+{
+ debug.maybeSpace() << "QDir(" << dir.path()
+ << ", nameFilters = {"
+ << qPrintable(dir.nameFilters().join(QLatin1String(",")))
+ << "}, "
+ << dir.sorting()
+ << ','
+ << dir.filter()
+ << ')';
+ return debug.space();
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
new file mode 100644
index 0000000000..18049403a8
--- /dev/null
+++ b/src/corelib/io/qdir.h
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIR_H
+#define QDIR_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QDirPrivate;
+
+class Q_CORE_EXPORT QDir
+{
+protected:
+ QSharedDataPointer<QDirPrivate> d_ptr;
+
+public:
+ enum Filter { Dirs = 0x001,
+ Files = 0x002,
+ Drives = 0x004,
+ NoSymLinks = 0x008,
+ AllEntries = Dirs | Files | Drives,
+ TypeMask = 0x00f,
+#ifdef QT3_SUPPORT
+ All = AllEntries,
+#endif
+
+ Readable = 0x010,
+ Writable = 0x020,
+ Executable = 0x040,
+ PermissionMask = 0x070,
+#ifdef QT3_SUPPORT
+ RWEMask = 0x070,
+#endif
+
+ Modified = 0x080,
+ Hidden = 0x100,
+ System = 0x200,
+
+ AccessMask = 0x3F0,
+
+ AllDirs = 0x400,
+ CaseSensitive = 0x800,
+ NoDotAndDotDot = 0x1000, // ### Qt5 NoDotAndDotDot = NoDot|NoDotDot
+ NoDot = 0x2000,
+ NoDotDot = 0x4000,
+
+ NoFilter = -1
+#ifdef QT3_SUPPORT
+ ,DefaultFilter = NoFilter
+#endif
+ };
+ Q_DECLARE_FLAGS(Filters, Filter)
+#ifdef QT3_SUPPORT
+ typedef Filters FilterSpec;
+#endif
+
+ enum SortFlag { Name = 0x00,
+ Time = 0x01,
+ Size = 0x02,
+ Unsorted = 0x03,
+ SortByMask = 0x03,
+
+ DirsFirst = 0x04,
+ Reversed = 0x08,
+ IgnoreCase = 0x10,
+ DirsLast = 0x20,
+ LocaleAware = 0x40,
+ Type = 0x80,
+ NoSort = -1
+#ifdef QT3_SUPPORT
+ ,DefaultSort = NoSort
+#endif
+ };
+ Q_DECLARE_FLAGS(SortFlags, SortFlag)
+
+ QDir(const QDir &);
+ QDir(const QString &path = QString());
+ QDir(const QString &path, const QString &nameFilter,
+ SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries);
+ ~QDir();
+
+ QDir &operator=(const QDir &);
+ QDir &operator=(const QString &path);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QDir &operator=(QDir &&other)
+ { qSwap(d_ptr, other.d_ptr); return *this; }
+#endif
+
+ void setPath(const QString &path);
+ QString path() const;
+ QString absolutePath() const;
+ QString canonicalPath() const;
+
+ static void addResourceSearchPath(const QString &path);
+
+ static void setSearchPaths(const QString &prefix, const QStringList &searchPaths);
+ static void addSearchPath(const QString &prefix, const QString &path);
+ static QStringList searchPaths(const QString &prefix);
+
+ QString dirName() const;
+ QString filePath(const QString &fileName) const;
+ QString absoluteFilePath(const QString &fileName) const;
+ QString relativeFilePath(const QString &fileName) const;
+
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED static QString convertSeparators(const QString &pathName);
+#endif
+ static QString toNativeSeparators(const QString &pathName);
+ static QString fromNativeSeparators(const QString &pathName);
+
+ bool cd(const QString &dirName);
+ bool cdUp();
+
+ QStringList nameFilters() const;
+ void setNameFilters(const QStringList &nameFilters);
+
+ Filters filter() const;
+ void setFilter(Filters filter);
+ SortFlags sorting() const;
+ void setSorting(SortFlags sort);
+
+ uint count() const;
+ QString operator[](int) const;
+
+ static QStringList nameFiltersFromString(const QString &nameFilter);
+
+ QStringList entryList(Filters filters = NoFilter, SortFlags sort = NoSort) const;
+ QStringList entryList(const QStringList &nameFilters, Filters filters = NoFilter,
+ SortFlags sort = NoSort) const;
+
+ QFileInfoList entryInfoList(Filters filters = NoFilter, SortFlags sort = NoSort) const;
+ QFileInfoList entryInfoList(const QStringList &nameFilters, Filters filters = NoFilter,
+ SortFlags sort = NoSort) const;
+
+ bool mkdir(const QString &dirName) const;
+ bool rmdir(const QString &dirName) const;
+ bool mkpath(const QString &dirPath) const;
+ bool rmpath(const QString &dirPath) const;
+
+ bool isReadable() const;
+ bool exists() const;
+ bool isRoot() const;
+
+ static bool isRelativePath(const QString &path);
+ inline static bool isAbsolutePath(const QString &path) { return !isRelativePath(path); }
+ bool isRelative() const;
+ inline bool isAbsolute() const { return !isRelative(); }
+ bool makeAbsolute();
+
+ bool operator==(const QDir &dir) const;
+ inline bool operator!=(const QDir &dir) const { return !operator==(dir); }
+
+ bool remove(const QString &fileName);
+ bool rename(const QString &oldName, const QString &newName);
+ bool exists(const QString &name) const;
+
+ static QFileInfoList drives();
+
+ static QChar separator();
+
+ static bool setCurrent(const QString &path);
+ static inline QDir current() { return QDir(currentPath()); }
+ static QString currentPath();
+
+ static inline QDir home() { return QDir(homePath()); }
+ static QString homePath();
+ static inline QDir root() { return QDir(rootPath()); }
+ static QString rootPath();
+ static inline QDir temp() { return QDir(tempPath()); }
+ static QString tempPath();
+
+#ifndef QT_NO_REGEXP
+ static bool match(const QStringList &filters, const QString &fileName);
+ static bool match(const QString &filter, const QString &fileName);
+#endif
+
+ static QString cleanPath(const QString &path);
+ void refresh() const;
+
+#ifdef QT3_SUPPORT
+ typedef SortFlags SortSpec;
+ inline QT3_SUPPORT QString absPath() const { return absolutePath(); }
+ inline QT3_SUPPORT QString absFilePath(const QString &fileName, bool acceptAbsPath = true) const
+ { Q_UNUSED(acceptAbsPath); return absoluteFilePath(fileName); }
+ QT3_SUPPORT bool matchAllDirs() const;
+ QT3_SUPPORT void setMatchAllDirs(bool on);
+ inline QT3_SUPPORT QStringList entryList(const QString &nameFilter, Filters filters = NoFilter,
+ SortFlags sort = NoSort) const
+ { return entryList(nameFiltersFromString(nameFilter), filters, sort); }
+ inline QT3_SUPPORT QFileInfoList entryInfoList(const QString &nameFilter,
+ Filters filters = NoFilter,
+ SortFlags sort = NoSort) const
+ { return entryInfoList(nameFiltersFromString(nameFilter), filters, sort); }
+
+ QT3_SUPPORT QString nameFilter() const;
+ QT3_SUPPORT void setNameFilter(const QString &nameFilter);
+
+ inline QT3_SUPPORT bool mkdir(const QString &dirName, bool acceptAbsPath) const
+ { Q_UNUSED(acceptAbsPath); return mkdir(dirName); }
+ inline QT3_SUPPORT bool rmdir(const QString &dirName, bool acceptAbsPath) const
+ { Q_UNUSED(acceptAbsPath); return rmdir(dirName); }
+
+ inline QT3_SUPPORT void convertToAbs() { makeAbsolute(); }
+ inline QT3_SUPPORT static QString currentDirPath() { return currentPath(); }
+ inline QT3_SUPPORT static QString homeDirPath() { return homePath(); }
+ inline QT3_SUPPORT static QString rootDirPath() { return rootPath(); }
+ inline QT3_SUPPORT static QString cleanDirPath(const QString &name) { return cleanPath(name); }
+#endif // QT3_SUPPORT
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDir::Filters)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDir::SortFlags)
+
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters);
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QDir &dir);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDIR_H
diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h
new file mode 100644
index 0000000000..7f77a84866
--- /dev/null
+++ b/src/corelib/io/qdir_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIR_PRIVATE_H
+#define QDIR_PRIVATE_H
+
+#include "qfilesystementry_p.h"
+#include "qfilesystemmetadata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDirPrivate : public QSharedData
+{
+public:
+ QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(),
+ QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
+ QDir::Filters filters_ = QDir::AllEntries);
+
+ QDirPrivate(const QDirPrivate &copy);
+
+ bool exists() const;
+
+ void initFileEngine();
+ void initFileLists(const QDir &dir) const;
+
+ static void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *);
+
+ static inline QChar getFilterSepChar(const QString &nameFilter);
+
+ static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0);
+
+ inline void setPath(const QString &path);
+
+ inline void clearFileLists();
+
+ inline void resolveAbsoluteEntry() const;
+
+ QStringList nameFilters;
+ QDir::SortFlags sort;
+ QDir::Filters filters;
+
+#ifdef QT3_SUPPORT
+ QChar filterSepChar;
+ bool matchAllDirs;
+#endif
+
+ QScopedPointer<QAbstractFileEngine> fileEngine;
+
+ mutable bool fileListsInitialized;
+ mutable QStringList files;
+ mutable QFileInfoList fileInfos;
+
+ QFileSystemEntry dirEntry;
+ mutable QFileSystemEntry absoluteDirEntry;
+ mutable QFileSystemMetaData metaData;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
new file mode 100644
index 0000000000..4a538f33db
--- /dev/null
+++ b/src/corelib/io/qdiriterator.cpp
@@ -0,0 +1,561 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \since 4.3
+ \class QDirIterator
+ \brief The QDirIterator class provides an iterator for directory entrylists.
+
+ You can use QDirIterator 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(), QDirIterator does not support sorting.
+
+ The QDirIterator constructor takes a QDir or a directory as
+ argument. After construction, the iterator is located before the first
+ directory entry. Here's how to iterate over all the entries sequentially:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qdiriterator.cpp 0
+
+ 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.
+
+ Unlike Qt's container iterators, QDirIterator is uni-directional (i.e.,
+ you cannot iterate directories in reverse order) and does not allow random
+ access.
+
+ QDirIterator works with all supported file engines, and is implemented
+ using QAbstractFileEngineIterator.
+
+ \sa QDir, QDir::entryList(), QAbstractFileEngineIterator
+*/
+
+/*! \enum QDirIterator::IteratorFlag
+
+ This enum describes flags that you can combine to configure the behavior
+ of QDirIterator.
+
+ \value NoIteratorFlags The default value, representing no flags. The
+ iterator will return entries for the assigned path.
+
+ \value Subdirectories List entries inside all subdirectories as well.
+
+ \value FollowSymlinks When combined with Subdirectories, 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.
+*/
+
+#include "qdiriterator.h"
+#include "qdir_p.h"
+
+#include "qabstractfileengine.h"
+
+#include <QtCore/qset.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qvariant.h>
+
+#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/qfsfileengine.h>
+#include <QtCore/private/qfileinfo_p.h>
+
+QT_BEGIN_NAMESPACE
+
+template <class Iterator>
+class QDirIteratorPrivateIteratorStack : public QStack<Iterator *>
+{
+public:
+ ~QDirIteratorPrivateIteratorStack()
+ {
+ qDeleteAll(*this);
+ }
+};
+
+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;
+
+ QScopedPointer<QAbstractFileEngine> engine;
+
+ QFileSystemEntry dirEntry;
+ const QStringList nameFilters;
+ const QDir::Filters filters;
+ const QDirIterator::IteratorFlags iteratorFlags;
+
+#ifndef QT_NO_REGEXP
+ QVector<QRegExp> nameRegExps;
+#endif
+
+ QDirIteratorPrivateIteratorStack<QAbstractFileEngineIterator> fileEngineIterators;
+#ifndef QT_NO_FILESYSTEMITERATOR
+ QDirIteratorPrivateIteratorStack<QFileSystemIterator> nativeIterators;
+#endif
+
+ QFileInfo currentFileInfo;
+ QFileInfo nextFileInfo;
+
+ // Loop protection
+ QSet<QString> visitedLinks;
+};
+
+/*!
+ \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)
+{
+#ifndef QT_NO_REGEXP
+ nameRegExps.reserve(nameFilters.size());
+ for (int i = 0; i < nameFilters.size(); ++i)
+ nameRegExps.append(
+ QRegExp(nameFilters.at(i),
+ (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
+ QRegExp::Wildcard));
+#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)
+ visitedLinks << fileInfo.canonicalFilePath();
+
+ 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;
+#endif
+ }
+}
+
+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;
+ }
+
+ 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;
+ }
+
+ nativeIterators.pop();
+ delete it;
+ }
+#endif
+ }
+
+ 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;
+
+ // Stop link loops
+ if (!visitedLinks.isEmpty() &&
+ visitedLinks.contains(fileInfo.canonicalFilePath()))
+ return;
+
+ pushDirectory(fileInfo);
+}
+
+/*!
+ \internal
+
+ This convenience function implements the iterator's filtering logics and
+ applies then to the current directory entry.
+
+ It returns 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
+{
+ Q_ASSERT(!fileName.isEmpty());
+
+ // 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;
+ if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot) // ### Qt5 remove (NoDotAndDotDot == NoDot|NoDotDot)
+ return false;
+
+ // name filter
+#ifndef QT_NO_REGEXP
+ // Pass all entries through name filters, except dirs if the AllDirs
+ if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) {
+ bool matched = false;
+ for (QVector<QRegExp>::const_iterator iter = nameRegExps.constBegin(),
+ end = nameRegExps.constEnd();
+ iter != end; ++iter) {
+
+ if (iter->exactMatch(fileName)) {
+ 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;
+ }
+
+ // 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;
+ }
+
+ return true;
+}
+
+/*!
+ Constructs a QDirIterator that can iterate over \a dir's entrylist, using
+ \a dir's name filters and regular 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 in QDir::entryList().
+
+ The sorting in \a dir is ignored.
+
+ \note To list symlinks that point to non existing files, QDir::System must be
+ passed to the flags.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
+{
+ // little trick to get hold of the QDirPrivate while there is no API on QDir to give it to us
+ class MyQDir : public QDir { public: const QDirPrivate *priv() const { return d_ptr.constData(); } };
+ const QDirPrivate *other = static_cast<const MyQDir*>(&dir)->priv();
+ d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, !other->fileEngine.isNull()));
+}
+
+/*!
+ Constructs a QDirIterator that can iterate over \a path, with no name
+ filtering and \a filters for entry filtering. 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
+ passed to the flags.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
+ : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), filters, flags))
+{
+}
+
+/*!
+ Constructs a QDirIterator 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().
+
+ \note To list symlinks that point to non existing files, QDir::System must be
+ passed to the flags.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
+ : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), QDir::NoFilter, flags))
+{
+}
+
+/*!
+ Constructs a QDirIterator 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().
+
+ \note To list symlinks that point to non existing files, QDir::System must be
+ passed to the flags.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirIterator::QDirIterator(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters, IteratorFlags flags)
+ : d(new QDirIteratorPrivate(QFileSystemEntry(path), nameFilters, filters, flags))
+{
+}
+
+/*!
+ Destroys the QDirIterator.
+*/
+QDirIterator::~QDirIterator()
+{
+}
+
+/*!
+ Advances the iterator to the next entry, and returns the file path of this
+ new entry. If hasNext() returns false, this function does nothing, and
+ returns a null QString.
+
+ You can call fileName() or filePath() to get the current entry file name
+ or path, or fileInfo() to get a QFileInfo for the current entry.
+
+ \sa hasNext(), fileName(), filePath(), fileInfo()
+*/
+QString QDirIterator::next()
+{
+ d->advance();
+ return filePath();
+}
+
+/*!
+ Returns true if there is at least one more entry in the directory;
+ otherwise, false is returned.
+
+ \sa next(), 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
+}
+
+/*!
+ Returns the file name for the current directory entry, without the path
+ prepended.
+
+ This function is convenient when iterating a single directory. When using
+ the QDirIterator::Subdirectories flag, you can use filePath() to get the
+ full path.
+
+ \sa filePath(), fileInfo()
+*/
+QString QDirIterator::fileName() const
+{
+ return d->currentFileInfo.fileName();
+}
+
+/*!
+ Returns the full file path for the current directory entry.
+
+ \sa fileInfo(), fileName()
+*/
+QString QDirIterator::filePath() const
+{
+ return d->currentFileInfo.filePath();
+}
+
+/*!
+ Returns a QFileInfo for the current directory entry.
+
+ \sa filePath(), fileName()
+*/
+QFileInfo QDirIterator::fileInfo() const
+{
+ return d->currentFileInfo;
+}
+
+/*!
+ Returns the base directory of the iterator.
+*/
+QString QDirIterator::path() const
+{
+ return d->dirEntry.filePath();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qdiriterator.h b/src/corelib/io/qdiriterator.h
new file mode 100644
index 0000000000..df2213f120
--- /dev/null
+++ b/src/corelib/io/qdiriterator.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRITERATOR_H
+#define QDIRITERATOR_H
+
+#include <QtCore/qdir.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QDirIteratorPrivate;
+class Q_CORE_EXPORT QDirIterator {
+public:
+ enum IteratorFlag {
+ NoIteratorFlags = 0x0,
+ FollowSymlinks = 0x1,
+ Subdirectories = 0x2
+ };
+ Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
+
+ QDirIterator(const QDir &dir, IteratorFlags flags = NoIteratorFlags);
+ QDirIterator(const QString &path,
+ IteratorFlags flags = NoIteratorFlags);
+ QDirIterator(const QString &path,
+ QDir::Filters filter,
+ IteratorFlags flags = NoIteratorFlags);
+ QDirIterator(const QString &path,
+ const QStringList &nameFilters,
+ QDir::Filters filters = QDir::NoFilter,
+ IteratorFlags flags = NoIteratorFlags);
+
+ virtual ~QDirIterator();
+
+ QString next();
+ bool hasNext() const;
+
+ QString fileName() const;
+ QString filePath() const;
+ QFileInfo fileInfo() const;
+ QString path() const;
+
+private:
+ Q_DISABLE_COPY(QDirIterator)
+
+ QScopedPointer<QDirIteratorPrivate> d;
+ friend class QDir;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDirIterator::IteratorFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
new file mode 100644
index 0000000000..0ade573ea4
--- /dev/null
+++ b/src/corelib/io/qfile.cpp
@@ -0,0 +1,1884 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qdebug.h"
+#include "qfile.h"
+#include "qfsfileengine.h"
+#include "qtemporaryfile.h"
+#include "qlist.h"
+#include "qfileinfo.h"
+#include "private/qiodevice_p.h"
+#include "private/qfile_p.h"
+#include "private/qsystemerror_p.h"
+#if defined(QT_BUILD_CORE_LIB)
+# include "qcoreapplication.h"
+#endif
+
+#ifdef QT_NO_QOBJECT
+#define tr(X) QString::fromLatin1(X)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const int QFILE_WRITEBUFFER_SIZE = 16384;
+
+static QByteArray locale_encode(const QString &f)
+{
+#if defined(Q_OS_DARWIN)
+ // Mac always expects UTF-8... and decomposed...
+ return f.normalized(QString::NormalizationForm_D).toUtf8();
+#elif defined(Q_OS_SYMBIAN)
+ return f.toUtf8();
+#else
+ return f.toLocal8Bit();
+#endif
+}
+
+static QString locale_decode(const QByteArray &f)
+{
+#if defined(Q_OS_DARWIN)
+ // Mac always gives us UTF-8 and decomposed, we want that composed...
+ return QString::fromUtf8(f).normalized(QString::NormalizationForm_C);
+#elif defined(Q_OS_SYMBIAN)
+ return QString::fromUtf8(f);
+#else
+ return QString::fromLocal8Bit(f);
+#endif
+}
+
+//************* QFilePrivate
+QFile::EncoderFn QFilePrivate::encoder = locale_encode;
+QFile::DecoderFn QFilePrivate::decoder = locale_decode;
+
+QFilePrivate::QFilePrivate()
+ : fileEngine(0), lastWasWrite(false),
+ writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
+ cachedSize(0)
+{
+}
+
+QFilePrivate::~QFilePrivate()
+{
+ delete fileEngine;
+ fileEngine = 0;
+}
+
+bool
+QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
+{
+#ifdef QT_NO_FSFILEENGINE
+ Q_UNUSED(flags);
+ Q_UNUSED(fd);
+ return false;
+#else
+ delete fileEngine;
+ fileEngine = 0;
+ QFSFileEngine *fe = new QFSFileEngine;
+ fileEngine = fe;
+ return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
+#endif
+}
+
+bool
+QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags)
+{
+#ifdef QT_NO_FSFILEENGINE
+ Q_UNUSED(flags);
+ Q_UNUSED(fh);
+ return false;
+#else
+ delete fileEngine;
+ fileEngine = 0;
+ QFSFileEngine *fe = new QFSFileEngine;
+ fileEngine = fe;
+ return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
+#endif
+}
+
+#ifdef Q_OS_SYMBIAN
+bool QFilePrivate::openExternalFile(int flags, const RFile &f, QFile::FileHandleFlags handleFlags)
+{
+#ifdef QT_NO_FSFILEENGINE
+ Q_UNUSED(flags);
+ Q_UNUSED(fh);
+ return false;
+#else
+ delete fileEngine;
+ fileEngine = 0;
+ QFSFileEngine *fe = new QFSFileEngine;
+ fileEngine = fe;
+ return fe->open(QIODevice::OpenMode(flags), f, handleFlags);
+#endif
+}
+#endif
+
+inline bool QFilePrivate::ensureFlushed() const
+{
+ // This function ensures that the write buffer has been flushed (const
+ // because certain const functions need to call it.
+ if (lastWasWrite) {
+ const_cast<QFilePrivate *>(this)->lastWasWrite = false;
+ if (!const_cast<QFile *>(q_func())->flush())
+ return false;
+ }
+ return true;
+}
+
+void
+QFilePrivate::setError(QFile::FileError err)
+{
+ error = err;
+ errorString.clear();
+}
+
+void
+QFilePrivate::setError(QFile::FileError err, const QString &errStr)
+{
+ error = err;
+ errorString = errStr;
+}
+
+void
+QFilePrivate::setError(QFile::FileError err, int errNum)
+{
+ error = err;
+ errorString = qt_error_string(errNum);
+}
+
+//************* QFile
+
+/*!
+ \class QFile
+ \brief The QFile class provides an interface for reading from and writing to files.
+
+ \ingroup io
+
+ \reentrant
+
+ QFile is an I/O device for reading and writing text and binary
+ files and \l{The Qt Resource System}{resources}. A QFile may be
+ used by itself or, more conveniently, with a QTextStream or
+ QDataStream.
+
+ The file name is usually passed in the constructor, but it can be
+ set at any time using setFileName(). QFile expects the file
+ separator to be '/' regardless of operating system. The use of
+ other separators (e.g., '\\') is not supported.
+
+ You can check for a file's existence using exists(), and remove a
+ file using remove(). (More advanced file system related operations
+ are provided by QFileInfo and QDir.)
+
+ The file is opened with open(), closed with close(), and flushed
+ with flush(). Data is usually read and written using QDataStream
+ or QTextStream, but you can also call the QIODevice-inherited
+ functions read(), readLine(), readAll(), write(). QFile also
+ inherits getChar(), putChar(), and ungetChar(), which work one
+ character at a time.
+
+ The size of the file is returned by size(). You can get the
+ current file position using pos(), or move to a new file position
+ using seek(). If you've reached the end of the file, atEnd()
+ returns true.
+
+ \section1 Reading Files Directly
+
+ The following example reads a text file line by line:
+
+ \snippet doc/src/snippets/file/file.cpp 0
+
+ The QIODevice::Text flag passed to open() tells Qt to convert
+ Windows-style line terminators ("\\r\\n") into C++-style
+ terminators ("\\n"). By default, QFile assumes binary, i.e. it
+ doesn't perform any conversion on the bytes stored in the file.
+
+ \section1 Using Streams to Read Files
+
+ The next example uses QTextStream to read a text file
+ line by line:
+
+ \snippet doc/src/snippets/file/file.cpp 1
+
+ QTextStream takes care of converting the 8-bit data stored on
+ disk into a 16-bit Unicode QString. By default, it assumes that
+ the user system's local 8-bit encoding is used (e.g., ISO 8859-1
+ for most of Europe; see QTextCodec::codecForLocale() for
+ details). This can be changed using setCodec().
+
+ To write text, we can use operator<<(), which is overloaded to
+ take a QTextStream on the left and various data types (including
+ QString) on the right:
+
+ \snippet doc/src/snippets/file/file.cpp 2
+
+ QDataStream is similar, in that you can use operator<<() to write
+ 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.
+
+ 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
+ from such a file; the data is generated in direct response to you calling
+ read(). In this case, however, you cannot use atEnd() to determine if
+ there is more data to read (since atEnd() will return true for a file that
+ claims to have size 0). Instead, you should either call readAll(), or call
+ read() or readLine() repeatedly until no more data can be read. The next
+ example uses QTextStream to read \c /proc/modules line by line:
+
+ \snippet doc/src/snippets/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 Linux/Mac OS X and
+ Windows. In a non \l{QIODevice::isWritable()}{writable}
+ directory on Linux, files cannot be created. This is not always
+ the case on Windows, where, for instance, the 'My Documents'
+ directory usually is not writable, but it is still possible to
+ create files in it.
+
+ \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
+*/
+
+/*!
+ \enum QFile::FileError
+
+ This enum describes the errors that may be returned by the error()
+ function.
+
+ \value NoError No error occurred.
+ \value ReadError An error occurred when reading from the file.
+ \value WriteError An error occurred when writing to the file.
+ \value FatalError A fatal error occurred.
+ \value ResourceError
+ \value OpenError The file could not be opened.
+ \value AbortError The operation was aborted.
+ \value TimeOutError A timeout occurred.
+ \value UnspecifiedError An unspecified error occurred.
+ \value RemoveError The file could not be removed.
+ \value RenameError The file could not be renamed.
+ \value PositionError The position in the file could not be changed.
+ \value ResizeError The file could not be resized.
+ \value PermissionsError The file could not be accessed.
+ \value CopyError The file could not be copied.
+
+ \omitvalue ConnectError
+*/
+
+/*!
+ \enum QFile::Permission
+
+ This enum is used by the permission() function to report the
+ permissions and ownership of a file. The values may be OR-ed
+ together to test multiple permissions and ownership values.
+
+ \value ReadOwner The file is readable by the owner of the file.
+ \value WriteOwner The file is writable by the owner of the file.
+ \value ExeOwner The file is executable by the owner of the file.
+ \value ReadUser The file is readable by the user.
+ \value WriteUser The file is writable by the user.
+ \value ExeUser The file is executable by the user.
+ \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.
+
+ \warning Because of differences in the platforms supported by Qt,
+ the semantics of ReadUser, WriteUser and ExeUser are
+ platform-dependent: On Unix, the rights of the owner of the file
+ are returned and on Windows the rights of the current user are
+ returned. This behavior might change in a future Qt version.
+
+ Note that Qt does not by default check for permissions on NTFS
+ file systems, as this may decrease the performance of file
+ handling considerably. It is possible to force permission checking
+ on NTFS by including the following code in your source:
+
+ \snippet doc/src/snippets/ntfsp.cpp 0
+
+ Permission checking is then turned on and off by incrementing and
+ decrementing \c qt_ntfs_permission_lookup by 1.
+
+ \snippet doc/src/snippets/ntfsp.cpp 1
+*/
+
+/*!
+ \enum QFile::FileHandleFlag
+
+ This enum is used when opening a file to specify additional
+ options which only apply to files and not to a generic
+ QIODevice.
+
+ \value AutoCloseHandle The file handle passed into open() should be
+ closed by close(), the default behaviour is that close just flushes
+ the file and the app is responsible for closing the file handle. When
+ opening a file by name, this flag is ignored as Qt always "owns" the
+ file handle and must close it.
+ */
+
+#ifdef QT3_SUPPORT
+/*!
+ \typedef QFile::PermissionSpec
+
+ Use QFile::Permission instead.
+*/
+#endif
+
+#ifdef QT_NO_QOBJECT
+QFile::QFile()
+ : QIODevice(*new QFilePrivate)
+{
+}
+QFile::QFile(const QString &name)
+ : QIODevice(*new QFilePrivate)
+{
+ d_func()->fileName = name;
+}
+QFile::QFile(QFilePrivate &dd)
+ : QIODevice(dd)
+{
+}
+#else
+/*!
+ \internal
+*/
+QFile::QFile()
+ : QIODevice(*new QFilePrivate, 0)
+{
+}
+/*!
+ Constructs a new file object with the given \a parent.
+*/
+QFile::QFile(QObject *parent)
+ : QIODevice(*new QFilePrivate, parent)
+{
+}
+/*!
+ Constructs a new file object to represent the file with the given \a name.
+*/
+QFile::QFile(const QString &name)
+ : QIODevice(*new QFilePrivate, 0)
+{
+ Q_D(QFile);
+ d->fileName = name;
+}
+/*!
+ Constructs a new file object with the given \a parent to represent the
+ file with the specified \a name.
+*/
+QFile::QFile(const QString &name, QObject *parent)
+ : QIODevice(*new QFilePrivate, parent)
+{
+ Q_D(QFile);
+ d->fileName = name;
+}
+/*!
+ \internal
+*/
+QFile::QFile(QFilePrivate &dd, QObject *parent)
+ : QIODevice(dd, parent)
+{
+}
+#endif
+
+/*!
+ Destroys the file object, closing it if necessary.
+*/
+QFile::~QFile()
+{
+ close();
+}
+
+/*!
+ Returns the name set by setFileName() or to the QFile
+ constructors.
+
+ \sa setFileName(), QFileInfo::fileName()
+*/
+QString QFile::fileName() const
+{
+ return fileEngine()->fileName(QAbstractFileEngine::DefaultName);
+}
+
+/*!
+ Sets the \a name of the file. The name can have no path, a
+ relative path, or an absolute path.
+
+ Do not call this function if the file has already been opened.
+
+ If the file name has no path or a relative path, the path used
+ will be the application's current directory path
+ \e{at the time of the open()} call.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 0
+
+ Note that the directory separator "/" works for all operating
+ systems supported by Qt.
+
+ \sa fileName(), QFileInfo, QDir
+*/
+void
+QFile::setFileName(const QString &name)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::setFileName: File (%s) is already opened",
+ qPrintable(fileName()));
+ close();
+ }
+ if(d->fileEngine) { //get a new file engine later
+ delete d->fileEngine;
+ d->fileEngine = 0;
+ }
+ d->fileName = name;
+}
+
+/*!
+ \fn QString QFile::decodeName(const char *localFileName)
+
+ \overload
+
+ Returns the Unicode version of the given \a localFileName. See
+ encodeName() for details.
+*/
+
+/*!
+ By default, this function 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.
+
+ \sa decodeName() setEncodingFunction()
+*/
+
+QByteArray
+QFile::encodeName(const QString &fileName)
+{
+ return (*QFilePrivate::encoder)(fileName);
+}
+
+/*!
+ \typedef QFile::EncoderFn
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 1
+
+ \sa setEncodingFunction(), encodeName()
+*/
+
+/*!
+ This does the reverse of QFile::encodeName() using \a localFileName.
+
+ \sa setDecodingFunction(), encodeName()
+*/
+
+QString
+QFile::decodeName(const QByteArray &localFileName)
+{
+ return (*QFilePrivate::decoder)(localFileName);
+}
+
+/*!
+ \fn void QFile::setEncodingFunction(EncoderFn function)
+
+ \nonreentrant
+
+ Sets the \a function for encoding Unicode file names. The
+ default encodes in the locale-specific 8-bit encoding.
+
+ \sa encodeName(), setDecodingFunction()
+*/
+
+void
+QFile::setEncodingFunction(EncoderFn f)
+{
+ if (!f)
+ f = locale_encode;
+ QFilePrivate::encoder = f;
+}
+
+/*!
+ \typedef QFile::DecoderFn
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 2
+
+ \sa setDecodingFunction()
+*/
+
+/*!
+ \fn void QFile::setDecodingFunction(DecoderFn function)
+
+ \nonreentrant
+
+ Sets the \a function for decoding 8-bit file names. The
+ default uses the locale-specific 8-bit encoding.
+
+ \sa setEncodingFunction(), decodeName()
+*/
+
+void
+QFile::setDecodingFunction(DecoderFn f)
+{
+ if (!f)
+ f = locale_decode;
+ QFilePrivate::decoder = f;
+}
+
+/*!
+ \overload
+
+ Returns true if the file specified by fileName() exists; otherwise
+ returns false.
+
+ \sa fileName(), setFileName()
+*/
+
+bool
+QFile::exists() const
+{
+ // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
+ return (fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask
+ | QAbstractFileEngine::FileFlag(0x1000000)) & QAbstractFileEngine::ExistsFlag);
+}
+
+/*!
+ Returns true if the file specified by \a fileName exists; otherwise
+ returns false.
+*/
+
+bool
+QFile::exists(const QString &fileName)
+{
+ return QFileInfo(fileName).exists();
+}
+
+/*!
+ \fn QString QFile::symLinkTarget() const
+ \since 4.2
+ \overload
+
+ Returns the absolute path of the file or directory a symlink (or shortcut
+ on Windows) points to, or a an empty string if the object isn't a symbolic
+ link.
+
+ This name may not represent an existing file; it is only a string.
+ QFile::exists() returns true if the symlink points to an existing file.
+
+ \sa fileName() setFileName()
+*/
+
+/*!
+ \obsolete
+
+ Use symLinkTarget() instead.
+*/
+QString
+QFile::readLink() const
+{
+ return fileEngine()->fileName(QAbstractFileEngine::LinkName);
+}
+
+/*!
+ \fn static QString QFile::symLinkTarget(const QString &fileName)
+ \since 4.2
+
+ Returns the absolute path of the file or directory referred to by the
+ symlink (or shortcut on Windows) specified by \a fileName, or returns an
+ empty string if the \a fileName does not correspond to a symbolic link.
+
+ This name may not represent an existing file; it is only a string.
+ QFile::exists() returns true if the symlink points to an existing file.
+*/
+
+/*!
+ \obsolete
+
+ Use symLinkTarget() instead.
+*/
+QString
+QFile::readLink(const QString &fileName)
+{
+ return QFileInfo(fileName).readLink();
+}
+
+/*!
+ Removes the file specified by fileName(). Returns true if successful;
+ otherwise returns false.
+
+ The file is closed before it is removed.
+
+ \sa setFileName()
+*/
+
+bool
+QFile::remove()
+{
+ Q_D(QFile);
+ if (d->fileName.isEmpty()) {
+ qWarning("QFile::remove: Empty or null file name");
+ return false;
+ }
+ unsetError();
+ close();
+ if(error() == QFile::NoError) {
+ if(fileEngine()->remove()) {
+ unsetError();
+ return true;
+ }
+ d->setError(QFile::RemoveError, d->fileEngine->errorString());
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Removes the file specified by the \a fileName given.
+
+ Returns true if successful; otherwise returns false.
+
+ \sa remove()
+*/
+
+bool
+QFile::remove(const QString &fileName)
+{
+ return QFile(fileName).remove();
+}
+
+/*!
+ Renames the file currently specified by fileName() to \a newName.
+ Returns true if successful; otherwise returns false.
+
+ If a file with the name \a newName already exists, rename() returns false
+ (i.e., QFile will not overwrite it).
+
+ The file is closed before it is renamed.
+
+ \sa setFileName()
+*/
+
+bool
+QFile::rename(const QString &newName)
+{
+ Q_D(QFile);
+ if (d->fileName.isEmpty()) {
+ qWarning("QFile::rename: Empty or null file name");
+ return false;
+ }
+ if (QFile(newName).exists()) {
+ // ### Race condition. If a file is moved in after this, it /will/ be
+ // overwritten. On Unix, the proper solution is to use hardlinks:
+ // return ::link(old, new) && ::remove(old);
+ d->setError(QFile::RenameError, tr("Destination file exists"));
+ return false;
+ }
+ unsetError();
+ close();
+ if(error() == QFile::NoError) {
+ if (fileEngine()->rename(newName)) {
+ unsetError();
+ // engine was able to handle the new name so we just reset it
+ d->fileEngine->setFileName(newName);
+ d->fileName = newName;
+ return true;
+ }
+
+ if (isSequential()) {
+ d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
+ return false;
+ }
+
+ QFile out(newName);
+ if (open(QIODevice::ReadOnly)) {
+ if (out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ bool error = false;
+ char block[4096];
+ qint64 bytes;
+ while ((bytes = read(block, sizeof(block))) > 0) {
+ if (bytes != out.write(block, bytes)) {
+ d->setError(QFile::RenameError, out.errorString());
+ error = true;
+ break;
+ }
+ }
+ if (bytes == -1) {
+ d->setError(QFile::RenameError, errorString());
+ error = true;
+ }
+ if(!error) {
+ if (!remove()) {
+ d->setError(QFile::RenameError, tr("Cannot remove source file"));
+ error = true;
+ }
+ }
+ if (error) {
+ out.remove();
+ } else {
+ d->fileEngine->setFileName(newName);
+ setPermissions(permissions());
+ unsetError();
+ setFileName(newName);
+ }
+ close();
+ return !error;
+ }
+ close();
+ }
+ d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString());
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Renames the file \a oldName to \a newName. Returns true if
+ successful; otherwise returns false.
+
+ If a file with the name \a newName already exists, rename() returns false
+ (i.e., QFile will not overwrite it).
+
+ \sa rename()
+*/
+
+bool
+QFile::rename(const QString &oldName, const QString &newName)
+{
+ return QFile(oldName).rename(newName);
+}
+
+/*!
+
+ Creates a link named \a linkName that points to the file currently specified by
+ fileName(). 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 false.
+
+ This function will not overwrite an already existing entity in the file system;
+ in this case, \c link() will return false and set \l{QFile::}{error()} to
+ return \l{QFile::}{RenameError}.
+
+ \note To create a valid link on Windows, \a linkName must have a \c{.lnk} file extension.
+
+ \note On Symbian, no link is created and false is returned if fileName()
+ currently specifies a directory.
+
+ \sa setFileName()
+*/
+
+bool
+QFile::link(const QString &linkName)
+{
+ Q_D(QFile);
+ if (d->fileName.isEmpty()) {
+ qWarning("QFile::link: Empty or null file name");
+ return false;
+ }
+ QFileInfo fi(linkName);
+ if(fileEngine()->link(fi.absoluteFilePath())) {
+ unsetError();
+ return true;
+ }
+ d->setError(QFile::RenameError, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ \overload
+
+ Creates a link named \a linkName that points to the file \a fileName. 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 false.
+
+ \sa link()
+*/
+
+bool
+QFile::link(const QString &fileName, const QString &linkName)
+{
+ return QFile(fileName).link(linkName);
+}
+
+/*!
+ Copies the file currently specified by fileName() to a file called
+ \a newName. Returns true if successful; otherwise returns false.
+
+ Note that if a file with the name \a newName already exists,
+ copy() returns false (i.e. QFile will not overwrite it).
+
+ The source file is closed before it is copied.
+
+ \sa setFileName()
+*/
+
+bool
+QFile::copy(const QString &newName)
+{
+ Q_D(QFile);
+ if (d->fileName.isEmpty()) {
+ qWarning("QFile::copy: Empty or null file name");
+ return false;
+ }
+ if (QFile(newName).exists()) {
+ // ### Race condition. If a file is moved in after this, it /will/ be
+ // overwritten. On Unix, the proper solution is to use hardlinks:
+ // return ::link(old, new) && ::remove(old); See also rename().
+ d->setError(QFile::CopyError, tr("Destination file exists"));
+ return false;
+ }
+ unsetError();
+ close();
+ if(error() == QFile::NoError) {
+ if(fileEngine()->copy(newName)) {
+ unsetError();
+ return true;
+ } else {
+ bool error = false;
+ if(!open(QFile::ReadOnly)) {
+ error = true;
+ d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
+ } else {
+ QString fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
+#ifdef QT_NO_TEMPORARYFILE
+ QFile out(fileTemplate.arg(QFileInfo(newName).path()));
+ if (!out.open(QIODevice::ReadWrite))
+ error = true;
+#else
+ QTemporaryFile out(fileTemplate.arg(QFileInfo(newName).path()));
+ if (!out.open()) {
+ out.setFileTemplate(fileTemplate.arg(QDir::tempPath()));
+ if (!out.open())
+ error = true;
+ }
+#endif
+ if (error) {
+ out.close();
+ d->setError(QFile::CopyError, tr("Cannot open for output"));
+ } else {
+ char block[4096];
+ qint64 totalRead = 0;
+ while(!atEnd()) {
+ qint64 in = read(block, sizeof(block));
+ if (in <= 0)
+ break;
+ totalRead += in;
+ if(in != out.write(block, in)) {
+ d->setError(QFile::CopyError, tr("Failure to write block"));
+ error = true;
+ break;
+ }
+ }
+
+ if (totalRead != size()) {
+ // Unable to read from the source. The error string is
+ // already set from read().
+ error = true;
+ }
+ if (!error && !out.rename(newName)) {
+ error = true;
+ d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
+ }
+#ifdef QT_NO_TEMPORARYFILE
+ if (error)
+ out.remove();
+#else
+ if (!error)
+ out.setAutoRemove(false);
+#endif
+ }
+ close();
+ }
+ if(!error) {
+ QFile::setPermissions(newName, permissions());
+ unsetError();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Copies the file \a fileName to \a newName. Returns true if successful;
+ otherwise returns false.
+
+ If a file with the name \a newName already exists, copy() returns false
+ (i.e., QFile will not overwrite it).
+
+ \sa rename()
+*/
+
+bool
+QFile::copy(const QString &fileName, const QString &newName)
+{
+ return QFile(fileName).copy(newName);
+}
+
+/*!
+ Returns true if the file can only be manipulated sequentially;
+ otherwise returns false.
+
+ Most files support random-access, but some special files may not.
+
+ \sa QIODevice::isSequential()
+*/
+bool QFile::isSequential() const
+{
+ Q_D(const QFile);
+ return d->fileEngine && d->fileEngine->isSequential();
+}
+
+/*!
+ Opens the file using OpenMode \a mode, returning true if successful;
+ otherwise false.
+
+ The \a mode must be QIODevice::ReadOnly, QIODevice::WriteOnly, or
+ QIODevice::ReadWrite. It may also have additional flags, such as
+ QIODevice::Text and QIODevice::Unbuffered.
+
+ \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.
+
+ \sa QIODevice::OpenMode, setFileName()
+*/
+bool QFile::open(OpenMode mode)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
+ return false;
+ }
+ if (mode & Append)
+ mode |= WriteOnly;
+
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QIODevice::open: File access not specified");
+ return false;
+ }
+
+#ifdef Q_OS_SYMBIAN
+ // For symbian, the unbuffered flag is used to control write-behind cache behaviour
+ if (fileEngine()->open(mode))
+#else
+ // QIODevice provides the buffering, so there's no need to request it from the file engine.
+ if (fileEngine()->open(mode | QIODevice::Unbuffered))
+#endif
+ {
+ 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;
+}
+
+/*! \fn QFile::open(OpenMode, FILE*)
+
+ Use open(FILE *, OpenMode) instead.
+*/
+
+/*!
+ \overload
+
+ Opens the existing file handle \a fh in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 3
+
+ When a QFile is opened using this function, close() does not actually
+ close the file, but only flushes it.
+
+ \bold{Warning:}
+ \list 1
+ \o If \a fh does not refer to a regular file, e.g., it is \c stdin,
+ \c stdout, or \c stderr, you may not be able to seek(). size()
+ returns \c 0 in those cases. See QIODevice::isSequential() for
+ more information.
+ \o Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+ \endlist
+
+ \note For Windows CE you may not be able to call resize().
+
+ \sa close(), {qmake Variable Reference#CONFIG}{qmake Variable Reference}
+
+ \bold{Note for the Windows Platform}
+
+ \a fh must be opened in binary mode (i.e., the mode string must contain
+ 'b', as in "rb" or "wb") when accessing files and other random-access
+ devices. Qt will translate the end-of-line characters if you pass
+ QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
+ are unaffected by this limitation.
+
+ You need to enable support for console applications in order to use the
+ stdin, stdout and stderr streams at the console. To do this, add the
+ following declaration to your application's project file:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 4
+*/
+// ### Qt5: merge this into new overload with a default parameter
+bool QFile::open(FILE *fh, OpenMode mode)
+{
+ return open(fh, mode, DontCloseHandle);
+}
+
+/*!
+ \overload
+
+ Opens the existing file handle \a fh in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 3
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ then calling close() closes the adopted handle.
+ Otherwise, close() does not actually close the file, but only flushes it.
+
+ \bold{Warning:}
+ \list 1
+ \o If \a fh does not refer to a regular file, e.g., it is \c stdin,
+ \c stdout, or \c stderr, you may not be able to seek(). size()
+ returns \c 0 in those cases. See QIODevice::isSequential() for
+ more information.
+ \o Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+ \endlist
+
+ \note For Windows CE you may not be able to call resize().
+
+ \sa close(), {qmake Variable Reference#CONFIG}{qmake Variable Reference}
+
+ \bold{Note for the Windows Platform}
+
+ \a fh must be opened in binary mode (i.e., the mode string must contain
+ 'b', as in "rb" or "wb") when accessing files and other random-access
+ devices. Qt will translate the end-of-line characters if you pass
+ QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
+ are unaffected by this limitation.
+
+ You need to enable support for console applications in order to use the
+ stdin, stdout and stderr streams at the console. To do this, add the
+ following declaration to your application's project file:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 4
+*/
+bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
+ return false;
+ }
+ if (mode & Append)
+ mode |= WriteOnly;
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QFile::open: File access not specified");
+ return false;
+ }
+ if (d->openExternalFile(mode, fh, handleFlags)) {
+ QIODevice::open(mode);
+ if (mode & Append) {
+ seek(size());
+ } else {
+ qint64 pos = (qint64)QT_FTELL(fh);
+ if (pos != -1)
+ seek(pos);
+ }
+ return true;
+ }
+ return false;
+}
+
+/*! \fn QFile::open(OpenMode, int)
+
+ Use open(int, OpenMode) instead.
+*/
+
+/*!
+ \overload
+
+ Opens the existing file descriptor \a fd in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ When a QFile is opened using this function, close() does not
+ actually close the file.
+
+ 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()
+ for more information.
+
+ \warning For Windows CE you may not be able to call seek(), setSize(),
+ fileTime(). size() returns \c 0.
+
+ \warning Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+
+ \sa close()
+*/
+// ### Qt5: merge this into new overload with a default parameter
+bool QFile::open(int fd, OpenMode mode)
+{
+ return open(fd, mode, DontCloseHandle);
+}
+
+/*!
+ \overload
+
+ Opens the existing file descriptor \a fd in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ 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()
+ for more information.
+
+ \warning For Windows CE you may not be able to call seek(), setSize(),
+ fileTime(). size() returns \c 0.
+
+ \warning Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+
+ \sa close()
+*/
+bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
+ return false;
+ }
+ if (mode & Append)
+ mode |= WriteOnly;
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QFile::open: File access not specified");
+ return false;
+ }
+ if (d->openExternalFile(mode, fd, handleFlags)) {
+ QIODevice::open(mode);
+ if (mode & Append) {
+ seek(size());
+ } else {
+ qint64 pos = (qint64)QT_LSEEK(fd, QT_OFF_T(0), SEEK_CUR);
+ if (pos != -1)
+ seek(pos);
+ }
+ return true;
+ }
+ return false;
+}
+
+#ifdef Q_OS_SYMBIAN
+/*!
+ \overload
+
+ Opens the existing file object \a f in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ then calling close() closes the adopted handle.
+ Otherwise, close() does not actually close the file, but only flushes it.
+
+ \warning If the file handle is adopted from another process,
+ you may not be able to use this QFile with a QFileInfo.
+
+ \sa close()
+*/
+bool QFile::open(const RFile &f, OpenMode mode, FileHandleFlags handleFlags)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
+ return false;
+ }
+ if (mode & Append)
+ mode |= WriteOnly;
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QFile::open: File access not specified");
+ return false;
+ }
+ if (d->openExternalFile(mode, f, handleFlags)) {
+ bool ok = QIODevice::open(mode);
+ if (ok) {
+ if (mode & Append) {
+ ok = seek(size());
+ } else {
+ qint64 pos = 0;
+ TInt err;
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ err = static_cast<const RFile64&>(f).Seek(ESeekCurrent, pos);
+#else
+ TInt pos32 = 0;
+ err = f.Seek(ESeekCurrent, pos32);
+ pos = pos32;
+#endif
+ ok = ok && (err == KErrNone);
+ ok = ok && seek(pos);
+ }
+ }
+ return ok;
+ }
+ return false;
+}
+#endif
+
+/*!
+ Returns the file handle of the file.
+
+ This is a small positive integer, suitable for use with C library
+ functions such as fdopen() and fcntl(). On systems that use file
+ descriptors for sockets (i.e. Unix systems, but not Windows) the handle
+ can be used with QSocketNotifier as well.
+
+ If the file is not open, or there is an error, handle() returns -1.
+
+ This function is not supported on Windows CE.
+
+ \sa QSocketNotifier
+*/
+
+int
+QFile::handle() const
+{
+ Q_D(const QFile);
+ if (!isOpen() || !d->fileEngine)
+ return -1;
+
+ return d->fileEngine->handle();
+}
+
+/*!
+ \enum QFile::MemoryMapFlags
+ \since 4.4
+
+ This enum describes special options that may be used by the map()
+ function.
+
+ \value NoOptions No options.
+*/
+
+/*!
+ \since 4.4
+ Maps \a size bytes of the file into memory starting at \a offset. A file
+ should be open for a map to succeed but the file does not need to stay
+ open after the memory has been mapped. When the QFile is destroyed
+ or a new file is opened with this object, any maps that have not been
+ unmapped will automatically be unmapped.
+
+ Any mapping options can be passed through \a flags.
+
+ Returns a pointer to the memory or 0 if there is an error.
+
+ \note On Windows CE 5.0 the file will be closed before mapping occurs.
+
+ \sa unmap(), QAbstractFileEngine::supportsExtension()
+ */
+uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags)
+{
+ Q_D(QFile);
+ if (fileEngine()
+ && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
+ unsetError();
+ uchar *address = d->fileEngine->map(offset, size, flags);
+ if (address == 0)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ return address;
+ }
+ return 0;
+}
+
+/*!
+ \since 4.4
+ Unmaps the memory \a address.
+
+ Returns true if the unmap succeeds; false otherwise.
+
+ \sa map(), QAbstractFileEngine::supportsExtension()
+ */
+bool QFile::unmap(uchar *address)
+{
+ Q_D(QFile);
+ if (fileEngine()
+ && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
+ unsetError();
+ bool success = d->fileEngine->unmap(address);
+ if (!success)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ return success;
+ }
+ d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
+ return false;
+}
+
+/*!
+ \fn QString QFile::name() const
+
+ Use fileName() instead.
+*/
+
+/*!
+ \fn void QFile::setName(const QString &name)
+
+ Use setFileName() instead.
+*/
+
+/*!
+ Sets the file size (in bytes) \a sz. Returns true if the file if the
+ resize succeeds; false otherwise. If \a sz is larger than the file
+ currently is the new bytes will be set to 0, if \a sz is smaller the
+ file is simply truncated.
+
+ \sa size(), setFileName()
+*/
+
+bool
+QFile::resize(qint64 sz)
+{
+ Q_D(QFile);
+ if (!d->ensureFlushed())
+ return false;
+ fileEngine();
+ if (isOpen() && d->fileEngine->pos() > sz)
+ seek(sz);
+ if(d->fileEngine->setSize(sz)) {
+ unsetError();
+ d->cachedSize = sz;
+ return true;
+ }
+ d->cachedSize = 0;
+ d->setError(QFile::ResizeError, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets \a fileName to size (in bytes) \a sz. Returns true if the file if
+ the resize succeeds; false otherwise. If \a sz is larger than \a
+ fileName currently is the new bytes will be set to 0, if \a sz is
+ smaller the file is simply truncated.
+
+ \sa resize()
+*/
+
+bool
+QFile::resize(const QString &fileName, qint64 sz)
+{
+ return QFile(fileName).resize(sz);
+}
+
+/*!
+ Returns the complete OR-ed together combination of
+ QFile::Permission for the file.
+
+ \sa setPermissions(), setFileName()
+*/
+
+QFile::Permissions
+QFile::permissions() const
+{
+ QAbstractFileEngine::FileFlags perms = fileEngine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
+ return QFile::Permissions((int)perms); //ewww
+}
+
+/*!
+ \overload
+
+ Returns the complete OR-ed together combination of
+ QFile::Permission for \a fileName.
+*/
+
+QFile::Permissions
+QFile::permissions(const QString &fileName)
+{
+ return QFile(fileName).permissions();
+}
+
+/*!
+ Sets the permissions for the file to the \a permissions specified.
+ Returns true if successful, or false if the permissions cannot be
+ modified.
+
+ \sa permissions(), setFileName()
+*/
+
+bool
+QFile::setPermissions(Permissions permissions)
+{
+ Q_D(QFile);
+ if(fileEngine()->setPermissions(permissions)) {
+ unsetError();
+ return true;
+ }
+ d->setError(QFile::PermissionsError, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets the permissions for \a fileName file to \a permissions.
+*/
+
+bool
+QFile::setPermissions(const QString &fileName, Permissions permissions)
+{
+ return QFile(fileName).setPermissions(permissions);
+}
+
+static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
+{
+ qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
+ if (ret > 0)
+ buffer->free(ret);
+ return ret;
+}
+
+/*!
+ Flushes any buffered data to the file. Returns true if successful;
+ otherwise returns false.
+*/
+
+bool
+QFile::flush()
+{
+ Q_D(QFile);
+ if (!d->fileEngine) {
+ qWarning("QFile::flush: No file engine. Is IODevice open?");
+ return false;
+ }
+
+ if (!d->writeBuffer.isEmpty()) {
+ qint64 size = d->writeBuffer.size();
+ if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
+ QFile::FileError err = d->fileEngine->error();
+ if(err == QFile::UnspecifiedError)
+ err = QFile::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ }
+
+ if (!d->fileEngine->flush()) {
+ QFile::FileError err = d->fileEngine->error();
+ if(err == QFile::UnspecifiedError)
+ err = QFile::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Calls QFile::flush() and closes the file. Errors from flush are ignored.
+
+ \sa QIODevice::close()
+*/
+void
+QFile::close()
+{
+ Q_D(QFile);
+ if(!isOpen())
+ return;
+ bool flushed = flush();
+ QIODevice::close();
+
+ // reset write buffer
+ d->lastWasWrite = false;
+ d->writeBuffer.clear();
+
+ // keep earlier error from flush
+ if (d->fileEngine->close() && flushed)
+ unsetError();
+ else if (flushed)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+}
+
+/*!
+ Returns the size of the file.
+
+ For regular empty files on Unix (e.g. those in \c /proc), this function
+ returns 0; the contents of such a file are generated on demand in response
+ to you calling read().
+*/
+
+qint64 QFile::size() const
+{
+ Q_D(const QFile);
+ if (!d->ensureFlushed())
+ return 0;
+ d->cachedSize = fileEngine()->size();
+ return d->cachedSize;
+}
+
+/*!
+ \reimp
+*/
+
+qint64 QFile::pos() const
+{
+ return QIODevice::pos();
+}
+
+/*!
+ Returns true if the end of the file has been reached; otherwise returns
+ false.
+
+ For regular empty files on Unix (e.g. those in \c /proc), this function
+ returns true, since the file system reports that the size of such a file is
+ 0. Therefore, you should not depend on atEnd() when reading data from such a
+ file, but rather call read() until no more data can be read.
+*/
+
+bool QFile::atEnd() const
+{
+ Q_D(const QFile);
+
+ // If there's buffered data left, we're not at the end.
+ if (!d->buffer.isEmpty())
+ return false;
+
+ if (!isOpen())
+ return true;
+
+ if (!d->ensureFlushed())
+ return false;
+
+ // If the file engine knows best, say what it says.
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
+ // Check if the file engine supports AtEndExtension, and if it does,
+ // check if the file engine claims to be at the end.
+ return d->fileEngine->atEnd();
+ }
+
+ // if it looks like we are at the end, or if size is not cached,
+ // fall through to bytesAvailable() to make sure.
+ if (pos() < d->cachedSize)
+ return false;
+
+ // Fall back to checking how much is available (will stat files).
+ return bytesAvailable() == 0;
+}
+
+/*!
+ For random-access devices, this function sets the current position
+ to \a pos, returning true on success, or false if an error occurred.
+ For sequential devices, the default behavior is to do nothing and
+ return false.
+
+ Seeking beyond the end of a file:
+ If the position is beyond the end of a file, then seek() shall not
+ immediately extend the file. If a write is performed at this position,
+ then the file shall be extended. The content of the file between the
+ previous end of file and the newly written data is UNDEFINED and
+ varies between platforms and file systems.
+*/
+
+bool QFile::seek(qint64 off)
+{
+ Q_D(QFile);
+ if (!isOpen()) {
+ qWarning("QFile::seek: IODevice is not open");
+ return false;
+ }
+
+ if (!d->ensureFlushed())
+ return false;
+
+ if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
+ QFile::FileError err = d->fileEngine->error();
+ if(err == QFile::UnspecifiedError)
+ err = QFile::PositionError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ unsetError();
+ return true;
+}
+
+/*!
+ \reimp
+*/
+qint64 QFile::readLineData(char *data, qint64 maxlen)
+{
+ Q_D(QFile);
+ if (!d->ensureFlushed())
+ return -1;
+
+ qint64 read;
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
+ read = d->fileEngine->readLine(data, maxlen);
+ } else {
+ // Fall back to QIODevice's readLine implementation if the engine
+ // cannot do it faster.
+ read = QIODevice::readLineData(data, maxlen);
+ }
+
+ if (read < maxlen) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
+ return read;
+}
+
+/*!
+ \reimp
+*/
+
+qint64 QFile::readData(char *data, qint64 len)
+{
+ Q_D(QFile);
+ unsetError();
+ if (!d->ensureFlushed())
+ return -1;
+
+ qint64 read = d->fileEngine->read(data, len);
+ if(read < 0) {
+ QFile::FileError err = d->fileEngine->error();
+ if(err == QFile::UnspecifiedError)
+ err = QFile::ReadError;
+ d->setError(err, d->fileEngine->errorString());
+ }
+
+ if (read < len) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
+ return read;
+}
+
+/*!
+ \internal
+*/
+bool QFilePrivate::putCharHelper(char c)
+{
+#ifdef QT_NO_QOBJECT
+ return QIODevicePrivate::putCharHelper(c);
+#else
+
+ // Cutoff for code that doesn't only touch the buffer.
+ int writeBufferSize = writeBuffer.size();
+ if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
+#ifdef Q_OS_WIN
+ || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
+#endif
+ ) {
+ return QIODevicePrivate::putCharHelper(c);
+ }
+
+ if (!(openMode & QIODevice::WriteOnly)) {
+ if (openMode == QIODevice::NotOpen)
+ qWarning("QIODevice::putChar: Closed device");
+ else
+ qWarning("QIODevice::putChar: ReadOnly device");
+ return false;
+ }
+
+ // Make sure the device is positioned correctly.
+ const bool sequential = isSequential();
+ if (pos != devicePos && !sequential && !q_func()->seek(pos))
+ return false;
+
+ lastWasWrite = true;
+
+ int len = 1;
+#ifdef Q_OS_WIN
+ if ((openMode & QIODevice::Text) && c == '\n') {
+ ++len;
+ *writeBuffer.reserve(1) = '\r';
+ }
+#endif
+
+ // Write to buffer.
+ *writeBuffer.reserve(1) = c;
+
+ if (!sequential) {
+ pos += len;
+ devicePos += len;
+ if (!buffer.isEmpty())
+ buffer.skip(len);
+ }
+
+ return true;
+#endif
+}
+
+/*!
+ \reimp
+*/
+
+qint64
+QFile::writeData(const char *data, qint64 len)
+{
+ Q_D(QFile);
+ unsetError();
+ d->lastWasWrite = true;
+ bool buffered = !(d->openMode & Unbuffered);
+
+ // Flush buffered data if this read will overflow.
+ if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
+ if (!flush())
+ return -1;
+ }
+
+ // Write directly to the engine if the block size is larger than
+ // the write buffer size.
+ if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
+ qint64 ret = d->fileEngine->write(data, len);
+ if(ret < 0) {
+ QFile::FileError err = d->fileEngine->error();
+ if(err == QFile::UnspecifiedError)
+ err = QFile::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ }
+ return ret;
+ }
+
+ // Write to the buffer.
+ char *writePointer = d->writeBuffer.reserve(len);
+ if (len == 1)
+ *writePointer = *data;
+ else
+ ::memcpy(writePointer, data, len);
+ return len;
+}
+
+/*!
+ \internal
+ Returns the QIOEngine for this QFile object.
+*/
+QAbstractFileEngine *QFile::fileEngine() const
+{
+ Q_D(const QFile);
+ if(!d->fileEngine)
+ d->fileEngine = QAbstractFileEngine::create(d->fileName);
+ return d->fileEngine;
+}
+
+/*!
+ Returns the file error status.
+
+ The I/O device status returns an error code. For example, if open()
+ returns false, or a read/write operation returns -1, this function can
+ be called to find out the reason why the operation failed.
+
+ \sa unsetError()
+*/
+
+QFile::FileError
+QFile::error() const
+{
+ Q_D(const QFile);
+ return d->error;
+}
+
+/*!
+ Sets the file's error to QFile::NoError.
+
+ \sa error()
+*/
+void
+QFile::unsetError()
+{
+ Q_D(QFile);
+ d->setError(QFile::NoError);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
new file mode 100644
index 0000000000..41835342f4
--- /dev/null
+++ b/src/corelib/io/qfile.h
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILE_H
+#define QFILE_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qstring.h>
+#include <stdio.h>
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
+
+#ifdef open
+#error qfile.h must be included before any header file that defines open
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractFileEngine;
+class QFilePrivate;
+
+class Q_CORE_EXPORT QFile : public QIODevice
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#endif
+ Q_DECLARE_PRIVATE(QFile)
+
+public:
+
+ enum FileError {
+ NoError = 0,
+ ReadError = 1,
+ WriteError = 2,
+ FatalError = 3,
+ ResourceError = 4,
+ OpenError = 5,
+ AbortError = 6,
+ TimeOutError = 7,
+ UnspecifiedError = 8,
+ RemoveError = 9,
+ RenameError = 10,
+ PositionError = 11,
+ ResizeError = 12,
+ PermissionsError = 13,
+ CopyError = 14
+#ifdef QT3_SUPPORT
+ , ConnectError = 30
+#endif
+ };
+
+ enum Permission {
+ ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
+ ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
+ ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010,
+ ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001
+ };
+ Q_DECLARE_FLAGS(Permissions, Permission)
+
+ enum FileHandleFlag {
+ AutoCloseHandle = 0x0001,
+ DontCloseHandle = 0
+ };
+ Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
+
+ QFile();
+ QFile(const QString &name);
+#ifndef QT_NO_QOBJECT
+ explicit QFile(QObject *parent);
+ QFile(const QString &name, QObject *parent);
+#endif
+ ~QFile();
+
+ FileError error() const;
+ void unsetError();
+
+ QString fileName() const;
+ void setFileName(const QString &name);
+
+ typedef QByteArray (*EncoderFn)(const QString &fileName);
+ typedef QString (*DecoderFn)(const QByteArray &localfileName);
+ static QByteArray encodeName(const QString &fileName);
+ static QString decodeName(const QByteArray &localFileName);
+ inline static QString decodeName(const char *localFileName)
+ { return decodeName(QByteArray(localFileName)); }
+ static void setEncodingFunction(EncoderFn);
+ static void setDecodingFunction(DecoderFn);
+
+ bool exists() const;
+ static bool exists(const QString &fileName);
+
+ QString readLink() const;
+ static QString readLink(const QString &fileName);
+ inline QString symLinkTarget() const { return readLink(); }
+ inline static QString symLinkTarget(const QString &fileName) { return readLink(fileName); }
+
+ bool remove();
+ static bool remove(const QString &fileName);
+
+ bool rename(const QString &newName);
+ static bool rename(const QString &oldName, const QString &newName);
+
+ bool link(const QString &newName);
+ static bool link(const QString &oldname, const QString &newName);
+
+ bool copy(const QString &newName);
+ static bool copy(const QString &fileName, const QString &newName);
+
+ bool isSequential() const;
+
+ bool open(OpenMode flags);
+ bool open(FILE *f, OpenMode flags);
+ bool open(int fd, OpenMode flags);
+#ifdef Q_OS_SYMBIAN
+ bool open(const RFile &f, OpenMode flags, FileHandleFlags handleFlags = DontCloseHandle);
+#endif
+ bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags);
+ bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags);
+ virtual void close();
+
+ qint64 size() const;
+ qint64 pos() const;
+ bool seek(qint64 offset);
+ bool atEnd() const;
+ bool flush();
+
+ bool resize(qint64 sz);
+ static bool resize(const QString &filename, qint64 sz);
+
+ Permissions permissions() const;
+ static Permissions permissions(const QString &filename);
+ bool setPermissions(Permissions permissionSpec);
+ static bool setPermissions(const QString &filename, Permissions permissionSpec);
+
+ int handle() const;
+
+ enum MemoryMapFlags {
+ NoOptions = 0
+ };
+
+ uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
+ bool unmap(uchar *address);
+
+ virtual QAbstractFileEngine *fileEngine() const;
+
+#ifdef QT3_SUPPORT
+ typedef Permission PermissionSpec;
+ inline QT3_SUPPORT QString name() const { return fileName(); }
+ inline QT3_SUPPORT void setName(const QString &aName) { setFileName(aName); }
+ inline QT3_SUPPORT bool open(OpenMode aFlags, FILE *f) { return open(f, aFlags); }
+ inline QT3_SUPPORT bool open(OpenMode aFlags, int fd) { return open(fd, aFlags); }
+#endif
+
+protected:
+#ifdef QT_NO_QOBJECT
+ QFile(QFilePrivate &dd);
+#else
+ QFile(QFilePrivate &dd, QObject *parent = 0);
+#endif
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+ qint64 readLineData(char *data, qint64 maxlen);
+
+private:
+ Q_DISABLE_COPY(QFile)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFile::Permissions)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFILE_H
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
new file mode 100644
index 0000000000..d647c958d7
--- /dev/null
+++ b/src/corelib/io/qfile_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILE_P_H
+#define QFILE_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/qabstractfileengine.h"
+#include "private/qiodevice_p.h"
+#include "private/qringbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFilePrivate : public QIODevicePrivate
+{
+ Q_DECLARE_PUBLIC(QFile)
+
+protected:
+ QFilePrivate();
+ ~QFilePrivate();
+
+ bool openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags);
+ bool openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags);
+#ifdef Q_OS_SYMBIAN
+ bool openExternalFile(int flags, const RFile& f, QFile::FileHandleFlags handleFlags);
+#endif
+
+ QString fileName;
+ mutable QAbstractFileEngine *fileEngine;
+
+ bool lastWasWrite;
+ QRingBuffer writeBuffer;
+ inline bool ensureFlushed() const;
+
+ bool putCharHelper(char c);
+
+ QFile::FileError error;
+ void setError(QFile::FileError err);
+ void setError(QFile::FileError err, const QString &errorString);
+ void setError(QFile::FileError err, int errNum);
+
+ mutable qint64 cachedSize;
+
+private:
+ static QFile::EncoderFn encoder;
+ static QFile::DecoderFn decoder;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFILE_P_H
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
new file mode 100644
index 0000000000..6b9c82c41b
--- /dev/null
+++ b/src/corelib/io/qfileinfo.cpp
@@ -0,0 +1,1399 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfileinfo.h"
+#include "qglobal.h"
+#include "qdir.h"
+#include "qfileinfo_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
+{
+ if (cache_enabled && !fileNames[(int)name].isNull())
+ return fileNames[(int)name];
+
+ QString ret;
+ if (fileEngine == 0) { // local file; use the QFileSystemEngine directly
+ switch (name) {
+ case QAbstractFileEngine::CanonicalName:
+ case QAbstractFileEngine::CanonicalPathName: {
+ QFileSystemEntry entry = QFileSystemEngine::canonicalName(fileEntry, metaData);
+ if (cache_enabled) { // be smart and store both
+ fileNames[QAbstractFileEngine::CanonicalName] = entry.filePath();
+ fileNames[QAbstractFileEngine::CanonicalPathName] = entry.path();
+ }
+ if (name == QAbstractFileEngine::CanonicalName)
+ ret = entry.filePath();
+ else
+ ret = entry.path();
+ break;
+ }
+ case QAbstractFileEngine::LinkName:
+ ret = QFileSystemEngine::getLinkTarget(fileEntry, metaData).filePath();
+ break;
+ case QAbstractFileEngine::BundleName:
+ ret = QFileSystemEngine::bundleName(fileEntry);
+ break;
+ case QAbstractFileEngine::AbsoluteName:
+ case QAbstractFileEngine::AbsolutePathName: {
+ QFileSystemEntry entry = QFileSystemEngine::absoluteName(fileEntry);
+ if (cache_enabled) { // be smart and store both
+ fileNames[QAbstractFileEngine::AbsoluteName] = entry.filePath();
+ fileNames[QAbstractFileEngine::AbsolutePathName] = entry.path();
+ }
+ if (name == QAbstractFileEngine::AbsoluteName)
+ ret = entry.filePath();
+ else
+ ret = entry.path();
+ break;
+ }
+ default: break;
+ }
+ } else {
+ ret = fileEngine->fileName(name);
+ }
+ if (ret.isNull())
+ ret = QLatin1String("");
+ if (cache_enabled)
+ fileNames[(int)name] = ret;
+ return ret;
+}
+
+QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const
+{
+ if (cache_enabled && !fileOwners[(int)own].isNull())
+ return fileOwners[(int)own];
+ QString ret;
+ if (fileEngine == 0) {
+ switch (own) {
+ case QAbstractFileEngine::OwnerUser:
+ ret = QFileSystemEngine::resolveUserName(fileEntry, metaData);
+ break;
+ case QAbstractFileEngine::OwnerGroup:
+ ret = QFileSystemEngine::resolveGroupName(fileEntry, metaData);
+ break;
+ }
+ } else {
+ ret = fileEngine->owner(own);
+ }
+ if (ret.isNull())
+ ret = QLatin1String("");
+ if (cache_enabled)
+ fileOwners[(int)own] = ret;
+ return ret;
+}
+
+uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) const
+{
+ 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
+ // 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
+ // paths, so we separate out that as well.
+
+ QAbstractFileEngine::FileFlags req = 0;
+ uint cachedFlags = 0;
+
+ if (request & (QAbstractFileEngine::FlagsMask | QAbstractFileEngine::TypesMask)) {
+ if (!getCachedFlag(CachedFileFlags)) {
+ req |= QAbstractFileEngine::FlagsMask;
+ req |= QAbstractFileEngine::TypesMask;
+ req &= (~QAbstractFileEngine::LinkType);
+ req &= (~QAbstractFileEngine::BundleType);
+
+ cachedFlags |= CachedFileFlags;
+ }
+
+ if (request & QAbstractFileEngine::LinkType) {
+ if (!getCachedFlag(CachedLinkTypeFlag)) {
+ req |= QAbstractFileEngine::LinkType;
+ cachedFlags |= CachedLinkTypeFlag;
+ }
+ }
+
+ if (request & QAbstractFileEngine::BundleType) {
+ if (!getCachedFlag(CachedBundleTypeFlag)) {
+ req |= QAbstractFileEngine::BundleType;
+ cachedFlags |= CachedBundleTypeFlag;
+ }
+ }
+ }
+
+ if (request & QAbstractFileEngine::PermsMask) {
+ if (!getCachedFlag(CachedPerms)) {
+ req |= QAbstractFileEngine::PermsMask;
+ cachedFlags |= CachedPerms;
+ }
+ }
+
+ if (req) {
+ if (cache_enabled)
+ req &= (~QAbstractFileEngine::Refresh);
+ else
+ req |= QAbstractFileEngine::Refresh;
+
+ QAbstractFileEngine::FileFlags flags = fileEngine->fileFlags(req);
+ fileFlags |= uint(flags);
+ setCachedFlag(cachedFlags);
+ }
+
+ return fileFlags & request;
+}
+
+QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) const
+{
+ Q_ASSERT(fileEngine); // should never be called when using the native FS
+ if (!cache_enabled)
+ clearFlags();
+ uint cf;
+ if (request == QAbstractFileEngine::CreationTime)
+ cf = CachedCTime;
+ else if (request == QAbstractFileEngine::ModificationTime)
+ cf = CachedMTime;
+ else
+ cf = CachedATime;
+ if (!getCachedFlag(cf)) {
+ fileTimes[request] = fileEngine->fileTime(request);
+ setCachedFlag(cf);
+ }
+ return fileTimes[request];
+}
+
+//************* QFileInfo
+
+/*!
+ \class QFileInfo
+ \reentrant
+ \brief The QFileInfo class provides system-independent file information.
+
+ \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 Mac OS X), the symlink has the same size() has
+ the file it points to, because Unix handles symlinks
+ transparently; similarly, opening a symlink using QFile
+ effectively opens the link's target. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 0
+
+ On Windows, symlinks (shortcuts) are \c .lnk files. The reported
+ size() is that of the symlink (not the link's target), and
+ opening a symlink using QFile opens the \c .lnk file. For
+ example:
+
+ \snippet doc/src/snippets/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 created(), lastModified() and
+ lastRead(). 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 Performance Issues
+
+ 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.
+
+ \note To speed up performance, QFileInfo caches information about
+ the file.
+
+ To speed up performance, QFileInfo caches information about the
+ file. 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).
+
+ \sa QDir, QFile
+*/
+
+/*!
+ \internal
+*/
+QFileInfo::QFileInfo(QFileInfoPrivate *p) : d_ptr(p)
+{
+}
+
+/*!
+ Constructs an empty QFileInfo object.
+
+ Note that an empty QFileInfo object contain no file reference.
+
+ \sa setFile()
+*/
+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.
+
+ \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
+*/
+QFileInfo::QFileInfo(const QString &file) : d_ptr(new QFileInfoPrivate(file))
+{
+}
+
+/*!
+ Constructs a new QFileInfo that gives information about file \a
+ file.
+
+ If the \a file has a relative path, the QFileInfo will also have a
+ relative path.
+
+ \sa isRelative()
+*/
+QFileInfo::QFileInfo(const QFile &file) : d_ptr(new QFileInfoPrivate(file.fileName()))
+{
+}
+
+/*!
+ Constructs a new QFileInfo that gives information about the given
+ \a file in the directory \a dir.
+
+ 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.
+
+ \sa isRelative()
+*/
+QFileInfo::QFileInfo(const QDir &dir, const QString &file)
+ : d_ptr(new QFileInfoPrivate(dir.filePath(file)))
+{
+}
+
+/*!
+ Constructs a new QFileInfo that is a copy of the given \a fileinfo.
+*/
+QFileInfo::QFileInfo(const QFileInfo &fileinfo)
+ : d_ptr(fileinfo.d_ptr)
+{
+
+}
+
+/*!
+ Destroys the QFileInfo and frees its resources.
+*/
+
+QFileInfo::~QFileInfo()
+{
+}
+
+/*!
+ \fn bool QFileInfo::operator!=(const QFileInfo &fileinfo)
+
+ Returns true if this QFileInfo object refers to a different file
+ than the one specified by \a fileinfo; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \overload
+ \fn bool QFileInfo::operator!=(const QFileInfo &fileinfo) const
+*/
+
+/*!
+ \overload
+*/
+bool QFileInfo::operator==(const QFileInfo &fileinfo) const
+{
+ Q_D(const QFileInfo);
+ // ### Qt 5: understand long and short file names on Windows
+ // ### (GetFullPathName()).
+ if (fileinfo.d_ptr == d_ptr)
+ return true;
+ if (d->isDefaultConstructed || fileinfo.d_ptr->isDefaultConstructed)
+ return false;
+ Qt::CaseSensitivity sensitive;
+ if (d->fileEngine == 0 || fileinfo.d_ptr->fileEngine == 0) {
+ if (d->fileEngine != fileinfo.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())
+ return false;
+ sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ }
+
+ if (fileinfo.size() != size()) //if the size isn't the same...
+ return false;
+
+ return canonicalFilePath().compare(fileinfo.canonicalFilePath(), sensitive) == 0;
+}
+
+/*!
+ Returns true if this QFileInfo object refers to a file in the same
+ location as \a fileinfo; otherwise returns false.
+
+ Note that the result of comparing two empty QFileInfo objects,
+ containing no file references, is undefined.
+
+ \warning This will not compare two different symbolic links
+ pointing to the same file.
+
+ \warning Long and short file names that refer to the same file on Windows
+ are treated as if they referred to different files.
+
+ \sa operator!=()
+*/
+bool QFileInfo::operator==(const QFileInfo &fileinfo)
+{
+ return const_cast<const QFileInfo *>(this)->operator==(fileinfo);
+}
+
+/*!
+ Makes a copy of the given \a fileinfo and assigns it to this QFileInfo.
+*/
+QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
+{
+ d_ptr = fileinfo.d_ptr;
+ return *this;
+}
+
+/*!
+ Sets the file that the QFileInfo provides information about to \a
+ file.
+
+ 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.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 2
+
+ \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath()
+*/
+void QFileInfo::setFile(const QString &file)
+{
+ bool caching = d_ptr.constData()->cache_enabled;
+ *this = QFileInfo(file);
+ d_ptr->cache_enabled = caching;
+}
+
+/*!
+ \overload
+
+ Sets the file that the QFileInfo provides information about to \a
+ file.
+
+ If \a file includes a relative path, the QFileInfo will also have
+ a relative path.
+
+ \sa isRelative()
+*/
+void QFileInfo::setFile(const QFile &file)
+{
+ setFile(file.fileName());
+}
+
+/*!
+ \overload
+
+ Sets the file that the QFileInfo provides information about to \a
+ file in directory \a dir.
+
+ If \a file includes a relative path, the QFileInfo will also
+ have a relative path.
+
+ \sa isRelative()
+*/
+void QFileInfo::setFile(const QDir &dir, const QString &file)
+{
+ setFile(dir.filePath(file));
+}
+
+/*!
+ Returns an absolute path including the file name.
+
+ 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.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp newstuff
+
+ This function returns the same as filePath(), unless isRelative()
+ is true. In contrast to canonicalFilePath(), symbolic links or
+ redundant "." or ".." elements are not necessarily removed.
+
+ If the QFileInfo is empty it returns QDir::currentPath().
+
+ \sa filePath(), canonicalFilePath(), isRelative()
+*/
+QString QFileInfo::absoluteFilePath() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ 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.
+
+ If the file does not exist, canonicalFilePath() returns an empty
+ string.
+
+ \sa filePath(), absoluteFilePath(), dir()
+*/
+QString QFileInfo::canonicalFilePath() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileName(QAbstractFileEngine::CanonicalName);
+}
+
+
+/*!
+ Returns a file's path absolute path. This doesn't include the
+ file name.
+
+ 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/'.
+
+ In contrast to canonicalPath() symbolic links or redundant "." or
+ ".." elements are not necessarily removed.
+
+ \warning If the QFileInfo object was created with an empty QString,
+ the behavior of this function is undefined.
+
+ \sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative()
+*/
+QString QFileInfo::absolutePath() const
+{
+ Q_D(const QFileInfo);
+
+ if (d->isDefaultConstructed) {
+ return QLatin1String("");
+ } else if (d->fileEntry.isEmpty()) {
+ qWarning("QFileInfo::absolutePath: Constructed with empty filename");
+ return QLatin1String("");
+ }
+ return d->getFileName(QAbstractFileEngine::AbsolutePathName);
+}
+
+/*!
+ Returns the file's path canonical path (excluding the file name),
+ i.e. an absolute path without symbolic links or redundant "." or ".." elements.
+
+ If the file does not exist, canonicalPath() returns an empty string.
+
+ \sa path(), absolutePath()
+*/
+QString QFileInfo::canonicalPath() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileName(QAbstractFileEngine::CanonicalPathName);
+}
+
+/*!
+ Returns the file's path. This doesn't include the file 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.
+
+ \sa filePath(), absolutePath(), canonicalPath(), dir(), fileName(), isRelative()
+*/
+QString QFileInfo::path() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.path();
+}
+
+/*!
+ \fn bool QFileInfo::isAbsolute() const
+
+ Returns true if the file path name is absolute, otherwise returns
+ false if the path is relative.
+
+ \sa isRelative()
+*/
+
+/*!
+ Returns 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 "/").
+
+ \sa isAbsolute()
+*/
+bool QFileInfo::isRelative() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return true;
+ if (d->fileEngine == 0)
+ return d->fileEntry.isRelative();
+ return d->fileEngine->isRelativePath();
+}
+
+/*!
+ Converts the file's path to an absolute path if it is not already in that form.
+ Returns true to indicate that the path was converted; otherwise returns false
+ to indicate that the path was already absolute.
+
+ \sa filePath(), isRelative()
+*/
+bool QFileInfo::makeAbsolute()
+{
+ if (d_ptr.constData()->isDefaultConstructed
+ || !d_ptr.constData()->fileEntry.isRelative())
+ return false;
+
+ setFile(absoluteFilePath());
+ return true;
+}
+
+/*!
+ Returns true if the file exists; otherwise returns false.
+
+ \note If the file is a symlink that points to a non existing
+ file, false is returned.
+*/
+bool QFileInfo::exists() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute);
+ return d->metaData.exists();
+ }
+ return d->getFileFlags(QAbstractFileEngine::ExistsFlag);
+}
+
+/*!
+ Refreshes the information about the file, i.e. reads in information
+ from the file system the next time a cached property is fetched.
+
+ \note On Windows CE, there might be a delay for the file system driver
+ to detect changes on the file.
+*/
+void QFileInfo::refresh()
+{
+ Q_D(QFileInfo);
+ d->clear();
+}
+
+/*!
+ Returns the file name, including the path (which may be absolute
+ or relative).
+
+ \sa absoluteFilePath(), canonicalFilePath(), isRelative()
+*/
+QString QFileInfo::filePath() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.filePath();
+}
+
+/*!
+ Returns the name of the file, excluding the path.
+
+ Example:
+ \snippet doc/src/snippets/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.
+
+ \sa isRelative(), filePath(), baseName(), extension()
+*/
+QString QFileInfo::fileName() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.fileName();
+}
+
+/*!
+ \since 4.3
+ Returns the name of the bundle.
+
+ On Mac OS X this returns the proper localized name for a bundle if the
+ path isBundle(). On all other platforms an empty QString is returned.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 4
+
+ \sa isBundle(), filePath(), baseName(), extension()
+*/
+QString QFileInfo::bundleName() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileName(QAbstractFileEngine::BundleName);
+}
+
+/*!
+ Returns the base name of the file without the path.
+
+ The base name consists of all characters in the file up to (but
+ not including) the \e first '.' character.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 5
+
+
+ The base name of a file is computed equally on all platforms, independent
+ of file naming conventions (e.g., ".bashrc" on Unix has an empty base
+ name, and the suffix is "bashrc").
+
+ \sa fileName(), suffix(), completeSuffix(), completeBaseName()
+*/
+QString QFileInfo::baseName() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.baseName();
+}
+
+/*!
+ Returns the complete base name of the file without the path.
+
+ The complete base name consists of all characters in the file up
+ to (but not including) the \e last '.' character.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 6
+
+ \sa fileName(), suffix(), completeSuffix(), baseName()
+*/
+QString QFileInfo::completeBaseName() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.completeBaseName();
+}
+
+/*!
+ Returns the complete suffix of the file.
+
+ The complete suffix consists of all characters in the file after
+ (but not including) the first '.'.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 7
+
+ \sa fileName(), suffix(), baseName(), completeBaseName()
+*/
+QString QFileInfo::completeSuffix() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.completeSuffix();
+}
+
+/*!
+ Returns the suffix of the file.
+
+ The suffix consists of all characters in the file after (but not
+ including) the last '.'.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 8
+
+ The suffix of a file is computed equally on all platforms, independent of
+ file naming conventions (e.g., ".bashrc" on Unix has an empty base name,
+ and the suffix is "bashrc").
+
+ \sa fileName(), completeSuffix(), baseName(), completeBaseName()
+*/
+QString QFileInfo::suffix() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->fileEntry.suffix();
+}
+
+
+/*!
+ Returns the path of the object's parent directory as a QDir object.
+
+ \bold{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 a QDir for
+ \c{"~/examples/191697"}.
+
+ \snippet doc/src/snippets/fileinfo/main.cpp 0
+
+ For each of the following, dir() returns a QDir for
+ \c{"."}.
+
+ \snippet doc/src/snippets/fileinfo/main.cpp 1
+
+ \sa absolutePath(), filePath(), fileName(), isRelative(), absoluteDir()
+*/
+QDir QFileInfo::dir() const
+{
+ Q_D(const QFileInfo);
+ // ### Qt5: Maybe rename this to parentDirectory(), considering what it actually do?
+ return QDir(d->fileEntry.path());
+}
+
+/*!
+ Returns the file's absolute path as a QDir object.
+
+ \sa dir(), filePath(), fileName(), isRelative()
+*/
+QDir QFileInfo::absoluteDir() const
+{
+ return QDir(absolutePath());
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use absoluteDir() or the dir() overload that takes no parameters
+ instead.
+*/
+QDir QFileInfo::dir(bool absPath) const
+{
+ if (absPath)
+ return absoluteDir();
+ return dir();
+}
+#endif //QT3_SUPPORT
+
+/*!
+ Returns true if the user can read the file; otherwise returns false.
+
+ \sa isWritable(), isExecutable(), permission()
+*/
+bool QFileInfo::isReadable() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserReadPermission);
+ return (d->metaData.permissions() & QFile::ReadUser) != 0;
+ }
+ return d->getFileFlags(QAbstractFileEngine::ReadUserPerm);
+}
+
+/*!
+ Returns true if the user can write to the file; otherwise returns false.
+
+ \sa isReadable(), isExecutable(), permission()
+*/
+bool QFileInfo::isWritable() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserWritePermission))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserWritePermission);
+ return (d->metaData.permissions() & QFile::WriteUser) != 0;
+ }
+ return d->getFileFlags(QAbstractFileEngine::WriteUserPerm);
+}
+
+/*!
+ Returns true if the file is executable; otherwise returns false.
+
+ \sa isReadable(), isWritable(), permission()
+*/
+bool QFileInfo::isExecutable() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserExecutePermission))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserExecutePermission);
+ return (d->metaData.permissions() & QFile::ExeUser) != 0;
+ }
+ return d->getFileFlags(QAbstractFileEngine::ExeUserPerm);
+}
+
+/*!
+ Returns true if this is a `hidden' file; otherwise returns false.
+
+ \bold{Note:} This function returns true for the special entries
+ "." and ".." on Unix, even though QDir::entryList threats them as shown.
+*/
+bool QFileInfo::isHidden() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::HiddenAttribute))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::HiddenAttribute);
+ return d->metaData.isHidden();
+ }
+ return d->getFileFlags(QAbstractFileEngine::HiddenFlag);
+}
+
+/*!
+ Returns true if this object points to a file or to a symbolic
+ link to a file. Returns false if the
+ object points to something which isn't a file, such as a directory.
+
+ \sa isDir(), isSymLink(), isBundle()
+*/
+bool QFileInfo::isFile() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::FileType))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::FileType);
+ return d->metaData.isFile();
+ }
+ return d->getFileFlags(QAbstractFileEngine::FileType);
+}
+
+/*!
+ Returns true if this object points to a directory or to a symbolic
+ link to a directory; otherwise returns false.
+
+ \sa isFile(), isSymLink(), isBundle()
+*/
+bool QFileInfo::isDir() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::DirectoryType))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::DirectoryType);
+ return d->metaData.isDirectory();
+ }
+ return d->getFileFlags(QAbstractFileEngine::DirectoryType);
+}
+
+
+/*!
+ \since 4.3
+ Returns true if this object points to a bundle or to a symbolic
+ link to a bundle on Mac OS X; otherwise returns false.
+
+ \sa isDir(), isSymLink(), isFile()
+*/
+bool QFileInfo::isBundle() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::BundleType))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::BundleType);
+ return d->metaData.isBundle();
+ }
+ return d->getFileFlags(QAbstractFileEngine::BundleType);
+}
+
+/*!
+ Returns true if this object points to a symbolic link (or to a
+ shortcut on Windows); otherwise returns false.
+
+ On Unix (including Mac OS X), opening a symlink effectively opens
+ the \l{symLinkTarget()}{link's target}. On Windows, it opens the \c
+ .lnk file itself.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 9
+
+ \note If the symlink points to a non existing file, exists() returns
+ false.
+
+ \sa isFile(), isDir(), symLinkTarget()
+*/
+bool QFileInfo::isSymLink() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::LegacyLinkType))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::LegacyLinkType);
+ return d->metaData.isLegacyLink();
+ }
+ return d->getFileFlags(QAbstractFileEngine::LinkType);
+}
+
+/*!
+ Returns true if the object points to a directory or to a symbolic
+ link to a directory, and that directory is the root directory; otherwise
+ returns false.
+*/
+bool QFileInfo::isRoot() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return true;
+ if (d->fileEngine == 0) {
+ if (d->fileEntry.isRoot()) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ //the path is a drive root, but the drive may not exist
+ //for backward compatibility, return true only if the drive exists
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute);
+ return d->metaData.exists();
+#else
+ return true;
+#endif
+ }
+ return false;
+ }
+ return d->getFileFlags(QAbstractFileEngine::RootFlag);
+}
+
+/*!
+ \fn QString QFileInfo::symLinkTarget() const
+ \since 4.2
+
+ Returns the absolute path to the file or directory a symlink (or shortcut
+ on Windows) points to, or a an empty string if the object isn't a symbolic
+ link.
+
+ This name may not represent an existing file; it is only a string.
+ QFileInfo::exists() returns true if the symlink points to an
+ existing file.
+
+ \sa exists(), isSymLink(), isDir(), isFile()
+*/
+
+/*!
+ \obsolete
+
+ Use symLinkTarget() instead.
+*/
+QString QFileInfo::readLink() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileName(QAbstractFileEngine::LinkName);
+}
+
+/*!
+ Returns the owner of the file. On systems where files
+ do not have owners, or if an error occurs, an empty string is
+ returned.
+
+ This function can be time consuming under Unix (in the order of
+ milliseconds).
+
+ \sa ownerId(), group(), groupId()
+*/
+QString QFileInfo::owner() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileOwner(QAbstractFileEngine::OwnerUser);
+}
+
+/*!
+ Returns the id of the owner of the file.
+
+ On Windows and on systems where files do not have owners this
+ function returns ((uint) -2).
+
+ \sa owner(), group(), groupId()
+*/
+uint QFileInfo::ownerId() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return 0;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserId))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserId);
+ return d->metaData.userId();
+ }
+ return d->fileEngine->ownerId(QAbstractFileEngine::OwnerUser);
+}
+
+/*!
+ Returns the group of the file. On Windows, on systems where files
+ do not have groups, or if an error occurs, an empty string is
+ returned.
+
+ This function can be time consuming under Unix (in the order of
+ milliseconds).
+
+ \sa groupId(), owner(), ownerId()
+*/
+QString QFileInfo::group() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QLatin1String("");
+ return d->getFileOwner(QAbstractFileEngine::OwnerGroup);
+}
+
+/*!
+ Returns the id of the group the file belongs to.
+
+ On Windows and on systems where files do not have groups this
+ function always returns (uint) -2.
+
+ \sa group(), owner(), ownerId()
+*/
+uint QFileInfo::groupId() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return 0;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::GroupId))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::GroupId);
+ return d->metaData.groupId();
+ }
+ return d->fileEngine->ownerId(QAbstractFileEngine::OwnerGroup);
+}
+
+/*!
+ Tests for file permissions. The \a permissions argument can be
+ several flags of type QFile::Permissions OR-ed together to check
+ for permission combinations.
+
+ On systems where files do not have permissions this function
+ always returns true.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 10
+
+ \sa isReadable(), isWritable(), isExecutable()
+*/
+bool QFileInfo::permission(QFile::Permissions permissions) const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return false;
+ if (d->fileEngine == 0) {
+ // the QFileSystemMetaData::MetaDataFlag and QFile::Permissions overlap, so just static cast.
+ QFileSystemMetaData::MetaDataFlag permissionFlags = static_cast<QFileSystemMetaData::MetaDataFlag>((int)permissions);
+ if (!d->cache_enabled || !d->metaData.hasFlags(permissionFlags))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, permissionFlags);
+ return (d->metaData.permissions() & permissions) == permissions;
+ }
+ return d->getFileFlags(QAbstractFileEngine::FileFlags((int)permissions)) == (uint)permissions;
+}
+
+/*!
+ Returns the complete OR-ed together combination of
+ QFile::Permissions for the file.
+*/
+QFile::Permissions QFileInfo::permissions() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return 0;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::Permissions))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::Permissions);
+ return d->metaData.permissions();
+ }
+ return QFile::Permissions(d->getFileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask);
+}
+
+
+/*!
+ Returns the file size in bytes. If the file does not exist or cannot be
+ fetched, 0 is returned.
+
+ \sa exists()
+*/
+qint64 QFileInfo::size() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return 0;
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::SizeAttribute))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::SizeAttribute);
+ return d->metaData.size();
+ }
+ if (!d->getCachedFlag(QFileInfoPrivate::CachedSize)) {
+ d->setCachedFlag(QFileInfoPrivate::CachedSize);
+ d->fileSize = d->fileEngine->size();
+ }
+ return d->fileSize;
+}
+
+/*!
+ Returns the date and time when the file was created.
+
+ On most Unix systems, this function returns the time of the last
+ status change. A status 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).
+
+ If neither creation time nor "last status change" time are not
+ available, returns the same as lastModified().
+
+ \sa lastModified() lastRead()
+*/
+QDateTime QFileInfo::created() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QDateTime();
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::CreationTime))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::CreationTime);
+ return d->metaData.creationTime();
+ }
+ return d->getFileTime(QAbstractFileEngine::CreationTime);
+}
+
+/*!
+ Returns the date and time when the file was last modified.
+
+ \sa created() lastRead()
+*/
+QDateTime QFileInfo::lastModified() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QDateTime();
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ModificationTime))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ModificationTime);
+ return d->metaData.modificationTime();
+ }
+ return d->getFileTime(QAbstractFileEngine::ModificationTime);
+}
+
+/*!
+ Returns the date and time when the file was last read (accessed).
+
+ On platforms where this information is not available, returns the
+ same as lastModified().
+
+ \sa created() lastModified()
+*/
+QDateTime QFileInfo::lastRead() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return QDateTime();
+ if (d->fileEngine == 0) {
+ if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::AccessTime))
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::AccessTime);
+ return d->metaData.accessTime();
+ }
+ return d->getFileTime(QAbstractFileEngine::AccessTime);
+}
+
+/*! \internal
+ Detaches all internal data.
+*/
+void QFileInfo::detach()
+{
+ d_ptr.detach();
+}
+
+/*!
+ Returns true if caching is enabled; otherwise returns false.
+
+ \sa setCaching(), refresh()
+*/
+bool QFileInfo::caching() const
+{
+ Q_D(const QFileInfo);
+ return d->cache_enabled;
+}
+
+/*!
+ If \a enable is true, enables caching of file information. If \a
+ enable is false caching is disabled.
+
+ When caching is enabled, QFileInfo reads the file information from
+ the file system the first time it's needed, but generally not
+ later.
+
+ Caching is enabled by default.
+
+ \sa refresh(), caching()
+*/
+void QFileInfo::setCaching(bool enable)
+{
+ Q_D(QFileInfo);
+ d->cache_enabled = enable;
+}
+
+/*!
+ \fn QString QFileInfo::baseName(bool complete)
+
+ Use completeBaseName() or the baseName() overload that takes no
+ parameters instead.
+*/
+
+/*!
+ \fn QString QFileInfo::extension(bool complete = true) const
+
+ Use completeSuffix() or suffix() instead.
+*/
+
+/*!
+ \fn QString QFileInfo::absFilePath() const
+
+ Use absoluteFilePath() instead.
+*/
+
+/*!
+ \fn QString QFileInfo::dirPath(bool absPath) const
+
+ Use absolutePath() if the absolute path is wanted (\a absPath
+ is true) or path() if it's not necessary (\a absPath is false).
+*/
+
+/*!
+ \fn bool QFileInfo::convertToAbs()
+
+ Use makeAbsolute() instead.
+*/
+
+/*!
+ \enum QFileInfo::Permission
+
+ \compat
+
+ \value ReadOwner
+ \value WriteOwner
+ \value ExeOwner
+ \value ReadUser
+ \value WriteUser
+ \value ExeUser
+ \value ReadGroup
+ \value WriteGroup
+ \value ExeGroup
+ \value ReadOther
+ \value WriteOther
+ \value ExeOther
+*/
+
+/*!
+ \fn bool QFileInfo::permission(PermissionSpec permissions) const
+ \compat
+
+ Use permission() instead.
+*/
+
+/*!
+ \typedef QFileInfoList
+ \relates QFileInfo
+
+ Synonym for QList<QFileInfo>.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
new file mode 100644
index 0000000000..5cfefb3a95
--- /dev/null
+++ b/src/corelib/io/qfileinfo.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEINFO_H
+#define QFILEINFO_H
+
+#include <QtCore/qfile.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QDir;
+class QDirIteratorPrivate;
+class QDateTime;
+class QFileInfoPrivate;
+
+class Q_CORE_EXPORT QFileInfo
+{
+ friend class QDirIteratorPrivate;
+public:
+ explicit QFileInfo(QFileInfoPrivate *d);
+
+ QFileInfo();
+ QFileInfo(const QString &file);
+ QFileInfo(const QFile &file);
+ QFileInfo(const QDir &dir, const QString &file);
+ QFileInfo(const QFileInfo &fileinfo);
+ ~QFileInfo();
+
+ QFileInfo &operator=(const QFileInfo &fileinfo);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QFileInfo&operator=(QFileInfo &&other)
+ { qSwap(d_ptr, other.d_ptr); return *this; }
+#endif
+ bool operator==(const QFileInfo &fileinfo); // 5.0 - remove me
+ bool operator==(const QFileInfo &fileinfo) const;
+ inline bool operator!=(const QFileInfo &fileinfo) { return !(operator==(fileinfo)); } // 5.0 - remove me
+ inline bool operator!=(const QFileInfo &fileinfo) const { return !(operator==(fileinfo)); }
+
+ void setFile(const QString &file);
+ void setFile(const QFile &file);
+ void setFile(const QDir &dir, const QString &file);
+ bool exists() const;
+ void refresh();
+
+ QString filePath() const;
+ QString absoluteFilePath() const;
+ QString canonicalFilePath() const;
+ QString fileName() const;
+ QString baseName() const;
+ QString completeBaseName() const;
+ QString suffix() const;
+ QString bundleName() const;
+ QString completeSuffix() const;
+
+ QString path() const;
+ QString absolutePath() const;
+ QString canonicalPath() const;
+ QDir dir() const;
+ QDir absoluteDir() const;
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isExecutable() const;
+ bool isHidden() const;
+
+ bool isRelative() const;
+ inline bool isAbsolute() const { return !isRelative(); }
+ bool makeAbsolute();
+
+ bool isFile() const;
+ bool isDir() const;
+ bool isSymLink() const;
+ bool isRoot() const;
+ bool isBundle() const;
+
+ QString readLink() const;
+ inline QString symLinkTarget() const { return readLink(); }
+
+ QString owner() const;
+ uint ownerId() const;
+ QString group() const;
+ uint groupId() const;
+
+ bool permission(QFile::Permissions permissions) const;
+ QFile::Permissions permissions() const;
+
+ qint64 size() const;
+
+ QDateTime created() const;
+ QDateTime lastModified() const;
+ QDateTime lastRead() const;
+
+ void detach();
+
+ bool caching() const;
+ void setCaching(bool on);
+
+#ifdef QT3_SUPPORT
+ enum Permission {
+ ReadOwner = QFile::ReadOwner, WriteOwner = QFile::WriteOwner, ExeOwner = QFile::ExeOwner,
+ ReadUser = QFile::ReadUser, WriteUser = QFile::WriteUser, ExeUser = QFile::ExeUser,
+ ReadGroup = QFile::ReadGroup, WriteGroup = QFile::WriteGroup, ExeGroup = QFile::ExeGroup,
+ ReadOther = QFile::ReadOther, WriteOther = QFile::WriteOther, ExeOther = QFile::ExeOther
+ };
+ Q_DECLARE_FLAGS(PermissionSpec, Permission)
+
+ inline QT3_SUPPORT QString baseName(bool complete) {
+ if(complete)
+ return completeBaseName();
+ return baseName();
+ }
+ inline QT3_SUPPORT QString extension(bool complete = true) const {
+ if(complete)
+ return completeSuffix();
+ return suffix();
+ }
+ inline QT3_SUPPORT QString absFilePath() const { return absoluteFilePath(); }
+
+ inline QT3_SUPPORT QString dirPath(bool absPath = false) const {
+ if(absPath)
+ return absolutePath();
+ return path();
+ }
+ QT3_SUPPORT QDir dir(bool absPath) const;
+ inline QT3_SUPPORT bool convertToAbs() { return makeAbsolute(); }
+#if !defined(Q_NO_TYPESAFE_FLAGS)
+ inline QT3_SUPPORT bool permission(PermissionSpec permissions) const
+ { return permission(QFile::Permissions(static_cast<int>(permissions))); }
+#endif
+#endif
+
+protected:
+ QSharedDataPointer<QFileInfoPrivate> d_ptr;
+private:
+ inline QFileInfoPrivate* d_func()
+ {
+ detach();
+ return const_cast<QFileInfoPrivate *>(d_ptr.constData());
+ }
+
+ inline const QFileInfoPrivate* d_func() const
+ {
+ return d_ptr.constData();
+ }
+};
+
+Q_DECLARE_TYPEINFO(QFileInfo, Q_MOVABLE_TYPE);
+
+#ifdef QT3_SUPPORT
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileInfo::PermissionSpec)
+#endif
+
+typedef QList<QFileInfo> QFileInfoList;
+#ifdef QT3_SUPPORT
+typedef QList<QFileInfo>::Iterator QFileInfoListIterator;
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFILEINFO_H
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
new file mode 100644
index 0000000000..db904c76bb
--- /dev/null
+++ b/src/corelib/io/qfileinfo_p.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEINFO_P_H
+#define QFILEINFO_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 "qfileinfo.h"
+#include "qabstractfileengine.h"
+#include "qdatetime.h"
+#include "qatomic.h"
+#include "qshareddata.h"
+#include "qfilesystemengine_p.h"
+
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileInfoPrivate : public QSharedData
+{
+public:
+ enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
+ CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
+ CachedSize =0x08, CachedPerms=0x80 };
+
+ inline QFileInfoPrivate()
+ : QSharedData(), fileEngine(0),
+ cachedFlags(0),
+ isDefaultConstructed(true),
+ cache_enabled(true), fileFlags(0), fileSize(0)
+ {}
+ inline QFileInfoPrivate(const QFileInfoPrivate &copy)
+ : QSharedData(copy),
+ fileEntry(copy.fileEntry),
+ metaData(copy.metaData),
+ fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
+ cachedFlags(0),
+#ifndef QT_NO_FSFILEENGINE
+ isDefaultConstructed(false),
+#else
+ isDefaultConstructed(!fileEngine),
+#endif
+ cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0)
+ {}
+ inline QFileInfoPrivate(const QString &file)
+ : fileEntry(QDir::fromNativeSeparators(file)),
+ fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
+ cachedFlags(0),
+#ifndef QT_NO_FSFILEENGINE
+ isDefaultConstructed(false),
+#else
+ isDefaultConstructed(!fileEngine),
+#endif
+ cache_enabled(true), fileFlags(0), fileSize(0)
+ {
+ }
+
+ inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data)
+ : QSharedData(),
+ fileEntry(file),
+ metaData(data),
+ cachedFlags(0),
+ isDefaultConstructed(false),
+ cache_enabled(true), fileFlags(0), fileSize(0)
+ {
+ }
+
+ inline void clearFlags() const {
+ fileFlags = 0;
+ cachedFlags = 0;
+ if (fileEngine)
+ (void)fileEngine->fileFlags(QAbstractFileEngine::Refresh);
+ }
+ inline void clear() {
+ metaData.clear();
+ clearFlags();
+ for (int i = QAbstractFileEngine::NFileNames - 1 ; i >= 0 ; --i)
+ fileNames[i].clear();
+ fileOwners[1].clear();
+ fileOwners[0].clear();
+ }
+
+ uint getFileFlags(QAbstractFileEngine::FileFlags) const;
+ QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
+ QString getFileName(QAbstractFileEngine::FileName) const;
+ QString getFileOwner(QAbstractFileEngine::FileOwner own) const;
+
+ QFileSystemEntry fileEntry;
+ mutable QFileSystemMetaData metaData;
+
+ QScopedPointer<QAbstractFileEngine> const fileEngine;
+
+ mutable QString fileNames[QAbstractFileEngine::NFileNames];
+ mutable QString fileOwners[2];
+
+ mutable uint cachedFlags : 30;
+ bool const isDefaultConstructed : 1; // QFileInfo is a default constructed instance
+ bool cache_enabled : 1;
+ mutable uint fileFlags;
+ mutable qint64 fileSize;
+ mutable QDateTime fileTimes[3];
+ inline bool getCachedFlag(uint c) const
+ { return cache_enabled ? (cachedFlags & c) : 0; }
+ inline void setCachedFlag(uint c) const
+ { if (cache_enabled) cachedFlags |= c; }
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QFILEINFO_P_H
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
new file mode 100644
index 0000000000..00c33bd797
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -0,0 +1,391 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemengine_p.h"
+#include <QtCore/qdir.h>
+#include <QtCore/qset.h>
+#include <QtCore/qstringbuilder.h>
+#include <QtCore/private/qabstractfileengine_p.h>
+#ifdef QT_BUILD_CORE_LIB
+#include <QtCore/private/qresource_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ Returns the canonicalized form of \a path (i.e., with all symlinks
+ resolved, and all redundant path elements removed.
+*/
+QString QFileSystemEngine::slowCanonicalized(const QString &path)
+{
+ if (path.isEmpty())
+ return path;
+
+ QFileInfo fi;
+ const QChar slash(QLatin1Char('/'));
+ QString tmpPath = path;
+ int separatorPos = 0;
+ QSet<QString> nonSymlinks;
+ QSet<QString> known;
+
+ known.insert(path);
+ do {
+#ifdef Q_OS_WIN
+ if (separatorPos == 0) {
+ 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) {
+ // volume root, skip since it can not be a symlink
+ separatorPos = 2;
+ }
+ }
+ if (separatorPos != -1)
+#endif
+ separatorPos = tmpPath.indexOf(slash, separatorPos + 1);
+ QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos);
+ if (
+#ifdef Q_OS_SYMBIAN
+ // Symbian doesn't support directory symlinks, so do not check for link unless we
+ // are handling the last path element. This not only slightly improves performance,
+ // but also saves us from lot of unnecessary platform security check failures
+ // when dealing with files under *:/private directories.
+ separatorPos == -1 &&
+#endif
+ !nonSymlinks.contains(prefix)) {
+ fi.setFile(prefix);
+ if (fi.isSymLink()) {
+ QString target = fi.symLinkTarget();
+ if(QFileInfo(target).isRelative())
+ target = fi.absolutePath() + slash + target;
+ if (separatorPos != -1) {
+ if (fi.isDir() && !target.endsWith(slash))
+ target.append(slash);
+ target.append(tmpPath.mid(separatorPos));
+ }
+ tmpPath = QDir::cleanPath(target);
+ separatorPos = 0;
+
+ if (known.contains(tmpPath))
+ return QString();
+ known.insert(tmpPath);
+ } else {
+ nonSymlinks.insert(prefix);
+ }
+ }
+ } while (separatorPos != -1);
+
+ return QDir::cleanPath(tmpPath);
+}
+
+static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry)
+{
+ if (resolvingEntry) {
+ if (!QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute)
+ || !data.exists()) {
+ data.clear();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry)
+{
+ if (resolvingEntry) {
+ if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
+ delete engine;
+ engine = 0;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
+ 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) {
+ QChar const ch = filePath[prefixSeparator];
+ if (ch == QLatin1Char('/'))
+ break;
+
+ if (ch == QLatin1Char(':')) {
+ if (prefixSeparator == 0) {
+ engine = new QResourceFileEngine(filePath);
+ return _q_checkEntry(engine, resolvingEntry);
+ }
+
+ if (prefixSeparator == 1)
+ 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('/') % filePath.mid(prefixSeparator + 1)));
+ // Recurse!
+ if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true))
+ return true;
+ }
+
+ // entry may have been clobbered at this point.
+ return false;
+ }
+
+ // There's no need to fully validate the prefix here. Consulting the
+ // unicode tables could be expensive and validation is already
+ // performed in QDir::setSearchPaths.
+ //
+ // if (!ch.isLetterOrNumber())
+ // break;
+ }
+#endif // defined(QT_BUILD_CORE_LIB)
+
+ return _q_checkEntry(entry, data, resolvingEntry);
+}
+
+/*!
+ \internal
+
+ Resolves the \a entry (see QDir::searchPaths) and returns an engine for
+ it, but never a QFSFileEngine.
+
+ \returns a file engine that can be used to access the entry. Returns 0 if
+ QFileSystemEngine API should be used to query and interact with the file
+ system object.
+*/
+QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
+ QFileSystemEntry &entry, QFileSystemMetaData &data) {
+ QFileSystemEntry copy = entry;
+ QAbstractFileEngine *engine = 0;
+
+ if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
+ // Reset entry to resolved copy.
+ entry = copy;
+ else
+ data.clear();
+
+ return engine;
+}
+
+//these unix functions are in this file, because they are shared by symbian port
+//for open C file handles.
+#ifdef Q_OS_UNIX
+//static
+bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
+{
+ data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
+ data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
+
+ QT_STATBUF statBuffer;
+ if (QT_FSTAT(fd, &statBuffer) == 0) {
+ data.fillFromStatBuf(statBuffer);
+ return true;
+ }
+
+ return false;
+}
+
+void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
+{
+ // Permissions
+ if (statBuffer.st_mode & S_IRUSR)
+ entryFlags |= QFileSystemMetaData::OwnerReadPermission;
+ if (statBuffer.st_mode & S_IWUSR)
+ entryFlags |= QFileSystemMetaData::OwnerWritePermission;
+ if (statBuffer.st_mode & S_IXUSR)
+ entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
+
+ if (statBuffer.st_mode & S_IRGRP)
+ entryFlags |= QFileSystemMetaData::GroupReadPermission;
+ if (statBuffer.st_mode & S_IWGRP)
+ entryFlags |= QFileSystemMetaData::GroupWritePermission;
+ if (statBuffer.st_mode & S_IXGRP)
+ entryFlags |= QFileSystemMetaData::GroupExecutePermission;
+
+ if (statBuffer.st_mode & S_IROTH)
+ entryFlags |= QFileSystemMetaData::OtherReadPermission;
+ if (statBuffer.st_mode & S_IWOTH)
+ entryFlags |= QFileSystemMetaData::OtherWritePermission;
+ if (statBuffer.st_mode & S_IXOTH)
+ entryFlags |= QFileSystemMetaData::OtherExecutePermission;
+
+ // Type
+ if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
+ entryFlags |= QFileSystemMetaData::FileType;
+ else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
+ entryFlags |= QFileSystemMetaData::DirectoryType;
+ else
+ entryFlags |= QFileSystemMetaData::SequentialType;
+
+ // Attributes
+ entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ size_ = statBuffer.st_size;
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) \
+ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if (statBuffer.st_flags & UF_HIDDEN) {
+ entryFlags |= QFileSystemMetaData::HiddenAttribute;
+ knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
+ }
+#endif
+
+ // Times
+#ifdef Q_OS_SYMBIAN
+ modificationTime_ = qt_symbian_time_t_To_TTime(statBuffer.st_mtime);
+#else
+ creationTime_ = statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime;
+ modificationTime_ = statBuffer.st_mtime;
+ accessTime_ = statBuffer.st_atime;
+ userId_ = statBuffer.st_uid;
+ groupId_ = statBuffer.st_gid;
+#endif
+}
+
+void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
+{
+#if defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4) || defined(Q_OS_SYMBIAN)
+ // BSD4 includes Mac OS X
+
+ // ### This will clear all entry flags and knownFlagsMask
+ switch (entry.d_type)
+ {
+ case DT_DIR:
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_BLK:
+ case DT_CHR:
+ case DT_FIFO:
+ case DT_SOCK:
+ // ### System attribute
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::AliasType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_LNK:
+ knownFlagsMask = QFileSystemMetaData::LinkType;
+ entryFlags = QFileSystemMetaData::LinkType;
+ break;
+
+ case DT_REG:
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::FileType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_UNKNOWN:
+ default:
+ clear();
+ }
+#else
+ Q_UNUSED(entry)
+#endif
+}
+
+#endif
+
+//static
+QString QFileSystemEngine::resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
+{
+#if defined (Q_OS_SYMBIAN)
+ Q_UNUSED(entry);
+ Q_UNUSED(metaData);
+ return QString();
+#elif defined(Q_OS_WIN)
+ Q_UNUSED(metaData);
+ return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerUser);
+#else //(Q_OS_UNIX)
+ if (!metaData.hasFlags(QFileSystemMetaData::UserId))
+ QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::UserId);
+ return resolveUserName(metaData.userId());
+#endif
+}
+
+//static
+QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
+{
+#if defined (Q_OS_SYMBIAN)
+ Q_UNUSED(entry);
+ Q_UNUSED(metaData);
+ return QString();
+#elif defined(Q_OS_WIN)
+ Q_UNUSED(metaData);
+ return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerGroup);
+#else //(Q_OS_UNIX)
+ if (!metaData.hasFlags(QFileSystemMetaData::GroupId))
+ QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::GroupId);
+ return resolveGroupName(metaData.groupId());
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_mac.cpp b/src/corelib/io/qfilesystemengine_mac.cpp
new file mode 100644
index 0000000000..1c0056bff4
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_mac.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// Mac-specific implementations only!
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
new file mode 100644
index 0000000000..d6033e66e7
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMENGINE_P_H_INCLUDED
+#define QFILESYSTEMENGINE_P_H_INCLUDED
+
+//
+// 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 "qfile.h"
+#include "qfilesystementry_p.h"
+#include "qfilesystemmetadata_p.h"
+#include <QtCore/private/qsystemerror_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemEngine
+{
+public:
+ static bool isCaseSensitive();
+
+ static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
+ static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
+ static QFileSystemEntry absoluteName(const QFileSystemEntry &entry);
+ static QString resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
+ static QString resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ static QString resolveUserName(uint userId);
+ static QString resolveGroupName(uint groupId);
+#endif
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ static QString bundleName(const QFileSystemEntry &entry);
+#else
+ static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
+#endif
+
+ static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what);
+#if defined(Q_OS_UNIX)
+ static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
+#endif
+#if defined(Q_OS_WIN)
+
+ static bool uncListSharesOnServer(const QString &server, QStringList *list); //Used also by QFSFileEngineIterator::hasNext()
+ static bool fillMetaData(int fd, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what);
+ static bool fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what);
+ static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what);
+ static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
+ static QString nativeAbsoluteFilePath(const QString &path);
+#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 removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents);
+
+ static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
+
+ static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
+ static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
+ static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
+
+ static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
+ QFileSystemMetaData *data = 0);
+
+ static bool setCurrentPath(const QFileSystemEntry &entry);
+ static QFileSystemEntry currentPath();
+
+ static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
+ QFileSystemMetaData &data);
+private:
+ static QString slowCanonicalized(const QString &path);
+#if defined(Q_OS_WIN)
+ static void clearWinStatData(QFileSystemMetaData &data);
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // include guard
diff --git a/src/corelib/io/qfilesystemengine_symbian.cpp b/src/corelib/io/qfilesystemengine_symbian.cpp
new file mode 100644
index 0000000000..41a550aa1f
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_symbian.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemengine_p.h"
+#include "qfsfileengine.h"
+#include <QtCore/private/qcore_symbian_p.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <f32file.h>
+#include <pathinfo.h>
+#include <wchar.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QFileSystemEngine::isCaseSensitive()
+{
+ return false;
+}
+
+//TODO: resolve this with QDir::cleanPath, without breaking the behaviour of that
+//function which is documented only by autotest
+//input: a dirty absolute path, e.g. c:/../../foo/./
+//output: a clean absolute path, e.g. c:/foo/
+static QString symbianCleanAbsolutePath(const QString& path)
+{
+ bool isDir = path.endsWith(QLatin1Char('/'));
+ //using SkipEmptyParts flag to eliminate duplicated slashes
+ QStringList components = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ int cdups = 0;
+ for(int i=components.count() - 1; i>=0; --i) {
+ if(components.at(i) == QLatin1String("..")) {
+ components.removeAt(i);
+ cdups++;
+ }
+ else if(components.at(i) == QLatin1String(".")) {
+ components.removeAt(i);
+ }
+ else if(cdups && i > 0) {
+ --cdups;
+ components.removeAt(i);
+ }
+ }
+ QString result = components.join(QLatin1String("/"));
+ if ((isDir&& !result.endsWith(QLatin1Char('/')))
+ || (result.length() == 2 && result.at(1).unicode() == ':'))
+ result.append(QLatin1Char('/'));
+ return result;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
+{
+ Q_UNUSED(data);
+ return link;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
+{
+ if (entry.isEmpty() || entry.isRoot())
+ return entry;
+
+ QFileSystemEntry result = absoluteName(entry);
+ if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute))
+ fillMetaData(result, data, QFileSystemMetaData::ExistsAttribute);
+ if (!data.exists()) {
+ // file doesn't exist
+ return QFileSystemEntry();
+ } else {
+ return result;
+ }
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
+{
+ QString orig = entry.filePath();
+ const bool isAbsolute = entry.isAbsolute();
+ const bool isDirty = (orig.contains(QLatin1String("/../")) || orig.contains(QLatin1String("/./")) ||
+ orig.contains(QLatin1String("//")) ||
+ orig.endsWith(QLatin1String("/..")) || orig.endsWith(QLatin1String("/.")));
+ if (isAbsolute && !isDirty)
+ return entry;
+
+ const bool isRelative = entry.isRelative();
+ const bool needsDrive = (!orig.isEmpty() && orig.at(0).unicode() == '/');
+ const bool isDriveLetter = !needsDrive && !isAbsolute && !isRelative && orig.length() == 2;
+ const bool isDriveRelative = !needsDrive && !isAbsolute && !isRelative && orig.length() > 2;
+
+ QString result;
+ if (needsDrive || isDriveLetter || isDriveRelative || !isAbsolute || orig.isEmpty()) {
+ QFileSystemEntry cur(currentPath());
+ if(needsDrive)
+ result = cur.filePath().left(2);
+ else if(isDriveRelative && cur.filePath().at(0) != orig.at(0))
+ result = orig.left(2); // for BC, see tst_QFileInfo::absolutePath(<not current drive>:my.dll)
+ else
+ result = cur.filePath();
+ if(isDriveLetter) {
+ result[0] = orig.at(0); //copy drive letter
+ orig.clear();
+ }
+ if(isDriveRelative) {
+ orig = orig.mid(2); //discard the drive specifier from orig
+ }
+ }
+ if (!orig.isEmpty() && !(orig.length() == 1 && orig.at(0).unicode() == '.')) {
+ if (!result.isEmpty() && !result.endsWith(QLatin1Char('/')))
+ result.append(QLatin1Char('/'));
+ result.append(orig);
+ }
+
+ return QFileSystemEntry(symbianCleanAbsolutePath(result), QFileSystemEntry::FromInternalPath());
+}
+
+void QFileSystemMetaData::fillFromTEntry(const TEntry& entry)
+{
+ entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags);
+ knownFlagsMask |= QFileSystemMetaData::SymbianTEntryFlags;
+ //Symbian doesn't have unix type file permissions
+ entryFlags |= QFileSystemMetaData::ReadPermissions;
+ if(!entry.IsReadOnly()) {
+ entryFlags |= QFileSystemMetaData::WritePermissions;
+ }
+ //set the type
+ if(entry.IsDir())
+ entryFlags |= (QFileSystemMetaData::DirectoryType | QFileSystemMetaData::ExecutePermissions);
+ else
+ entryFlags |= QFileSystemMetaData::FileType;
+
+ //set the attributes
+ entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ if(entry.IsHidden())
+ entryFlags |= QFileSystemMetaData::HiddenAttribute;
+
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ size_ = entry.FileSize();
+#else
+ size_ = (TUint)(entry.iSize);
+#endif
+
+ modificationTime_ = entry.iModified;
+}
+
+void QFileSystemMetaData::fillFromVolumeInfo(const TVolumeInfo& info)
+{
+ entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags);
+ knownFlagsMask |= QFileSystemMetaData::SymbianTEntryFlags;
+ entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ entryFlags |= QFileSystemMetaData::Permissions;
+ if(info.iDrive.iDriveAtt & KDriveAttRom) {
+ entryFlags &= ~(QFileSystemMetaData::WritePermissions);
+ }
+ entryFlags |= QFileSystemMetaData::DirectoryType;
+ size_ = info.iSize;
+ modificationTime_ = qt_symbian_time_t_To_TTime(0);
+}
+
+//static
+bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
+{
+ if (what & QFileSystemMetaData::SymbianTEntryFlags) {
+ RFs& fs(qt_s60GetRFs());
+ TInt err;
+ QFileSystemEntry absentry(absoluteName(entry));
+ if (entry.isEmpty()) {
+ err = KErrNotFound;
+ } else if (absentry.isRoot()) {
+ //Root directories don't have an entry, and Entry() returns KErrBadName.
+ //Therefore get information about the volume instead.
+ TInt drive;
+ err = RFs::CharToDrive(TChar(absentry.nativeFilePath().at(0).unicode()), drive);
+ if (!err) {
+ TVolumeInfo info;
+ err = fs.Volume(info, drive);
+ if (!err)
+ data.fillFromVolumeInfo(info);
+ }
+ } else {
+ TEntry ent;
+ err = fs.Entry(qt_QString2TPtrC(absentry.nativeFilePath()), ent);
+ if (!err)
+ data.fillFromTEntry(ent);
+ }
+ if (err) {
+ data.size_ = 0;
+ data.modificationTime_ = TTime(0);
+ data.entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags);
+ }
+ //files in /sys/bin on any drive are executable, even though we don't normally have permission to check whether they exist or not
+ if(absentry.filePath().midRef(1,10).compare(QLatin1String(":/sys/bin/"), Qt::CaseInsensitive) == 0)
+ data.entryFlags |= QFileSystemMetaData::ExecutePermissions;
+ }
+ return data.hasFlags(what);
+}
+
+//static
+bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
+{
+ QString abspath = absoluteName(entry).nativeFilePath();
+ if (!abspath.endsWith(QLatin1Char('\\')))
+ abspath.append(QLatin1Char('\\'));
+ TInt r;
+ if (createParents)
+ r = qt_s60GetRFs().MkDirAll(qt_QString2TPtrC(abspath));
+ else
+ r = qt_s60GetRFs().MkDir(qt_QString2TPtrC(abspath));
+ if (createParents && r == KErrAlreadyExists)
+ return true; //# Qt5 - QDir::mkdir returns false for existing dir, QDir::mkpath returns true (should be made consistent in Qt 5)
+ return (r == KErrNone);
+}
+
+//static
+bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
+{
+ QString abspath = absoluteName(entry).nativeFilePath();
+ if (!abspath.endsWith(QLatin1Char('\\')))
+ abspath.append(QLatin1Char('\\'));
+ TPtrC dir(qt_QString2TPtrC(abspath));
+ RFs& fs = qt_s60GetRFs();
+ bool ok = false;
+ //behaviour of FS file engine:
+ //returns true if the directory could be removed
+ //success/failure of removing parent directories does not matter
+ while (KErrNone == fs.RmDir(dir)) {
+ ok = true;
+ if (!removeEmptyParents)
+ break;
+ //RFs::RmDir treats "c:\foo\bar" and "c:\foo\" the same, so it is sufficient to remove the last \ to the end
+ dir.Set(dir.Left(dir.LocateReverse(TChar('\\'))));
+ }
+ return ok;
+}
+
+//static
+bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ Q_UNUSED(source)
+ Q_UNUSED(target)
+ error = QSystemError(KErrNotSupported, QSystemError::NativeError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ //CFileMan is allocated each time because it is not thread-safe
+ CFileMan *fm = 0;
+ TRAPD(err, fm = CFileMan::NewL(qt_s60GetRFs()));
+ if (err == KErrNone) {
+ err = fm->Copy(qt_QString2TPtrC(absoluteName(source).nativeFilePath()), qt_QString2TPtrC(absoluteName(target).nativeFilePath()), 0);
+ delete fm;
+ }
+ if (err == KErrNone)
+ return true;
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ QString sourcepath = absoluteName(source).nativeFilePath();
+ QString targetpath = absoluteName(target).nativeFilePath();
+ RFs& fs(qt_s60GetRFs());
+ TInt err = fs.Rename(qt_QString2TPtrC(sourcepath), qt_QString2TPtrC(targetpath));
+ if (err == KErrNone)
+ return true;
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
+{
+ QString targetpath = absoluteName(entry).nativeFilePath();
+ RFs& fs(qt_s60GetRFs());
+ TInt err = fs.Delete(qt_QString2TPtrC(targetpath));
+ if (err == KErrNone)
+ return true;
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
+{
+ QString targetpath = absoluteName(entry).nativeFilePath();
+ TUint setmask = 0;
+ TUint clearmask = 0;
+ RFs& fs(qt_s60GetRFs());
+ if (permissions & (QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther))
+ clearmask = KEntryAttReadOnly; //if anyone can write, it's not read-only
+ else
+ setmask = KEntryAttReadOnly;
+ TInt err = fs.SetAtt(qt_QString2TPtrC(targetpath), setmask, clearmask);
+ if (data && !err) {
+ data->entryFlags &= ~QFileSystemMetaData::Permissions;
+ data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
+ data->knownFlagsMask |= QFileSystemMetaData::Permissions;
+ }
+ if (err == KErrNone)
+ return true;
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+}
+
+QString QFileSystemEngine::homePath()
+{
+ QString home = QDir::fromNativeSeparators(qt_TDesC2QString(PathInfo::PhoneMemoryRootPath()));
+ if(home.endsWith(QLatin1Char('/')))
+ home.chop(1);
+ return home;
+}
+
+QString QFileSystemEngine::rootPath()
+{
+ TChar drive;
+ TInt err = RFs::DriveToChar(RFs::GetSystemDrive(), drive); //RFs::GetSystemDriveChar not supported on S60 3.1
+ Q_ASSERT(err == KErrNone); //RFs::GetSystemDrive() shall always return a convertible drive number on a valid OS configuration
+ return QString(QChar(drive)).append(QLatin1String(":/"));
+}
+
+QString QFileSystemEngine::tempPath()
+{
+ return rootPath().append(QLatin1String("system/temp"));
+}
+
+//static
+bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry)
+{
+ QFileSystemMetaData meta;
+ QFileSystemEntry absname = absoluteName(entry);
+ fillMetaData(absname, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType);
+ if(!(meta.exists() && meta.isDirectory()))
+ return false;
+
+ RFs& fs = qt_s60GetRFs();
+ QString abspath = absname.nativeFilePath();
+ if(!abspath.endsWith(QLatin1Char('\\')))
+ abspath.append(QLatin1Char('\\'));
+ TInt r = fs.SetSessionPath(qt_QString2TPtrC(abspath));
+ //SetSessionPath succeeds for non existent directory, which is why it's checked above
+ if (r == KErrNone) {
+ __ASSERT_COMPILE(sizeof(wchar_t) == sizeof(unsigned short));
+ //attempt to set open C to the same path
+ r = ::wchdir(reinterpret_cast<const wchar_t *>(absname.filePath().utf16()));
+ if (r < 0)
+ qWarning("failed to sync path to open C");
+ return true;
+ }
+ return false;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::currentPath()
+{
+ TFileName fn;
+ QFileSystemEntry ret;
+ TInt r = qt_s60GetRFs().SessionPath(fn);
+ if(r == KErrNone) {
+ //remove terminating slash from non root paths (session path is clean, absolute and always ends in a \)
+ if(fn.Length() > 3 && fn[fn.Length() - 1] == '\\')
+ fn.SetLength(fn.Length() - 1);
+ ret = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath());
+ }
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
new file mode 100644
index 0000000000..c9ebaa48bc
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -0,0 +1,660 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfilesystemengine_p.h"
+#include "qplatformdefs.h"
+#include "qfsfileengine.h"
+#include "qfile.h"
+
+#include <QtCore/qvarlengtharray.h>
+
+#include <stdlib.h> // for realpath()
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+#if defined(Q_OS_MAC)
+# include <QtCore/private/qcore_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+static inline bool _q_isMacHidden(const char *nativePath)
+{
+ OSErr err;
+
+ FSRef fsRef;
+ err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath),
+ kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
+ if (err != noErr)
+ return false;
+
+ FSCatalogInfo catInfo;
+ err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL);
+ if (err != noErr)
+ return false;
+
+ FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
+ return (fileInfo->finderFlags & kIsInvisible);
+}
+#else
+static inline bool _q_isMacHidden(const char *nativePath)
+{
+ Q_UNUSED(nativePath);
+ // no-op
+ return false;
+}
+#endif
+
+bool QFileSystemEngine::isCaseSensitive()
+{
+ return true;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
+{
+#if defined(__GLIBC__) && !defined(PATH_MAX)
+#define PATH_CHUNK_SIZE 256
+ char *s = 0;
+ int len = -1;
+ int size = PATH_CHUNK_SIZE;
+
+ while (1) {
+ s = (char *) ::realloc(s, size);
+ Q_CHECK_PTR(s);
+ len = ::readlink(link.nativeFilePath().constData(), s, size);
+ if (len < 0) {
+ ::free(s);
+ break;
+ }
+ if (len < size) {
+ break;
+ }
+ size *= 2;
+ }
+#else
+ char s[PATH_MAX+1];
+ int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX);
+#endif
+ if (len > 0) {
+ QString ret;
+ if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
+ fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
+ if (data.isDirectory() && s[0] != '/') {
+ QDir parent(link.filePath());
+ parent.cdUp();
+ ret = parent.path();
+ if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
+ ret += QLatin1Char('/');
+ }
+ s[len] = '\0';
+ ret += QFile::decodeName(QByteArray(s));
+#if defined(__GLIBC__) && !defined(PATH_MAX)
+ ::free(s);
+#endif
+
+ if (!ret.startsWith(QLatin1Char('/'))) {
+ if (link.filePath().startsWith(QLatin1Char('/'))) {
+ ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/')))
+ + QLatin1Char('/'));
+ } else {
+ ret.prepend(QDir::currentPath() + QLatin1Char('/'));
+ }
+ }
+ ret = QDir::cleanPath(ret);
+ if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
+ ret.chop(1);
+ return QFileSystemEntry(ret);
+ }
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ {
+ FSRef fref;
+ if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) {
+ // TODO get the meta data info from the QFileSystemMetaData object
+ Boolean isAlias, isFolder;
+ if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) {
+ AliasHandle alias;
+ if (FSNewAlias(0, &fref, &alias) == noErr && alias) {
+ QCFString cfstr;
+ if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr)
+ return QFileSystemEntry(QCFString::toQString(cfstr));
+ }
+ }
+ }
+ }
+#endif
+ return QFileSystemEntry();
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
+{
+ if (entry.isEmpty() || entry.isRoot())
+ return entry;
+
+#if !defined(Q_OS_MAC) && _POSIX_VERSION < 200809L
+ // realpath(X,0) is not supported
+ Q_UNUSED(data);
+ return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
+#else
+ char *ret = 0;
+# if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES)
+ // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here.
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
+ ret = realpath(entry.nativeFilePath().constData(), (char*)0);
+ } else {
+ // on 10.5 we can use FSRef to resolve the file path.
+ QString path = QDir::cleanPath(entry.filePath());
+ FSRef fsref;
+ if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) {
+ CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref);
+ CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle);
+ QString ret = QCFString::toQString(canonicalPath);
+ CFRelease(canonicalPath);
+ CFRelease(urlref);
+ return QFileSystemEntry(ret);
+ }
+ }
+# else
+ ret = realpath(entry.nativeFilePath().constData(), (char*)0);
+# endif
+ if (ret) {
+ data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
+ data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret));
+ free(ret);
+ return QFileSystemEntry(canonicalPath);
+ } else if (errno == ENOENT) { // file doesn't exist
+ data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
+ data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute);
+ return QFileSystemEntry();
+ }
+ return entry;
+#endif
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
+{
+ if (entry.isAbsolute())
+ return entry;
+
+ QByteArray orig = entry.nativeFilePath();
+ QByteArray result;
+ if (orig.isEmpty() || !orig.startsWith('/')) {
+ QFileSystemEntry cur(currentPath());
+ result = cur.nativeFilePath();
+ }
+ if (!orig.isEmpty() && !(orig.length() == 1 && orig[0] == '.')) {
+ if (!result.isEmpty() && !result.endsWith('/'))
+ result.append('/');
+ result.append(orig);
+ }
+
+ if (result.length() == 1 && result[0] == '/')
+ return QFileSystemEntry(result, QFileSystemEntry::FromNativePath());
+ const bool isDir = result.endsWith('/');
+
+ /* as long as QDir::cleanPath() operates on a QString we have to convert to a string here.
+ * ideally we never convert to a string since that loses information. Please fix after
+ * we get a QByteArray version of QDir::cleanPath()
+ */
+ QFileSystemEntry resultingEntry(result, QFileSystemEntry::FromNativePath());
+ QString stringVersion = QDir::cleanPath(resultingEntry.filePath());
+ if (isDir)
+ stringVersion.append(QLatin1Char('/'));
+ return QFileSystemEntry(stringVersion);
+}
+
+//static
+QString QFileSystemEngine::resolveUserName(uint userId)
+{
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+ int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (size_max == -1)
+ size_max = 1024;
+ QVarLengthArray<char, 1024> buf(size_max);
+#endif
+
+ struct passwd *pw = 0;
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+ struct passwd entry;
+ getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw);
+#else
+ pw = getpwuid(userId);
+#endif
+ if (pw)
+ return QFile::decodeName(QByteArray(pw->pw_name));
+ return QString();
+}
+
+//static
+QString QFileSystemEngine::resolveGroupName(uint groupId)
+{
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+ int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (size_max == -1)
+ size_max = 1024;
+ QVarLengthArray<char, 1024> buf(size_max);
+#endif
+
+ struct group *gr = 0;
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+ size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (size_max == -1)
+ size_max = 1024;
+ buf.resize(size_max);
+ 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)
+ {
+ buf.resize(size);
+ // ERANGE indicates that the buffer was too small
+ if (!getgrgid_r(groupId, &entry, buf.data(), buf.size(), &gr)
+ || errno != ERANGE)
+ break;
+ }
+#else
+ gr = getgrgid(groupId);
+#endif
+ if (gr)
+ return QFile::decodeName(QByteArray(gr->gr_name));
+ return QString();
+}
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+//static
+QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
+{
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(entry.filePath()),
+ kCFURLPOSIXPathStyle, true);
+ if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(url)) {
+ if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
+ if (CFGetTypeID(name) == CFStringGetTypeID())
+ return QCFString::toQString((CFStringRef)name);
+ }
+ }
+ return QString();
+}
+#endif
+
+//static
+bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what)
+{
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ if (what & QFileSystemMetaData::BundleType) {
+ if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
+ what |= QFileSystemMetaData::DirectoryType;
+ }
+#endif
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) \
+ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if (what & QFileSystemMetaData::HiddenAttribute) {
+ // Mac OS >= 10.5: st_flags & UF_HIDDEN
+ what |= QFileSystemMetaData::PosixStatFlags;
+ }
+#endif
+
+ if (what & QFileSystemMetaData::PosixStatFlags)
+ what |= QFileSystemMetaData::PosixStatFlags;
+
+ if (what & QFileSystemMetaData::ExistsAttribute) {
+ // FIXME: Would other queries being performed provide this bit?
+ what |= QFileSystemMetaData::PosixStatFlags;
+ }
+
+ data.entryFlags &= ~what;
+
+ const char * nativeFilePath;
+ int nativeFilePathLength;
+ {
+ const QByteArray &path = entry.nativeFilePath();
+ nativeFilePath = path.constData();
+ nativeFilePathLength = path.size();
+ }
+
+ bool entryExists = true; // innocent until proven otherwise
+
+ QT_STATBUF statBuffer;
+ bool statBufferValid = false;
+ if (what & QFileSystemMetaData::LinkType) {
+ if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
+ if (S_ISLNK(statBuffer.st_mode)) {
+ data.entryFlags |= QFileSystemMetaData::LinkType;
+ } else {
+ statBufferValid = true;
+ data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
+ }
+ } else {
+ entryExists = false;
+ }
+
+ data.knownFlagsMask |= QFileSystemMetaData::LinkType;
+ }
+
+ if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
+ if (entryExists && !statBufferValid)
+ statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
+
+ if (statBufferValid)
+ data.fillFromStatBuf(statBuffer);
+ else {
+ entryExists = false;
+ data.creationTime_ = 0;
+ data.modificationTime_ = 0;
+ data.accessTime_ = 0;
+ data.size_ = 0;
+ data.userId_ = (uint) -2;
+ data.groupId_ = (uint) -2;
+ }
+
+ // reset the mask
+ data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags
+ | QFileSystemMetaData::ExistsAttribute;
+ }
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ if (what & QFileSystemMetaData::AliasType)
+ {
+ if (entryExists) {
+ FSRef fref;
+ if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) {
+ Boolean isAlias, isFolder;
+ if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) {
+ if (isAlias)
+ data.entryFlags |= QFileSystemMetaData::AliasType;
+ }
+ }
+ }
+ data.knownFlagsMask |= QFileSystemMetaData::AliasType;
+ }
+#endif
+
+ if (what & QFileSystemMetaData::UserPermissions) {
+ // calculate user permissions
+
+ if (entryExists) {
+ if (what & QFileSystemMetaData::UserReadPermission) {
+ if (QT_ACCESS(nativeFilePath, R_OK) == 0)
+ data.entryFlags |= QFileSystemMetaData::UserReadPermission;
+ }
+ if (what & QFileSystemMetaData::UserWritePermission) {
+ if (QT_ACCESS(nativeFilePath, W_OK) == 0)
+ data.entryFlags |= QFileSystemMetaData::UserWritePermission;
+ }
+ if (what & QFileSystemMetaData::UserExecutePermission) {
+ if (QT_ACCESS(nativeFilePath, X_OK) == 0)
+ data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
+ }
+ }
+ data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions);
+ }
+
+ if (what & QFileSystemMetaData::HiddenAttribute
+ && !data.isHidden()) {
+ QString fileName = entry.fileName();
+ if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
+ || (entryExists && _q_isMacHidden(nativeFilePath)))
+ data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
+ data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
+ }
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ if (what & QFileSystemMetaData::BundleType) {
+ if (entryExists && data.isDirectory()) {
+ QCFType<CFStringRef> path = CFStringCreateWithBytes(0,
+ (const UInt8*)nativeFilePath, nativeFilePathLength,
+ kCFStringEncodingUTF8, false);
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path,
+ kCFURLPOSIXPathStyle, true);
+
+ UInt32 type, creator;
+ if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
+ data.entryFlags |= QFileSystemMetaData::BundleType;
+ }
+
+ data.knownFlagsMask |= QFileSystemMetaData::BundleType;
+ }
+#endif
+
+ return data.hasFlags(what);
+}
+
+//static
+bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
+{
+ QString dirName = entry.filePath();
+ if (createParents) {
+ dirName = QDir::cleanPath(dirName);
+ for (int oldslash = -1, slash=0; slash != -1; oldslash = slash) {
+ slash = dirName.indexOf(QDir::separator(), oldslash+1);
+ if (slash == -1) {
+ if (oldslash == dirName.length())
+ break;
+ slash = dirName.length();
+ }
+ if (slash) {
+ QByteArray chunk = QFile::encodeName(dirName.left(slash));
+ QT_STATBUF st;
+ if (QT_STAT(chunk, &st) != -1) {
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ return false;
+ } else if (QT_MKDIR(chunk, 0777) != 0) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s
+ if (dirName.endsWith(QLatin1Char('/')))
+ dirName.chop(1);
+#endif
+ return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0);
+}
+
+//static
+bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
+{
+ if (removeEmptyParents) {
+ QString dirName = QDir::cleanPath(entry.filePath());
+ for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
+ QByteArray chunk = QFile::encodeName(dirName.left(slash));
+ QT_STATBUF st;
+ if (QT_STAT(chunk, &st) != -1) {
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ return false;
+ if (::rmdir(chunk) != 0)
+ return oldslash != 0;
+ } else {
+ return false;
+ }
+ slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
+ }
+ return true;
+ }
+ return rmdir(QFile::encodeName(entry.filePath())) == 0;
+}
+
+//static
+bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ if (::symlink(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
+ return true;
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ Q_UNUSED(source);
+ Q_UNUSED(target);
+ error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
+ return false;
+}
+
+//static
+bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
+ return true;
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
+{
+ if (unlink(entry.nativeFilePath().constData()) == 0)
+ return true;
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+
+}
+
+//static
+bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
+{
+ mode_t mode = 0;
+ if (permissions & QFile::ReadOwner)
+ mode |= S_IRUSR;
+ if (permissions & QFile::WriteOwner)
+ mode |= S_IWUSR;
+ if (permissions & QFile::ExeOwner)
+ mode |= S_IXUSR;
+ if (permissions & QFile::ReadUser)
+ mode |= S_IRUSR;
+ if (permissions & QFile::WriteUser)
+ mode |= S_IWUSR;
+ if (permissions & 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;
+
+ bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;
+ if (success && data) {
+ data->entryFlags &= ~QFileSystemMetaData::Permissions;
+ data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
+ data->knownFlagsMask |= QFileSystemMetaData::Permissions;
+ }
+ if (!success)
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return success;
+}
+
+QString QFileSystemEngine::homePath()
+{
+ QString home = QFile::decodeName(qgetenv("HOME"));
+ if (home.isNull())
+ home = rootPath();
+ return QDir::cleanPath(home);
+}
+
+QString QFileSystemEngine::rootPath()
+{
+ return QLatin1String("/");
+}
+
+QString QFileSystemEngine::tempPath()
+{
+#ifdef QT_UNIX_TEMP_PATH_OVERRIDE
+ return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE);
+#else
+ QString temp = QFile::decodeName(qgetenv("TMPDIR"));
+ if (temp.isEmpty())
+ temp = QLatin1String("/tmp/");
+ return QDir::cleanPath(temp);
+#endif
+}
+
+bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path)
+{
+ int r;
+ r = QT_CHDIR(path.nativeFilePath());
+ return r >= 0;
+}
+
+QFileSystemEntry QFileSystemEngine::currentPath()
+{
+ QFileSystemEntry result;
+ QT_STATBUF st;
+ if (QT_STAT(".", &st) == 0) {
+#if defined(__GLIBC__) && !defined(PATH_MAX)
+ char *currentName = ::get_current_dir_name();
+ if (currentName) {
+ result = QFile::decodeName(QByteArray(currentName));
+ ::free(currentName);
+ }
+#else
+ char currentName[PATH_MAX+1];
+ if (::getcwd(currentName, PATH_MAX))
+ result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
+# if defined(QT_DEBUG)
+ if (result.isEmpty())
+ qWarning("QFSFileEngine::currentPath: getcwd() failed");
+# endif
+#endif
+ } else {
+# if defined(QT_DEBUG)
+ qWarning("QFSFileEngine::currentPath: stat(\".\") failed");
+# endif
+ }
+ return result;
+}
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
new file mode 100644
index 0000000000..82c6ebad05
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -0,0 +1,1218 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemengine_p.h"
+
+#define _POSIX_
+#include "qplatformdefs.h"
+#include "qabstractfileengine.h"
+#include "private/qfsfileengine_p.h"
+#include <private/qsystemlibrary_p.h>
+#include <qdebug.h>
+
+#include "qfile.h"
+#include "qdir.h"
+#include "private/qmutexpool_p.h"
+#include "qvarlengtharray.h"
+#include "qdatetime.h"
+#include "qt_windows.h"
+
+#if !defined(Q_OS_WINCE)
+# include <sys/types.h>
+# include <direct.h>
+# include <winioctl.h>
+#else
+# include <types.h>
+#endif
+#include <objbase.h>
+#include <shlobj.h>
+#include <initguid.h>
+#include <accctrl.h>
+#include <ctype.h>
+#include <limits.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+#ifndef SPI_GETPLATFORMTYPE
+#define SPI_GETPLATFORMTYPE 257
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX FILENAME_MAX
+#endif
+
+#ifndef _INTPTR_T_DEFINED
+#ifdef _WIN64
+typedef __int64 intptr_t;
+#else
+#ifdef _W64
+typedef _W64 int intptr_t;
+#else
+typedef INT_PTR intptr_t;
+#endif
+#endif
+#define _INTPTR_T_DEFINED
+#endif
+
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
+#endif
+
+#if !defined(Q_OS_WINCE)
+# if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE)
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+# define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
+# endif // !defined(REPARSE_DATA_BUFFER_HEADER_SIZE)
+
+# ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
+# define MAXIMUM_REPARSE_DATA_BUFFER_SIZE 16384
+# endif
+# ifndef IO_REPARSE_TAG_SYMLINK
+# 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)
+# endif
+#endif // !defined(Q_OS_WINCE)
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0;
+
+#if defined(Q_OS_WINCE)
+static QString qfsPrivateCurrentDir = QLatin1String("");
+// As none of the functions we try to resolve do exist on Windows CE
+// we use QT_NO_LIBRARY to shorten everything up a little bit.
+#define QT_NO_LIBRARY 1
+#endif
+
+#if !defined(QT_NO_LIBRARY)
+QT_BEGIN_INCLUDE_NAMESPACE
+typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
+static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0;
+typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
+static PtrLookupAccountSidW ptrLookupAccountSidW = 0;
+typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID);
+static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0;
+typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK);
+static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0;
+static TRUSTEE_W currentUserTrusteeW;
+static TRUSTEE_W worldTrusteeW;
+
+typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
+static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0;
+typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD);
+static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0;
+QT_END_INCLUDE_NAMESPACE
+
+
+static void resolveLibs()
+{
+ static bool triedResolve = false;
+ if (!triedResolve) {
+ // need to resolve the security info functions
+
+ // protect initialization
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ // check triedResolve again, since another thread may have already
+ // done the initialization
+ if (triedResolve) {
+ // another thread did initialize the security function pointers,
+ // so we shouldn't do it again.
+ return;
+ }
+#endif
+
+ triedResolve = true;
+#if !defined(Q_OS_WINCE)
+ HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32");
+ if (advapiHnd) {
+ ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW");
+ ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW");
+ ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW");
+ ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW");
+ }
+ if (ptrBuildTrusteeWithSidW) {
+ // Create TRUSTEE for current user
+ HANDLE hnd = ::GetCurrentProcess();
+ HANDLE token = 0;
+ if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
+ TOKEN_USER tu;
+ DWORD retsize;
+ if (::GetTokenInformation(token, TokenUser, &tu, sizeof(tu), &retsize))
+ ptrBuildTrusteeWithSidW(&currentUserTrusteeW, tu.User.Sid);
+ ::CloseHandle(token);
+ }
+
+ typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
+ PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid");
+ typedef PVOID (WINAPI *PtrFreeSid)(PSID);
+ PtrFreeSid ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid");
+ if (ptrAllocateAndInitializeSid && ptrFreeSid) {
+ // Create TRUSTEE for Everyone (World)
+ SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY };
+ PSID pWorld = 0;
+ if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pWorld))
+ ptrBuildTrusteeWithSidW(&worldTrusteeW, pWorld);
+ ptrFreeSid(pWorld);
+ }
+ }
+ HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv");
+ if (userenvHnd)
+ ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW");
+ HINSTANCE kernel32 = LoadLibrary(L"kernel32");
+ if(kernel32)
+ ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW");
+#endif
+ }
+}
+#endif // QT_NO_LIBRARY
+
+typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
+static PtrNetShareEnum ptrNetShareEnum = 0;
+typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID);
+static PtrNetApiBufferFree ptrNetApiBufferFree = 0;
+typedef struct _SHARE_INFO_1 {
+ LPWSTR shi1_netname;
+ DWORD shi1_type;
+ LPWSTR shi1_remark;
+} SHARE_INFO_1;
+
+
+static bool resolveUNCLibs()
+{
+ static bool triedResolve = false;
+ if (!triedResolve) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ if (triedResolve) {
+ return ptrNetShareEnum && ptrNetApiBufferFree;
+ }
+#endif
+ triedResolve = true;
+#if !defined(Q_OS_WINCE)
+ HINSTANCE hLib = QSystemLibrary::load(L"Netapi32");
+ if (hLib) {
+ ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum");
+ if (ptrNetShareEnum)
+ ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree");
+ }
+#endif
+ }
+ return ptrNetShareEnum && ptrNetApiBufferFree;
+}
+
+static QString readSymLink(const QFileSystemEntry &link)
+{
+ QString result;
+#if !defined(Q_OS_WINCE)
+ HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(),
+ FILE_READ_EA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+ 0);
+ if (handle != INVALID_HANDLE_VALUE) {
+ DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize);
+ DWORD retsize = 0;
+ if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) {
+ if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+ int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
+ int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
+ const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset];
+ result = QString::fromWCharArray(PathBuffer, length);
+ } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
+ int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
+ int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
+ 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);
+ }
+ qFree(rdb);
+ CloseHandle(handle);
+
+#if !defined(QT_NO_LIBRARY)
+ resolveLibs();
+ if (ptrGetVolumePathNamesForVolumeNameW) {
+ QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive);
+ if(matchVolName.indexIn(result) == 0) {
+ DWORD len;
+ wchar_t buffer[MAX_PATH];
+ QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\"));
+ if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0)
+ result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer));
+ }
+ }
+#endif
+ }
+#else
+ Q_UNUSED(link);
+#endif // Q_OS_WINCE
+ return result;
+}
+
+static QString readLink(const QFileSystemEntry &link)
+{
+#if !defined(Q_OS_WINCE)
+#if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS)
+ QString ret;
+
+ bool neededCoInit = false;
+ IShellLink *psl; // pointer to IShellLink i/f
+ WIN32_FIND_DATA wfd;
+ wchar_t szGotPath[MAX_PATH];
+
+ // Get pointer to the IShellLink interface.
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, 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);
+ if (SUCCEEDED(hres)) {
+ hres = ppf->Load((LPOLESTR)link.nativeFilePath().utf16(), STGM_READ);
+ //The original path of the link is retrieved. If the file/folder
+ //was moved, the return value still have the old path.
+ if (SUCCEEDED(hres)) {
+ if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
+ ret = QString::fromWCharArray(szGotPath);
+ }
+ ppf->Release();
+ }
+ psl->Release();
+ }
+ if (neededCoInit)
+ CoUninitialize();
+
+ return ret;
+#else
+ Q_UNUSED(link);
+ return QString();
+#endif // QT_NO_LIBRARY
+#else
+ wchar_t target[MAX_PATH];
+ QString result;
+ if (SHGetShortcutTarget((wchar_t*)QFileInfo(link.filePath()).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) {
+ result = QString::fromWCharArray(target);
+ if (result.startsWith(QLatin1Char('"')))
+ result.remove(0,1);
+ if (result.endsWith(QLatin1Char('"')))
+ result.remove(result.size()-1,1);
+ }
+ return result;
+#endif // Q_OS_WINCE
+}
+
+static bool uncShareExists(const QString &server)
+{
+ // This code assumes the UNC path is always like \\?\UNC\server...
+ QStringList parts = server.split(QLatin1Char('\\'), QString::SkipEmptyParts);
+ if (parts.count() >= 3) {
+ QStringList shares;
+ if (QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(2), &shares))
+ return parts.count() >= 4 ? shares.contains(parts.at(3), Qt::CaseInsensitive) : true;
+ }
+ return false;
+}
+
+static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
+{
+ // path should not end with a trailing slash
+ while (path.endsWith(QLatin1Char('\\')))
+ path.chop(1);
+
+ // can't handle drives
+ if (!path.endsWith(QLatin1Char(':'))) {
+ HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list)
+{
+ if (resolveUNCLibs()) {
+ SHARE_INFO_1 *BufPtr, *p;
+ DWORD res;
+ DWORD er = 0, tr = 0, resume = 0, i;
+ do {
+ res = ptrNetShareEnum((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) {
+ if (list && p->shi1_type == 0)
+ list->append(QString::fromWCharArray(p->shi1_netname));
+ p++;
+ }
+ }
+ ptrNetApiBufferFree(BufPtr);
+ } while (res == ERROR_MORE_DATA);
+ return res == ERROR_SUCCESS;
+ }
+ return false;
+}
+
+void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data)
+{
+ data.size_ = 0;
+ data.fileAttribute_ = 0;
+ data.creationTime_ = FILETIME();
+ data.lastAccessTime_ = FILETIME();
+ data.lastWriteTime_ = FILETIME();
+}
+
+bool QFileSystemEngine::isCaseSensitive()
+{
+ return false;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
+ QFileSystemMetaData &data)
+{
+ if (data.missingFlags(QFileSystemMetaData::LinkType))
+ QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
+
+ QString ret;
+ if (data.isLnkFile())
+ ret = readLink(link);
+ else if (data.isLink())
+ ret = readSymLink(link);
+ return QFileSystemEntry(ret);
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
+{
+ if (data.missingFlags(QFileSystemMetaData::ExistsAttribute))
+ QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
+
+ if (data.exists())
+ return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
+ else
+ return QFileSystemEntry();
+}
+
+//static
+QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
+{
+ // can be //server or //server/share
+ QString absPath;
+#if !defined(Q_OS_WINCE)
+ QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1));
+ wchar_t *fileName = 0;
+ DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
+ if (retLen > (DWORD)buf.size()) {
+ buf.resize(retLen);
+ retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
+ }
+ if (retLen != 0)
+ absPath = QString::fromWCharArray(buf.data(), retLen);
+#else
+ if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\')))
+ absPath = QDir::toNativeSeparators(path);
+ else
+ absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path));
+#endif
+ // This is really ugly, but GetFullPathName strips off whitespace at the end.
+ // If you for instance write ". " in the lineedit of QFileDialog,
+ // (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(' '));
+ return absPath;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
+{
+ QString ret;
+
+ if (!entry.isRelative()) {
+#if !defined(Q_OS_WINCE)
+ if (entry.isAbsolute()
+ && !entry.filePath().contains(QLatin1String("/../"))
+ && !entry.filePath().contains(QLatin1String("/./"))
+ && !entry.filePath().endsWith(QLatin1String("/.."))
+ && !entry.filePath().endsWith(QLatin1String("/."))) {
+ ret = entry.filePath();
+ } else {
+ ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(entry.filePath()));
+ }
+#else
+ ret = entry.filePath();
+#endif
+ } else {
+ ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + 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('/')) {
+ Q_ASSERT(ret.length() >= 2);
+ Q_ASSERT(ret.at(0).isLetter());
+ Q_ASSERT(ret.at(1) == QLatin1Char(':'));
+
+ // Force uppercase drive letters.
+ ret[0] = ret.at(0).toUpper();
+ }
+ return QFileSystemEntry(ret);
+}
+
+//static
+QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own)
+{
+ QString name;
+#if !defined(QT_NO_LIBRARY)
+ extern int qt_ntfs_permission_lookup;
+ if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
+ resolveLibs();
+ if (ptrGetNamedSecurityInfoW && ptrLookupAccountSidW) {
+ PSID pOwner = 0;
+ PSECURITY_DESCRIPTOR pSD;
+ if (ptrGetNamedSecurityInfoW((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) {
+ 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 (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
+ (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&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 (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
+ (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) {
+ lowner = 0;
+ }
+ } else {
+ lowner = 0;
+ }
+ }
+ if (lowner != 0)
+ name = QString::fromWCharArray(owner.data());
+ LocalFree(pSD);
+ }
+ }
+ }
+#else
+ Q_UNUSED(own);
+#endif
+ return name;
+}
+
+//static
+bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what)
+{
+ QAbstractFileEngine::FileFlags ret = 0;
+
+#if !defined(QT_NO_LIBRARY)
+ if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
+ resolveLibs();
+ if(ptrGetNamedSecurityInfoW && ptrBuildTrusteeWithSidW && ptrGetEffectiveRightsFromAclW) {
+ enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 };
+
+ QString fname = entry.filePath();
+ PSID pOwner = 0;
+ PSID pGroup = 0;
+ PACL pDacl;
+ PSECURITY_DESCRIPTOR pSD;
+ DWORD res = ptrGetNamedSecurityInfoW((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
+ data.knownFlagsMask |= QFileSystemMetaData::UserPermissions;
+ if(ptrGetEffectiveRightsFromAclW(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;
+ ptrBuildTrusteeWithSidW(&trustee, pOwner);
+ if(ptrGetEffectiveRightsFromAclW(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;
+ ptrBuildTrusteeWithSidW(&trustee, pGroup);
+ if(ptrGetEffectiveRightsFromAclW(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(ptrGetEffectiveRightsFromAclW(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);
+ }
+ }
+ } else
+#endif
+ {
+ //### what to do with permissions if we don't use NTFS
+ // for now just add all permissions and what about exe missions ??
+ // also qt_ntfs_permission_lookup is now not set by default ... should it ?
+ data.entryFlags |= QFileSystemMetaData::OwnerReadPermission
+ | QFileSystemMetaData::GroupReadPermission
+ | QFileSystemMetaData::OtherReadPermission;
+
+ if (!(data.fileAttribute_ & FILE_ATTRIBUTE_READONLY)) {
+ data.entryFlags |= QFileSystemMetaData::OwnerWritePermission
+ | QFileSystemMetaData::GroupWritePermission
+ | QFileSystemMetaData::OtherWritePermission;
+ }
+
+ 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;
+ }
+ 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)
+ data.entryFlags |= QFileSystemMetaData::UserReadPermission;
+ data.knownFlagsMask |= QFileSystemMetaData::UserReadPermission;
+ }
+ if (what & QFileSystemMetaData::UserWritePermission) {
+ if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), W_OK) == 0)
+ data.entryFlags |= QFileSystemMetaData::UserWritePermission;
+ data.knownFlagsMask |= QFileSystemMetaData::UserReadPermission;
+ }
+ }
+
+ return data.hasFlags(what);
+}
+
+static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data)
+{
+ bool entryExists = false;
+ DWORD fileAttrib = 0;
+#if !defined(Q_OS_WINCE)
+ if (fname.isDriveRoot()) {
+ // a valid drive ??
+ DWORD drivesBitmask = ::GetLogicalDrives();
+ int drivebit = 1 << (fname.filePath().at(0).toUpper().unicode() - QLatin1Char('A').unicode());
+ if (drivesBitmask & drivebit) {
+ fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM;
+ entryExists = true;
+ }
+ } else {
+#endif
+ const QString &path = fname.nativeFilePath();
+ bool is_dir = false;
+ if (path.startsWith(QLatin1String("\\\\?\\UNC"))) {
+ // UNC - stat doesn't work for all cases (Windows bug)
+ int s = path.indexOf(path.at(0),7);
+ if (s > 0) {
+ // "\\?\UNC\server\..."
+ s = path.indexOf(path.at(0),s+1);
+ if (s > 0) {
+ // "\\?\UNC\server\share\..."
+ if (s == path.size() - 1) {
+ // "\\?\UNC\server\share\"
+ is_dir = true;
+ } else {
+ // "\\?\UNC\server\share\notfound"
+ }
+ } else {
+ // "\\?\UNC\server\share"
+ is_dir = true;
+ }
+ } else {
+ // "\\?\UNC\server"
+ is_dir = true;
+ }
+ }
+ if (is_dir && uncShareExists(path)) {
+ // looks like a UNC dir, is a dir.
+ fileAttrib = FILE_ATTRIBUTE_DIRECTORY;
+ entryExists = true;
+ }
+#if !defined(Q_OS_WINCE)
+ }
+#endif
+ if (entryExists)
+ data.fillFromFileAttribute(fileAttrib);
+ return entryExists;
+}
+
+static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data)
+{
+ bool filledData = false;
+ // This assumes the last call to a Windows API failed.
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ WIN32_FIND_DATA findData;
+ if (getFindData(fname.nativeFilePath(), findData)
+ && findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
+ data.fillFromFindData(findData, true, fname.isDriveRoot());
+ filledData = true;
+ }
+ }
+ return filledData;
+}
+
+#if !defined(Q_OS_WINCE)
+//static
+bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what)
+{
+ HANDLE fHandle = (HANDLE)_get_osfhandle(fd);
+ if (fHandle != INVALID_HANDLE_VALUE) {
+ return fillMetaData(fHandle, data, what);
+ }
+ return false;
+}
+#endif
+
+//static
+bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what)
+{
+ data.entryFlags &= ~what;
+ clearWinStatData(data);
+ BY_HANDLE_FILE_INFORMATION fileInfo;
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ if (GetFileInformationByHandle(fHandle , &fileInfo)) {
+ data.fillFromFindInfo(fileInfo);
+ }
+ SetErrorMode(oldmode);
+ return data.hasFlags(what);
+}
+
+//static
+bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QFileSystemMetaData::MetaDataFlags what)
+{
+ what |= QFileSystemMetaData::WinLnkType | QFileSystemMetaData::WinStatFlags;
+ data.entryFlags &= ~what;
+
+ QFileSystemEntry fname;
+ data.knownFlagsMask |= QFileSystemMetaData::WinLnkType;
+ if(entry.filePath().endsWith(QLatin1String(".lnk"))) {
+ data.entryFlags |= QFileSystemMetaData::WinLnkType;
+ fname = QFileSystemEntry(readLink(entry));
+ } else {
+ fname = entry;
+ }
+
+ if (fname.isEmpty()) {
+ data.knownFlagsMask |= what;
+ clearWinStatData(data);
+ return false;
+ }
+
+ if (what & QFileSystemMetaData::WinStatFlags) {
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ clearWinStatData(data);
+ 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((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))
+ tryDriveUNCFallback(fname, data);
+ }
+ SetErrorMode(oldmode);
+ }
+
+ if (what & QFileSystemMetaData::Permissions)
+ fillPermissions(fname, data, what);
+ if ((what & QFileSystemMetaData::LinkType)
+ && data.missingFlags(QFileSystemMetaData::LinkType)) {
+ data.knownFlagsMask |= QFileSystemMetaData::LinkType;
+ if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
+ WIN32_FIND_DATA findData;
+ if (getFindData(fname.nativeFilePath(), findData))
+ data.fillFromFindData(findData, true);
+ }
+ }
+ data.knownFlagsMask |= what;
+ return data.hasFlags(what);
+}
+
+static inline bool mkDir(const QString &path)
+{
+#if defined(Q_OS_WINCE)
+ // Unfortunately CreateDirectory returns true for paths longer than
+ // 256, but does not create a directory. It starts to fail, when
+ // path length > MAX_PATH, which is 260 usually on CE.
+ // This only happens on a Windows Mobile device. Windows CE seems
+ // not to be affected by this.
+ static int platformId = 0;
+ if (platformId == 0) {
+ wchar_t platformString[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(platformString)/sizeof(*platformString),platformString,0)) {
+ if (0 == wcscmp(platformString, L"PocketPC") || 0 == wcscmp(platformString, L"Smartphone"))
+ platformId = 1;
+ else
+ platformId = 2;
+ }
+ }
+ if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256)
+ return false;
+#endif
+ return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0);
+}
+
+static inline bool rmDir(const QString &path)
+{
+ return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
+}
+
+static bool isDirPath(const QString &dirPath, bool *existed)
+{
+ QString path = dirPath;
+ if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
+ path += QLatin1Char('\\');
+
+ DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
+ if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ WIN32_FIND_DATA findData;
+ if (getFindData(QFSFileEnginePrivate::longFileName(path), findData))
+ fileAttrib = findData.dwFileAttributes;
+ }
+ }
+
+ if (existed)
+ *existed = fileAttrib != INVALID_FILE_ATTRIBUTES;
+
+ if (fileAttrib == INVALID_FILE_ATTRIBUTES)
+ return false;
+
+ return fileAttrib & FILE_ATTRIBUTE_DIRECTORY;
+}
+
+//static
+bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
+{
+ QString dirName = entry.filePath();
+ if (createParents) {
+ dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
+ // We spefically search for / so \ would break it..
+ int oldslash = -1;
+ if (dirName.startsWith(QLatin1String("\\\\"))) {
+ // Don't try to create the root path of a UNC path;
+ // CreateDirectory() will just return ERROR_INVALID_NAME.
+ for (int i = 0; i < dirName.size(); ++i) {
+ if (dirName.at(i) != QDir::separator()) {
+ oldslash = i;
+ break;
+ }
+ }
+ if (oldslash != -1)
+ oldslash = dirName.indexOf(QDir::separator(), oldslash);
+ }
+ for (int slash=0; slash != -1; oldslash = slash) {
+ slash = dirName.indexOf(QDir::separator(), oldslash+1);
+ if (slash == -1) {
+ if (oldslash == dirName.length())
+ break;
+ slash = dirName.length();
+ }
+ if (slash) {
+ QString chunk = dirName.left(slash);
+ bool existed = false;
+ if (!isDirPath(chunk, &existed)) {
+ if (!existed) {
+ if (!mkDir(chunk))
+ return false;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return mkDir(entry.filePath());
+}
+
+//static
+bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
+{
+ QString dirName = entry.filePath();
+ if (removeEmptyParents) {
+ dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
+ for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
+ QString chunk = dirName.left(slash);
+ if (chunk.length() == 2 && chunk.at(0).isLetter() && chunk.at(1) == QLatin1Char(':'))
+ break;
+ if (!isDirPath(chunk, 0))
+ return false;
+ if (!rmDir(chunk))
+ return oldslash != 0;
+ slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
+ }
+ return true;
+ }
+ return rmDir(entry.filePath());
+}
+
+//static
+QString QFileSystemEngine::rootPath()
+{
+#if defined(Q_OS_WINCE)
+ QString ret = QLatin1String("/");
+#elif defined(Q_FS_FAT)
+ QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData());
+ if (ret.isEmpty())
+ ret = QLatin1String("c:");
+ ret.append(QLatin1Char('/'));
+#elif defined(Q_OS_OS2EMX)
+ char dir[4];
+ _abspath(dir, QLatin1String("/"), _MAX_PATH);
+ QString ret(dir);
+#endif
+ return ret;
+}
+
+//static
+QString QFileSystemEngine::homePath()
+{
+ QString ret;
+#if !defined(QT_NO_LIBRARY)
+ resolveLibs();
+ if (ptrGetUserProfileDirectoryW) {
+ HANDLE hnd = ::GetCurrentProcess();
+ HANDLE token = 0;
+ BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token);
+ if (ok) {
+ DWORD dwBufferSize = 0;
+ // First call, to determine size of the strings (with '\0').
+ ok = ptrGetUserProfileDirectoryW(token, NULL, &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.
+ ok = ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize);
+ if (ok)
+ ret = QString::fromWCharArray(userDirectory);
+ delete [] userDirectory;
+ }
+ ::CloseHandle(token);
+ }
+ }
+#endif
+ if (ret.isEmpty() || !QFile::exists(ret)) {
+ ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData());
+ if (ret.isEmpty() || !QFile::exists(ret)) {
+ ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData())
+ + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData());
+ if (ret.isEmpty() || !QFile::exists(ret)) {
+ ret = QString::fromLocal8Bit(qgetenv("HOME").constData());
+ if (ret.isEmpty() || !QFile::exists(ret)) {
+#if defined(Q_OS_WINCE)
+ ret = QLatin1String("\\My Documents");
+ if (!QFile::exists(ret))
+#endif
+ ret = rootPath();
+ }
+ }
+ }
+ }
+ return QDir::fromNativeSeparators(ret);
+}
+
+QString QFileSystemEngine::tempPath()
+{
+ QString ret;
+ wchar_t tempPath[MAX_PATH];
+ DWORD len = GetTempPath(MAX_PATH, tempPath);
+ if (len)
+ ret = QString::fromWCharArray(tempPath, len);
+ if (!ret.isEmpty()) {
+ while (ret.endsWith(QLatin1Char('\\')))
+ ret.chop(1);
+ ret = QDir::fromNativeSeparators(ret);
+ }
+ if (ret.isEmpty()) {
+#if !defined(Q_OS_WINCE)
+ ret = QLatin1String("c:/tmp");
+#else
+ ret = QLatin1String("/Temp");
+#endif
+ }
+ return ret;
+}
+
+bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry)
+{
+ QFileSystemMetaData meta;
+ fillMetaData(entry, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType);
+ if(!(meta.exists() && meta.isDirectory()))
+ return false;
+
+#if !defined(Q_OS_WINCE)
+ //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;
+#else
+ qfsPrivateCurrentDir = entry.filePath();
+ return true;
+#endif
+}
+
+QFileSystemEntry QFileSystemEngine::currentPath()
+{
+ QString ret;
+#if !defined(Q_OS_WINCE)
+ 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);
+ }
+ }
+ if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
+#else
+ Q_UNUSED(fileName);
+ //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads
+ if (qfsPrivateCurrentDir.isEmpty())
+ qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
+
+ ret = qfsPrivateCurrentDir;
+#endif
+ return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath());
+}
+
+//static
+bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ Q_ASSERT(false);
+ Q_UNUSED(source)
+ Q_UNUSED(target)
+ Q_UNUSED(error)
+
+ return false; // TODO implement; - code needs to be moved from qfsfileengine_win.cpp
+}
+
+//static
+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)
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+ return ret;
+}
+
+//static
+bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(),
+ (wchar_t*)target.nativeFilePath().utf16()) != 0;
+ if(!ret)
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+ return ret;
+}
+
+//static
+bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
+{
+ bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0;
+ if(!ret)
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+ return ret;
+}
+
+//static
+bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
+ QFileSystemMetaData *data)
+{
+ Q_UNUSED(data);
+ int mode = 0;
+
+ if (permissions & QFile::ReadOwner || permissions & QFile::ReadUser
+ || permissions & QFile::ReadGroup || permissions & QFile::ReadOther)
+ mode |= _S_IREAD;
+ if (permissions & QFile::WriteOwner || permissions & QFile::WriteUser
+ || permissions & QFile::WriteGroup || permissions & QFile::WriteOther)
+ mode |= _S_IWRITE;
+
+ if (mode == 0) // not supported
+ return false;
+
+ bool ret = (::_wchmod((wchar_t*)entry.nativeFilePath().utf16(), mode) == 0);
+ if(!ret)
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return ret;
+}
+
+static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
+{
+ QDateTime ret;
+
+#if defined(Q_OS_WINCE)
+ SYSTEMTIME systime;
+ FILETIME ftime;
+ systime.wYear = 1970;
+ systime.wMonth = 1;
+ systime.wDay = 1;
+ systime.wHour = 0;
+ systime.wMinute = 0;
+ systime.wSecond = 0;
+ systime.wMilliseconds = 0;
+ systime.wDayOfWeek = 4;
+ SystemTimeToFileTime(&systime, &ftime);
+ unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime;
+ FileTimeToSystemTime(time, &systime);
+ unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime;
+ unsigned __int64 difftime = acttime - time1970;
+ difftime /= 10000000;
+ ret.setTime_t((unsigned int)difftime);
+#else
+ SYSTEMTIME sTime, lTime;
+ FileTimeToSystemTime(time, &sTime);
+ SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime);
+ ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay));
+ ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds));
+#endif
+
+ return ret;
+}
+
+QDateTime QFileSystemMetaData::creationTime() const
+{
+ return fileTimeToQDateTime(&creationTime_);
+}
+QDateTime QFileSystemMetaData::modificationTime() const
+{
+ return fileTimeToQDateTime(&lastWriteTime_);
+}
+QDateTime QFileSystemMetaData::accessTime() const
+{
+ return fileTimeToQDateTime(&lastAccessTime_);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
new file mode 100644
index 0000000000..ccbb10d82c
--- /dev/null
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystementry_p.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/private/qfsfileengine_p.h>
+#ifdef Q_OS_WIN
+#include <QtCore/qstringbuilder.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+static bool isUncRoot(const QString &server)
+{
+ QString localPath = QDir::toNativeSeparators(server);
+ if (!localPath.startsWith(QLatin1String("\\\\")))
+ return false;
+
+ int idx = localPath.indexOf(QLatin1Char('\\'), 2);
+ if (idx == -1 || idx + 1 == localPath.length())
+ return true;
+
+ localPath = localPath.right(localPath.length() - idx - 1).trimmed();
+ return localPath.isEmpty();
+}
+
+static inline QString fixIfRelativeUncPath(const QString &path)
+{
+ QString currentPath = QDir::currentPath();
+ if (currentPath.startsWith(QLatin1String("//")))
+ return currentPath % QChar(QLatin1Char('/')) % path;
+ return path;
+}
+#endif
+
+QFileSystemEntry::QFileSystemEntry()
+ : m_lastSeparator(0),
+ m_firstDotInFileName(0),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path is supplied by user code, as it may contain a mix
+ of '/' and the native separator.
+ */
+QFileSystemEntry::QFileSystemEntry(const QString &filePath)
+ : m_filePath(QDir::fromNativeSeparators(filePath)),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path is guaranteed to be in internal format, i.e. all
+ directory separators are '/' and not the native separator.
+ */
+QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */)
+ : m_filePath(filePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path comes from a native API
+ */
+QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */)
+ : m_nativeFilePath(nativeFilePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
+ : m_filePath(QDir::fromNativeSeparators(filePath)),
+ m_nativeFilePath(nativeFilePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+QString QFileSystemEntry::filePath() const
+{
+ resolveFilePath();
+ return m_filePath;
+}
+
+QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const
+{
+ resolveNativeFilePath();
+ return m_nativeFilePath;
+}
+
+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
+#else
+ m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
+#endif
+ }
+}
+
+void QFileSystemEntry::resolveNativeFilePath() const
+{
+ if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
+#ifdef Q_OS_WIN
+ QString filePath = m_filePath;
+ 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
+ }
+}
+
+QString QFileSystemEntry::fileName() const
+{
+ findLastSeparator();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ return m_filePath.mid(m_lastSeparator + 1);
+}
+
+QString QFileSystemEntry::path() const
+{
+ findLastSeparator();
+ if (m_lastSeparator == -1) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.left(2);
+#endif
+ return QString(QLatin1Char('.'));
+ }
+ if (m_lastSeparator == 0)
+ return QString(QLatin1Char('/'));
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.left(m_lastSeparator + 1);
+#endif
+ return m_filePath.left(m_lastSeparator);
+}
+
+QString QFileSystemEntry::baseName() const
+{
+ findFileNameSeparators();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ int length = -1;
+ if (m_firstDotInFileName >= 0) {
+ length = m_firstDotInFileName;
+ if (m_lastSeparator != -1) // avoid off by one
+ length--;
+ }
+ return m_filePath.mid(m_lastSeparator + 1, length);
+}
+
+QString QFileSystemEntry::completeBaseName() const
+{
+ findFileNameSeparators();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ int length = -1;
+ if (m_firstDotInFileName >= 0) {
+ length = m_firstDotInFileName + m_lastDotInFileName;
+ if (m_lastSeparator != -1) // avoid off by one
+ length--;
+ }
+ return m_filePath.mid(m_lastSeparator + 1, length);
+}
+
+QString QFileSystemEntry::suffix() const
+{
+ findFileNameSeparators();
+
+ if (m_lastDotInFileName == -1)
+ return QString();
+
+ return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
+}
+
+QString QFileSystemEntry::completeSuffix() const
+{
+ findFileNameSeparators();
+ if (m_firstDotInFileName == -1)
+ return QString();
+
+ return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
+}
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+bool QFileSystemEntry::isRelative() const
+{
+ resolveFilePath();
+ return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
+ && (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
+}
+
+bool QFileSystemEntry::isAbsolute() const
+{
+ resolveFilePath();
+ return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
+ && (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
+#ifdef Q_OS_WIN
+ || (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
+#endif
+ ));
+}
+#else
+bool QFileSystemEntry::isRelative() const
+{
+ return !isAbsolute();
+}
+
+bool QFileSystemEntry::isAbsolute() const
+{
+ resolveFilePath();
+ return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
+}
+#endif
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+bool QFileSystemEntry::isDriveRoot() const
+{
+ resolveFilePath();
+ return (m_filePath.length() == 3
+ && m_filePath.at(0).isLetter() && m_filePath.at(1) == QLatin1Char(':')
+ && m_filePath.at(2) == QLatin1Char('/'));
+}
+#endif
+
+bool QFileSystemEntry::isRoot() const
+{
+ resolveFilePath();
+ if (m_filePath == QLatin1String("/")
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ || isDriveRoot()
+#if defined(Q_OS_WIN)
+ || isUncRoot(m_filePath)
+#endif
+#endif
+ )
+ return true;
+
+ return false;
+}
+
+bool QFileSystemEntry::isEmpty() const
+{
+ resolveNativeFilePath();
+ return m_nativeFilePath.isEmpty();
+}
+
+// private methods
+
+void QFileSystemEntry::findLastSeparator() const
+{
+ if (m_lastSeparator == -2) {
+ resolveFilePath();
+ m_lastSeparator = -1;
+ for (int i = m_filePath.size() - 1; i >= 0; --i) {
+ if (m_filePath[i].unicode() == '/') {
+ m_lastSeparator = i;
+ break;
+ }
+ }
+ }
+}
+
+void QFileSystemEntry::findFileNameSeparators() const
+{
+ if (m_firstDotInFileName == -2) {
+ resolveFilePath();
+ int firstDotInFileName = -1;
+ int lastDotInFileName = -1;
+ int lastSeparator = m_lastSeparator;
+
+ int stop;
+ if (lastSeparator < 0) {
+ lastSeparator = -1;
+ stop = 0;
+ } else {
+ stop = lastSeparator;
+ }
+
+ int i = m_filePath.size() - 1;
+ for (; i >= stop; --i) {
+ if (m_filePath[i].unicode() == '.') {
+ firstDotInFileName = lastDotInFileName = i;
+ break;
+ } else if (m_filePath[i].unicode() == '/') {
+ lastSeparator = i;
+ break;
+ }
+ }
+
+ if (lastSeparator != i) {
+ for (--i; i >= stop; --i) {
+ if (m_filePath[i].unicode() == '.')
+ firstDotInFileName = i;
+ else if (m_filePath[i].unicode() == '/') {
+ lastSeparator = i;
+ break;
+ }
+ }
+ }
+ m_lastSeparator = lastSeparator;
+ m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
+ if (lastDotInFileName == -1)
+ m_lastDotInFileName = -1;
+ else if (firstDotInFileName == lastDotInFileName)
+ m_lastDotInFileName = 0;
+ else
+ m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystementry_p.h b/src/corelib/io/qfilesystementry_p.h
new file mode 100644
index 0000000000..d4d16d0de6
--- /dev/null
+++ b/src/corelib/io/qfilesystementry_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMENTRY_P_H_INCLUDED
+#define QFILESYSTEMENTRY_P_H_INCLUDED
+
+//
+// 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/qstring.h>
+#include <QtCore/qbytearray.h>
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+#define QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemEntry
+{
+public:
+
+#ifndef QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
+ typedef QByteArray NativePath;
+#else
+ typedef QString NativePath;
+#endif
+ 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;
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ bool isDriveRoot() const;
+#endif
+ bool isRoot() const;
+
+ bool isEmpty() const;
+ void clear()
+ {
+ *this = QFileSystemEntry();
+ }
+
+private:
+ // creates the QString version out of the bytearray version
+ void resolveFilePath() const;
+ // creates the bytearray version out of the QString version
+ void resolveNativeFilePath() const;
+ // resolves the separator
+ void findLastSeparator() const;
+ // resolves the dots and the separator
+ void findFileNameSeparators() const;
+
+ mutable QString m_filePath; // always has slashes as separator
+ mutable NativePath m_nativeFilePath; // native encoding and separators
+
+ mutable qint16 m_lastSeparator; // index in m_filePath of last separator
+ mutable qint16 m_firstDotInFileName; // index after m_filePath for first dot (.)
+ mutable qint16 m_lastDotInFileName; // index after m_firstDotInFileName for last dot (.)
+};
+
+QT_END_NAMESPACE
+
+#endif // include guard
diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h
new file mode 100644
index 0000000000..fb8bfe69e9
--- /dev/null
+++ b/src/corelib/io/qfilesystemiterator_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMITERATOR_P_H_INCLUDED
+#define QFILESYSTEMITERATOR_P_H_INCLUDED
+
+//
+// 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>
+
+#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)
+#elif defined (Q_OS_SYMBIAN)
+#include <f32file.h>
+#else
+#include <QtCore/qscopedpointer.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemIterator
+{
+public:
+ QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
+ const QStringList &nameFilters, QDirIterator::IteratorFlags flags
+ = QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
+ ~QFileSystemIterator();
+
+ bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData);
+
+private:
+ QFileSystemEntry::NativePath nativePath;
+
+ // Platform-specific data
+#if defined(Q_OS_WIN)
+ QFileSystemEntry::NativePath dirPath;
+ HANDLE findFileHandle;
+ QStringList uncShares;
+ bool uncFallback;
+ int uncShareIndex;
+ bool onlyDirs;
+#elif defined (Q_OS_SYMBIAN)
+ RDir dirHandle;
+ TEntryArray entries;
+ TInt lastError;
+ TInt entryIndex;
+#else
+ QT_DIR *dir;
+ QT_DIRENT *dirEntry;
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
+ // for readdir_r
+ QScopedPointer<QT_DIRENT, QScopedPointerPodDeleter> mt_file;
+#endif
+ int lastError;
+#endif
+
+ Q_DISABLE_COPY(QFileSystemIterator)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILESYSTEMITERATOR
+
+#endif // include guard
diff --git a/src/corelib/io/qfilesystemiterator_symbian.cpp b/src/corelib/io/qfilesystemiterator_symbian.cpp
new file mode 100644
index 0000000000..a39f9c3096
--- /dev/null
+++ b/src/corelib/io/qfilesystemiterator_symbian.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemiterator_p.h"
+#include "qfilesystemengine_p.h"
+#include <QtCore/private/qcore_symbian_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &path, QDir::Filters filters,
+ const QStringList &nameFilters, QDirIterator::IteratorFlags iteratorFlags)
+ : lastError(KErrNone), entryIndex(-1)
+{
+ RFs& fs = qt_s60GetRFs();
+
+ nativePath = path.nativeFilePath();
+ if (!nativePath.endsWith(QLatin1Char('\\')))
+ nativePath.append(QLatin1Char('\\'));
+
+ QString absPath = QFileSystemEngine::absoluteName(path).nativeFilePath();
+
+ if (!absPath.endsWith(QLatin1Char('\\')))
+ absPath.append(QLatin1Char('\\'));
+
+ int pathLen = absPath.length();
+ if (pathLen > KMaxFileName) {
+ lastError = KErrBadName;
+ return;
+ }
+
+ //set up server side filtering to reduce IPCs
+ //RDir won't accept all valid name filters e.g. "*. bar"
+ if (nameFilters.count() == 1 && !(filters & QDir::AllDirs) && iteratorFlags
+ == QDirIterator::NoIteratorFlags && pathLen + nameFilters[0].length()
+ <= KMaxFileName) {
+ //server side supports one mask - skip this for recursive mode or if only files should be filtered
+ absPath.append(nameFilters[0]);
+ }
+
+ TUint symbianMask = 0;
+ if ((filters & QDir::Dirs) || (filters & QDir::AllDirs) || (iteratorFlags
+ & QDirIterator::Subdirectories))
+ symbianMask |= KEntryAttDir; //include directories
+ if (filters & QDir::Hidden)
+ symbianMask |= KEntryAttHidden;
+ if (filters & QDir::System)
+ symbianMask |= KEntryAttSystem;
+ if (((filters & QDir::Files) == 0) && symbianMask == KEntryAttDir)
+ symbianMask |= KEntryAttMatchExclusive; //exclude non-directories
+ else if (symbianMask == 0) {
+ if ((filters & QDir::PermissionMask) == QDir::Writable)
+ symbianMask = KEntryAttMatchExclude | KEntryAttReadOnly;
+ }
+
+ lastError = dirHandle.Open(fs, qt_QString2TPtrC(absPath), symbianMask);
+}
+
+QFileSystemIterator::~QFileSystemIterator()
+{
+ dirHandle.Close();
+}
+
+bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
+{
+ //1st time, lastError is result of dirHandle.Open(), entries.Count() is 0 and entryIndex is -1 so initial read is triggered
+ //subsequent times, read is triggered each time we reach the end of the entry list
+ //final time, lastError is KErrEof so we don't need to read anymore.
+ ++entryIndex;
+ if (lastError == KErrNone && entryIndex >= entries.Count()) {
+ lastError = dirHandle.Read(entries);
+ entryIndex = 0;
+ }
+
+ //each call to advance() gets the next entry from the entry list.
+ //from the final (or only) read call, KErrEof is returned together with a full buffer so we still need to go through the list
+ if ((lastError == KErrNone || lastError == KErrEof) && entryIndex < entries.Count()) {
+ Q_ASSERT(entryIndex >= 0);
+ const TEntry &entry(entries[entryIndex]);
+ fileEntry = QFileSystemEntry(nativePath + qt_TDesC2QString(entry.iName), QFileSystemEntry::FromNativePath());
+ metaData.fillFromTEntry(entry);
+ return true;
+ }
+
+ //TODO: error reporting, to allow user to distinguish empty directory from error condition.
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
new file mode 100644
index 0000000000..3d6012b47c
--- /dev/null
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfilesystemiterator_p.h"
+
+#ifndef QT_NO_FILESYSTEMITERATOR
+
+#include <stdlib.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
+ const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
+ : nativePath(entry.nativeFilePath())
+ , dir(0)
+ , dirEntry(0)
+ , lastError(0)
+{
+ Q_UNUSED(filters)
+ Q_UNUSED(nameFilters)
+ Q_UNUSED(flags)
+
+ if ((dir = QT_OPENDIR(nativePath.constData())) == 0) {
+ lastError = errno;
+ } else {
+
+ if (!nativePath.endsWith('/'))
+ nativePath.append('/');
+
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
+ // ### Race condition; we should use fpathconf and dirfd().
+ size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
+ if (maxPathName == size_t(-1))
+ maxPathName = FILENAME_MAX;
+ maxPathName += sizeof(QT_DIRENT) + 1;
+
+ QT_DIRENT *p = reinterpret_cast<QT_DIRENT*>(::malloc(maxPathName));
+ Q_CHECK_PTR(p);
+
+ mt_file.reset(p);
+#endif
+ }
+}
+
+QFileSystemIterator::~QFileSystemIterator()
+{
+ if (dir)
+ QT_CLOSEDIR(dir);
+}
+
+bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
+{
+ if (!dir)
+ return false;
+
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
+ lastError = QT_READDIR_R(dir, mt_file.data(), &dirEntry);
+ if (lastError)
+ return false;
+#else
+ // ### add local lock to prevent breaking reentrancy
+ dirEntry = QT_READDIR(dir);
+#endif // _POSIX_THREAD_SAFE_FUNCTIONS
+
+ if (dirEntry) {
+ fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath());
+ metaData.fillFromDirEnt(*dirEntry);
+ return true;
+ }
+
+ lastError = errno;
+ return false;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILESYSTEMITERATOR
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
new file mode 100644
index 0000000000..0e94130049
--- /dev/null
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if _WIN32_WINNT < 0x0500
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include "qfilesystemiterator_p.h"
+#include "qfilesystemengine_p.h"
+#include "qplatformdefs.h"
+
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+bool done = true;
+
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
+ const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
+ : nativePath(entry.nativeFilePath())
+ , dirPath(entry.filePath())
+ , findFileHandle(INVALID_HANDLE_VALUE)
+ , uncFallback(false)
+ , uncShareIndex(0)
+ , onlyDirs(false)
+{
+ Q_UNUSED(nameFilters)
+ Q_UNUSED(flags)
+ if (nativePath.endsWith(QLatin1String(".lnk"))) {
+ QFileSystemMetaData metaData;
+ QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData);
+ nativePath = link.nativeFilePath();
+ }
+ if (!nativePath.endsWith(QLatin1Char('\\')))
+ nativePath.append(QLatin1Char('\\'));
+ nativePath.append(QLatin1Char('*'));
+ if (!dirPath.endsWith(QLatin1Char('/')))
+ dirPath.append(QLatin1Char('/'));
+ if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files))))
+ onlyDirs = true;
+}
+
+QFileSystemIterator::~QFileSystemIterator()
+{
+ if (findFileHandle != INVALID_HANDLE_VALUE)
+ FindClose(findFileHandle);
+}
+
+bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
+{
+ bool haveData = false;
+ WIN32_FIND_DATA findData;
+
+ if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) {
+ haveData = true;
+ int infoLevel = 0 ; // FindExInfoStandard;
+ DWORD dwAdditionalFlags = 0;
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
+ 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\\"))) {
+ QStringList parts = nativePath.split(QLatin1Char('\\'), QString::SkipEmptyParts);
+ if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer(
+ QLatin1String("\\\\") + parts.at(2), &uncShares)) {
+ if (uncShares.isEmpty())
+ return false; // No shares found in the server
+ else
+ uncFallback = true;
+ }
+ }
+ }
+ }
+ if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback)
+ return false;
+ // Retrieve the new file information.
+ if (!haveData) {
+ if (uncFallback) {
+ if (++uncShareIndex >= uncShares.count())
+ return false;
+ } else {
+ if (!FindNextFile(findFileHandle, &findData))
+ return false;
+ }
+ }
+ // Create the new file system entry & meta data.
+ if (uncFallback) {
+ fileEntry = QFileSystemEntry(dirPath + uncShares.at(uncShareIndex));
+ metaData.fillFromFileAttribute(FILE_ATTRIBUTE_DIRECTORY);
+ return true;
+ } else {
+ QString fileName = QString::fromWCharArray(findData.cFileName);
+ fileEntry = QFileSystemEntry(dirPath + fileName);
+ metaData = QFileSystemMetaData();
+ if (!fileName.endsWith(QLatin1String(".lnk"))) {
+ metaData.fillFromFindData(findData, true);
+ }
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
new file mode 100644
index 0000000000..f7f1fa1b8d
--- /dev/null
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMMETADATA_P_H_INCLUDED
+#define QFILESYSTEMMETADATA_P_H_INCLUDED
+
+//
+// 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 "qplatformdefs.h"
+#include <QtCore/qglobal.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qabstractfileengine.h>
+
+// Platform-specific includes
+#if defined(Q_OS_WIN)
+#ifndef IO_REPARSE_TAG_SYMLINK
+#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
+#endif
+#elif defined(Q_OS_SYMBIAN)
+#include <f32file.h>
+#include <QtCore/private/qdatetime_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemEngine;
+
+class QFileSystemMetaData
+{
+public:
+ QFileSystemMetaData()
+ : knownFlagsMask(0)
+ {
+ }
+
+ enum MetaDataFlag {
+ // Permissions, overlaps with QFile::Permissions
+ OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
+ GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
+ UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
+ OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
+
+ OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
+ GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
+ UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
+ OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
+
+ ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
+ WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
+ ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
+
+ Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
+
+ // Type
+#ifdef Q_OS_SYMBIAN
+ LinkType = 0,
+#else
+ LinkType = 0x00010000,
+#endif
+ FileType = 0x00020000,
+ DirectoryType = 0x00040000,
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+ BundleType = 0x00080000,
+ AliasType = 0x08000000,
+#else
+ BundleType = 0x0,
+ AliasType = 0x0,
+#endif
+#if defined(Q_OS_WIN)
+ WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
+#else
+ WinLnkType = 0x0,
+#endif
+ SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
+
+ LegacyLinkType = LinkType | AliasType | WinLnkType,
+
+ Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
+
+ // Attributes
+ HiddenAttribute = 0x00100000,
+ SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
+ ExistsAttribute = 0x00400000,
+
+ Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute,
+
+ // Times
+ CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
+ ModificationTime = 0x02000000,
+ AccessTime = 0x04000000,
+
+ Times = CreationTime | ModificationTime | AccessTime,
+
+ // Owner IDs
+ UserId = 0x10000000,
+ GroupId = 0x20000000,
+
+ OwnerIds = UserId | GroupId,
+
+ PosixStatFlags = QFileSystemMetaData::OtherPermissions
+ | QFileSystemMetaData::GroupPermissions
+ | QFileSystemMetaData::OwnerPermissions
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::SizeAttribute
+ | QFileSystemMetaData::Times
+ | QFileSystemMetaData::OwnerIds,
+
+ SymbianTEntryFlags = QFileSystemMetaData::Permissions
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::Attributes
+ | QFileSystemMetaData::Times,
+#if defined(Q_OS_WIN)
+ WinStatFlags = QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::HiddenAttribute
+ | QFileSystemMetaData::ExistsAttribute
+ | QFileSystemMetaData::SizeAttribute
+ | QFileSystemMetaData::Times,
+#endif
+
+ AllMetaDataFlags = 0xFFFFFFFF
+
+ };
+ Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
+
+ bool hasFlags(MetaDataFlags flags) const
+ {
+ return ((knownFlagsMask & flags) == flags);
+ }
+
+ MetaDataFlags missingFlags(MetaDataFlags flags)
+ {
+ return flags & ~knownFlagsMask;
+ }
+
+ void clear()
+ {
+ knownFlagsMask = 0;
+ }
+
+ void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
+ {
+ knownFlagsMask &= ~flags;
+ }
+
+ bool exists() const { return (entryFlags & ExistsAttribute); }
+
+ bool isLink() const { return (entryFlags & LinkType); }
+ bool isFile() const { return (entryFlags & FileType); }
+ bool isDirectory() const { return (entryFlags & 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); }
+#if defined(Q_OS_WIN)
+ bool isLnkFile() const { return (entryFlags & WinLnkType); }
+#else
+ bool isLnkFile() const { return false; }
+#endif
+
+ qint64 size() const { return size_; }
+
+ QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
+
+ QDateTime creationTime() const;
+ QDateTime modificationTime() const;
+ QDateTime accessTime() const;
+
+ QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
+ uint userId() const;
+ uint groupId() const;
+ uint ownerId(QAbstractFileEngine::FileOwner owner) const;
+
+#ifdef Q_OS_UNIX
+ void fillFromStatBuf(const QT_STATBUF &statBuffer);
+ void fillFromDirEnt(const QT_DIRENT &statBuffer);
+#endif
+#ifdef Q_OS_SYMBIAN
+ void fillFromTEntry(const TEntry& entry);
+ void fillFromVolumeInfo(const TVolumeInfo& info);
+#endif
+
+#if defined(Q_OS_WIN)
+ inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
+ inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
+ inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
+#endif
+private:
+ friend class QFileSystemEngine;
+
+ MetaDataFlags knownFlagsMask;
+ MetaDataFlags entryFlags;
+
+ qint64 size_;
+
+ // Platform-specific data goes here:
+#if defined(Q_OS_WIN)
+ DWORD fileAttribute_;
+ FILETIME creationTime_;
+ FILETIME lastAccessTime_;
+ FILETIME lastWriteTime_;
+#elif defined(Q_OS_SYMBIAN)
+ TTime modificationTime_;
+#else
+ time_t creationTime_;
+ time_t modificationTime_;
+ time_t accessTime_;
+
+ uint userId_;
+ uint groupId_;
+#endif
+
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
+
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
+inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & 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_SYMBIAN)) || defined (Q_OS_WIN)
+inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
+{
+ switch (time) {
+ case QAbstractFileEngine::ModificationTime:
+ return modificationTime();
+
+ case QAbstractFileEngine::AccessTime:
+ return accessTime();
+
+ case QAbstractFileEngine::CreationTime:
+ return creationTime();
+ }
+
+ return QDateTime();
+}
+#endif
+
+#if defined(Q_OS_UNIX) && !defined (Q_OS_SYMBIAN)
+inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromTime_t(creationTime_); }
+inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromTime_t(modificationTime_); }
+inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromTime_t(accessTime_); }
+
+inline uint QFileSystemMetaData::userId() const { return userId_; }
+inline uint QFileSystemMetaData::groupId() const { return groupId_; }
+
+inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
+{
+ if (owner == QAbstractFileEngine::OwnerUser)
+ return userId();
+ else
+ return groupId();
+}
+#endif
+
+#ifdef Q_OS_SYMBIAN
+inline QDateTime QFileSystemMetaData::creationTime() const { return modificationTime(); }
+inline QDateTime QFileSystemMetaData::modificationTime() const { return qt_symbian_TTime_To_QDateTime(modificationTime_); }
+inline QDateTime QFileSystemMetaData::accessTime() const { return modificationTime(); }
+
+inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
+{
+ Q_UNUSED(time);
+ return modificationTime();
+}
+inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
+inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
+inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
+{
+ Q_UNUSED(owner);
+ return (uint) -2;
+}
+#endif
+
+#if defined(Q_OS_WIN)
+inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
+inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
+inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
+{
+ if (owner == QAbstractFileEngine::OwnerUser)
+ return userId();
+ else
+ return groupId();
+}
+
+inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
+{
+ fileAttribute_ = fileAttribute;
+ // Ignore the hidden attribute for drives.
+ if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
+ entryFlags |= HiddenAttribute;
+ entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
+ entryFlags |= ExistsAttribute;
+ knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
+}
+
+inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
+{
+ fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
+ creationTime_ = findData.ftCreationTime;
+ lastAccessTime_ = findData.ftLastAccessTime;
+ lastWriteTime_ = findData.ftLastWriteTime;
+ if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
+ size_ = 0;
+ } else {
+ size_ = findData.nFileSizeHigh;
+ size_ <<= 32;
+ size_ += findData.nFileSizeLow;
+ }
+ knownFlagsMask |= Times | SizeAttribute;
+ if (setLinkType) {
+ knownFlagsMask |= LinkType;
+ entryFlags &= ~LinkType;
+#if !defined(Q_OS_WINCE)
+ if ((fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT)
+ && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK
+ || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
+ entryFlags |= LinkType;
+ }
+#endif
+
+ }
+}
+
+inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
+{
+ fillFromFileAttribute(fileInfo.dwFileAttributes);
+ creationTime_ = fileInfo.ftCreationTime;
+ lastAccessTime_ = fileInfo.ftLastAccessTime;
+ lastWriteTime_ = fileInfo.ftLastWriteTime;
+ if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
+ size_ = 0;
+ } else {
+ size_ = fileInfo.nFileSizeHigh;
+ size_ <<= 32;
+ size_ += fileInfo.nFileSizeLow;
+ }
+ knownFlagsMask |= Times | SizeAttribute;
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // include guard
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
new file mode 100644
index 0000000000..e0f2f44913
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -0,0 +1,640 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qdatetime.h>
+#include <qdebug.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qmutex.h>
+#include <qset.h>
+#include <qtimer.h>
+
+#if defined(Q_OS_WIN)
+# include "qfilesystemwatcher_win_p.h"
+#elif defined(Q_OS_LINUX)
+# include "qfilesystemwatcher_inotify_p.h"
+# include "qfilesystemwatcher_dnotify_p.h"
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
+# if (defined Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+# include "qfilesystemwatcher_fsevents_p.h"
+# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+# include "qfilesystemwatcher_kqueue_p.h"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfilesystemwatcher_symbian_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+enum { PollingInterval = 1000 };
+
+class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+
+ class FileInfo
+ {
+ uint ownerId;
+ uint groupId;
+ QFile::Permissions permissions;
+ QDateTime lastModified;
+ QStringList entries;
+
+ public:
+ FileInfo(const QFileInfo &fileInfo)
+ : ownerId(fileInfo.ownerId()),
+ groupId(fileInfo.groupId()),
+ permissions(fileInfo.permissions()),
+ lastModified(fileInfo.lastModified())
+ {
+ if (fileInfo.isDir()) {
+ entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
+ }
+ }
+ FileInfo &operator=(const QFileInfo &fileInfo)
+ {
+ *this = FileInfo(fileInfo);
+ return *this;
+ }
+
+ bool operator!=(const QFileInfo &fileInfo) const
+ {
+ if (fileInfo.isDir() && entries != fileInfo.absoluteDir().entryList(QDir::AllEntries))
+ return true;
+ return (ownerId != fileInfo.ownerId()
+ || groupId != fileInfo.groupId()
+ || permissions != fileInfo.permissions()
+ || lastModified != fileInfo.lastModified());
+ }
+ };
+
+ mutable QMutex mutex;
+ QHash<QString, FileInfo> files, directories;
+
+public:
+ QPollingFileSystemWatcherEngine();
+
+ void run();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+private Q_SLOTS:
+ void timeout();
+};
+
+QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine()
+{
+#ifndef QT_NO_THREAD
+ moveToThread(this);
+#endif
+}
+
+void QPollingFileSystemWatcherEngine::run()
+{
+ QTimer timer;
+ connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
+ timer.start(PollingInterval);
+ (void) exec();
+}
+
+QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QFileInfo fi(path);
+ if (!fi.exists())
+ continue;
+ if (fi.isDir()) {
+ if (!directories->contains(path))
+ directories->append(path);
+ if (!path.endsWith(QLatin1Char('/')))
+ fi = QFileInfo(path + QLatin1Char('/'));
+ this->directories.insert(path, fi);
+ } else {
+ if (!files->contains(path))
+ files->append(path);
+ this->files.insert(path, fi);
+ }
+ it.remove();
+ }
+ start();
+ return p;
+}
+
+QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ if (this->directories.remove(path)) {
+ directories->removeAll(path);
+ it.remove();
+ } else if (this->files.remove(path)) {
+ files->removeAll(path);
+ it.remove();
+ }
+ }
+ if (this->files.isEmpty() && this->directories.isEmpty()) {
+ locker.unlock();
+ stop();
+ wait();
+ }
+ return p;
+}
+
+void QPollingFileSystemWatcherEngine::stop()
+{
+ quit();
+}
+
+void QPollingFileSystemWatcherEngine::timeout()
+{
+ QMutexLocker locker(&mutex);
+ QMutableHashIterator<QString, FileInfo> fit(files);
+ while (fit.hasNext()) {
+ QHash<QString, FileInfo>::iterator x = fit.next();
+ QString path = x.key();
+ QFileInfo fi(path);
+ if (!fi.exists()) {
+ fit.remove();
+ emit fileChanged(path, true);
+ } else if (x.value() != fi) {
+ x.value() = fi;
+ emit fileChanged(path, false);
+ }
+ }
+ QMutableHashIterator<QString, FileInfo> dit(directories);
+ while (dit.hasNext()) {
+ QHash<QString, FileInfo>::iterator x = dit.next();
+ QString path = x.key();
+ QFileInfo fi(path);
+ if (!path.endsWith(QLatin1Char('/')))
+ fi = QFileInfo(path + QLatin1Char('/'));
+ if (!fi.exists()) {
+ dit.remove();
+ emit directoryChanged(path, true);
+ } else if (x.value() != fi) {
+ fi.refresh();
+ if (!fi.exists()) {
+ dit.remove();
+ emit directoryChanged(path, true);
+ } else {
+ x.value() = fi;
+ emit directoryChanged(path, false);
+ }
+ }
+
+ }
+}
+
+
+
+
+QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine()
+{
+#if defined(Q_OS_WIN)
+ return new QWindowsFileSystemWatcherEngine;
+#elif defined(Q_OS_LINUX)
+ QFileSystemWatcherEngine *eng = QInotifyFileSystemWatcherEngine::create();
+ if(!eng)
+ eng = QDnotifyFileSystemWatcherEngine::create();
+ return eng;
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
+# if 0 && defined(Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
+ return QFSEventsFileSystemWatcherEngine::create();
+ else
+# endif
+ return QKqueueFileSystemWatcherEngine::create();
+#elif defined(Q_OS_SYMBIAN)
+ return new QSymbianFileSystemWatcherEngine;
+#else
+ return 0;
+#endif
+}
+
+QFileSystemWatcherPrivate::QFileSystemWatcherPrivate()
+ : native(0), poller(0), forced(0)
+{
+}
+
+void QFileSystemWatcherPrivate::init()
+{
+ Q_Q(QFileSystemWatcher);
+ native = createNativeEngine();
+ 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)));
+ }
+}
+
+void QFileSystemWatcherPrivate::initForcedEngine(const QString &forceName)
+{
+ if(forced)
+ return;
+
+ Q_Q(QFileSystemWatcher);
+
+#if defined(Q_OS_LINUX)
+ if(forceName == QLatin1String("inotify")) {
+ forced = QInotifyFileSystemWatcherEngine::create();
+ } else if(forceName == QLatin1String("dnotify")) {
+ forced = QDnotifyFileSystemWatcherEngine::create();
+ }
+#else
+ Q_UNUSED(forceName);
+#endif
+
+ if(forced) {
+ QObject::connect(forced,
+ SIGNAL(fileChanged(QString,bool)),
+ q,
+ SLOT(_q_fileChanged(QString,bool)));
+ QObject::connect(forced,
+ SIGNAL(directoryChanged(QString,bool)),
+ q,
+ SLOT(_q_directoryChanged(QString,bool)));
+ }
+}
+
+void QFileSystemWatcherPrivate::initPollerEngine()
+{
+ if(poller)
+ return;
+
+ Q_Q(QFileSystemWatcher);
+ poller = new QPollingFileSystemWatcherEngine; // 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)));
+}
+
+void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed)
+{
+ Q_Q(QFileSystemWatcher);
+ if (!files.contains(path)) {
+ // the path was removed after a change was detected, but before we delivered the signal
+ return;
+ }
+ if (removed)
+ files.removeAll(path);
+ emit q->fileChanged(path);
+}
+
+void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool removed)
+{
+ Q_Q(QFileSystemWatcher);
+ if (!directories.contains(path)) {
+ // perhaps the path was removed after a change was detected, but before we delivered the signal
+ return;
+ }
+ if (removed)
+ directories.removeAll(path);
+ emit q->directoryChanged(path);
+}
+
+
+
+/*!
+ \class QFileSystemWatcher
+ \brief The QFileSystemWatcher class provides an interface for monitoring files and directories for modifications.
+ \ingroup io
+ \since 4.2
+ \reentrant
+
+ QFileSystemWatcher monitors the file system for changes to files
+ and directories by watching a list of specified paths.
+
+ Call addPath() to watch a particular file or directory. Multiple
+ paths can be added using the addPaths() function. Existing paths can
+ be removed by using the removePath() and removePaths() functions.
+
+ QFileSystemWatcher examines each path added to it. Files that have
+ been added to the QFileSystemWatcher can be accessed using the
+ files() function, and directories using the directories() function.
+
+ The fileChanged() signal is emitted when a file has been modified,
+ renamed or removed from disk. Similarly, the directoryChanged()
+ signal is emitted when a directory or its contents is modified or
+ removed. Note that QFileSystemWatcher stops monitoring files once
+ they have been renamed or removed from disk, and directories once
+ they have been removed from disk.
+
+ \note On systems running a Linux kernel without inotify support,
+ file systems that contain watched paths cannot be unmounted.
+
+ \note Windows CE does not support directory monitoring by
+ default as this depends on the file system driver installed.
+
+ \note The act of monitoring files and directories for
+ modifications consumes system resources. This implies there is a
+ limit to the number of files and directories your process can
+ monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for
+ example, an open file descriptor is required for each monitored
+ file. Some system limits the number of open file descriptors to 256
+ by default. This means that addPath() and addPaths() will fail if
+ your process tries to add more than 256 files or directories to
+ the file system monitor. Also note that your process may have
+ other file descriptors open in addition to the ones for files
+ being monitored, and these other open descriptors also count in
+ the total. Mac OS X 10.5 and up use a different backend and do not
+ suffer from this issue.
+
+
+ \sa QFile, QDir
+*/
+
+
+/*!
+ Constructs a new file system watcher object with the given \a parent.
+*/
+QFileSystemWatcher::QFileSystemWatcher(QObject *parent)
+ : QObject(*new QFileSystemWatcherPrivate, parent)
+{
+ d_func()->init();
+}
+
+/*!
+ Constructs a new file system watcher object with the given \a parent
+ which monitors the specified \a paths list.
+*/
+QFileSystemWatcher::QFileSystemWatcher(const QStringList &paths, QObject *parent)
+ : QObject(*new QFileSystemWatcherPrivate, parent)
+{
+ d_func()->init();
+ addPaths(paths);
+}
+
+/*!
+ Destroys the file system watcher.
+*/
+QFileSystemWatcher::~QFileSystemWatcher()
+{
+ Q_D(QFileSystemWatcher);
+ if (d->native) {
+ d->native->stop();
+ d->native->wait();
+ delete d->native;
+ d->native = 0;
+ }
+ if (d->poller) {
+ d->poller->stop();
+ d->poller->wait();
+ delete d->poller;
+ d->poller = 0;
+ }
+ if (d->forced) {
+ d->forced->stop();
+ d->forced->wait();
+ delete d->forced;
+ d->forced = 0;
+ }
+}
+
+/*!
+ Adds \a path to the file system watcher if \a path exists. The
+ path is not added if it does not exist, or if it is already being
+ monitored by the file system watcher.
+
+ If \a path specifies a directory, the directoryChanged() signal
+ will be emitted when \a path is modified or removed from disk;
+ otherwise the fileChanged() signal is emitted when \a path is
+ modified, renamed or removed.
+
+ \note There is a system dependent limit to the number of files and
+ directories that can be monitored simultaneously. If this limit
+ has been reached, \a path will not be added to the file system
+ watcher, and a warning message will be printed to \e{stderr}.
+
+ \sa addPaths(), removePath()
+*/
+void QFileSystemWatcher::addPath(const QString &path)
+{
+ if (path.isEmpty()) {
+ qWarning("QFileSystemWatcher::addPath: path is empty");
+ return;
+ }
+ addPaths(QStringList(path));
+}
+
+/*!
+ Adds each path in \a paths to the file system watcher. Paths are
+ not added if they not exist, or if they are already being
+ monitored by the file system watcher.
+
+ If a path specifies a directory, the directoryChanged() signal
+ will be emitted when the path is modified or removed from disk;
+ otherwise the fileChanged() signal is emitted when the path is
+ modified, renamed, or removed.
+
+ \note There is a system dependent limit to the number of files and
+ directories that can be monitored simultaneously. If this limit
+ has been reached, the excess \a paths will not be added to the
+ file system watcher, and a warning message will be printed to
+ \e{stderr} for each path that could not be added.
+
+ \sa addPath(), removePaths()
+*/
+void QFileSystemWatcher::addPaths(const QStringList &paths)
+{
+ Q_D(QFileSystemWatcher);
+ if (paths.isEmpty()) {
+ qWarning("QFileSystemWatcher::addPaths: list is empty");
+ return;
+ }
+
+ QStringList p = paths;
+ QFileSystemWatcherEngine *engine = 0;
+
+ if(!objectName().startsWith(QLatin1String("_qt_autotest_force_engine_"))) {
+ // Normal runtime case - search intelligently for best engine
+ if(d->native) {
+ engine = d->native;
+ } else {
+ d_func()->initPollerEngine();
+ engine = d->poller;
+ }
+
+ } else {
+ // Autotest override case - use the explicitly selected engine only
+ QString forceName = objectName().mid(26);
+ if(forceName == QLatin1String("poller")) {
+ qDebug() << "QFileSystemWatcher: skipping native engine, using only polling engine";
+ d_func()->initPollerEngine();
+ engine = d->poller;
+ } else if(forceName == QLatin1String("native")) {
+ qDebug() << "QFileSystemWatcher: skipping polling engine, using only native engine";
+ engine = d->native;
+ } else {
+ qDebug() << "QFileSystemWatcher: skipping polling and native engine, using only explicit" << forceName << "engine";
+ d_func()->initForcedEngine(forceName);
+ engine = d->forced;
+ }
+ }
+
+ if(engine)
+ p = engine->addPaths(p, &d->files, &d->directories);
+
+ if (!p.isEmpty())
+ qWarning("QFileSystemWatcher: failed to add paths: %s",
+ qPrintable(p.join(QLatin1String(", "))));
+}
+
+/*!
+ Removes the specified \a path from the file system watcher.
+
+ \sa removePaths(), addPath()
+*/
+void QFileSystemWatcher::removePath(const QString &path)
+{
+ if (path.isEmpty()) {
+ qWarning("QFileSystemWatcher::removePath: path is empty");
+ return;
+ }
+ removePaths(QStringList(path));
+}
+
+/*!
+ Removes the specified \a paths from the file system watcher.
+
+ \sa removePath(), addPaths()
+*/
+void QFileSystemWatcher::removePaths(const QStringList &paths)
+{
+ if (paths.isEmpty()) {
+ qWarning("QFileSystemWatcher::removePaths: list is empty");
+ return;
+ }
+ Q_D(QFileSystemWatcher);
+ QStringList p = paths;
+ if (d->native)
+ p = d->native->removePaths(p, &d->files, &d->directories);
+ if (d->poller)
+ p = d->poller->removePaths(p, &d->files, &d->directories);
+ if (d->forced)
+ p = d->forced->removePaths(p, &d->files, &d->directories);
+}
+
+/*!
+ \fn void QFileSystemWatcher::fileChanged(const QString &path)
+
+ This signal is emitted when the file at the specified \a path is
+ modified, renamed or removed from disk.
+
+ \sa directoryChanged()
+*/
+
+/*!
+ \fn void QFileSystemWatcher::directoryChanged(const QString &path)
+
+ This signal is emitted when the directory at a specified \a path,
+ is modified (e.g., when a file is added, modified or deleted) or
+ removed from disk. Note that if there are several changes during a
+ short period of time, some of the changes might not emit this
+ signal. However, the last change in the sequence of changes will
+ always generate this signal.
+
+ \sa fileChanged()
+*/
+
+/*!
+ \fn QStringList QFileSystemWatcher::directories() const
+
+ Returns a list of paths to directories that are being watched.
+
+ \sa files()
+*/
+
+/*!
+ \fn QStringList QFileSystemWatcher::files() const
+
+ Returns a list of paths to files that are being watched.
+
+ \sa directories()
+*/
+
+QStringList QFileSystemWatcher::directories() const
+{
+ Q_D(const QFileSystemWatcher);
+ return d->directories;
+}
+
+QStringList QFileSystemWatcher::files() const
+{
+ Q_D(const QFileSystemWatcher);
+ return d->files;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qfilesystemwatcher.cpp"
+
+#include "qfilesystemwatcher.moc"
+
+#endif // QT_NO_FILESYSTEMWATCHER
+
diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h
new file mode 100644
index 0000000000..26b3dec90f
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_H
+#define QFILESYSTEMWATCHER_H
+
+#include <QtCore/qobject.h>
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QFileSystemWatcherPrivate;
+
+class Q_CORE_EXPORT QFileSystemWatcher : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFileSystemWatcher)
+
+public:
+ QFileSystemWatcher(QObject *parent = 0);
+ QFileSystemWatcher(const QStringList &paths, QObject *parent = 0);
+ ~QFileSystemWatcher();
+
+ void addPath(const QString &file);
+ void addPaths(const QStringList &files);
+ void removePath(const QString &file);
+ void removePaths(const QStringList &files);
+
+ QStringList files() const;
+ QStringList directories() const;
+
+Q_SIGNALS:
+ void fileChanged(const QString &path);
+ void directoryChanged(const QString &path);
+
+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
+
+QT_END_HEADER
+
+#endif // QT_NO_FILESYSTEMWATCHER
+#endif // QFILESYSTEMWATCHER_H
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
new file mode 100644
index 0000000000..2fcadf1488
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_dnotify_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qsocketnotifier.h>
+#include <qcoreapplication.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <dirent.h>
+#include <qdir.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "private/qcore_unix_p.h"
+
+#ifdef QT_LINUXBASE
+
+/* LSB doesn't standardize these */
+#define F_NOTIFY 1026
+#define DN_ACCESS 0x00000001
+#define DN_MODIFY 0x00000002
+#define DN_CREATE 0x00000004
+#define DN_DELETE 0x00000008
+#define DN_RENAME 0x00000010
+#define DN_ATTRIB 0x00000020
+#define DN_MULTISHOT 0x80000000
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static int qfswd_fileChanged_pipe[2];
+static void (*qfswd_old_sigio_handler)(int) = 0;
+static void (*qfswd_old_sigio_action)(int, siginfo_t *, void *) = 0;
+static void qfswd_sigio_monitor(int signum, siginfo_t *i, void *v)
+{
+ qt_safe_write(qfswd_fileChanged_pipe[1], reinterpret_cast<char*>(&i->si_fd), sizeof(int));
+
+ if (qfswd_old_sigio_handler && qfswd_old_sigio_handler != SIG_IGN)
+ qfswd_old_sigio_handler(signum);
+ if (qfswd_old_sigio_action)
+ qfswd_old_sigio_action(signum, i, v);
+}
+
+class QDnotifySignalThread : public QThread
+{
+Q_OBJECT
+public:
+ QDnotifySignalThread();
+ virtual ~QDnotifySignalThread();
+
+ void startNotify();
+
+ virtual void run();
+
+signals:
+ void fdChanged(int);
+
+protected:
+ virtual bool event(QEvent *);
+
+private slots:
+ void readFromDnotify();
+
+private:
+ QMutex mutex;
+ QWaitCondition wait;
+ bool isExecing;
+};
+
+Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal)
+
+QDnotifySignalThread::QDnotifySignalThread()
+: isExecing(false)
+{
+ moveToThread(this);
+
+ qt_safe_pipe(qfswd_fileChanged_pipe, O_NONBLOCK);
+
+ struct sigaction oldAction;
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_sigaction = qfswd_sigio_monitor;
+ action.sa_flags = SA_SIGINFO;
+ ::sigaction(SIGIO, &action, &oldAction);
+ if (!(oldAction.sa_flags & SA_SIGINFO))
+ qfswd_old_sigio_handler = oldAction.sa_handler;
+ else
+ qfswd_old_sigio_action = oldAction.sa_sigaction;
+}
+
+QDnotifySignalThread::~QDnotifySignalThread()
+{
+ if(isRunning()) {
+ quit();
+ QThread::wait();
+ }
+}
+
+bool QDnotifySignalThread::event(QEvent *e)
+{
+ if(e->type() == QEvent::User) {
+ QMutexLocker locker(&mutex);
+ isExecing = true;
+ wait.wakeAll();
+ return true;
+ } else {
+ return QThread::event(e);
+ }
+}
+
+void QDnotifySignalThread::startNotify()
+{
+ // Note: All this fancy waiting for the thread to enter its event
+ // loop is to avoid nasty messages at app shutdown when the
+ // QDnotifySignalThread singleton is deleted
+ start();
+ mutex.lock();
+ while(!isExecing)
+ wait.wait(&mutex);
+ mutex.unlock();
+}
+
+void QDnotifySignalThread::run()
+{
+ QSocketNotifier sn(qfswd_fileChanged_pipe[0], QSocketNotifier::Read, this);
+ connect(&sn, SIGNAL(activated(int)), SLOT(readFromDnotify()));
+
+ QCoreApplication::instance()->postEvent(this, new QEvent(QEvent::User));
+ (void) exec();
+}
+
+void QDnotifySignalThread::readFromDnotify()
+{
+ int fd;
+ int readrv = qt_safe_read(qfswd_fileChanged_pipe[0], reinterpret_cast<char*>(&fd), sizeof(int));
+ // Only expect EAGAIN or EINTR. Other errors are assumed to be impossible.
+ if(readrv != -1) {
+ Q_ASSERT(readrv == sizeof(int));
+ Q_UNUSED(readrv);
+
+ if(0 == fd)
+ quit();
+ else
+ emit fdChanged(fd);
+ }
+}
+
+QDnotifyFileSystemWatcherEngine::QDnotifyFileSystemWatcherEngine()
+{
+ QObject::connect(dnotifySignal(), SIGNAL(fdChanged(int)),
+ this, SLOT(refresh(int)), Qt::DirectConnection);
+}
+
+QDnotifyFileSystemWatcherEngine::~QDnotifyFileSystemWatcherEngine()
+{
+ QMutexLocker locker(&mutex);
+
+ for(QHash<int, Directory>::ConstIterator iter = fdToDirectory.constBegin();
+ iter != fdToDirectory.constEnd();
+ ++iter) {
+ qt_safe_close(iter->fd);
+ if(iter->parentFd)
+ qt_safe_close(iter->parentFd);
+ }
+}
+
+QDnotifyFileSystemWatcherEngine *QDnotifyFileSystemWatcherEngine::create()
+{
+ return new QDnotifyFileSystemWatcherEngine();
+}
+
+void QDnotifyFileSystemWatcherEngine::run()
+{
+ qFatal("QDnotifyFileSystemWatcherEngine thread should not be run");
+}
+
+QStringList QDnotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+
+ while (it.hasNext()) {
+ QString path = it.next();
+
+ QFileInfo fi(path);
+
+ if(!fi.exists()) {
+ continue;
+ }
+
+ bool isDir = fi.isDir();
+
+ if (isDir && directories->contains(path)) {
+ continue; // Skip monitored directories
+ } else if(!isDir && files->contains(path)) {
+ continue; // Skip monitored files
+ }
+
+ if(!isDir)
+ path = fi.canonicalPath();
+
+ // Locate the directory entry (creating if needed)
+ int fd = pathToFD[path];
+
+ if(fd == 0) {
+
+ QT_DIR *d = QT_OPENDIR(path.toUtf8().constData());
+ if(!d) continue; // Could not open directory
+ QT_DIR *parent = 0;
+
+ QDir parentDir(path);
+ if(!parentDir.isRoot()) {
+ parentDir.cdUp();
+ parent = QT_OPENDIR(parentDir.path().toUtf8().constData());
+ if(!parent) {
+ QT_CLOSEDIR(d);
+ continue;
+ }
+ }
+
+ fd = qt_safe_dup(::dirfd(d));
+ int parentFd = parent ? qt_safe_dup(::dirfd(parent)) : 0;
+
+ QT_CLOSEDIR(d);
+ if(parent) QT_CLOSEDIR(parent);
+
+ Q_ASSERT(fd);
+ if(::fcntl(fd, F_SETSIG, SIGIO) ||
+ ::fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE |
+ DN_RENAME | DN_ATTRIB | DN_MULTISHOT) ||
+ (parent && ::fcntl(parentFd, F_SETSIG, SIGIO)) ||
+ (parent && ::fcntl(parentFd, F_NOTIFY, DN_DELETE | DN_RENAME |
+ DN_MULTISHOT))) {
+ continue; // Could not set appropriate flags
+ }
+
+ Directory dir;
+ dir.path = path;
+ dir.fd = fd;
+ dir.parentFd = parentFd;
+
+ fdToDirectory.insert(fd, dir);
+ pathToFD.insert(path, fd);
+ if(parentFd)
+ parentToFD.insert(parentFd, fd);
+ }
+
+ Directory &directory = fdToDirectory[fd];
+
+ if(isDir) {
+ directory.isMonitored = true;
+ } else {
+ Directory::File file;
+ file.path = fi.filePath();
+ file.lastWrite = fi.lastModified();
+ directory.files.append(file);
+ pathToFD.insert(fi.filePath(), fd);
+ }
+
+ it.remove();
+
+ if(isDir) {
+ directories->append(path);
+ } else {
+ files->append(fi.filePath());
+ }
+ }
+
+ dnotifySignal()->startNotify();
+
+ return p;
+}
+
+QStringList QDnotifyFileSystemWatcherEngine::removePaths(const QStringList &paths, QStringList *files, QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+
+ QString path = it.next();
+ int fd = pathToFD.take(path);
+
+ if(!fd)
+ continue;
+
+ Directory &directory = fdToDirectory[fd];
+ bool isDir = false;
+ if(directory.path == path) {
+ isDir = true;
+ directory.isMonitored = false;
+ } else {
+ for(int ii = 0; ii < directory.files.count(); ++ii) {
+ if(directory.files.at(ii).path == path) {
+ directory.files.removeAt(ii);
+ break;
+ }
+ }
+ }
+
+ if(!directory.isMonitored && directory.files.isEmpty()) {
+ // No longer needed
+ qt_safe_close(directory.fd);
+ pathToFD.remove(directory.path);
+ fdToDirectory.remove(fd);
+ }
+
+ if(isDir) {
+ directories->removeAll(path);
+ } else {
+ files->removeAll(path);
+ }
+
+ it.remove();
+ }
+
+ return p;
+}
+
+void QDnotifyFileSystemWatcherEngine::refresh(int fd)
+{
+ QMutexLocker locker(&mutex);
+
+ bool wasParent = false;
+ QHash<int, Directory>::Iterator iter = fdToDirectory.find(fd);
+ if(iter == fdToDirectory.end()) {
+ QHash<int, int>::Iterator pIter = parentToFD.find(fd);
+ if(pIter == parentToFD.end())
+ return;
+
+ iter = fdToDirectory.find(*pIter);
+ if (iter == fdToDirectory.end())
+ return;
+ wasParent = true;
+ }
+
+ Directory &directory = *iter;
+
+ if(!wasParent) {
+ for(int ii = 0; ii < directory.files.count(); ++ii) {
+ Directory::File &file = directory.files[ii];
+ if(file.updateInfo()) {
+ // Emit signal
+ QString filePath = file.path;
+ bool removed = !QFileInfo(filePath).exists();
+
+ if(removed) {
+ directory.files.removeAt(ii);
+ --ii;
+ }
+
+ emit fileChanged(filePath, removed);
+ }
+ }
+ }
+
+ if(directory.isMonitored) {
+ // Emit signal
+ bool removed = !QFileInfo(directory.path).exists();
+ QString path = directory.path;
+
+ if(removed)
+ directory.isMonitored = false;
+
+ emit directoryChanged(path, removed);
+ }
+
+ if(!directory.isMonitored && directory.files.isEmpty()) {
+ qt_safe_close(directory.fd);
+ if(directory.parentFd) {
+ qt_safe_close(directory.parentFd);
+ parentToFD.remove(directory.parentFd);
+ }
+ fdToDirectory.erase(iter);
+ }
+}
+
+void QDnotifyFileSystemWatcherEngine::stop()
+{
+}
+
+bool QDnotifyFileSystemWatcherEngine::Directory::File::updateInfo()
+{
+ QFileInfo fi(path);
+ QDateTime nLastWrite = fi.lastModified();
+ uint nOwnerId = fi.ownerId();
+ uint nGroupId = fi.groupId();
+ QFile::Permissions nPermissions = fi.permissions();
+
+ if(nLastWrite != lastWrite ||
+ nOwnerId != ownerId ||
+ nGroupId != groupId ||
+ nPermissions != permissions) {
+ ownerId = nOwnerId;
+ groupId = nGroupId;
+ permissions = nPermissions;
+ lastWrite = nLastWrite;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qfilesystemwatcher_dnotify.moc"
+
+#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify_p.h b/src/corelib/io/qfilesystemwatcher_dnotify_p.h
new file mode 100644
index 0000000000..9531a3e81b
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_dnotify_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_DNOTIFY_P_H
+#define QFILESYSTEMWATCHER_DNOTIFY_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qmutex.h>
+#include <qhash.h>
+#include <qdatetime.h>
+#include <qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDnotifyFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+
+public:
+ virtual ~QDnotifyFileSystemWatcherEngine();
+
+ static QDnotifyFileSystemWatcherEngine *create();
+
+ void run();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+private Q_SLOTS:
+ void refresh(int);
+
+private:
+ struct Directory {
+ Directory() : fd(0), parentFd(0), isMonitored(false) {}
+ Directory(const Directory &o) : path(o.path),
+ fd(o.fd),
+ parentFd(o.parentFd),
+ isMonitored(o.isMonitored),
+ files(o.files) {}
+ QString path;
+ int fd;
+ int parentFd;
+ bool isMonitored;
+
+ struct File {
+ File() : ownerId(0u), groupId(0u), permissions(0u) { }
+ File(const File &o) : path(o.path),
+ ownerId(o.ownerId),
+ groupId(o.groupId),
+ permissions(o.permissions),
+ lastWrite(o.lastWrite) {}
+ QString path;
+
+ bool updateInfo();
+
+ uint ownerId;
+ uint groupId;
+ QFile::Permissions permissions;
+ QDateTime lastWrite;
+ };
+
+ QList<File> files;
+ };
+
+ QDnotifyFileSystemWatcherEngine();
+
+ QMutex mutex;
+ QHash<QString, int> pathToFD;
+ QHash<int, Directory> fdToDirectory;
+ QHash<int, int> parentToFD;
+};
+
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_FILESYSTEMWATCHER
+#endif // QFILESYSTEMWATCHER_DNOTIFY_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
new file mode 100644
index 0000000000..19b720c8b3
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
@@ -0,0 +1,492 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qplatformdefs.h>
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_fsevents_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include <qvarlengtharray.h>
+
+#include <mach/mach.h>
+#include <sys/types.h>
+#include <CoreFoundation/CFRunLoop.h>
+#include <CoreFoundation/CFUUID.h>
+#include <CoreServices/CoreServices.h>
+#include <AvailabilityMacros.h>
+#include <private/qcore_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+// Static operator overloading so for the sake of some convieniece.
+// They only live in this compilation unit to avoid polluting Qt in general.
+static bool operator==(const struct ::timespec &left, const struct ::timespec &right)
+{
+ return left.tv_sec == right.tv_sec
+ && left.tv_nsec == right.tv_nsec;
+}
+
+static bool operator==(const struct ::stat64 &left, const struct ::stat64 &right)
+{
+ return left.st_dev == right.st_dev
+ && left.st_mode == right.st_mode
+ && left.st_size == right.st_size
+ && left.st_ino == right.st_ino
+ && left.st_uid == right.st_uid
+ && left.st_gid == right.st_gid
+ && left.st_mtimespec == right.st_mtimespec
+ && left.st_ctimespec == right.st_ctimespec
+ && left.st_flags == right.st_flags;
+}
+
+static bool operator!=(const struct ::stat64 &left, const struct ::stat64 &right)
+{
+ return !(operator==(left, right));
+}
+
+
+static void addPathToHash(PathHash &pathHash, const QString &key, const QFileInfo &fileInfo,
+ const QString &path)
+{
+ PathInfoList &list = pathHash[key];
+ list.push_back(PathInfo(path,
+ fileInfo.canonicalFilePath().normalized(QString::NormalizationForm_D).toUtf8()));
+ pathHash.insert(key, list);
+}
+
+static void removePathFromHash(PathHash &pathHash, const QString &key, const QString &path)
+{
+ PathInfoList &list = pathHash[key];
+ // We make the assumption that the list contains unique paths
+ PathInfoList::iterator End = list.end();
+ PathInfoList::iterator it = list.begin();
+ while (it != End) {
+ if (it->originalPath == path) {
+ list.erase(it);
+ break;
+ }
+ ++it;
+ }
+ if (list.isEmpty())
+ pathHash.remove(key);
+}
+
+static void stopFSStream(FSEventStreamRef stream)
+{
+ if (stream) {
+ FSEventStreamStop(stream);
+ FSEventStreamInvalidate(stream);
+ }
+}
+
+static QString createFSStreamPath(const QString &absolutePath)
+{
+ // The path returned has a trailing slash, so ensure that here.
+ QString string = absolutePath;
+ string.reserve(string.size() + 1);
+ string.append(QLatin1Char('/'));
+ return string;
+}
+
+static void cleanupFSStream(FSEventStreamRef stream)
+{
+ if (stream)
+ FSEventStreamRelease(stream);
+}
+
+const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer /* | kFSEventStreamCreateFlagWatchRoot*/);
+
+const CFTimeInterval Latency = 0.033; // This will do updates 30 times a second which is probably more than you need.
+#endif
+
+QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine()
+ : fsStream(0), pathsToWatch(0), threadsRunLoop(0)
+{
+}
+
+QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ // I assume that at this point, QFileSystemWatcher has already called stop
+ // on me, so I don't need to invalidate or stop my stream, simply
+ // release it.
+ cleanupFSStream(fsStream);
+ if (pathsToWatch)
+ CFRelease(pathsToWatch);
+#endif
+}
+
+QFSEventsFileSystemWatcherEngine *QFSEventsFileSystemWatcherEngine::create()
+{
+ return new QFSEventsFileSystemWatcherEngine();
+}
+
+QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ stop();
+ wait();
+ QMutexLocker locker(&mutex);
+ QStringList failedToAdd;
+ // if we have a running FSStreamEvent, we have to kill it, we'll re-add the stream soon.
+ FSEventStreamEventId idToCheck;
+ if (fsStream) {
+ idToCheck = FSEventStreamGetLatestEventId(fsStream);
+ cleanupFSStream(fsStream);
+ } else {
+ idToCheck = kFSEventStreamEventIdSinceNow;
+ }
+
+ // Brain-dead approach, but works. FSEvents actually can already read sub-trees, but since it's
+ // work to figure out if we are doing a double register, we just register it twice as FSEvents
+ // seems smart enough to only deliver one event. We also duplicate directory entries in here
+ // (e.g., if you watch five files in the same directory, you get that directory included in the
+ // array 5 times). This stupidity also makes remove work correctly though. I'll freely admit
+ // that we could make this a bit smarter. If you do, check the auto-tests, they should catch at
+ // least a couple of the issues.
+ QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ for (int i = 0; i < paths.size(); ++i) {
+ const QString &path = paths.at(i);
+
+ QFileInfo fileInfo(path);
+ if (!fileInfo.exists()) {
+ failedToAdd.append(path);
+ continue;
+ }
+
+ if (fileInfo.isDir()) {
+ if (directories->contains(path)) {
+ failedToAdd.append(path);
+ continue;
+ } else {
+ directories->append(path);
+ // Full file path for dirs.
+ QCFString cfpath(createFSStreamPath(fileInfo.canonicalFilePath()));
+ addPathToHash(dirPathInfoHash, cfpath, fileInfo, path);
+ CFArrayAppendValue(tmpArray, cfpath);
+ }
+ } else {
+ if (files->contains(path)) {
+ failedToAdd.append(path);
+ continue;
+ } else {
+ // Just the absolute path (minus it's filename) for files.
+ QCFString cfpath(createFSStreamPath(fileInfo.canonicalPath()));
+ files->append(path);
+ addPathToHash(filePathInfoHash, cfpath, fileInfo, path);
+ CFArrayAppendValue(tmpArray, cfpath);
+ }
+ }
+ }
+
+ if (!pathsToWatch && failedToAdd.size() == paths.size()) {
+ return failedToAdd;
+ }
+
+ if (CFArrayGetCount(tmpArray) > 0) {
+ if (pathsToWatch) {
+ CFArrayAppendArray(tmpArray, pathsToWatch, CFRangeMake(0, CFArrayGetCount(pathsToWatch)));
+ CFRelease(pathsToWatch);
+ }
+ pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
+ }
+
+ FSEventStreamContext context = { 0, this, 0, 0, 0 };
+ fsStream = FSEventStreamCreate(kCFAllocatorDefault,
+ QFSEventsFileSystemWatcherEngine::fseventsCallback,
+ &context, pathsToWatch,
+ idToCheck, Latency, QtFSEventFlags);
+ warmUpFSEvents();
+
+ return failedToAdd;
+#else
+ Q_UNUSED(paths);
+ Q_UNUSED(files);
+ Q_UNUSED(directories);
+ return QStringList();
+#endif
+}
+
+void QFSEventsFileSystemWatcherEngine::warmUpFSEvents()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ // This function assumes that the mutex has already been grabbed before calling it.
+ // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-).
+ start();
+ waitCondition.wait(&mutex);
+#endif
+}
+
+QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ stop();
+ wait();
+ QMutexLocker locker(&mutex);
+ // short circuit for smarties that call remove before add and we have nothing.
+ if (pathsToWatch == 0)
+ return paths;
+ QStringList failedToRemove;
+ // if we have a running FSStreamEvent, we have to stop it, we'll re-add the stream soon.
+ FSEventStreamEventId idToCheck;
+ if (fsStream) {
+ idToCheck = FSEventStreamGetLatestEventId(fsStream);
+ cleanupFSStream(fsStream);
+ fsStream = 0;
+ } else {
+ idToCheck = kFSEventStreamEventIdSinceNow;
+ }
+
+ CFIndex itemCount = CFArrayGetCount(pathsToWatch);
+ QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, itemCount,
+ pathsToWatch);
+ CFRelease(pathsToWatch);
+ pathsToWatch = 0;
+ for (int i = 0; i < paths.size(); ++i) {
+ // Get the itemCount at the beginning to avoid any overruns during the iteration.
+ itemCount = CFArrayGetCount(tmpArray);
+ const QString &path = paths.at(i);
+ QFileInfo fi(path);
+ QCFString cfpath(createFSStreamPath(fi.canonicalPath()));
+
+ CFIndex index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath);
+ if (index != -1) {
+ CFArrayRemoveValueAtIndex(tmpArray, index);
+ files->removeAll(path);
+ removePathFromHash(filePathInfoHash, cfpath, path);
+ } else {
+ // Could be a directory we are watching instead.
+ QCFString cfdirpath(createFSStreamPath(fi.canonicalFilePath()));
+ index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath);
+ if (index != -1) {
+ CFArrayRemoveValueAtIndex(tmpArray, index);
+ directories->removeAll(path);
+ removePathFromHash(dirPathInfoHash, cfpath, path);
+ } else {
+ failedToRemove.append(path);
+ }
+ }
+ }
+ itemCount = CFArrayGetCount(tmpArray);
+ if (itemCount != 0) {
+ pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
+
+ FSEventStreamContext context = { 0, this, 0, 0, 0 };
+ fsStream = FSEventStreamCreate(kCFAllocatorDefault,
+ QFSEventsFileSystemWatcherEngine::fseventsCallback,
+ &context, pathsToWatch, idToCheck, Latency, QtFSEventFlags);
+ warmUpFSEvents();
+ }
+ return failedToRemove;
+#else
+ Q_UNUSED(paths);
+ Q_UNUSED(files);
+ Q_UNUSED(directories);
+ return QStringList();
+#endif
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals)
+{
+ PathInfoList::iterator End = list.end();
+ PathInfoList::iterator it = list.begin();
+ while (it != End) {
+ struct ::stat64 newInfo;
+ if (::stat64(it->absolutePath, &newInfo) == 0) {
+ if (emitSignals) {
+ if (newInfo != it->savedInfo) {
+ it->savedInfo = newInfo;
+ if (directory)
+ emit directoryChanged(it->originalPath, false);
+ else
+ emit fileChanged(it->originalPath, false);
+ }
+ } else {
+ it->savedInfo = newInfo;
+ }
+ } else {
+ if (errno == ENOENT) {
+ if (emitSignals) {
+ if (directory)
+ emit directoryChanged(it->originalPath, true);
+ else
+ emit fileChanged(it->originalPath, true);
+ }
+ it = list.erase(it);
+ continue;
+ } else {
+ qWarning("%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s",
+ __FILE__, __LINE__, qPrintable(it->originalPath), strerror(errno));
+
+ }
+ }
+ ++it;
+ }
+}
+
+void QFSEventsFileSystemWatcherEngine::updateHash(PathHash &pathHash)
+{
+ PathHash::iterator HashEnd = pathHash.end();
+ PathHash::iterator it = pathHash.begin();
+ const bool IsDirectory = (&pathHash == &dirPathInfoHash);
+ while (it != HashEnd) {
+ updateList(it.value(), IsDirectory, false);
+ if (it.value().isEmpty())
+ it = pathHash.erase(it);
+ else
+ ++it;
+ }
+}
+#endif
+
+void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef ,
+ void *clientCallBackInfo, size_t numEvents,
+ void *eventPaths,
+ const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId [])
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo);
+ QMutexLocker locker(&watcher->mutex);
+ CFArrayRef paths = static_cast<CFArrayRef>(eventPaths);
+ for (size_t i = 0; i < numEvents; ++i) {
+ const QString path = QCFString::toQString(
+ static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i)));
+ const FSEventStreamEventFlags pathFlags = eventFlags[i];
+ // There are several flags that may be passed, but we really don't care about them ATM.
+ // Here they are and why we don't care.
+ // kFSEventStreamEventFlagHistoryDone--(very unlikely to be gotten, but even then, not much changes).
+ // kFSEventStreamEventFlagMustScanSubDirs--Likely means the data is very much out of date, we
+ // aren't coalescing our directories, so again not so much of an issue
+ // kFSEventStreamEventFlagRootChanged | kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount--
+ // These three flags indicate something has changed, but the stat will likely show this, so
+ // there's not really much to worry about.
+ // (btw, FSEvents is not the correct way of checking for mounts/unmounts,
+ // there are real CarbonCore events for that.)
+ Q_UNUSED(pathFlags);
+ if (watcher->filePathInfoHash.contains(path))
+ watcher->updateList(watcher->filePathInfoHash[path], false, true);
+
+ if (watcher->dirPathInfoHash.contains(path))
+ watcher->updateList(watcher->dirPathInfoHash[path], true, true);
+ }
+#else
+ Q_UNUSED(clientCallBackInfo);
+ Q_UNUSED(numEvents);
+ Q_UNUSED(eventPaths);
+ Q_UNUSED(eventFlags);
+#endif
+}
+
+void QFSEventsFileSystemWatcherEngine::stop()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ QMutexLocker locker(&mutex);
+ stopFSStream(fsStream);
+ if (threadsRunLoop) {
+ CFRunLoopStop(threadsRunLoop);
+ waitForStop.wait(&mutex);
+ }
+#endif
+}
+
+void QFSEventsFileSystemWatcherEngine::updateFiles()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ QMutexLocker locker(&mutex);
+ updateHash(filePathInfoHash);
+ updateHash(dirPathInfoHash);
+ if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) {
+ // Everything disappeared before we got to start, don't bother.
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ // Code duplicated from stop(), with the exception that we
+ // don't wait on waitForStop here. Doing this will lead to
+ // a deadlock since this function is called from the worker
+ // thread. (waitForStop.wakeAll() is only called from the
+ // end of run()).
+ stopFSStream(fsStream);
+ if (threadsRunLoop)
+ CFRunLoopStop(threadsRunLoop);
+#endif
+ cleanupFSStream(fsStream);
+ }
+ waitCondition.wakeAll();
+#endif
+}
+
+void QFSEventsFileSystemWatcherEngine::run()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ threadsRunLoop = CFRunLoopGetCurrent();
+ FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode);
+ bool startedOK = FSEventStreamStart(fsStream);
+ // It's recommended by Apple that you only update the files after you've started
+ // the stream, because otherwise you might miss an update in between starting it.
+ updateFiles();
+#ifdef QT_NO_DEBUG
+ Q_UNUSED(startedOK);
+#else
+ Q_ASSERT(startedOK);
+#endif
+ // If for some reason we called stop up above (and invalidated our stream), this call will return
+ // immediately.
+ CFRunLoopRun();
+ threadsRunLoop = 0;
+ QMutexLocker locker(&mutex);
+ waitForStop.wakeAll();
+#endif
+}
+
+QT_END_NAMESPACE
+#endif //QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
new file mode 100644
index 0000000000..bbfdd32fd4
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef FILEWATCHER_FSEVENTS_P_H
+#define FILEWATCHER_FSEVENTS_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qlinkedlist.h>
+#include <private/qcore_mac_p.h>
+#include <sys/stat.h>
+
+typedef struct __FSEventStream *FSEventStreamRef;
+typedef const struct __FSEventStream *ConstFSEventStreamRef;
+typedef const struct __CFArray *CFArrayRef;
+typedef UInt32 FSEventStreamEventFlags;
+typedef uint64_t FSEventStreamEventId;
+
+QT_BEGIN_NAMESPACE
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+// Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation
+// details to be used as a long-standing record. Since I'm going to have to store this information, I can
+// do the stat myself too.
+struct PathInfo {
+ PathInfo(const QString &path, const QByteArray &absPath)
+ : originalPath(path), absolutePath(absPath) {}
+ QString originalPath; // The path we need to emit
+ QByteArray absolutePath; // The path we need to stat.
+ struct ::stat64 savedInfo; // All the info for the path so we can compare it.
+};
+typedef QLinkedList<PathInfo> PathInfoList;
+typedef QHash<QString, PathInfoList> PathHash;
+#endif
+
+class QFSEventsFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+public:
+ ~QFSEventsFileSystemWatcherEngine();
+
+ static QFSEventsFileSystemWatcherEngine *create();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+private:
+ QFSEventsFileSystemWatcherEngine();
+ void warmUpFSEvents();
+ void updateFiles();
+
+ static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents,
+ void *eventPaths, const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId eventIds[]);
+ void run();
+ FSEventStreamRef fsStream;
+ CFArrayRef pathsToWatch;
+ CFRunLoopRef threadsRunLoop;
+ QMutex mutex;
+ QWaitCondition waitCondition;
+ QWaitCondition waitForStop;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ PathHash filePathInfoHash;
+ PathHash dirPathInfoHash;
+ void updateHash(PathHash &pathHash);
+ void updateList(PathInfoList &list, bool directory, bool emitSignals);
+#endif
+};
+
+#endif //QT_NO_FILESYSTEMWATCHER
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
new file mode 100644
index 0000000000..8fc2d31312
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_inotify_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include "private/qcore_unix_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qsocketnotifier.h>
+#include <qvarlengtharray.h>
+
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if defined(QT_NO_INOTIFY)
+#include <linux/types.h>
+
+#if defined(__i386__)
+# define __NR_inotify_init 291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch 293
+# define __NR_inotify_init1 332
+#elif defined(__x86_64__)
+# define __NR_inotify_init 253
+# define __NR_inotify_add_watch 254
+# define __NR_inotify_rm_watch 255
+# define __NR_inotify_init1 294
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init 275
+# define __NR_inotify_add_watch 276
+# define __NR_inotify_rm_watch 277
+# define __NR_inotify_init1 318
+#elif defined (__ia64__)
+# define __NR_inotify_init 1277
+# define __NR_inotify_add_watch 1278
+# define __NR_inotify_rm_watch 1279
+# define __NR_inotify_init1 1318
+#elif defined (__s390__) || defined (__s390x__)
+# define __NR_inotify_init 284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 324
+#elif defined (__alpha__)
+# define __NR_inotify_init 444
+# define __NR_inotify_add_watch 445
+# define __NR_inotify_rm_watch 446
+// no inotify_init1 for the Alpha
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init 151
+# define __NR_inotify_add_watch 152
+# define __NR_inotify_rm_watch 156
+# define __NR_inotify_init1 322
+#elif defined (__arm__)
+# define __NR_inotify_init 316
+# define __NR_inotify_add_watch 317
+# define __NR_inotify_rm_watch 318
+# define __NR_inotify_init1 360
+#elif defined (__sh__)
+# define __NR_inotify_init 290
+# define __NR_inotify_add_watch 291
+# define __NR_inotify_rm_watch 292
+# define __NR_inotify_init1 332
+#elif defined (__sh64__)
+# define __NR_inotify_init 318
+# define __NR_inotify_add_watch 319
+# define __NR_inotify_rm_watch 320
+# define __NR_inotify_init1 360
+#elif defined (__mips__)
+# define __NR_inotify_init 284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 329
+#elif defined (__hppa__)
+# define __NR_inotify_init 269
+# define __NR_inotify_add_watch 270
+# define __NR_inotify_rm_watch 271
+# define __NR_inotify_init1 314
+#elif defined (__avr32__)
+# define __NR_inotify_init 240
+# define __NR_inotify_add_watch 241
+# define __NR_inotify_rm_watch 242
+// no inotify_init1 for AVR32
+#elif defined (__mc68000__)
+# define __NR_inotify_init 284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 328
+#else
+# error "This architecture is not supported. Please talk to qt-bugs@trolltech.com"
+#endif
+
+#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
+# define IN_CLOEXEC O_CLOEXEC
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_LINUXBASE
+// ### the LSB doesn't standardize syscall, need to wait until glib2.4 is standardized
+static inline int syscall(...) { return -1; }
+#endif
+
+static inline int inotify_init()
+{
+ return syscall(__NR_inotify_init);
+}
+
+static inline int inotify_add_watch(int fd, const char *name, __u32 mask)
+{
+ return syscall(__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch(int fd, __u32 wd)
+{
+ return syscall(__NR_inotify_rm_watch, fd, wd);
+}
+
+#ifdef IN_CLOEXEC
+static inline int inotify_init1(int flags)
+{
+ return syscall(__NR_inotify_init1, flags);
+}
+#endif
+
+// the following struct and values are documented in linux/inotify.h
+extern "C" {
+
+struct inotify_event {
+ __s32 wd;
+ __u32 mask;
+ __u32 cookie;
+ __u32 len;
+ char name[0];
+};
+
+#define IN_ACCESS 0x00000001
+#define IN_MODIFY 0x00000002
+#define IN_ATTRIB 0x00000004
+#define IN_CLOSE_WRITE 0x00000008
+#define IN_CLOSE_NOWRITE 0x00000010
+#define IN_OPEN 0x00000020
+#define IN_MOVED_FROM 0x00000040
+#define IN_MOVED_TO 0x00000080
+#define IN_CREATE 0x00000100
+#define IN_DELETE 0x00000200
+#define IN_DELETE_SELF 0x00000400
+#define IN_MOVE_SELF 0x00000800
+#define IN_UNMOUNT 0x00002000
+#define IN_Q_OVERFLOW 0x00004000
+#define IN_IGNORED 0x00008000
+
+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
+#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO)
+}
+
+QT_END_NAMESPACE
+
+// --------- inotify.h end ----------
+
+#else /* QT_NO_INOTIFY */
+
+#include <sys/inotify.h>
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create()
+{
+ register int fd = -1;
+#ifdef IN_CLOEXEC
+ fd = inotify_init1(IN_CLOEXEC);
+#endif
+ if (fd == -1) {
+ fd = inotify_init();
+ if (fd == -1)
+ return 0;
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
+ return new QInotifyFileSystemWatcherEngine(fd);
+}
+
+QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd)
+ : inotifyFd(fd)
+{
+ fcntl(inotifyFd, F_SETFD, FD_CLOEXEC);
+
+ moveToThread(this);
+}
+
+QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine()
+{
+ foreach (int id, pathToID)
+ inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
+
+ ::close(inotifyFd);
+}
+
+void QInotifyFileSystemWatcherEngine::run()
+{
+ QSocketNotifier sn(inotifyFd, QSocketNotifier::Read, this);
+ connect(&sn, SIGNAL(activated(int)), SLOT(readFromInotify()));
+ (void) exec();
+}
+
+QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QFileInfo fi(path);
+ bool isDir = fi.isDir();
+ if (isDir) {
+ if (directories->contains(path))
+ continue;
+ } else {
+ if (files->contains(path))
+ continue;
+ }
+
+ int wd = inotify_add_watch(inotifyFd,
+ QFile::encodeName(path),
+ (isDir
+ ? (0
+ | IN_ATTRIB
+ | IN_MOVE
+ | IN_CREATE
+ | IN_DELETE
+ | IN_DELETE_SELF
+ )
+ : (0
+ | IN_ATTRIB
+ | IN_MODIFY
+ | IN_MOVE
+ | IN_MOVE_SELF
+ | IN_DELETE_SELF
+ )));
+ if (wd <= 0) {
+ perror("QInotifyFileSystemWatcherEngine::addPaths: inotify_add_watch failed");
+ continue;
+ }
+
+ it.remove();
+
+ int id = isDir ? -wd : wd;
+ if (id < 0) {
+ directories->append(path);
+ } else {
+ files->append(path);
+ }
+
+ pathToID.insert(path, id);
+ idToPath.insert(id, path);
+ }
+
+ start();
+
+ return p;
+}
+
+QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int id = pathToID.take(path);
+ QString x = idToPath.take(id);
+ if (x.isEmpty() || x != path)
+ continue;
+
+ int wd = id < 0 ? -id : id;
+ // qDebug() << "removing watch for path" << path << "wd" << wd;
+ inotify_rm_watch(inotifyFd, wd);
+
+ it.remove();
+ if (id < 0) {
+ directories->removeAll(path);
+ } else {
+ files->removeAll(path);
+ }
+ }
+
+ return p;
+}
+
+void QInotifyFileSystemWatcherEngine::stop()
+{
+ quit();
+}
+
+void QInotifyFileSystemWatcherEngine::readFromInotify()
+{
+ QMutexLocker locker(&mutex);
+
+ // qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify";
+
+ int buffSize = 0;
+ ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
+ QVarLengthArray<char, 4096> buffer(buffSize);
+ buffSize = read(inotifyFd, buffer.data(), buffSize);
+ char *at = buffer.data();
+ char * const end = at + buffSize;
+
+ QHash<int, inotify_event *> eventForId;
+ while (at < end) {
+ inotify_event *event = reinterpret_cast<inotify_event *>(at);
+
+ if (eventForId.contains(event->wd))
+ eventForId[event->wd]->mask |= event->mask;
+ else
+ eventForId.insert(event->wd, event);
+
+ at += sizeof(inotify_event) + event->len;
+ }
+
+ QHash<int, inotify_event *>::const_iterator it = eventForId.constBegin();
+ while (it != eventForId.constEnd()) {
+ const inotify_event &event = **it;
+ ++it;
+
+ // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
+
+ int id = event.wd;
+ QString path = idToPath.value(id);
+ if (path.isEmpty()) {
+ // perhaps a directory?
+ id = -id;
+ path = idToPath.value(id);
+ if (path.isEmpty())
+ continue;
+ }
+
+ // qDebug() << "event for path" << path;
+
+ if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
+ pathToID.remove(path);
+ idToPath.remove(id);
+ inotify_rm_watch(inotifyFd, event.wd);
+
+ if (id < 0)
+ emit directoryChanged(path, true);
+ else
+ emit fileChanged(path, true);
+ } else {
+ if (id < 0)
+ emit directoryChanged(path, false);
+ else
+ emit fileChanged(path, false);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h
new file mode 100644
index 0000000000..870d9b48d5
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_INOTIFY_P_H
+#define QFILESYSTEMWATCHER_INOTIFY_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qhash.h>
+#include <qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QInotifyFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+
+public:
+ ~QInotifyFileSystemWatcherEngine();
+
+ static QInotifyFileSystemWatcherEngine *create();
+
+ void run();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+private Q_SLOTS:
+ void readFromInotify();
+
+private:
+ QInotifyFileSystemWatcherEngine(int fd);
+ int inotifyFd;
+ QMutex mutex;
+ QHash<QString, int> pathToID;
+ QHash<int, QString> idToPath;
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_FILESYSTEMWATCHER
+#endif // QFILESYSTEMWATCHER_INOTIFY_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
new file mode 100644
index 0000000000..6c36a82fd1
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qplatformdefs.h>
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_kqueue_p.h"
+#include "private/qcore_unix_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qsocketnotifier.h>
+#include <qvarlengtharray.h>
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+QT_BEGIN_NAMESPACE
+
+// #define KEVENT_DEBUG
+#ifdef KEVENT_DEBUG
+# define DEBUG qDebug
+#else
+# define DEBUG if(false)qDebug
+#endif
+
+QKqueueFileSystemWatcherEngine *QKqueueFileSystemWatcherEngine::create()
+{
+ int kqfd = kqueue();
+ if (kqfd == -1)
+ return 0;
+ return new QKqueueFileSystemWatcherEngine(kqfd);
+}
+
+QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd)
+ : kqfd(kqfd)
+{
+ fcntl(kqfd, F_SETFD, FD_CLOEXEC);
+
+ if (pipe(kqpipe) == -1) {
+ perror("QKqueueFileSystemWatcherEngine: cannot create pipe");
+ kqpipe[0] = kqpipe[1] = -1;
+ return;
+ }
+ fcntl(kqpipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl(kqpipe[1], F_SETFD, FD_CLOEXEC);
+
+ struct kevent kev;
+ EV_SET(&kev,
+ kqpipe[0],
+ EVFILT_READ,
+ EV_ADD | EV_ENABLE,
+ 0,
+ 0,
+ 0);
+ if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
+ perror("QKqueueFileSystemWatcherEngine: cannot watch pipe, kevent returned");
+ return;
+ }
+}
+
+QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine()
+{
+ stop();
+ wait();
+
+ close(kqfd);
+ close(kqpipe[0]);
+ close(kqpipe[1]);
+
+ foreach (int id, pathToID)
+ ::close(id < 0 ? -id : id);
+}
+
+QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QStringList p = paths;
+ {
+ QMutexLocker locker(&mutex);
+
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int fd;
+#if defined(O_EVTONLY)
+ fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
+#else
+ fd = qt_safe_open(QFile::encodeName(path), O_RDONLY);
+#endif
+ if (fd == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: open");
+ continue;
+ }
+ if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) {
+ int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE);
+ if (fddup != -1) {
+ ::close(fd);
+ fd = fddup;
+ }
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ QT_STATBUF st;
+ if (QT_FSTAT(fd, &st) == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: fstat");
+ ::close(fd);
+ continue;
+ }
+ int id = (S_ISDIR(st.st_mode)) ? -fd : fd;
+ if (id < 0) {
+ if (directories->contains(path)) {
+ ::close(fd);
+ continue;
+ }
+ } else {
+ if (files->contains(path)) {
+ ::close(fd);
+ continue;
+ }
+ }
+
+ struct kevent kev;
+ EV_SET(&kev,
+ fd,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
+ 0,
+ 0);
+ if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: kevent");
+ ::close(fd);
+ continue;
+ }
+
+ it.remove();
+ if (id < 0) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
+ directories->append(path);
+ } else {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path;
+ files->append(path);
+ }
+
+ pathToID.insert(path, id);
+ idToPath.insert(id, path);
+ }
+ }
+
+ if (!isRunning())
+ start();
+ else
+ write(kqpipe[1], "@", 1);
+
+ return p;
+}
+
+QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ bool isEmpty;
+ QStringList p = paths;
+ {
+ QMutexLocker locker(&mutex);
+ if (pathToID.isEmpty())
+ return p;
+
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int id = pathToID.take(path);
+ QString x = idToPath.take(id);
+ if (x.isEmpty() || x != path)
+ continue;
+
+ ::close(id < 0 ? -id : id);
+
+ it.remove();
+ if (id < 0)
+ directories->removeAll(path);
+ else
+ files->removeAll(path);
+ }
+ isEmpty = pathToID.isEmpty();
+ }
+
+ if (isEmpty) {
+ stop();
+ wait();
+ } else {
+ write(kqpipe[1], "@", 1);
+ }
+
+ return p;
+}
+
+void QKqueueFileSystemWatcherEngine::stop()
+{
+ write(kqpipe[1], "q", 1);
+}
+
+void QKqueueFileSystemWatcherEngine::run()
+{
+ forever {
+ int r;
+ struct kevent kev;
+ DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents...";
+ EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, 0));
+ if (r < 0) {
+ perror("QKqueueFileSystemWatcherEngine: error during kevent wait");
+ return;
+ } else {
+ int fd = kev.ident;
+
+ DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter;
+ if (fd == kqpipe[0]) {
+ // read all pending data from the pipe
+ QByteArray ba;
+ ba.resize(kev.data);
+ if (read(kqpipe[0], ba.data(), ba.size()) != ba.size()) {
+ perror("QKqueueFileSystemWatcherEngine: error reading from pipe");
+ return;
+ }
+ // read the command from the buffer (but break and return on 'q')
+ char cmd = 0;
+ for (int i = 0; i < ba.size(); ++i) {
+ cmd = ba.constData()[i];
+ if (cmd == 'q')
+ break;
+ }
+ // handle the command
+ switch (cmd) {
+ case 'q':
+ DEBUG() << "QKqueueFileSystemWatcherEngine: thread received 'q', exiting...";
+ return;
+ case '@':
+ DEBUG() << "QKqueueFileSystemWatcherEngine: thread received '@', continuing...";
+ break;
+ default:
+ DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << cmd;
+ break;
+ }
+ } else {
+ QMutexLocker locker(&mutex);
+
+ int id = fd;
+ QString path = idToPath.value(id);
+ if (path.isEmpty()) {
+ // perhaps a directory?
+ id = -id;
+ path = idToPath.value(id);
+ if (path.isEmpty()) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching";
+ continue;
+ }
+ }
+ if (kev.filter != EVFILT_VNODE) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter";
+ continue;
+ }
+
+ if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) {
+ DEBUG() << path << "removed, removing watch also";
+
+ pathToID.remove(path);
+ idToPath.remove(id);
+ ::close(fd);
+
+ if (id < 0)
+ emit directoryChanged(path, true);
+ else
+ emit fileChanged(path, true);
+ } else {
+ DEBUG() << path << "changed";
+
+ if (id < 0)
+ emit directoryChanged(path, false);
+ else
+ emit fileChanged(path, false);
+ }
+ }
+ }
+ }
+}
+
+#endif //QT_NO_FILESYSTEMWATCHER
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
new file mode 100644
index 0000000000..38b893753e
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEWATCHER_KQUEUE_P_H
+#define FILEWATCHER_KQUEUE_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher_p.h"
+
+#include <QtCore/qhash.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qvector.h>
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+struct kevent;
+
+QT_BEGIN_NAMESPACE
+
+class QKqueueFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+public:
+ ~QKqueueFileSystemWatcherEngine();
+
+ static QKqueueFileSystemWatcherEngine *create();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+private:
+ QKqueueFileSystemWatcherEngine(int kqfd);
+
+ void run();
+
+ int kqfd;
+ int kqpipe[2];
+
+ QMutex mutex;
+ QHash<QString, int> pathToID;
+ QHash<int, QString> idToPath;
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_FILESYSTEMWATCHER
+#endif // FILEWATCHER_KQUEUE_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h
new file mode 100644
index 0000000000..6fbf7531fc
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_P_H
+#define QFILESYSTEMWATCHER_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <private/qobject_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qthread.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemWatcherEngine : public QThread
+{
+ Q_OBJECT
+
+protected:
+ inline QFileSystemWatcherEngine(bool move = true)
+ {
+ if (move)
+ moveToThread(this);
+ }
+
+public:
+ // fills \a files and \a directories with the \a paths it could
+ // watch, and returns a list of paths this engine could not watch
+ virtual QStringList addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories) = 0;
+ // removes \a paths from \a files and \a directories, and returns
+ // a list of paths this engine does not know about (either addPath
+ // failed or wasn't called)
+ virtual QStringList removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories) = 0;
+
+ virtual void stop() = 0;
+
+Q_SIGNALS:
+ void fileChanged(const QString &path, bool removed);
+ void directoryChanged(const QString &path, bool removed);
+};
+
+class QFileSystemWatcherPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFileSystemWatcher)
+
+ static QFileSystemWatcherEngine *createNativeEngine();
+
+public:
+ QFileSystemWatcherPrivate();
+ void init();
+ void initPollerEngine();
+ void initForcedEngine(const QString &);
+
+ QFileSystemWatcherEngine *native, *poller, *forced;
+ QStringList files, directories;
+
+ // private slots
+ void _q_fileChanged(const QString &path, bool removed);
+ void _q_directoryChanged(const QString &path, bool removed);
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_FILESYSTEMWATCHER
+#endif // QFILESYSTEMWATCHER_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp
new file mode 100644
index 0000000000..8e8dfe5f30
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_symbian_p.h"
+#include "qfileinfo.h"
+#include "qdebug.h"
+#include "private/qcore_symbian_p.h"
+#include <QDir>
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+
+QT_BEGIN_NAMESPACE
+
+QNotifyChangeEvent::QNotifyChangeEvent(RFs &fs, const TDesC &file,
+ QSymbianFileSystemWatcherEngine *e, bool aIsDir,
+ TInt aPriority) :
+ CActive(aPriority),
+ isDir(aIsDir),
+ fsSession(fs),
+ watchedPath(file),
+ engine(e),
+ failureCount(0)
+{
+ if (isDir) {
+ fsSession.NotifyChange(ENotifyEntry, iStatus, file);
+ } else {
+ fsSession.NotifyChange(ENotifyAll, iStatus, file);
+ }
+ CActiveScheduler::Add(this);
+ SetActive();
+}
+
+QNotifyChangeEvent::~QNotifyChangeEvent()
+{
+ Cancel();
+}
+
+void QNotifyChangeEvent::RunL()
+{
+ if(iStatus.Int() == KErrNone) {
+ failureCount = 0;
+ } else {
+ qWarning("QNotifyChangeEvent::RunL() - Failed to order change notifications: %d", iStatus.Int());
+ failureCount++;
+ }
+
+ // Re-request failed notification once, but if it won't start working,
+ // we can't do much besides just not request any more notifications.
+ if (failureCount < 2) {
+ if (isDir) {
+ fsSession.NotifyChange(ENotifyEntry, iStatus, watchedPath);
+ } else {
+ fsSession.NotifyChange(ENotifyAll, iStatus, watchedPath);
+ }
+ SetActive();
+
+ if (!failureCount) {
+ int err;
+ QT_TRYCATCH_ERROR(err, engine->emitPathChanged(this));
+ if (err != KErrNone)
+ qWarning("QNotifyChangeEvent::RunL() - emitPathChanged threw exception (Converted error code: %d)", err);
+ }
+ }
+}
+
+void QNotifyChangeEvent::DoCancel()
+{
+ fsSession.NotifyChangeCancel(iStatus);
+}
+
+QSymbianFileSystemWatcherEngine::QSymbianFileSystemWatcherEngine() :
+ watcherStarted(false)
+{
+ moveToThread(this);
+}
+
+QSymbianFileSystemWatcherEngine::~QSymbianFileSystemWatcherEngine()
+{
+ stop();
+}
+
+QStringList QSymbianFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+ QStringList p = paths;
+
+ startWatcher();
+
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QFileInfo fi(path);
+ if (!fi.exists())
+ continue;
+
+ bool isDir = fi.isDir();
+ if (isDir) {
+ if (directories->contains(path))
+ continue;
+ } else {
+ if (files->contains(path))
+ continue;
+ }
+
+ // Use absolute filepath as relative paths seem to have some issues.
+ QString filePath = fi.absoluteFilePath();
+ if (isDir && filePath.at(filePath.size() - 1) != QChar(L'/')) {
+ filePath += QChar(L'/');
+ }
+
+ currentAddEvent = NULL;
+ QMetaObject::invokeMethod(this,
+ "addNativeListener",
+ Qt::QueuedConnection,
+ Q_ARG(QString, filePath));
+
+ syncCondition.wait(&mutex);
+ if (currentAddEvent) {
+ currentAddEvent->isDir = isDir;
+
+ activeObjectToPath.insert(currentAddEvent, path);
+ it.remove();
+
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+ }
+ }
+
+ return p;
+}
+
+QStringList QSymbianFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+
+ currentRemoveEvent = activeObjectToPath.key(path);
+ if (!currentRemoveEvent)
+ continue;
+ activeObjectToPath.remove(currentRemoveEvent);
+
+ QMetaObject::invokeMethod(this,
+ "removeNativeListener",
+ Qt::QueuedConnection);
+
+ syncCondition.wait(&mutex);
+
+ it.remove();
+
+ files->removeAll(path);
+ directories->removeAll(path);
+ }
+
+ return p;
+}
+
+void QSymbianFileSystemWatcherEngine::emitPathChanged(QNotifyChangeEvent *e)
+{
+ QMutexLocker locker(&mutex);
+
+ QString path = activeObjectToPath.value(e);
+ QFileInfo fi(path);
+
+ if (e->isDir)
+ emit directoryChanged(path, !fi.exists());
+ else
+ emit fileChanged(path, !fi.exists());
+}
+
+void QSymbianFileSystemWatcherEngine::stop()
+{
+ quit();
+ wait();
+}
+
+// This method must be called inside mutex
+void QSymbianFileSystemWatcherEngine::startWatcher()
+{
+ if (!watcherStarted) {
+ setStackSize(0x5000);
+ start();
+ syncCondition.wait(&mutex);
+ watcherStarted = true;
+ }
+}
+
+
+void QSymbianFileSystemWatcherEngine::run()
+{
+ mutex.lock();
+ syncCondition.wakeOne();
+ mutex.unlock();
+
+ exec();
+
+ foreach(QNotifyChangeEvent *e, activeObjectToPath.keys()) {
+ e->Cancel();
+ delete e;
+ }
+
+ activeObjectToPath.clear();
+}
+
+void QSymbianFileSystemWatcherEngine::addNativeListener(const QString &directoryPath)
+{
+ QMutexLocker locker(&mutex);
+ QString nativeDir(QDir::toNativeSeparators(directoryPath));
+ TPtrC ptr(qt_QString2TPtrC(nativeDir));
+ currentAddEvent = new QNotifyChangeEvent(qt_s60GetRFs(), ptr, this, directoryPath.endsWith(QChar(L'/'), Qt::CaseSensitive));
+ syncCondition.wakeOne();
+}
+
+void QSymbianFileSystemWatcherEngine::removeNativeListener()
+{
+ QMutexLocker locker(&mutex);
+ currentRemoveEvent->Cancel();
+ delete currentRemoveEvent;
+ currentRemoveEvent = NULL;
+ syncCondition.wakeOne();
+}
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_symbian_p.h b/src/corelib/io/qfilesystemwatcher_symbian_p.h
new file mode 100644
index 0000000000..d642e3a382
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_symbian_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_SYMBIAN_P_H
+#define QFILESYSTEMWATCHER_SYMBIAN_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 "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include "qhash.h"
+#include "qmutex.h"
+#include "qwaitcondition.h"
+
+#include <e32base.h>
+#include <f32file.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSymbianFileSystemWatcherEngine;
+
+class QNotifyChangeEvent : public CActive
+{
+public:
+ QNotifyChangeEvent(RFs &fsSession, const TDesC &file, QSymbianFileSystemWatcherEngine *engine,
+ bool aIsDir, TInt aPriority = EPriorityStandard);
+ ~QNotifyChangeEvent();
+
+ bool isDir;
+
+private:
+ void RunL();
+ void DoCancel();
+
+ RFs &fsSession;
+ TPath watchedPath;
+ QSymbianFileSystemWatcherEngine *engine;
+
+ int failureCount;
+};
+
+class QSymbianFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+
+public:
+ QSymbianFileSystemWatcherEngine();
+ ~QSymbianFileSystemWatcherEngine();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files,
+ QStringList *directories);
+
+ void stop();
+
+protected:
+ void run();
+
+public Q_SLOTS:
+ void addNativeListener(const QString &directoryPath);
+ void removeNativeListener();
+
+private:
+ friend class QNotifyChangeEvent;
+ void emitPathChanged(QNotifyChangeEvent *e);
+
+ void startWatcher();
+
+ QHash<QNotifyChangeEvent*, QString> activeObjectToPath;
+ QMutex mutex;
+ QWaitCondition syncCondition;
+ bool watcherStarted;
+ QNotifyChangeEvent *currentAddEvent;
+ QNotifyChangeEvent *currentRemoveEvent;
+};
+
+#endif // QT_NO_FILESYSTEMWATCHER
+
+QT_END_NAMESPACE
+
+#endif // QFILESYSTEMWATCHER_WIN_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
new file mode 100644
index 0000000000..26b83b21dc
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_win_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qdebug.h>
+#include <qfileinfo.h>
+#include <qstringlist.h>
+#include <qset.h>
+#include <qdatetime.h>
+#include <qdir.h>
+
+QT_BEGIN_NAMESPACE
+
+void QWindowsFileSystemWatcherEngine::stop()
+{
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads)
+ thread->stop();
+}
+
+QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine()
+ : QFileSystemWatcherEngine(false)
+{
+}
+
+QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
+{
+ if (threads.isEmpty())
+ return;
+
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) {
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ // qDebug()<<"Adding"<<paths.count()<<"to existing"<<(files->count() + directories->count())<<"watchers";
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QString normalPath = path;
+ if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/")))
+ || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\")))
+#ifdef Q_OS_WINCE
+ && normalPath.size() > 1)
+#else
+ )
+#endif
+ normalPath.chop(1);
+ QFileInfo fileInfo(normalPath.toLower());
+ if (!fileInfo.exists())
+ continue;
+
+ bool isDir = fileInfo.isDir();
+ if (isDir) {
+ if (directories->contains(path))
+ continue;
+ } else {
+ if (files->contains(path))
+ continue;
+ }
+
+ // qDebug()<<"Looking for a thread/handle for"<<normalPath;
+
+ const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath();
+ const uint flags = isDir
+ ? (FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_FILE_NAME)
+ : (FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES
+ | FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_SECURITY);
+
+ QWindowsFileSystemWatcherEngine::PathInfo pathInfo;
+ pathInfo.absolutePath = absolutePath;
+ pathInfo.isDir = isDir;
+ pathInfo.path = path;
+ pathInfo = fileInfo;
+
+ // Look for a thread
+ QWindowsFileSystemWatcherEngineThread *thread = 0;
+ QWindowsFileSystemWatcherEngine::Handle handle;
+ QList<QWindowsFileSystemWatcherEngineThread *>::const_iterator jt, end;
+ end = threads.constEnd();
+ for(jt = threads.constBegin(); jt != end; ++jt) {
+ thread = *jt;
+ QMutexLocker locker(&(thread->mutex));
+
+ handle = thread->handleForDir.value(absolutePath);
+ if (handle.handle != INVALID_HANDLE_VALUE && handle.flags == flags) {
+ // found a thread now insert...
+ // qDebug()<<" Found a thread"<<thread;
+
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h
+ = thread->pathInfoForHandle[handle.handle];
+ if (!h.contains(fileInfo.absoluteFilePath())) {
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+ }
+ it.remove();
+ thread->wakeup();
+ break;
+ }
+ }
+
+ // no thread found, first create a handle
+ if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) {
+ // qDebug()<<" No thread found";
+ // Volume and folder paths need a trailing slash for proper notification
+ // (e.g. "c:" -> "c:/").
+ const QString effectiveAbsolutePath =
+ isDir ? (absolutePath + QLatin1Char('/')) : absolutePath;
+
+ handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags);
+ handle.flags = flags;
+ if (handle.handle == INVALID_HANDLE_VALUE)
+ continue;
+
+ // now look for a thread to insert
+ bool found = false;
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) {
+ QMutexLocker(&(thread->mutex));
+ if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) {
+ // qDebug() << " Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath();
+ // qDebug()<< " to existing thread"<<thread;
+ thread->handles.append(handle.handle);
+ thread->handleForDir.insert(absolutePath, handle);
+
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+
+ it.remove();
+ found = true;
+ thread->wakeup();
+ break;
+ }
+ }
+ if (!found) {
+ QWindowsFileSystemWatcherEngineThread *thread = new QWindowsFileSystemWatcherEngineThread();
+ //qDebug()<<" ###Creating new thread"<<thread<<"("<<(threads.count()+1)<<"threads)";
+ thread->handles.append(handle.handle);
+ thread->handleForDir.insert(absolutePath, handle);
+
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+
+ connect(thread, SIGNAL(fileChanged(QString,bool)),
+ this, SIGNAL(fileChanged(QString,bool)));
+ connect(thread, SIGNAL(directoryChanged(QString,bool)),
+ this, SIGNAL(directoryChanged(QString,bool)));
+
+ thread->msg = '@';
+ thread->start();
+ threads.append(thread);
+ it.remove();
+ }
+ }
+ }
+ return p;
+}
+
+QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ // qDebug()<<"removePaths"<<paths;
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QString normalPath = path;
+ if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
+ normalPath.chop(1);
+ QFileInfo fileInfo(normalPath.toLower());
+ // qDebug()<<"removing"<<normalPath;
+ QString absolutePath = fileInfo.absoluteFilePath();
+ QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
+ end = threads.end();
+ for(jt = threads.begin(); jt!= end; ++jt) {
+ QWindowsFileSystemWatcherEngineThread *thread = *jt;
+ if (*jt == 0)
+ continue;
+
+ QMutexLocker locker(&(thread->mutex));
+
+ QWindowsFileSystemWatcherEngine::Handle handle = thread->handleForDir.value(absolutePath);
+ if (handle.handle == INVALID_HANDLE_VALUE) {
+ // perhaps path is a file?
+ absolutePath = fileInfo.absolutePath();
+ handle = thread->handleForDir.value(absolutePath);
+ }
+ if (handle.handle != INVALID_HANDLE_VALUE) {
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h =
+ thread->pathInfoForHandle[handle.handle];
+ if (h.remove(fileInfo.absoluteFilePath())) {
+ // ###
+ files->removeAll(path);
+ directories->removeAll(path);
+
+ if (h.isEmpty()) {
+ // qDebug() << "Closing handle" << handle.handle;
+ FindCloseChangeNotification(handle.handle); // This one might generate a notification
+
+ int indexOfHandle = thread->handles.indexOf(handle.handle);
+ Q_ASSERT(indexOfHandle != -1);
+ thread->handles.remove(indexOfHandle);
+
+ thread->handleForDir.remove(absolutePath);
+ // h is now invalid
+
+ it.remove();
+
+ if (thread->handleForDir.isEmpty()) {
+ // qDebug()<<"Stopping thread "<<thread;
+ locker.unlock();
+ thread->stop();
+ thread->wait();
+ locker.relock();
+ // We can't delete the thread until the mutex locker is
+ // out of scope
+ }
+ }
+ }
+ // Found the file, go to next one
+ break;
+ }
+ }
+ }
+
+ // Remove all threads that we stopped
+ QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
+ end = threads.end();
+ for(jt = threads.begin(); jt != end; ++jt) {
+ if (!(*jt)->isRunning()) {
+ delete *jt;
+ *jt = 0;
+ }
+ }
+
+ threads.removeAll(0);
+ return p;
+}
+
+///////////
+// QWindowsFileSystemWatcherEngineThread
+///////////
+
+QWindowsFileSystemWatcherEngineThread::QWindowsFileSystemWatcherEngineThread()
+ : msg(0)
+{
+ if (HANDLE h = CreateEvent(0, false, false, 0)) {
+ handles.reserve(MAXIMUM_WAIT_OBJECTS);
+ handles.append(h);
+ }
+ moveToThread(this);
+}
+
+
+QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
+{
+ CloseHandle(handles.at(0));
+ handles[0] = INVALID_HANDLE_VALUE;
+
+ foreach (HANDLE h, handles) {
+ if (h == INVALID_HANDLE_VALUE)
+ continue;
+ FindCloseChangeNotification(h);
+ }
+}
+
+void QWindowsFileSystemWatcherEngineThread::run()
+{
+ QMutexLocker locker(&mutex);
+ forever {
+ QVector<HANDLE> handlesCopy = handles;
+ locker.unlock();
+ // qDebug() << "QWindowsFileSystemWatcherThread"<<this<<"waiting on" << handlesCopy.count() << "handles";
+ DWORD r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
+ locker.relock();
+ do {
+ if (r == WAIT_OBJECT_0) {
+ int m = msg;
+ msg = 0;
+ if (m == 'q') {
+ // qDebug() << "thread"<<this<<"told to quit";
+ return;
+ }
+ if (m != '@') {
+ qDebug("QWindowsFileSystemWatcherEngine: unknown message '%c' send to thread", char(m));
+ }
+ break;
+ } else if (r > WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + uint(handlesCopy.count())) {
+ int at = r - WAIT_OBJECT_0;
+ Q_ASSERT(at < handlesCopy.count());
+ HANDLE handle = handlesCopy.at(at);
+
+ // When removing a path, FindCloseChangeNotification might actually fire a notification
+ // for some reason, so we must check if the handle exist in the handles vector
+ if (handles.contains(handle)) {
+ // qDebug()<<"thread"<<this<<"Acknowledged handle:"<<at<<handle;
+ if (!FindNextChangeNotification(handle)) {
+ qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed!!");
+ }
+
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle];
+ QMutableHashIterator<QString, QWindowsFileSystemWatcherEngine::PathInfo> it(h);
+ while (it.hasNext()) {
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo>::iterator x = it.next();
+ QString absolutePath = x.value().absolutePath;
+ QFileInfo fileInfo(x.value().path);
+ // qDebug() << "checking" << x.key();
+ if (!fileInfo.exists()) {
+ // qDebug() << x.key() << "removed!";
+ if (x.value().isDir)
+ emit directoryChanged(x.value().path, true);
+ else
+ emit fileChanged(x.value().path, true);
+ h.erase(x);
+
+ // close the notification handle if the directory has been removed
+ if (h.isEmpty()) {
+ // qDebug() << "Thread closing handle" << handle;
+ FindCloseChangeNotification(handle); // This one might generate a notification
+
+ int indexOfHandle = handles.indexOf(handle);
+ Q_ASSERT(indexOfHandle != -1);
+ handles.remove(indexOfHandle);
+
+ handleForDir.remove(absolutePath);
+ // h is now invalid
+ }
+ } else if (x.value().isDir) {
+ // qDebug() << x.key() << "directory changed!";
+ emit directoryChanged(x.value().path, false);
+ x.value() = fileInfo;
+ } else if (x.value() != fileInfo) {
+ // qDebug() << x.key() << "file changed!";
+ emit fileChanged(x.value().path, false);
+ x.value() = fileInfo;
+ }
+ }
+ }
+ } else {
+ // qErrnoWarning("QFileSystemWatcher: error while waiting for change notification");
+ break; // avoid endless loop
+ }
+ handlesCopy = handles;
+ r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, 0);
+ } while (r != WAIT_TIMEOUT);
+ }
+}
+
+
+void QWindowsFileSystemWatcherEngineThread::stop()
+{
+ msg = 'q';
+ SetEvent(handles.at(0));
+}
+
+void QWindowsFileSystemWatcherEngineThread::wakeup()
+{
+ msg = '@';
+ SetEvent(handles.at(0));
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
new file mode 100644
index 0000000000..4f00abfa00
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMWATCHER_WIN_P_H
+#define QFILESYSTEMWATCHER_WIN_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemwatcher_p.h"
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+
+#include <qt_windows.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsFileSystemWatcherEngineThread;
+
+// Even though QWindowsFileSystemWatcherEngine is derived of QThread
+// via QFileSystemWatcher, it does not start a thread.
+// Instead QWindowsFileSystemWatcher creates QWindowsFileSystemWatcherEngineThreads
+// to do the actually watching.
+class QWindowsFileSystemWatcherEngine : public QFileSystemWatcherEngine
+{
+ Q_OBJECT
+public:
+ QWindowsFileSystemWatcherEngine();
+ ~QWindowsFileSystemWatcherEngine();
+
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+
+ void stop();
+
+
+ class Handle
+ {
+ public:
+ HANDLE handle;
+ uint flags;
+
+ Handle()
+ : handle(INVALID_HANDLE_VALUE), flags(0u)
+ { }
+ Handle(const Handle &other)
+ : handle(other.handle), flags(other.flags)
+ { }
+ };
+
+ class PathInfo {
+ public:
+ QString absolutePath;
+ QString path;
+ bool isDir;
+
+ // fileinfo bits
+ uint ownerId;
+ uint groupId;
+ QFile::Permissions permissions;
+ QDateTime lastModified;
+
+ PathInfo &operator=(const QFileInfo &fileInfo)
+ {
+ ownerId = fileInfo.ownerId();
+ groupId = fileInfo.groupId();
+ permissions = fileInfo.permissions();
+ lastModified = fileInfo.lastModified();
+ return *this;
+ }
+
+ bool operator!=(const QFileInfo &fileInfo) const
+ {
+ return (ownerId != fileInfo.ownerId()
+ || groupId != fileInfo.groupId()
+ || permissions != fileInfo.permissions()
+ || lastModified != fileInfo.lastModified());
+ }
+ };
+private:
+ QList<QWindowsFileSystemWatcherEngineThread *> threads;
+
+};
+
+class QWindowsFileSystemWatcherEngineThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ QWindowsFileSystemWatcherEngineThread();
+ ~QWindowsFileSystemWatcherEngineThread();
+ void run();
+ void stop();
+ void wakeup();
+
+ QMutex mutex;
+ QVector<HANDLE> handles;
+ int msg;
+
+ QHash<QString, QWindowsFileSystemWatcherEngine::Handle> handleForDir;
+
+ QHash<HANDLE, QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> > pathInfoForHandle;
+
+Q_SIGNALS:
+ void fileChanged(const QString &path, bool removed);
+ void directoryChanged(const QString &path, bool removed);
+};
+
+#endif // QT_NO_FILESYSTEMWATCHER
+
+QT_END_NAMESPACE
+
+#endif // QFILESYSTEMWATCHER_WIN_P_H
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
new file mode 100644
index 0000000000..802d394af1
--- /dev/null
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -0,0 +1,965 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#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>
+
+#ifndef QT_NO_FSFILEENGINE
+
+#if !defined(Q_OS_WINCE)
+#include <errno.h>
+#endif
+#if defined(Q_OS_UNIX)
+#include "private/qcore_unix_p.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(Q_OS_MAC)
+# include <private/qcore_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+# ifndef S_ISREG
+# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
+# endif
+# ifndef S_ISCHR
+# define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
+# endif
+# ifndef S_ISFIFO
+# define S_ISFIFO(x) false
+# endif
+# ifndef S_ISSOCK
+# define S_ISSOCK(x) false
+# endif
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
+# endif
+#endif
+
+/*! \class QFSFileEngine
+ \brief The QFSFileEngine class implements Qt's default file engine.
+ \since 4.1
+
+ This class is part of the file engine framework in Qt. If you only want to
+ access files or directories, use QFile, QFileInfo or QDir instead.
+
+ QFSFileEngine is the default file engine for accessing regular files. It
+ is provided for convenience; by subclassing this class, you can alter its
+ behavior slightly, without having to write a complete QAbstractFileEngine
+ subclass. To install your custom file engine, you must also subclass
+ QAbstractFileEngineHandler and create an instance of your handler.
+
+ It can also be useful to create a QFSFileEngine object directly if you
+ need to use the local file system inside QAbstractFileEngine::create(), in
+ order to avoid recursion (as higher-level classes tend to call
+ QAbstractFileEngine::create()).
+*/
+
+//**************** QFSFileEnginePrivate
+QFSFileEnginePrivate::QFSFileEnginePrivate() : QAbstractFileEnginePrivate()
+{
+ init();
+}
+
+/*!
+ \internal
+*/
+void QFSFileEnginePrivate::init()
+{
+ is_sequential = 0;
+ tried_stat = 0;
+#if !defined(Q_OS_WINCE)
+ need_lstat = 1;
+ is_link = 0;
+#endif
+ openMode = QIODevice::NotOpen;
+ fd = -1;
+ fh = 0;
+#ifdef Q_OS_SYMBIAN
+ fileHandleForMaps = -1;
+#endif
+ lastIOCommand = IOFlushCommand;
+ lastFlushFailed = false;
+ closeFileHandle = false;
+#ifdef Q_OS_WIN
+ fileAttrib = INVALID_FILE_ATTRIBUTES;
+ fileHandle = INVALID_HANDLE_VALUE;
+ mapHandle = INVALID_HANDLE_VALUE;
+#ifndef Q_OS_WINCE
+ cachedFd = -1;
+#endif
+#endif
+}
+
+/*!
+ Constructs a QFSFileEngine for the file name \a file.
+*/
+QFSFileEngine::QFSFileEngine(const QString &file)
+ : QAbstractFileEngine(*new QFSFileEnginePrivate)
+{
+ Q_D(QFSFileEngine);
+ d->fileEntry = QFileSystemEntry(file);
+}
+
+/*!
+ Constructs a QFSFileEngine.
+*/
+QFSFileEngine::QFSFileEngine() : QAbstractFileEngine(*new QFSFileEnginePrivate)
+{
+}
+
+/*!
+ \internal
+*/
+QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd)
+ : QAbstractFileEngine(dd)
+{
+}
+
+/*!
+ Destructs the QFSFileEngine.
+*/
+QFSFileEngine::~QFSFileEngine()
+{
+ Q_D(QFSFileEngine);
+ if (d->closeFileHandle) {
+ if (d->fh) {
+ int ret;
+ do {
+ ret = fclose(d->fh);
+ } while (ret == EOF && errno == EINTR);
+ } else if (d->fd != -1) {
+ int ret;
+ do {
+ ret = QT_CLOSE(d->fd);
+ } while (ret == -1 && errno == EINTR);
+ }
+ }
+ QList<uchar*> keys = d->maps.keys();
+ for (int i = 0; i < keys.count(); ++i)
+ unmap(keys.at(i));
+}
+
+/*!
+ \reimp
+*/
+void QFSFileEngine::setFileName(const QString &file)
+{
+ Q_D(QFSFileEngine);
+ d->init();
+ d->fileEntry = QFileSystemEntry(file);
+}
+
+/*!
+ \reimp
+*/
+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"));
+ return false;
+ }
+
+ // Append implies WriteOnly.
+ if (openMode & QFile::Append)
+ openMode |= QFile::WriteOnly;
+
+ // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
+ if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
+ openMode |= QFile::Truncate;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->tried_stat = 0;
+ d->fh = 0;
+ d->fd = -1;
+
+ return d->nativeOpen(openMode);
+}
+
+/*!
+ Opens the file handle \a fh in \a openMode mode. Returns true on
+ success; otherwise returns false.
+*/
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
+{
+ return open(openMode, fh, QFile::DontCloseHandle);
+}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
+{
+ Q_D(QFSFileEngine);
+
+ // Append implies WriteOnly.
+ if (openMode & QFile::Append)
+ openMode |= QFile::WriteOnly;
+
+ // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
+ if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
+ openMode |= QFile::Truncate;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->fileEntry.clear();
+ d->tried_stat = 0;
+ d->fd = -1;
+
+ return d->openFh(openMode, fh);
+}
+
+/*!
+ Opens the file handle \a fh using the open mode \a flags.
+*/
+bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
+{
+ Q_Q(QFSFileEngine);
+ this->fh = fh;
+ fd = -1;
+
+ // Seek to the end when in Append mode.
+ if (openMode & QIODevice::Append) {
+ int ret;
+ do {
+ ret = QT_FSEEK(fh, 0, SEEK_END);
+ } while (ret != 0 && errno == EINTR);
+
+ if (ret != 0) {
+ q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
+ qt_error_string(int(errno)));
+
+ this->openMode = QIODevice::NotOpen;
+ this->fh = 0;
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*!
+ Opens the file descriptor \a fd in \a openMode mode. Returns true
+ on success; otherwise returns false.
+*/
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
+{
+ return open(openMode, fd, QFile::DontCloseHandle);
+}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandleFlags handleFlags)
+{
+ Q_D(QFSFileEngine);
+
+ // Append implies WriteOnly.
+ if (openMode & QFile::Append)
+ openMode |= QFile::WriteOnly;
+
+ // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
+ if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
+ openMode |= QFile::Truncate;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->fileEntry.clear();
+ d->fh = 0;
+ d->fd = -1;
+ d->tried_stat = 0;
+
+ return d->openFd(openMode, fd);
+}
+
+
+/*!
+ Opens the file descriptor \a fd to the file engine, using the open mode \a
+ flags.
+*/
+bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
+{
+ Q_Q(QFSFileEngine);
+ this->fd = fd;
+ fh = 0;
+
+ // Seek to the end when in Append mode.
+ if (openMode & QFile::Append) {
+ int 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)));
+
+ this->openMode = QIODevice::NotOpen;
+ this->fd = -1;
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::close()
+{
+ Q_D(QFSFileEngine);
+ d->openMode = QIODevice::NotOpen;
+ return d->nativeClose();
+}
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::closeFdFh()
+{
+ Q_Q(QFSFileEngine);
+ if (fd == -1 && !fh
+#ifdef Q_OS_SYMBIAN
+ && !symbianFile.SubSessionHandle()
+ && fileHandleForMaps == -1
+#endif
+ )
+ return false;
+
+ // Flush the file if it's buffered, and if the last flush didn't fail.
+ bool flushed = !fh || (!lastFlushFailed && q->flush());
+ bool closed = true;
+ tried_stat = 0;
+
+#ifdef Q_OS_SYMBIAN
+ // Map handle is always owned by us so always close it
+ if (fileHandleForMaps >= 0) {
+ QT_CLOSE(fileHandleForMaps);
+ fileHandleForMaps = -1;
+ }
+#endif
+
+ // Close the file if we created the handle.
+ if (closeFileHandle) {
+ int ret;
+ do {
+#ifdef Q_OS_SYMBIAN
+ if (symbianFile.SubSessionHandle()) {
+ symbianFile.Close();
+ ret = 0;
+ } else
+#endif
+ if (fh) {
+ // Close buffered file.
+ ret = fclose(fh) != 0 ? -1 : 0;
+ } else {
+ // Close unbuffered file.
+ ret = QT_CLOSE(fd);
+ }
+ } while (ret == -1 && errno == EINTR);
+
+ // We must reset these guys regardless; calling close again after a
+ // failed close causes crashes on some systems.
+ fh = 0;
+ fd = -1;
+ closed = (ret == 0);
+ }
+
+ // Report errors.
+ if (!flushed || !closed) {
+ if (flushed) {
+ // If not flushed, we want the flush error to fall through.
+ q->setError(QFile::UnspecifiedError, qt_error_string(errno));
+ }
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::flush()
+{
+ Q_D(QFSFileEngine);
+ if ((d->openMode & QIODevice::WriteOnly) == 0) {
+ // Nothing in the write buffers, so flush succeeds in doing
+ // nothing.
+ return true;
+ }
+ return d->nativeFlush();
+}
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::flushFh()
+{
+ Q_Q(QFSFileEngine);
+
+ // Never try to flush again if the last flush failed. Otherwise you can
+ // get crashes on some systems (AIX).
+ if (lastFlushFailed)
+ return false;
+
+ int ret = fflush(fh);
+
+ lastFlushFailed = (ret != 0);
+ lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
+
+ if (ret != 0) {
+ q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
+ qt_error_string(errno));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+qint64 QFSFileEngine::size() const
+{
+ Q_D(const QFSFileEngine);
+ return d->nativeSize();
+}
+
+/*!
+ \internal
+*/
+#ifndef Q_OS_WIN
+qint64 QFSFileEnginePrivate::sizeFdFh() const
+{
+ Q_Q(const QFSFileEngine);
+ const_cast<QFSFileEngine *>(q)->flush();
+
+ tried_stat = 0;
+ metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
+ if (!doStat(QFileSystemMetaData::SizeAttribute))
+ return 0;
+ return metaData.size();
+}
+#endif
+
+/*!
+ \reimp
+*/
+qint64 QFSFileEngine::pos() const
+{
+ Q_D(const QFSFileEngine);
+ return d->nativePos();
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::posFdFh() const
+{
+ if (fh)
+ return qint64(QT_FTELL(fh));
+ return QT_LSEEK(fd, 0, SEEK_CUR);
+}
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::seek(qint64 pos)
+{
+ Q_D(QFSFileEngine);
+ return d->nativeSeek(pos);
+}
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
+{
+ Q_Q(QFSFileEngine);
+
+ // On Windows' stdlib implementation, the results of calling fread and
+ // fwrite are undefined if not called either in sequence, or if preceded
+ // with a call to fflush().
+ if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
+ return false;
+
+ if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
+ return false;
+
+ if (fh) {
+ // Buffered stdlib mode.
+ int ret;
+ do {
+ ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
+ } while (ret != 0 && errno == EINTR);
+
+ if (ret != 0) {
+ q->setError(QFile::ReadError, qt_error_string(int(errno)));
+ return false;
+ }
+ } else {
+ // Unbuffered stdio mode.
+ if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
+ qWarning() << "QFile::at: Cannot set file position" << pos;
+ q->setError(QFile::PositionError, qt_error_string(errno));
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+int QFSFileEngine::handle() const
+{
+ Q_D(const QFSFileEngine);
+ return d->nativeHandle();
+}
+
+/*!
+ \reimp
+*/
+qint64 QFSFileEngine::read(char *data, qint64 maxlen)
+{
+ Q_D(QFSFileEngine);
+
+ // On Windows' stdlib implementation, the results of calling fread and
+ // fwrite are undefined if not called either in sequence, or if preceded
+ // with a call to fflush().
+ if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
+ flush();
+ d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
+ }
+
+ return d->nativeRead(data, maxlen);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
+{
+ Q_Q(QFSFileEngine);
+
+ if (len < 0 || len != qint64(size_t(len))) {
+ q->setError(QFile::ReadError, qt_error_string(EINVAL));
+ return -1;
+ }
+
+ qint64 readBytes = 0;
+ bool eof = false;
+
+ if (fh) {
+ // 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) {
+ // On Mac OS, 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;
+ }
+ readBytes += result;
+ } while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
+
+ } else if (fd != -1) {
+ // Unbuffered stdio mode.
+
+#ifdef Q_OS_WIN
+ int result;
+#else
+ ssize_t result;
+#endif
+ do {
+ result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
+ } while ((result == -1 && errno == EINTR)
+ || (result > 0 && (readBytes += result) < len));
+
+ eof = !(result == -1);
+ }
+
+ if (!eof && readBytes == 0) {
+ readBytes = -1;
+ q->setError(QFile::ReadError, qt_error_string(errno));
+ }
+
+ return readBytes;
+}
+
+/*!
+ \reimp
+*/
+qint64 QFSFileEngine::readLine(char *data, qint64 maxlen)
+{
+ Q_D(QFSFileEngine);
+
+ // On Windows' stdlib implementation, the results of calling fread and
+ // fwrite are undefined if not called either in sequence, or if preceded
+ // with a call to fflush().
+ if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
+ flush();
+ d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
+ }
+
+ return d->nativeReadLine(data, maxlen);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
+{
+ Q_Q(QFSFileEngine);
+ if (!fh)
+ return q->QAbstractFileEngine::readLine(data, maxlen);
+
+ QT_OFF_T oldPos = 0;
+#ifdef Q_OS_WIN
+ bool seq = q->isSequential();
+ if (!seq)
+#endif
+ oldPos = QT_FTELL(fh);
+
+ // QIODevice::readLine() passes maxlen - 1 to QFile::readLineData()
+ // because it has made space for the '\0' at the end of data. But fgets
+ // 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, qt_error_string(int(errno)));
+ return -1; // error
+ }
+
+#ifdef Q_OS_WIN
+ if (seq)
+ return qstrlen(data);
+#endif
+
+ qint64 lineLength = QT_FTELL(fh) - oldPos;
+ return lineLength > 0 ? lineLength : qstrlen(data);
+}
+
+/*!
+ \reimp
+*/
+qint64 QFSFileEngine::write(const char *data, qint64 len)
+{
+ Q_D(QFSFileEngine);
+
+ // On Windows' stdlib implementation, the results of calling fread and
+ // fwrite are undefined if not called either in sequence, or if preceded
+ // with a call to fflush().
+ if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
+ flush();
+ d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
+ }
+
+ return d->nativeWrite(data, len);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
+{
+ Q_Q(QFSFileEngine);
+
+ if (len < 0 || len != qint64(size_t(len))) {
+ q->setError(QFile::WriteError, qt_error_string(EINVAL));
+ return -1;
+ }
+
+ qint64 writtenBytes = 0;
+
+ if (fh) {
+ // Buffered stdlib mode.
+
+ size_t result;
+ do {
+ result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
+ writtenBytes += result;
+ } while (result == 0 ? errno == EINTR : writtenBytes < len);
+
+ } else if (fd != -1) {
+ // Unbuffered stdio mode.
+
+#ifdef Q_OS_WIN
+ int result;
+#else
+ ssize_t result;
+#endif
+ do {
+ result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
+ } while ((result == -1 && errno == EINTR)
+ || (result > 0 && (writtenBytes += result) < len));
+ }
+
+ if (len && writtenBytes == 0) {
+ writtenBytes = -1;
+ q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
+ }
+
+ return writtenBytes;
+}
+
+/*!
+ \internal
+*/
+QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+{
+ return new QFSFileEngineIterator(filters, filterNames);
+}
+
+/*!
+ \internal
+*/
+QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
+{
+ return 0;
+}
+
+/*!
+ \internal
+*/
+QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
+{
+ return QAbstractFileEngine::entryList(filters, filterNames);
+}
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::isSequential() const
+{
+ Q_D(const QFSFileEngine);
+ if (d->is_sequential == 0)
+ d->is_sequential = d->nativeIsSequential() ? 1 : 2;
+ return d->is_sequential == 1;
+}
+
+/*!
+ \internal
+*/
+#ifdef Q_OS_UNIX
+bool QFSFileEnginePrivate::isSequentialFdFh() const
+{
+ if (doStat(QFileSystemMetaData::SequentialType))
+ return metaData.isSequential();
+ return true;
+}
+#endif
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
+{
+ Q_D(QFSFileEngine);
+ if (extension == AtEndExtension && d->fh && isSequential())
+ return feof(d->fh);
+
+ if (extension == MapExtension) {
+ const MapExtensionOption *options = (MapExtensionOption*)(option);
+ MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
+ returnValue->address = d->map(options->offset, options->size, options->flags);
+ return (returnValue->address != 0);
+ }
+ if (extension == UnMapExtension) {
+ UnMapExtensionOption *options = (UnMapExtensionOption*)option;
+ return d->unmap(options->address);
+ }
+
+ return false;
+}
+
+/*!
+ \reimp
+*/
+bool QFSFileEngine::supportsExtension(Extension extension) const
+{
+ Q_D(const QFSFileEngine);
+ if (extension == AtEndExtension && d->fh && isSequential())
+ return true;
+ if (extension == FastReadLineExtension && d->fh)
+ return true;
+ if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
+ return true;
+ if (extension == UnMapExtension || extension == MapExtension)
+ return true;
+ return false;
+}
+
+/*! \fn bool QFSFileEngine::caseSensitive() const
+ Returns true for Windows, false for Unix.
+*/
+
+/*! \fn bool QFSFileEngine::copy(const QString &copyName)
+
+ For windows, copy the file to file \a copyName.
+
+ Not implemented for Unix.
+*/
+
+/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
+ For Unix, returns the current working directory for the file
+ engine.
+
+ For Windows, returns the canonicalized form of the current path used
+ by the file engine for the drive specified by \a fileName. On
+ Windows, each drive has its own current directory, so a different
+ path is returned for file names that include different drive names
+ (e.g. A: or C:).
+
+ \sa setCurrentPath()
+*/
+
+/*! \fn QFileInfoList QFSFileEngine::drives()
+ For Windows, returns the list of drives in the file system as a list
+ of QFileInfo objects. On unix, Mac OS X and Windows CE, only the
+ root path is returned. On Windows, this function returns all drives
+ (A:\, C:\, D:\, etc.).
+
+ For Unix, the list contains just the root path "/".
+*/
+
+/*! \fn QString QFSFileEngine::fileName(FileName file) const
+ \reimp
+*/
+
+/*! \fn QDateTime QFSFileEngine::fileTime(FileTime time) const
+ \reimp
+*/
+
+/*! \fn QString QFSFileEngine::homePath()
+ Returns the home path of the current user.
+
+ \sa rootPath()
+*/
+
+/*! \fn bool QFSFileEngine::isRelativePath() const
+ \reimp
+*/
+
+/*! \fn bool QFSFileEngine::link(const QString &newName)
+
+ 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 false.
+*/
+
+/*! \fn bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
+ \reimp
+*/
+
+/*! \fn uint QFSFileEngine::ownerId(FileOwner own) const
+ In Unix, if stat() is successful, the \c uid is returned if
+ \a own is the owner. Otherwise the \c gid is returned. If stat()
+ is unsuccessful, -2 is reuturned.
+
+ For Windows, -2 is always returned.
+*/
+
+/*! \fn QString QFSFileEngine::owner(FileOwner own) const
+ \reimp
+*/
+
+/*! \fn bool QFSFileEngine::remove()
+ \reimp
+*/
+
+/*! \fn bool QFSFileEngine::rename(const QString &newName)
+ \reimp
+*/
+
+/*! \fn bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
+ \reimp
+*/
+
+/*! \fn QString QFSFileEngine::rootPath()
+ Returns the root path.
+
+ \sa homePath()
+*/
+
+/*! \fn bool QFSFileEngine::setCurrentPath(const QString &path)
+ Sets the current path (e.g., for QDir), to \a path. Returns true if the
+ new path exists; otherwise this function does nothing, and returns false.
+
+ \sa currentPath()
+*/
+
+/*! \fn bool QFSFileEngine::setPermissions(uint perms)
+ \reimp
+*/
+
+/*! \fn bool QFSFileEngine::setSize(qint64 size)
+ \reimp
+*/
+
+/*! \fn QString QFSFileEngine::tempPath()
+ Returns the temporary path (i.e., a path in which it is safe
+ to store temporary files).
+*/
+
+/*! \fn QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const
+ \internal
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FSFILEENGINE
diff --git a/src/corelib/io/qfsfileengine.h b/src/corelib/io/qfsfileengine.h
new file mode 100644
index 0000000000..726d5814f8
--- /dev/null
+++ b/src/corelib/io/qfsfileengine.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFSFILEENGINE_H
+#define QFSFILEENGINE_H
+
+#include <QtCore/qabstractfileengine.h>
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
+
+#ifndef QT_NO_FSFILEENGINE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QFSFileEnginePrivate;
+
+class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine
+{
+ Q_DECLARE_PRIVATE(QFSFileEngine)
+public:
+ QFSFileEngine();
+ explicit QFSFileEngine(const QString &file);
+ ~QFSFileEngine();
+
+ bool open(QIODevice::OpenMode openMode);
+ bool open(QIODevice::OpenMode flags, FILE *fh);
+ bool close();
+ bool flush();
+ qint64 size() const;
+ qint64 pos() const;
+ bool seek(qint64);
+ bool isSequential() const;
+ bool remove();
+ bool copy(const QString &newName);
+ bool rename(const QString &newName);
+ bool link(const QString &newName);
+ bool mkdir(const QString &dirName, bool createParentDirectories) const;
+ bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
+ bool setSize(qint64 size);
+ bool caseSensitive() const;
+ bool isRelativePath() const;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+ FileFlags fileFlags(FileFlags type) const;
+ bool setPermissions(uint perms);
+ QString fileName(FileName file) const;
+ uint ownerId(FileOwner) const;
+ QString owner(FileOwner) const;
+ QDateTime fileTime(FileTime time) const;
+ void setFileName(const QString &file);
+ int handle() const;
+
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
+ Iterator *endEntryList();
+
+ qint64 read(char *data, qint64 maxlen);
+ qint64 readLine(char *data, qint64 maxlen);
+ qint64 write(const char *data, qint64 len);
+
+ bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
+ bool supportsExtension(Extension extension) const;
+
+ //FS only!!
+ bool open(QIODevice::OpenMode flags, int fd);
+ bool open(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags);
+ bool open(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags);
+#ifdef Q_OS_SYMBIAN
+ bool open(QIODevice::OpenMode flags, const RFile &f, QFile::FileHandleFlags handleFlags);
+#endif
+ static bool setCurrentPath(const QString &path);
+ static QString currentPath(const QString &path = QString());
+ static QString homePath();
+ static QString rootPath();
+ static QString tempPath();
+ static QFileInfoList drives();
+
+protected:
+ QFSFileEngine(QFSFileEnginePrivate &dd);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_FSFILEENGINE
+
+#endif // QFSFILEENGINE_H
diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp
new file mode 100644
index 0000000000..d4c0e3f193
--- /dev/null
+++ b/src/corelib/io/qfsfileengine_iterator.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfsfileengine_iterator_p.h"
+#include "qfileinfo_p.h"
+#include "qvariant.h"
+
+#ifndef QT_NO_FSFILEENGINE
+
+QT_BEGIN_NAMESPACE
+
+QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames)
+ : QAbstractFileEngineIterator(filters, filterNames)
+ , done(false)
+{
+}
+
+QFSFileEngineIterator::~QFSFileEngineIterator()
+{
+}
+
+bool QFSFileEngineIterator::hasNext() const
+{
+ 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;
+
+ QFileSystemEntry entry;
+ QFileSystemMetaData data;
+ if (nativeIterator->advance(entry, data)) {
+ nextInfo = QFileInfo(new QFileInfoPrivate(entry, data));
+ } else {
+ done = true;
+ nativeIterator.reset();
+ }
+}
+
+QString QFSFileEngineIterator::currentFileName() const
+{
+ return currentInfo.fileName();
+}
+
+QFileInfo QFSFileEngineIterator::currentFileInfo() const
+{
+ return currentInfo;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FSFILEENGINE
diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h
new file mode 100644
index 0000000000..d4155d6112
--- /dev/null
+++ b/src/corelib/io/qfsfileengine_iterator_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFSFILEENGINE_ITERATOR_P_H
+#define QFSFILEENGINE_ITERATOR_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 "qabstractfileengine.h"
+#include "qfilesystemiterator_p.h"
+#include "qdir.h"
+
+#ifndef QT_NO_FSFILEENGINE
+
+QT_BEGIN_NAMESPACE
+
+class QFSFileEngineIteratorPrivate;
+class QFSFileEngineIteratorPlatformSpecificData;
+
+class QFSFileEngineIterator : public QAbstractFileEngineIterator
+{
+public:
+ QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
+ ~QFSFileEngineIterator();
+
+ QString next();
+ bool hasNext() const;
+
+ QString currentFileName() const;
+ QFileInfo currentFileInfo() const;
+
+private:
+ void advance() const;
+ mutable QScopedPointer<QFileSystemIterator> nativeIterator;
+ mutable QFileInfo currentInfo;
+ mutable QFileInfo nextInfo;
+ mutable bool done;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FSFILEENGINE
+
+#endif // QFSFILEENGINE_ITERATOR_P_H
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
new file mode 100644
index 0000000000..253f461fd1
--- /dev/null
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFSFILEENGINE_P_H
+#define QFSFILEENGINE_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 "qplatformdefs.h"
+#include "QtCore/qfsfileengine.h"
+#include "private/qabstractfileengine_p.h"
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+#include <qhash.h>
+
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
+
+#ifndef QT_NO_FSFILEENGINE
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_WINCE_STD) && _WIN32_WCE < 0x600
+#define Q_USE_DEPRECATED_MAP_API 1
+#endif
+
+class Q_AUTOTEST_EXPORT QFSFileEnginePrivate : public QAbstractFileEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QFSFileEngine)
+
+public:
+#ifdef Q_WS_WIN
+ static QString longFileName(const QString &path);
+#endif
+
+ QFileSystemEntry fileEntry;
+ QIODevice::OpenMode openMode;
+
+ bool nativeOpen(QIODevice::OpenMode openMode);
+ bool openFh(QIODevice::OpenMode flags, FILE *fh);
+ bool openFd(QIODevice::OpenMode flags, int fd);
+ bool nativeClose();
+ bool closeFdFh();
+ bool nativeFlush();
+ bool flushFh();
+ qint64 nativeSize() const;
+#ifndef Q_OS_WIN
+ qint64 sizeFdFh() const;
+#endif
+ qint64 nativePos() const;
+ qint64 posFdFh() const;
+ bool nativeSeek(qint64);
+ bool seekFdFh(qint64);
+ qint64 nativeRead(char *data, qint64 maxlen);
+ qint64 readFdFh(char *data, qint64 maxlen);
+ qint64 nativeReadLine(char *data, qint64 maxlen);
+ qint64 readLineFdFh(char *data, qint64 maxlen);
+ qint64 nativeWrite(const char *data, qint64 len);
+ qint64 writeFdFh(const char *data, qint64 len);
+ int nativeHandle() const;
+ bool nativeIsSequential() const;
+#ifndef Q_OS_WIN
+ bool isSequentialFdFh() const;
+#endif
+
+ uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
+ bool unmap(uchar *ptr);
+
+ mutable QFileSystemMetaData metaData;
+
+ FILE *fh;
+#ifdef Q_OS_SYMBIAN
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ RFile64 symbianFile;
+ TInt64 symbianFilePos;
+#else
+ RFile symbianFile;
+
+ /**
+ * The cursor position in the underlying file. This differs
+ * from devicePos because the latter is updated on calls to
+ * writeData, even if no data was physically transferred to
+ * the file, but instead stored in the write buffer.
+ *
+ * iFilePos is updated on calls to RFile::Read and
+ * RFile::Write. It is also updated on calls to seek() but
+ * RFile::Seek is not called when that happens because
+ * Symbian supports positioned reads and writes, saving a file
+ * server call, and because Symbian does not support seeking
+ * past the end of a file.
+ */
+ TInt symbianFilePos;
+#endif
+ mutable int fileHandleForMaps;
+ int getMapHandle();
+#endif
+
+#ifdef Q_WS_WIN
+ HANDLE fileHandle;
+ HANDLE mapHandle;
+ QHash<uchar *, DWORD /* offset % AllocationGranularity */> maps;
+
+#ifndef Q_OS_WINCE
+ mutable int cachedFd;
+#endif
+
+ mutable DWORD fileAttrib;
+#else
+ QHash<uchar *, QPair<int /*offset % PageSize*/, size_t /*length + offset % PageSize*/> > maps;
+#endif
+ int fd;
+
+ enum LastIOCommand
+ {
+ IOFlushCommand,
+ IOReadCommand,
+ IOWriteCommand
+ };
+ LastIOCommand lastIOCommand;
+ bool lastFlushFailed;
+ bool closeFileHandle;
+
+ mutable uint is_sequential : 2;
+ mutable uint could_stat : 1;
+ mutable uint tried_stat : 1;
+#if !defined(Q_OS_WINCE)
+ mutable uint need_lstat : 1;
+ mutable uint is_link : 1;
+#endif
+
+#if defined(Q_OS_WIN)
+ bool doStat(QFileSystemMetaData::MetaDataFlags flags) const;
+#else
+ bool doStat(QFileSystemMetaData::MetaDataFlags flags = QFileSystemMetaData::PosixStatFlags) const;
+#endif
+ bool isSymlink() const;
+
+#if defined(Q_OS_WIN32)
+ int sysOpen(const QString &, int flags);
+#endif
+
+protected:
+ QFSFileEnginePrivate();
+
+ void init();
+
+ QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FSFILEENGINE
+
+#endif // QFSFILEENGINE_P_H
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
new file mode 100644
index 0000000000..6c03b32a83
--- /dev/null
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -0,0 +1,1108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qabstractfileengine.h"
+#include "private/qfsfileengine_p.h"
+#include "private/qcore_unix_p.h"
+#include "qfilesystementry_p.h"
+#include "qfilesystemengine_p.h"
+
+#ifndef QT_NO_FSFILEENGINE
+
+#include "qfile.h"
+#include "qdir.h"
+#include "qdatetime.h"
+#include "qvarlengtharray.h"
+
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <limits.h>
+#if defined(Q_OS_SYMBIAN)
+# include <sys/syslimits.h>
+# include <f32file.h>
+# include <pathinfo.h>
+# include "private/qcore_symbian_p.h"
+#endif
+#include <errno.h>
+#if !defined(QWS) && defined(Q_OS_MAC)
+# include <private/qcore_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_SYMBIAN)
+/*!
+ \internal
+
+ Returns true if supplied path is a relative path
+*/
+static bool isRelativePathSymbian(const QString& fileName)
+{
+ return !(fileName.startsWith(QLatin1Char('/'))
+ || (fileName.length() >= 2
+ && ((fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':'))
+ || (fileName.at(0) == QLatin1Char('/') && fileName.at(1) == QLatin1Char('/')))));
+}
+
+#endif
+
+#ifndef Q_OS_SYMBIAN
+/*!
+ \internal
+
+ Returns the stdlib open string corresponding to a QIODevice::OpenMode.
+*/
+static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QFileSystemEntry &fileEntry,
+ QFileSystemMetaData &metaData)
+{
+ QByteArray mode;
+ if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) {
+ mode = "rb";
+ if (flags & QIODevice::WriteOnly) {
+ metaData.clearFlags(QFileSystemMetaData::FileType);
+ if (!fileEntry.isEmpty()
+ && QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::FileType)
+ && metaData.isFile()) {
+ mode += '+';
+ } else {
+ mode = "wb+";
+ }
+ }
+ } else if (flags & QIODevice::WriteOnly) {
+ mode = "wb";
+ if (flags & QIODevice::ReadOnly)
+ mode += '+';
+ }
+ if (flags & QIODevice::Append) {
+ mode = "ab";
+ if (flags & QIODevice::ReadOnly)
+ mode += '+';
+ }
+
+#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207
+ // must be glibc >= 2.7
+ mode += 'e';
+#endif
+
+ return mode;
+}
+#endif
+
+/*!
+ \internal
+
+ Returns the stdio open flags corresponding to a QIODevice::OpenMode.
+*/
+static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
+{
+ int oflags = QT_OPEN_RDONLY;
+#ifdef QT_LARGEFILE_SUPPORT
+ oflags |= QT_OPEN_LARGEFILE;
+#endif
+
+ if ((mode & QFile::ReadWrite) == QFile::ReadWrite) {
+ oflags = QT_OPEN_RDWR | QT_OPEN_CREAT;
+ } else if (mode & QFile::WriteOnly) {
+ oflags = QT_OPEN_WRONLY | QT_OPEN_CREAT;
+ }
+
+ if (mode & QFile::Append) {
+ oflags |= QT_OPEN_APPEND;
+ } else if (mode & QFile::WriteOnly) {
+ if ((mode & QFile::Truncate) || !(mode & QFile::ReadOnly))
+ oflags |= QT_OPEN_TRUNC;
+ }
+
+ return oflags;
+}
+
+#ifndef Q_OS_SYMBIAN
+/*!
+ \internal
+
+ Sets the file descriptor to close on exec. That is, the file
+ descriptor is not inherited by child processes.
+*/
+static inline bool setCloseOnExec(int fd)
+{
+ return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1;
+}
+#endif
+
+#ifdef Q_OS_SYMBIAN
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
+{
+ Q_Q(QFSFileEngine);
+
+ fh = 0;
+ fd = -1;
+
+ QString fn(QFileSystemEngine::absoluteName(fileEntry).nativeFilePath());
+ RFs& fs = qt_s60GetRFs();
+
+ TUint symbianMode = 0;
+
+ if(openMode & QIODevice::ReadOnly)
+ symbianMode |= EFileRead;
+ if(openMode & QIODevice::WriteOnly)
+ symbianMode |= EFileWrite;
+ if(openMode & QIODevice::Text)
+ symbianMode |= EFileStreamText;
+
+ // pre Symbian 9.4, file I/O is always unbuffered, and the enum values don't exist
+ if(QSysInfo::symbianVersion() >= QSysInfo::SV_9_4) {
+ if (openMode & QFile::Unbuffered) {
+ if (openMode & QIODevice::WriteOnly)
+ symbianMode |= 0x00001000; //EFileWriteDirectIO;
+ // ### Unbuffered read is not used, because it prevents file open in /resource
+ // ### and has no obvious benefits
+ } else {
+ if (openMode & QIODevice::WriteOnly)
+ symbianMode |= 0x00000800; //EFileWriteBuffered;
+ // use implementation defaults for read buffering
+ }
+ }
+
+ // Until Qt supports file sharing, we can't support EFileShareReadersOrWriters safely,
+ // but Qt does this on other platforms and autotests rely on it.
+ // The reason is that Unix locks are only advisory - the application needs to test the
+ // lock after opening the file. Symbian and Windows locks are mandatory - opening a
+ // locked file will fail.
+ symbianMode |= EFileShareReadersOrWriters;
+
+ TInt r;
+ //note QIODevice::Truncate only has meaning for read/write access
+ //write-only files are always truncated unless append is specified
+ //reference openModeToOpenFlags in qfsfileengine_unix.cpp
+ if ((openMode & QIODevice::Truncate) || (!(openMode & QIODevice::ReadOnly) && !(openMode & QIODevice::Append))) {
+ r = symbianFile.Replace(fs, qt_QString2TPtrC(fn), symbianMode);
+ } else {
+ r = symbianFile.Open(fs, qt_QString2TPtrC(fn), symbianMode);
+ if (r == KErrNotFound && (openMode & QIODevice::WriteOnly)) {
+ r = symbianFile.Create(fs, qt_QString2TPtrC(fn), symbianMode);
+ }
+ }
+
+ if (r == KErrNone) {
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ TInt64 size;
+#else
+ TInt size;
+#endif
+ r = symbianFile.Size(size);
+ if (r==KErrNone) {
+ if (openMode & QIODevice::Append)
+ symbianFilePos = size;
+ else
+ symbianFilePos = 0;
+ //TODO: port this (QFileSystemMetaData in open?)
+ //cachedSize = size;
+ }
+ }
+
+ if (r != KErrNone) {
+ q->setError(QFile::OpenError, QSystemError(r, QSystemError::NativeError).toString());
+ symbianFile.Close();
+ return false;
+ }
+
+ closeFileHandle = true;
+ return true;
+}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, const RFile &file, QFile::FileHandleFlags handleFlags)
+{
+ Q_D(QFSFileEngine);
+
+ // Append implies WriteOnly.
+ if (openMode & QFile::Append)
+ openMode |= QFile::WriteOnly;
+
+ // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
+ if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
+ openMode |= QFile::Truncate;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->fileEntry.clear();
+ d->fh = 0;
+ d->fd = -1;
+ d->tried_stat = 0;
+
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ //RFile64 adds only functions to RFile, no data members
+ d->symbianFile = static_cast<const RFile64&>(file);
+#else
+ d->symbianFile = file;
+#endif
+ TInt ret;
+ d->symbianFilePos = 0;
+ if (openMode & QFile::Append) {
+ // Seek to the end when in Append mode.
+ ret = d->symbianFile.Size(d->symbianFilePos);
+ } else {
+ // Seek to current otherwise
+ ret = d->symbianFile.Seek(ESeekCurrent, d->symbianFilePos);
+ }
+
+ if (ret != KErrNone) {
+ setError(QFile::OpenError, QSystemError(ret, QSystemError::NativeError).toString());
+
+ d->openMode = QIODevice::NotOpen;
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ d->symbianFile = RFile64();
+#else
+ d->symbianFile = RFile();
+#endif
+ return false;
+ }
+
+ // Extract filename (best effort)
+ TFileName fn;
+ TInt err = d->symbianFile.FullName(fn);
+ if (err == KErrNone)
+ d->fileEntry = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath());
+ else
+ d->fileEntry.clear();
+
+ return true;
+}
+#else
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
+{
+ Q_Q(QFSFileEngine);
+
+ if (openMode & QIODevice::Unbuffered) {
+ int flags = openModeToOpenFlags(openMode);
+
+ // Try to open the file in unbuffered mode.
+ do {
+ fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
+ } while (fd == -1 && errno == EINTR);
+
+ // On failure, return and report the error.
+ if (fd == -1) {
+ q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
+ qt_error_string(errno));
+ return false;
+ }
+
+ if (!(openMode & QIODevice::WriteOnly)) {
+ // we don't need this check if we tried to open for writing because then
+ // we had received EISDIR anyway.
+ if (QFileSystemEngine::fillMetaData(fd, metaData)
+ && metaData.isDirectory()) {
+ q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
+ QT_CLOSE(fd);
+ return false;
+ }
+ }
+
+ // Seek to the end when in Append mode.
+ if (flags & QFile::Append) {
+ int 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)));
+ return false;
+ }
+ }
+
+ fh = 0;
+ } else {
+ QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);
+
+ // Try to open the file in buffered mode.
+ do {
+ fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
+ } while (!fh && errno == EINTR);
+
+ // On failure, return and report the error.
+ if (!fh) {
+ q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
+ qt_error_string(int(errno)));
+ return false;
+ }
+
+ if (!(openMode & QIODevice::WriteOnly)) {
+ // we don't need this check if we tried to open for writing because then
+ // we had received EISDIR anyway.
+ if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
+ && metaData.isDirectory()) {
+ q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
+ fclose(fh);
+ return false;
+ }
+ }
+
+ setCloseOnExec(fileno(fh)); // ignore failure
+
+ // Seek to the end when in Append mode.
+ if (openMode & QIODevice::Append) {
+ int ret;
+ do {
+ ret = QT_FSEEK(fh, 0, SEEK_END);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret == -1) {
+ q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
+ qt_error_string(int(errno)));
+ return false;
+ }
+ }
+
+ fd = -1;
+ }
+
+ closeFileHandle = true;
+ return true;
+}
+#endif
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeClose()
+{
+ return closeFdFh();
+}
+
+/*!
+ \internal
+
+*/
+bool QFSFileEnginePrivate::nativeFlush()
+{
+#ifdef Q_OS_SYMBIAN
+ if (symbianFile.SubSessionHandle())
+ return (KErrNone == symbianFile.Flush());
+#endif
+ return fh ? flushFh() : fd != -1;
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len)
+{
+ Q_Q(QFSFileEngine);
+
+#ifdef Q_OS_SYMBIAN
+ if (symbianFile.SubSessionHandle()) {
+ if(len > KMaxTInt) {
+ //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..)
+ q->setError(QFile::ReadError, QLatin1String("Maximum 2GB in single read on this platform"));
+ return -1;
+ }
+ TPtr8 ptr(reinterpret_cast<TUint8*>(data), static_cast<TInt>(len));
+ TInt r = symbianFile.Read(symbianFilePos, ptr);
+ if (r != KErrNone)
+ {
+ q->setError(QFile::ReadError, QSystemError(r, QSystemError::NativeError).toString());
+ return -1;
+ }
+ symbianFilePos += ptr.Length();
+ return qint64(ptr.Length());
+ }
+#endif
+ if (fh && nativeIsSequential()) {
+ size_t readBytes = 0;
+ int oldFlags = fcntl(QT_FILENO(fh), F_GETFL);
+ for (int i = 0; i < 2; ++i) {
+ // Unix: Make the underlying file descriptor non-blocking
+ if ((oldFlags & O_NONBLOCK) == 0)
+ fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK);
+
+ // Cross platform stdlib read
+ size_t read = 0;
+ do {
+ read = fread(data + readBytes, 1, size_t(len - readBytes), fh);
+ } while (read == 0 && !feof(fh) && errno == EINTR);
+ if (read > 0) {
+ readBytes += read;
+ break;
+ } else {
+ if (readBytes)
+ break;
+ readBytes = read;
+ }
+
+ // Unix: Restore the blocking state of the underlying socket
+ if ((oldFlags & O_NONBLOCK) == 0) {
+ fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
+ if (readBytes == 0) {
+ int readByte = 0;
+ do {
+ readByte = fgetc(fh);
+ } while (readByte == -1 && errno == EINTR);
+ if (readByte != -1) {
+ *data = uchar(readByte);
+ readBytes += 1;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ // Unix: Restore the blocking state of the underlying socket
+ if ((oldFlags & O_NONBLOCK) == 0) {
+ fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
+ }
+ 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)));
+ return -1;
+ }
+ return readBytes;
+ }
+
+ return readFdFh(data, len);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeReadLine(char *data, qint64 maxlen)
+{
+ return readLineFdFh(data, maxlen);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
+{
+#ifdef Q_OS_SYMBIAN
+ Q_Q(QFSFileEngine);
+ if (symbianFile.SubSessionHandle()) {
+ if(len > KMaxTInt) {
+ //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..)
+ q->setError(QFile::WriteError, QLatin1String("Maximum 2GB in single write on this platform"));
+ return -1;
+ }
+ const TPtrC8 ptr(reinterpret_cast<const TUint8*>(data), static_cast<TInt>(len));
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ TInt64 eofpos = 0;
+#else
+ TInt eofpos = 0;
+#endif
+ //The end of file position is not cached because QFile is read/write sharable, therefore another
+ //process may have altered the file size.
+ TInt r = symbianFile.Seek(ESeekEnd, eofpos);
+ if (r == KErrNone && symbianFilePos > eofpos) {
+ //seek position is beyond end of file so file needs to be extended before write.
+ //note that SetSize does not zero-initialise (c.f. posix lseek)
+ r = symbianFile.SetSize(symbianFilePos);
+ }
+ if (r == KErrNone) {
+ //write to specific position in the file (i.e. use our own cursor rather than calling seek)
+ r = symbianFile.Write(symbianFilePos, ptr);
+ }
+ if (r != KErrNone) {
+ q->setError(QFile::WriteError, QSystemError(r, QSystemError::NativeError).toString());
+ return -1;
+ }
+ symbianFilePos += len;
+ return len;
+ }
+#endif
+ return writeFdFh(data, len);
+}
+
+/*!
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativePos() const
+{
+#ifdef Q_OS_SYMBIAN
+ const Q_Q(QFSFileEngine);
+ if (symbianFile.SubSessionHandle()) {
+ return symbianFilePos;
+ }
+#endif
+ return posFdFh();
+}
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeSeek(qint64 pos)
+{
+#ifdef Q_OS_SYMBIAN
+ Q_Q(QFSFileEngine);
+ if (symbianFile.SubSessionHandle()) {
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ if(pos > KMaxTInt) {
+ q->setError(QFile::PositionError, QLatin1String("Maximum 2GB file position on this platform"));
+ return false;
+ }
+#endif
+ symbianFilePos = pos;
+ return true;
+ }
+#endif
+ return seekFdFh(pos);
+}
+
+/*!
+ \internal
+*/
+int QFSFileEnginePrivate::nativeHandle() const
+{
+ return fh ? fileno(fh) : fd;
+}
+
+#ifdef Q_OS_SYMBIAN
+int QFSFileEnginePrivate::getMapHandle()
+{
+ if (symbianFile.SubSessionHandle()) {
+ // Symbian file handle can't be used for open C mmap() so open the file with open C as well.
+ if (fileHandleForMaps < 0) {
+ int flags = openModeToOpenFlags(openMode);
+ flags &= ~(O_CREAT | O_TRUNC);
+ fileHandleForMaps = ::wopen((wchar_t*)(fileEntry.nativeFilePath().utf16()), flags, 0666);
+ }
+ return fileHandleForMaps;
+ }
+ return nativeHandle();
+}
+#endif
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeIsSequential() const
+{
+#ifdef Q_OS_SYMBIAN
+ if (symbianFile.SubSessionHandle())
+ return false;
+#endif
+ return isSequentialFdFh();
+}
+
+bool QFSFileEngine::remove()
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
+ d->metaData.clear();
+ if (!ret) {
+ setError(QFile::RemoveError, error.toString());
+ }
+ return ret;
+}
+
+bool QFSFileEngine::copy(const QString &newName)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(newName), error);
+ if (!ret) {
+ setError(QFile::CopyError, error.toString());
+ }
+ return ret;
+}
+
+bool QFSFileEngine::rename(const QString &newName)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
+
+ if (!ret) {
+ setError(QFile::RenameError, error.toString());
+ }
+
+ return ret;
+}
+
+bool QFSFileEngine::link(const QString &newName)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::createLink(d->fileEntry, QFileSystemEntry(newName), error);
+ if (!ret) {
+ setError(QFile::RenameError, error.toString());
+ }
+ return ret;
+}
+
+qint64 QFSFileEnginePrivate::nativeSize() const
+{
+#ifdef Q_OS_SYMBIAN
+ const Q_Q(QFSFileEngine);
+ if (symbianFile.SubSessionHandle()) {
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ qint64 size;
+#else
+ TInt size;
+#endif
+ TInt err = symbianFile.Size(size);
+ if(err != KErrNone) {
+ const_cast<QFSFileEngine*>(q)->setError(QFile::PositionError, QSystemError(err, QSystemError::NativeError).toString());
+ return 0;
+ }
+ return size;
+ }
+#endif
+ return sizeFdFh();
+}
+
+bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
+{
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
+}
+
+bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
+{
+ return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
+}
+
+bool QFSFileEngine::caseSensitive() const
+{
+#if defined(Q_OS_SYMBIAN)
+ return false;
+#else
+ return true;
+#endif
+}
+
+bool QFSFileEngine::setCurrentPath(const QString &path)
+{
+ return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
+}
+
+QString QFSFileEngine::currentPath(const QString &)
+{
+ return QFileSystemEngine::currentPath().filePath();
+}
+
+QString QFSFileEngine::homePath()
+{
+ return QFileSystemEngine::homePath();
+}
+
+QString QFSFileEngine::rootPath()
+{
+ return QFileSystemEngine::rootPath();
+}
+
+QString QFSFileEngine::tempPath()
+{
+ return QFileSystemEngine::tempPath();
+}
+
+QFileInfoList QFSFileEngine::drives()
+{
+ QFileInfoList ret;
+#if defined(Q_OS_SYMBIAN)
+ TDriveList driveList;
+ RFs rfs = qt_s60GetRFs();
+ TInt err = rfs.DriveList(driveList);
+ if (err == KErrNone) {
+ char driveName[] = "A:/";
+
+ for (char i = 0; i < KMaxDrives; i++) {
+ if (driveList[i]) {
+ driveName[0] = 'A' + i;
+ ret.append(QFileInfo(QLatin1String(driveName)));
+ }
+ }
+ } else {
+ qWarning("QFSFileEngine::drives: Getting drives failed");
+ }
+#else
+ ret.append(QFileInfo(rootPath()));
+#endif
+ return ret;
+}
+
+bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
+{
+ if (!tried_stat || !metaData.hasFlags(flags)) {
+ tried_stat = 1;
+
+ int localFd = fd;
+ if (fh && fileEntry.isEmpty())
+ localFd = QT_FILENO(fh);
+ if (localFd != -1)
+ QFileSystemEngine::fillMetaData(localFd, metaData);
+
+ if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
+ QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags));
+ }
+
+ return metaData.exists();
+}
+
+bool QFSFileEnginePrivate::isSymlink() const
+{
+ if (!metaData.hasFlags(QFileSystemMetaData::LinkType))
+ QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::LinkType);
+
+ return metaData.isLink();
+}
+
+/*!
+ \reimp
+*/
+QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
+{
+ Q_D(const QFSFileEngine);
+
+ if (type & Refresh)
+ d->metaData.clear();
+
+ QAbstractFileEngine::FileFlags ret = 0;
+
+ if (type & FlagsMask)
+ ret |= LocalDiskFlag;
+
+ bool exists;
+ {
+ QFileSystemMetaData::MetaDataFlags queryFlags = 0;
+
+ queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
+ & QFileSystemMetaData::Permissions;
+
+ if (type & TypesMask)
+ queryFlags |= QFileSystemMetaData::AliasType
+ | QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType;
+
+ if (type & FlagsMask)
+ queryFlags |= QFileSystemMetaData::HiddenAttribute
+ | QFileSystemMetaData::ExistsAttribute;
+
+ queryFlags |= QFileSystemMetaData::LinkType;
+
+ exists = d->doStat(queryFlags);
+ }
+
+ if (!exists && !d->metaData.isLink())
+ return ret;
+
+ if (exists && (type & PermsMask))
+ ret |= FileFlags(uint(d->metaData.permissions()));
+
+ if (type & TypesMask) {
+ if (d->metaData.isAlias()) {
+ ret |= LinkType;
+ } else {
+ if ((type & LinkType) && d->metaData.isLink())
+ ret |= LinkType;
+ if (exists) {
+ if (d->metaData.isFile()) {
+ ret |= FileType;
+ } else if (d->metaData.isDirectory()) {
+ ret |= DirectoryType;
+ if ((type & BundleType) && d->metaData.isBundle())
+ ret |= BundleType;
+ }
+ }
+ }
+ }
+
+ if (type & FlagsMask) {
+ if (exists)
+ ret |= ExistsFlag;
+ if (d->fileEntry.isRoot())
+ ret |= RootFlag;
+ else if (d->metaData.isHidden())
+ ret |= HiddenFlag;
+ }
+
+ return ret;
+}
+
+QString QFSFileEngine::fileName(FileName file) const
+{
+ Q_D(const QFSFileEngine);
+ if (file == BundleName) {
+ return QFileSystemEngine::bundleName(d->fileEntry);
+ } else if (file == BaseName) {
+ return d->fileEntry.fileName();
+ } else if (file == PathName) {
+ return d->fileEntry.path();
+ } else if (file == AbsoluteName || file == AbsolutePathName) {
+ QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry));
+ if (file == AbsolutePathName) {
+ return entry.path();
+ }
+ return entry.filePath();
+ } else if (file == CanonicalName || file == CanonicalPathName) {
+ QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
+ if (file == CanonicalPathName)
+ return entry.path();
+ return entry.filePath();
+ } else if (file == LinkName) {
+ if (d->isSymlink()) {
+ QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
+ return entry.filePath();
+ }
+ return QString();
+ }
+ return d->fileEntry.filePath();
+}
+
+bool QFSFileEngine::isRelativePath() const
+{
+ Q_D(const QFSFileEngine);
+#if defined(Q_OS_SYMBIAN)
+ return isRelativePathSymbian(d->fileEntry.filePath());
+#else
+ return d->fileEntry.filePath().length() ? d->fileEntry.filePath()[0] != QLatin1Char('/') : true;
+#endif
+}
+
+uint QFSFileEngine::ownerId(FileOwner own) const
+{
+ Q_D(const QFSFileEngine);
+ static const uint nobodyID = (uint) -2;
+
+ if (d->doStat(QFileSystemMetaData::OwnerIds))
+ return d->metaData.ownerId(own);
+
+ return nobodyID;
+}
+
+QString QFSFileEngine::owner(FileOwner own) const
+{
+#ifndef Q_OS_SYMBIAN
+ if (own == OwnerUser)
+ return QFileSystemEngine::resolveUserName(ownerId(own));
+ return QFileSystemEngine::resolveGroupName(ownerId(own));
+#else
+ return QString();
+#endif
+}
+
+bool QFSFileEngine::setPermissions(uint perms)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ if (!QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0)) {
+ setError(QFile::PermissionsError, error.toString());
+ return false;
+ }
+ return true;
+}
+
+#ifdef Q_OS_SYMBIAN
+bool QFSFileEngine::setSize(qint64 size)
+{
+ Q_D(QFSFileEngine);
+ bool ret = false;
+ TInt err = KErrNone;
+ if (d->symbianFile.SubSessionHandle()) {
+ TInt err = d->symbianFile.SetSize(size);
+ ret = (err == KErrNone);
+ if (ret && d->symbianFilePos > size)
+ d->symbianFilePos = size;
+ }
+ else if (d->fd != -1)
+ ret = QT_FTRUNCATE(d->fd, size) == 0;
+ else if (d->fh)
+ ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0;
+ else {
+ RFile tmp;
+ QString symbianFilename(d->fileEntry.nativeFilePath());
+ err = tmp.Open(qt_s60GetRFs(), qt_QString2TPtrC(symbianFilename), EFileWrite);
+ if (err == KErrNone)
+ {
+ err = tmp.SetSize(size);
+ tmp.Close();
+ }
+ ret = (err == KErrNone);
+ }
+ if (!ret) {
+ QSystemError error;
+ if (err)
+ error = QSystemError(err, QSystemError::NativeError);
+ else
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ setError(QFile::ResizeError, error.toString());
+ }
+ return ret;
+}
+#else
+bool QFSFileEngine::setSize(qint64 size)
+{
+ Q_D(QFSFileEngine);
+ bool ret = false;
+ if (d->fd != -1)
+ ret = QT_FTRUNCATE(d->fd, size) == 0;
+ else if (d->fh)
+ ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0;
+ else
+ ret = QT_TRUNCATE(d->fileEntry.nativeFilePath().constData(), size) == 0;
+ if (!ret)
+ setError(QFile::ResizeError, qt_error_string(errno));
+ return ret;
+}
+#endif
+
+QDateTime QFSFileEngine::fileTime(FileTime time) const
+{
+ Q_D(const QFSFileEngine);
+
+ if (d->doStat(QFileSystemMetaData::Times))
+ return d->metaData.fileTime(time);
+
+ return QDateTime();
+}
+
+uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
+{
+ Q_Q(QFSFileEngine);
+ Q_UNUSED(flags);
+ if (openMode == QIODevice::NotOpen) {
+ q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
+ return 0;
+ }
+
+ if (offset < 0 || offset != qint64(QT_OFF_T(offset))
+ || size < 0 || quint64(size) > quint64(size_t(-1))) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
+ return 0;
+ }
+
+ // 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)
+ && (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset)))
+ qWarning("QFSFileEngine::map: Mapping a file beyond its size is not portable");
+
+ int access = 0;
+ if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
+ if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
+
+#if defined(Q_OS_INTEGRITY)
+ int pageSize = sysconf(_SC_PAGESIZE);
+#else
+ int pageSize = getpagesize();
+#endif
+ int extra = offset % pageSize;
+
+ if (quint64(size + extra) > quint64((size_t)-1)) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
+ return 0;
+ }
+
+ size_t realSize = (size_t)size + extra;
+ QT_OFF_T realOffset = QT_OFF_T(offset);
+ realOffset &= ~(QT_OFF_T(pageSize - 1));
+
+#ifdef Q_OS_SYMBIAN
+ void *mapAddress;
+ TRAPD(err, mapAddress = QT_MMAP((void*)0, realSize,
+ access, MAP_SHARED, getMapHandle(), realOffset));
+ if (err != KErrNone) {
+ qWarning("OpenC bug: leave from mmap %d", err);
+ mapAddress = MAP_FAILED;
+ errno = EINVAL;
+ }
+#else
+ void *mapAddress = QT_MMAP((void*)0, realSize,
+ access, MAP_SHARED, nativeHandle(), realOffset);
+#endif
+ if (MAP_FAILED != mapAddress) {
+ uchar *address = extra + static_cast<uchar*>(mapAddress);
+ maps[address] = QPair<int,size_t>(extra, realSize);
+ return address;
+ }
+
+ switch(errno) {
+ case EBADF:
+ q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
+ break;
+ case ENFILE:
+ case ENOMEM:
+ q->setError(QFile::ResourceError, qt_error_string(int(errno)));
+ break;
+ case EINVAL:
+ // size are out of bounds
+ default:
+ q->setError(QFile::UnspecifiedError, qt_error_string(int(errno)));
+ break;
+ }
+ return 0;
+}
+
+bool QFSFileEnginePrivate::unmap(uchar *ptr)
+{
+#if !defined(Q_OS_INTEGRITY)
+ Q_Q(QFSFileEngine);
+ if (!maps.contains(ptr)) {
+ q->setError(QFile::PermissionsError, qt_error_string(EACCES));
+ return false;
+ }
+
+ uchar *start = ptr - maps[ptr].first;
+ size_t len = maps[ptr].second;
+ if (-1 == munmap(start, len)) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(errno));
+ return false;
+ }
+ maps.remove(ptr);
+ return true;
+#else
+ return false;
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FSFILEENGINE
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
new file mode 100644
index 0000000000..9c858c2e1d
--- /dev/null
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -0,0 +1,1008 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define _POSIX_
+#include "qplatformdefs.h"
+#include "qabstractfileengine.h"
+#include "private/qfsfileengine_p.h"
+#include "qfilesystemengine_p.h"
+#include <qdebug.h>
+
+#include "qfile.h"
+#include "qdir.h"
+#include "private/qmutexpool_p.h"
+#include "qvarlengtharray.h"
+#include "qdatetime.h"
+#include "qt_windows.h"
+
+#if !defined(Q_OS_WINCE)
+# include <sys/types.h>
+# include <direct.h>
+# include <winioctl.h>
+#else
+# include <types.h>
+#endif
+#include <objbase.h>
+#include <shlobj.h>
+#include <initguid.h>
+#include <accctrl.h>
+#include <ctype.h>
+#include <limits.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX FILENAME_MAX
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WINCE)
+static inline bool isUncPath(const QString &path)
+{
+ // Starts with \\, but not \\.
+ return (path.startsWith(QLatin1String("\\\\"))
+ && path.size() > 2 && path.at(2) != QLatin1Char('.'));
+}
+#endif
+
+/*!
+ \internal
+*/
+QString QFSFileEnginePrivate::longFileName(const QString &path)
+{
+ if (path.startsWith(QLatin1String("\\\\.\\")))
+ return path;
+
+ QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path);
+#if !defined(Q_OS_WINCE)
+ QString prefix = QLatin1String("\\\\?\\");
+ if (isUncPath(absPath)) {
+ prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\"
+ absPath.remove(0, 2);
+ }
+ return prefix + absPath;
+#else
+ return absPath;
+#endif
+}
+
+/*
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
+{
+ Q_Q(QFSFileEngine);
+
+ // All files are opened in share mode (both read and write).
+ DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ int accessRights = 0;
+ if (openMode & QIODevice::ReadOnly)
+ accessRights |= GENERIC_READ;
+ if (openMode & QIODevice::WriteOnly)
+ accessRights |= GENERIC_WRITE;
+
+ SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
+
+ // WriteOnly can create files, ReadOnly cannot.
+ DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING;
+ // Create the file handle.
+ fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
+ accessRights,
+ shareMode,
+ &securityAtts,
+ creationDisp,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ // Bail out on error.
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ q->setError(QFile::OpenError, qt_error_string());
+ return false;
+ }
+
+ // Truncate the file after successfully opening it if Truncate is passed.
+ if (openMode & QIODevice::Truncate)
+ q->setSize(0);
+
+ return true;
+}
+
+/*
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeClose()
+{
+ Q_Q(QFSFileEngine);
+ if (fh || fd != -1) {
+ // stdlib / stdio mode.
+ return closeFdFh();
+ }
+
+ // Windows native mode.
+ bool ok = true;
+
+#ifndef Q_OS_WINCE
+ if (cachedFd != -1) {
+ if (::_close(cachedFd) && !::CloseHandle(fileHandle)) {
+ q->setError(QFile::UnspecifiedError, qt_error_string());
+ ok = false;
+ }
+
+ // System handle is closed with associated file descriptor.
+ fileHandle = INVALID_HANDLE_VALUE;
+ cachedFd = -1;
+
+ return ok;
+ }
+#endif
+
+ if ((fileHandle == INVALID_HANDLE_VALUE || !::CloseHandle(fileHandle))) {
+ q->setError(QFile::UnspecifiedError, qt_error_string());
+ ok = false;
+ }
+ fileHandle = INVALID_HANDLE_VALUE;
+ return ok;
+}
+
+/*
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeFlush()
+{
+ if (fh) {
+ // Buffered stdlib mode.
+ return flushFh();
+ }
+ if (fd != -1) {
+ // Unbuffered stdio mode; always succeeds (no buffer).
+ return true;
+ }
+
+ // Windows native mode; flushing is
+ // unnecessary. FlushFileBuffers(), the equivalent of sync() or
+ // fsync() on Unix, does a low-level flush to the disk, and we
+ // don't expose an API for this.
+ return true;
+}
+
+/*
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeSize() const
+{
+ Q_Q(const QFSFileEngine);
+ QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
+
+ // ### Don't flush; for buffered files, we should get away with ftell.
+ thatQ->flush();
+
+ // Always retrive the current information
+ metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
+#if defined(Q_OS_WINCE)
+ // Buffered stdlib mode.
+ if (fh) {
+ QT_OFF_T oldPos = QT_FTELL(fh);
+ QT_FSEEK(fh, 0, SEEK_END);
+ qint64 fileSize = (qint64)QT_FTELL(fh);
+ QT_FSEEK(fh, oldPos, SEEK_SET);
+ if (fileSize == -1) {
+ fileSize = 0;
+ thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno));
+ }
+ return fileSize;
+ }
+ if (fd != -1) {
+ thatQ->setError(QFile::UnspecifiedError, QLatin1String("Not implemented!"));
+ return 0;
+ }
+#endif
+ bool filled = false;
+ if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen )
+ filled = QFileSystemEngine::fillMetaData(fileHandle, metaData,
+ QFileSystemMetaData::SizeAttribute);
+ else
+ filled = doStat(QFileSystemMetaData::SizeAttribute);
+
+ if (!filled) {
+ thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno));
+ }
+ return metaData.size();
+}
+
+/*
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativePos() const
+{
+ Q_Q(const QFSFileEngine);
+ QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
+
+ if (fh || fd != -1) {
+ // stdlib / stido mode.
+ return posFdFh();
+ }
+
+ // Windows native mode.
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return 0;
+
+#if !defined(Q_OS_WINCE)
+ LARGE_INTEGER currentFilePos;
+ LARGE_INTEGER offset;
+ offset.QuadPart = 0;
+ if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_CURRENT)) {
+ thatQ->setError(QFile::UnspecifiedError, qt_error_string());
+ return 0;
+ }
+
+ return qint64(currentFilePos.QuadPart);
+#else
+ LARGE_INTEGER filepos;
+ filepos.HighPart = 0;
+ DWORD newFilePointer = SetFilePointer(fileHandle, 0, &filepos.HighPart, FILE_CURRENT);
+ if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ thatQ->setError(QFile::UnspecifiedError, qt_error_string());
+ return 0;
+ }
+
+ filepos.LowPart = newFilePointer;
+ return filepos.QuadPart;
+#endif
+}
+
+/*
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeSeek(qint64 pos)
+{
+ Q_Q(QFSFileEngine);
+
+ if (fh || fd != -1) {
+ // stdlib / stdio mode.
+ return seekFdFh(pos);
+ }
+
+#if !defined(Q_OS_WINCE)
+ LARGE_INTEGER currentFilePos;
+ LARGE_INTEGER offset;
+ offset.QuadPart = pos;
+ if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_BEGIN)) {
+ q->setError(QFile::UnspecifiedError, qt_error_string());
+ return false;
+ }
+
+ return true;
+#else
+ DWORD newFilePointer;
+ LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER*>(&pos);
+ newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
+ if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ q->setError(QFile::PositionError, qt_error_string());
+ return false;
+ }
+
+ return true;
+#endif
+}
+
+/*
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 maxlen)
+{
+ Q_Q(QFSFileEngine);
+
+ if (fh || fd != -1) {
+ // stdio / stdlib mode.
+ if (fh && nativeIsSequential() && feof(fh)) {
+ q->setError(QFile::ReadError, qt_error_string(int(errno)));
+ return -1;
+ }
+
+ return readFdFh(data, maxlen);
+ }
+
+ // Windows native mode.
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ DWORD bytesToRead = DWORD(maxlen); // <- lossy
+
+ // Reading on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
+ // the chunks are too large, so we limit the block size to 32MB.
+ static const DWORD maxBlockSize = 32 * 1024 * 1024;
+
+ qint64 totalRead = 0;
+ do {
+ DWORD blockSize = qMin<DWORD>(bytesToRead, maxBlockSize);
+ DWORD bytesRead;
+ if (!ReadFile(fileHandle, data + totalRead, blockSize, &bytesRead, NULL)) {
+ if (totalRead == 0) {
+ // Note: only return failure if the first ReadFile fails.
+ q->setError(QFile::ReadError, qt_error_string());
+ return -1;
+ }
+ break;
+ }
+ if (bytesRead == 0)
+ break;
+ totalRead += bytesRead;
+ bytesToRead -= bytesRead;
+ } while (totalRead < maxlen);
+ return qint64(totalRead);
+}
+
+/*
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeReadLine(char *data, qint64 maxlen)
+{
+ Q_Q(QFSFileEngine);
+
+ if (fh || fd != -1) {
+ // stdio / stdlib mode.
+ return readLineFdFh(data, maxlen);
+ }
+
+ // Windows native mode.
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ // ### No equivalent in Win32?
+ return q->QAbstractFileEngine::readLine(data, maxlen);
+}
+
+/*
+ \internal
+*/
+qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
+{
+ Q_Q(QFSFileEngine);
+
+ if (fh || fd != -1) {
+ // stdio / stdlib mode.
+ return writeFdFh(data, len);
+ }
+
+ // Windows native mode.
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ qint64 bytesToWrite = DWORD(len); // <- lossy
+
+ // Writing on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
+ // the chunks are too large, so we limit the block size to 32MB.
+ static const DWORD maxBlockSize = 32 * 1024 * 1024;
+
+ qint64 totalWritten = 0;
+ do {
+ DWORD blockSize = qMin<DWORD>(bytesToWrite, maxBlockSize);
+ DWORD bytesWritten;
+ if (!WriteFile(fileHandle, data + totalWritten, blockSize, &bytesWritten, NULL)) {
+ if (totalWritten == 0) {
+ // Note: Only return error if the first WriteFile failed.
+ q->setError(QFile::WriteError, qt_error_string());
+ return -1;
+ }
+ break;
+ }
+ if (bytesWritten == 0)
+ break;
+ totalWritten += bytesWritten;
+ bytesToWrite -= bytesWritten;
+ } while (totalWritten < len);
+ return qint64(totalWritten);
+}
+
+/*
+ \internal
+*/
+int QFSFileEnginePrivate::nativeHandle() const
+{
+ if (fh || fd != -1)
+ return fh ? QT_FILENO(fh) : fd;
+#ifndef Q_OS_WINCE
+ if (cachedFd != -1)
+ return cachedFd;
+
+ int flags = 0;
+ if (openMode & QIODevice::Append)
+ flags |= _O_APPEND;
+ if (!(openMode & QIODevice::WriteOnly))
+ flags |= _O_RDONLY;
+ cachedFd = _open_osfhandle((intptr_t) fileHandle, flags);
+ return cachedFd;
+#else
+ return -1;
+#endif
+}
+
+/*
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeIsSequential() const
+{
+#if !defined(Q_OS_WINCE)
+ HANDLE handle = fileHandle;
+ if (fh || fd != -1)
+ handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ DWORD fileType = GetFileType(handle);
+ return (fileType == FILE_TYPE_CHAR)
+ || (fileType == FILE_TYPE_PIPE);
+#else
+ return false;
+#endif
+}
+
+bool QFSFileEngine::remove()
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
+ if (!ret)
+ setError(QFile::RemoveError, error.toString());
+ return ret;
+}
+
+bool QFSFileEngine::copy(const QString &copyName)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error);
+ if (!ret)
+ setError(QFile::CopyError, error.toString());
+ return ret;
+}
+
+bool QFSFileEngine::rename(const QString &newName)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
+ if (!ret)
+ setError(QFile::RenameError, error.toString());
+ return ret;
+}
+
+bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
+{
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
+}
+
+bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
+{
+ return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
+}
+
+bool QFSFileEngine::caseSensitive() const
+{
+ return false;
+}
+
+bool QFSFileEngine::setCurrentPath(const QString &path)
+{
+ return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
+}
+
+QString QFSFileEngine::currentPath(const QString &fileName)
+{
+#if !defined(Q_OS_WINCE)
+ 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(':')) {
+ int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1;
+ if (_getdrive() != drv) {
+ wchar_t buf[PATH_MAX];
+ ::_wgetdcwd(drv, buf, PATH_MAX);
+ ret = QString::fromWCharArray(buf);
+ }
+ }
+ if (ret.isEmpty()) {
+ //just the pwd
+ ret = QFileSystemEngine::currentPath().filePath();
+ }
+ if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
+ return ret;
+#else
+ Q_UNUSED(fileName);
+ return QFileSystemEngine::currentPath();
+#endif
+}
+
+QString QFSFileEngine::homePath()
+{
+ return QFileSystemEngine::homePath();
+}
+
+QString QFSFileEngine::rootPath()
+{
+ return QFileSystemEngine::rootPath();
+}
+
+QString QFSFileEngine::tempPath()
+{
+ return QFileSystemEngine::tempPath();
+}
+
+QFileInfoList QFSFileEngine::drives()
+{
+ QFileInfoList ret;
+#if !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN32)
+ quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
+#elif defined(Q_OS_OS2EMX)
+ quint32 driveBits, cur;
+ if (DosQueryCurrentDisk(&cur, &driveBits) != NO_ERROR)
+ exit(1);
+ driveBits &= 0x3ffffff;
+#endif
+ char driveName[] = "A:/";
+
+ while (driveBits) {
+ if (driveBits & 1)
+ ret.append(QFileInfo(QLatin1String(driveName)));
+ driveName[0]++;
+ driveBits = driveBits >> 1;
+ }
+ return ret;
+#else
+ ret.append(QFileInfo(QLatin1String("/")));
+ return ret;
+#endif
+}
+
+bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
+{
+ if (!tried_stat || !metaData.hasFlags(flags)) {
+ tried_stat = true;
+
+#if !defined(Q_OS_WINCE)
+ int localFd = fd;
+ if (fh && fileEntry.isEmpty())
+ localFd = QT_FILENO(fh);
+ if (localFd != -1)
+ QFileSystemEngine::fillMetaData(localFd, metaData, flags);
+#endif
+ if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
+ QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags));
+ }
+
+ return metaData.exists();
+}
+
+
+bool QFSFileEngine::link(const QString &newName)
+{
+#if !defined(Q_OS_WINCE)
+#if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS)
+ bool ret = false;
+
+ QString linkName = newName;
+ //### assume that they add .lnk
+
+ IShellLink *psl;
+ bool neededCoInit = false;
+
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+
+ if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
+ neededCoInit = true;
+ CoInitialize(NULL);
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+ }
+
+ if (SUCCEEDED(hres)) {
+ hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
+ if (SUCCEEDED(hres)) {
+ hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
+ if (SUCCEEDED(hres)) {
+ IPersistFile *ppf;
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE);
+ if (SUCCEEDED(hres))
+ ret = true;
+ ppf->Release();
+ }
+ }
+ }
+ psl->Release();
+ }
+ if (!ret)
+ setError(QFile::RenameError, qt_error_string());
+
+ if (neededCoInit)
+ CoUninitialize();
+
+ return ret;
+#else
+ Q_UNUSED(newName);
+ return false;
+#endif // QT_NO_LIBRARY
+#else
+ QString linkName = newName;
+ if (!linkName.endsWith(QLatin1String(".lnk")))
+ linkName += QLatin1String(".lnk");
+ QString orgName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\'));
+ // Need to append on our own
+ orgName.prepend(QLatin1Char('"'));
+ orgName.append(QLatin1Char('"'));
+ bool ret = SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16()));
+ if (!ret)
+ setError(QFile::RenameError, qt_error_string());
+ return ret;
+#endif // Q_OS_WINCE
+}
+
+/*!
+ \reimp
+*/
+QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const
+{
+ Q_D(const QFSFileEngine);
+
+ if (type & Refresh)
+ d->metaData.clear();
+
+ QAbstractFileEngine::FileFlags ret = 0;
+
+ if (type & FlagsMask)
+ ret |= LocalDiskFlag;
+
+ bool exists;
+ {
+ QFileSystemMetaData::MetaDataFlags queryFlags = 0;
+
+ queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
+ & QFileSystemMetaData::Permissions;
+
+ // AliasType and BundleType are 0x0
+ if (type & TypesMask)
+ queryFlags |= QFileSystemMetaData::AliasType
+ | QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType;
+
+ if (type & FlagsMask)
+ queryFlags |= QFileSystemMetaData::HiddenAttribute
+ | QFileSystemMetaData::ExistsAttribute;
+
+ queryFlags |= QFileSystemMetaData::LinkType;
+
+ exists = d->doStat(queryFlags);
+ }
+
+ if (exists && (type & PermsMask))
+ ret |= FileFlags(uint(d->metaData.permissions()));
+
+ if (type & TypesMask) {
+ if ((type & LinkType) && d->metaData.isLegacyLink())
+ ret |= LinkType;
+ if (d->metaData.isDirectory()) {
+ ret |= DirectoryType;
+ } else {
+ ret |= FileType;
+ }
+ }
+ if (type & FlagsMask) {
+ if (d->metaData.exists()) {
+ ret |= ExistsFlag;
+ if (d->fileEntry.isRoot())
+ ret |= RootFlag;
+ else if (d->metaData.isHidden())
+ ret |= HiddenFlag;
+ }
+ }
+ return ret;
+}
+
+QString QFSFileEngine::fileName(FileName file) const
+{
+ Q_D(const QFSFileEngine);
+ if (file == BaseName) {
+ return d->fileEntry.fileName();
+ } else if (file == PathName) {
+ return d->fileEntry.path();
+ } else if (file == AbsoluteName || file == AbsolutePathName) {
+ QString ret;
+
+ if (!isRelativePath()) {
+#if !defined(Q_OS_WINCE)
+ 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
+#endif
+ {
+ ret = d->fileEntry.filePath();
+ }
+ } else {
+ ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->fileEntry.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('/')) {
+ Q_ASSERT(ret.length() >= 2);
+ Q_ASSERT(ret.at(0).isLetter());
+ Q_ASSERT(ret.at(1) == QLatin1Char(':'));
+
+ // Force uppercase drive letters.
+ ret[0] = ret.at(0).toUpper();
+ }
+
+ if (file == AbsolutePathName) {
+ int slash = ret.lastIndexOf(QLatin1Char('/'));
+ if (slash < 0)
+ return ret;
+ else if (ret.at(0) != QLatin1Char('/') && slash == 2)
+ return ret.left(3); // include the slash
+ else
+ return ret.left(slash > 0 ? slash : 1);
+ }
+ return ret;
+ } else if (file == CanonicalName || file == CanonicalPathName) {
+ if (!(fileFlags(ExistsFlag) & ExistsFlag))
+ return QString();
+ QFileSystemEntry entry(QFileSystemEngine::canonicalName(QFileSystemEntry(fileName(AbsoluteName)), d->metaData));
+
+ if (file == CanonicalPathName)
+ return entry.path();
+ return entry.filePath();
+ } else if (file == LinkName) {
+ return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath();
+ } else if (file == BundleName) {
+ return QString();
+ }
+ return d->fileEntry.filePath();
+}
+
+bool QFSFileEngine::isRelativePath() const
+{
+ Q_D(const QFSFileEngine);
+ // drive, e.g. "a:", or UNC root, e.q. "//"
+ return d->fileEntry.isRelative();
+}
+
+uint QFSFileEngine::ownerId(FileOwner /*own*/) const
+{
+ static const uint nobodyID = (uint) -2;
+ return nobodyID;
+}
+
+QString QFSFileEngine::owner(FileOwner own) const
+{
+ Q_D(const QFSFileEngine);
+ return QFileSystemEngine::owner(d->fileEntry, own);
+}
+
+bool QFSFileEngine::setPermissions(uint perms)
+{
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
+ if (!ret)
+ setError(QFile::PermissionsError, error.toString());
+ return ret;
+}
+
+bool QFSFileEngine::setSize(qint64 size)
+{
+ Q_D(QFSFileEngine);
+
+ if (d->fileHandle != INVALID_HANDLE_VALUE || d->fd != -1 || d->fh) {
+ // resize open file
+ HANDLE fh = d->fileHandle;
+#if !defined(Q_OS_WINCE)
+ if (fh == INVALID_HANDLE_VALUE) {
+ if (d->fh)
+ fh = (HANDLE)_get_osfhandle(QT_FILENO(d->fh));
+ else
+ fh = (HANDLE)_get_osfhandle(d->fd);
+ }
+#endif
+ if (fh == INVALID_HANDLE_VALUE)
+ return false;
+ qint64 currentPos = pos();
+
+ if (seek(size) && SetEndOfFile(fh)) {
+ seek(qMin(currentPos, size));
+ return true;
+ }
+
+ seek(currentPos);
+ return false;
+ }
+
+ if (!d->fileEntry.isEmpty()) {
+ // resize file on disk
+ QFile file(d->fileEntry.filePath());
+ if (file.open(QFile::ReadWrite)) {
+ bool ret = file.resize(size);
+ if (!ret)
+ setError(QFile::ResizeError, file.errorString());
+ return ret;
+ }
+ }
+ return false;
+}
+
+
+QDateTime QFSFileEngine::fileTime(FileTime time) const
+{
+ Q_D(const QFSFileEngine);
+
+ if (d->doStat(QFileSystemMetaData::Times))
+ return d->metaData.fileTime(time);
+
+ return QDateTime();
+}
+
+uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
+ QFile::MemoryMapFlags flags)
+{
+ Q_Q(QFSFileEngine);
+ Q_UNUSED(flags);
+ if (openMode == QFile::NotOpen) {
+ q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
+ return 0;
+ }
+ if (offset == 0 && size == 0) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
+ return 0;
+ }
+
+ if (mapHandle == INVALID_HANDLE_VALUE) {
+ // get handle to the file
+ HANDLE handle = fileHandle;
+
+#ifndef Q_OS_WINCE
+ if (handle == INVALID_HANDLE_VALUE && fh)
+ handle = (HANDLE)::_get_osfhandle(QT_FILENO(fh));
+#endif
+
+#ifdef Q_USE_DEPRECATED_MAP_API
+ nativeClose();
+ // handle automatically closed by kernel with mapHandle (below).
+ handle = ::CreateFileForMapping((const wchar_t*)fileEntry.nativeFilePath().utf16(),
+ GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0),
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ 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)
+ handle = INVALID_HANDLE_VALUE;
+#endif
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
+ return 0;
+ }
+
+ // first create the file mapping handle
+ DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY;
+ mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0);
+ if (mapHandle == INVALID_HANDLE_VALUE) {
+ q->setError(QFile::PermissionsError, qt_error_string());
+#ifdef Q_USE_DEPRECATED_MAP_API
+ ::CloseHandle(handle);
+#endif
+ return 0;
+ }
+ }
+
+ // setup args to map
+ DWORD access = 0;
+ if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ;
+ if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE;
+
+ DWORD offsetHi = offset >> 32;
+ DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
+ SYSTEM_INFO sysinfo;
+ ::GetSystemInfo(&sysinfo);
+ DWORD mask = sysinfo.dwAllocationGranularity - 1;
+ DWORD extra = offset & mask;
+ if (extra)
+ offsetLo &= ~mask;
+
+ // attempt to create the map
+ LPVOID mapAddress = ::MapViewOfFile(mapHandle, access,
+ offsetHi, offsetLo, size + extra);
+ if (mapAddress) {
+ uchar *address = extra + static_cast<uchar*>(mapAddress);
+ maps[address] = extra;
+ return address;
+ }
+
+ switch(GetLastError()) {
+ case ERROR_ACCESS_DENIED:
+ q->setError(QFile::PermissionsError, qt_error_string());
+ break;
+ case ERROR_INVALID_PARAMETER:
+ // size are out of bounds
+ default:
+ q->setError(QFile::UnspecifiedError, qt_error_string());
+ }
+
+ ::CloseHandle(mapHandle);
+ return 0;
+}
+
+bool QFSFileEnginePrivate::unmap(uchar *ptr)
+{
+ Q_Q(QFSFileEngine);
+ if (!maps.contains(ptr)) {
+ q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
+ return false;
+ }
+ uchar *start = ptr - maps[ptr];
+ if (!UnmapViewOfFile(start)) {
+ q->setError(QFile::PermissionsError, qt_error_string());
+ return false;
+ }
+
+ maps.remove(ptr);
+ if (maps.isEmpty()) {
+ ::CloseHandle(mapHandle);
+ mapHandle = INVALID_HANDLE_VALUE;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
new file mode 100644
index 0000000000..8759f8b4c4
--- /dev/null
+++ b/src/corelib/io/qiodevice.cpp
@@ -0,0 +1,1846 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QIODEVICE_DEBUG
+
+#include "qbytearray.h"
+#include "qdebug.h"
+#include "qiodevice_p.h"
+#include "qfile.h"
+#include "qstringlist.h"
+#include <limits.h>
+
+#ifdef QIODEVICE_DEBUG
+# include <ctype.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QIODEVICE_DEBUG
+void debugBinaryString(const QByteArray &input)
+{
+ QByteArray tmp;
+ int startOffset = 0;
+ for (int i = 0; i < input.size(); ++i) {
+ tmp += input[i];
+
+ if ((i % 16) == 15 || i == (input.size() - 1)) {
+ printf("\n%15d:", startOffset);
+ startOffset += tmp.size();
+
+ for (int j = 0; j < tmp.size(); ++j)
+ printf(" %02x", int(uchar(tmp[j])));
+ for (int 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] : '.');
+ tmp.clear();
+ }
+ }
+ printf("\n\n");
+}
+
+void debugBinaryString(const char *data, qint64 maxlen)
+{
+ debugBinaryString(QByteArray(data, maxlen));
+}
+#endif
+
+#define Q_VOID
+
+#define CHECK_MAXLEN(function, returnType) \
+ do { \
+ if (maxSize < 0) { \
+ qWarning("QIODevice::"#function": Called with maxSize < 0"); \
+ return returnType; \
+ } \
+ } while (0)
+
+#define CHECK_WRITABLE(function, returnType) \
+ do { \
+ if ((d->openMode & WriteOnly) == 0) { \
+ if (d->openMode == NotOpen) \
+ return returnType; \
+ qWarning("QIODevice::"#function": ReadOnly device"); \
+ return returnType; \
+ } \
+ } while (0)
+
+#define CHECK_READABLE(function, returnType) \
+ do { \
+ if ((d->openMode & ReadOnly) == 0) { \
+ if (d->openMode == NotOpen) \
+ return returnType; \
+ qWarning("QIODevice::"#function": WriteOnly device"); \
+ return returnType; \
+ } \
+ } while (0)
+
+/*! \internal
+ */
+QIODevicePrivate::QIODevicePrivate()
+ : openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE),
+ pos(0), devicePos(0)
+ , pPos(&pos), pDevicePos(&devicePos)
+ , baseReadLineDataCalled(false)
+ , firstRead(true)
+ , accessMode(Unset)
+#ifdef QT_NO_QOBJECT
+ , q_ptr(0)
+#endif
+{
+}
+
+/*! \internal
+ */
+QIODevicePrivate::~QIODevicePrivate()
+{
+}
+
+/*!
+ \class QIODevice
+ \reentrant
+
+ \brief The QIODevice class is the base interface class of all I/O
+ devices in Qt.
+
+ \ingroup io
+
+ QIODevice provides both a common implementation and an abstract
+ interface for devices that support reading and writing of blocks
+ of data, such as QFile, QBuffer and QTcpSocket. QIODevice is
+ abstract and can not be instantiated, but it is common to use the
+ interface it defines to provide device-independent I/O features.
+ For example, Qt's XML classes operate on a QIODevice pointer,
+ allowing them to be used with various devices (such as files and
+ buffers).
+
+ Before accessing the device, open() must be called to set the
+ correct OpenMode (such as ReadOnly or ReadWrite). You can then
+ write to the device with write() or putChar(), and read by calling
+ either read(), readLine(), or readAll(). Call close() when you are
+ done with the device.
+
+ QIODevice distinguishes between two types of devices:
+ random-access devices and sequential devices.
+
+ \list
+ \o Random-access devices support seeking to arbitrary
+ positions using seek(). The current position in the file is
+ available by calling pos(). QFile and QBuffer are examples of
+ random-access devices.
+
+ \o Sequential devices don't support seeking to arbitrary
+ positions. The data must be read in one pass. The functions
+ pos() and size() don't work for sequential devices.
+ QTcpSocket and QProcess are examples of sequential devices.
+ \endlist
+
+ You can use isSequential() to determine the type of device.
+
+ QIODevice emits readyRead() when new data is available for
+ reading; for example, if new data has arrived on the network or if
+ additional data is appended to a file that you are reading
+ from. You can call bytesAvailable() to determine the number of
+ bytes that are currently available for reading. It's common to use
+ bytesAvailable() together with the readyRead() signal when
+ programming with asynchronous devices such as QTcpSocket, where
+ fragments of data can arrive at arbitrary points in
+ time. QIODevice emits the bytesWritten() signal every time a
+ payload of data has been written to the device. Use bytesToWrite()
+ to determine the current amount of data waiting to be written.
+
+ Certain subclasses of QIODevice, such as QTcpSocket and QProcess,
+ are asynchronous. This means that I/O functions such as write()
+ or read() always return immediately, while communication with the
+ device itself may happen when control goes back to the event loop.
+ QIODevice provides functions that allow you to force these
+ operations to be performed immediately, while blocking the
+ calling thread and without entering the event loop. This allows
+ QIODevice subclasses to be used without an event loop, or in
+ a separate thread:
+
+ \list
+ \o waitForReadyRead() - This function suspends operation in the
+ calling thread until new data is available for reading.
+
+ \o waitForBytesWritten() - This function suspends operation in the
+ calling thread until one payload of data has been written to the
+ device.
+
+ \o waitFor....() - Subclasses of QIODevice implement blocking
+ functions for device-specific operations. For example, QProcess
+ has a function called waitForStarted() which suspends operation in
+ the calling thread until the process has started.
+ \endlist
+
+ Calling these functions from the main, GUI thread, may cause your
+ user interface to freeze. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 0
+
+ By subclassing QIODevice, you can provide the same interface to
+ your own I/O devices. Subclasses of QIODevice are only required to
+ implement the protected readData() and writeData() functions.
+ QIODevice uses these functions to implement all its convenience
+ functions, such as getChar(), readLine() and write(). QIODevice
+ also handles access control for you, so you can safely assume that
+ the device is opened in write mode if writeData() is called.
+
+ Some subclasses, such as QFile and QTcpSocket, are implemented
+ using a memory buffer for intermediate storing of data. This
+ reduces the number of required device accessing calls, which are
+ often very slow. Buffering makes functions like getChar() and
+ putChar() fast, as they can operate on the memory buffer instead
+ of directly on the device itself. Certain I/O operations, however,
+ don't work well with a buffer. For example, if several users open
+ the same device and read it character by character, they may end
+ up reading the same data when they meant to read a separate chunk
+ each. For this reason, QIODevice allows you to bypass any
+ buffering by passing the Unbuffered flag to open(). When
+ subclassing QIODevice, remember to bypass any buffer you may use
+ when the device is open in Unbuffered mode.
+
+ \sa QBuffer QFile QTcpSocket
+*/
+
+/*!
+ \typedef QIODevice::Offset
+ \compat
+
+ Use \c qint64 instead.
+*/
+
+/*!
+ \typedef QIODevice::Status
+ \compat
+
+ Use QIODevice::OpenMode instead, or see the documentation for
+ specific devices.
+*/
+
+/*!
+ \enum QIODevice::OpenModeFlag
+
+ This enum is used with open() to describe the mode in which a device
+ is opened. It is also returned by openMode().
+
+ \value NotOpen The device is not open.
+ \value ReadOnly The device is open for reading.
+ \value WriteOnly The device is open for writing.
+ \value ReadWrite The device is open for reading and writing.
+ \value Append The device is opened in append mode, so that all data is
+ written to the end of the file.
+ \value Truncate If possible, the device is truncated before it is opened.
+ All earlier contents of the device are lost.
+ \value Text When reading, the end-of-line terminators are
+ translated to '\n'. When writing, the end-of-line
+ terminators are translated to the local encoding, for
+ example '\r\n' for Win32.
+ \value Unbuffered Any buffer in the device is bypassed.
+
+ Certain flags, such as \c Unbuffered and \c Truncate, are
+ meaningless when used with some subclasses. Some of these
+ restrictions are implied by the type of device that is represented
+ by a subclass. In other cases, the restriction may be due to the
+ implementation, or may be imposed by the underlying platform; for
+ example, QTcpSocket does not support \c Unbuffered mode, and
+ limitations in the native API prevent QFile from supporting \c
+ Unbuffered on Windows.
+*/
+
+/*! \fn QIODevice::bytesWritten(qint64 bytes)
+
+ This signal is emitted every time a payload of data has been
+ written to the device. The \a bytes argument is set to the number
+ of bytes that were written in this payload.
+
+ bytesWritten() is not emitted recursively; if you reenter the event loop
+ or call waitForBytesWritten() inside a slot connected to the
+ bytesWritten() signal, the signal will not be reemitted (although
+ waitForBytesWritten() may still return true).
+
+ \sa readyRead()
+*/
+
+/*!
+ \fn QIODevice::readyRead()
+
+ This signal is emitted once every time new data is available for
+ reading from the device. It will only be emitted again once new
+ data is available, such as when a new payload of network data has
+ arrived on your network socket, or when a new block of data has
+ been appended to your device.
+
+ readyRead() is not emitted recursively; if you reenter the event loop or
+ call waitForReadyRead() inside a slot connected to the readyRead() signal,
+ the signal will not be reemitted (although waitForReadyRead() may still
+ return true).
+
+ Note for developers implementing classes derived from QIODevice:
+ you should always emit readyRead() when new data has arrived (do not
+ emit it only because there's data still to be read in your
+ buffers). Do not emit readyRead() in other conditions.
+
+ \sa bytesWritten()
+*/
+
+/*! \fn QIODevice::aboutToClose()
+
+ This signal is emitted when the device is about to close. Connect
+ this signal if you have operations that need to be performed
+ before the device closes (e.g., if you have data in a separate
+ buffer that needs to be written to the device).
+*/
+
+/*!
+ \fn QIODevice::readChannelFinished()
+ \since 4.4
+
+ This signal is emitted when the input (reading) stream is closed
+ in this device. It is emitted as soon as the closing is detected,
+ which means that there might still be data available for reading
+ with read().
+
+ \sa atEnd(), read()
+*/
+
+#ifdef QT_NO_QOBJECT
+QIODevice::QIODevice()
+ : d_ptr(new QIODevicePrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*! \internal
+*/
+QIODevice::QIODevice(QIODevicePrivate &dd)
+ : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+}
+#else
+
+/*!
+ Constructs a QIODevice object.
+*/
+
+QIODevice::QIODevice()
+ : QObject(*new QIODevicePrivate, 0)
+{
+#if defined QIODEVICE_DEBUG
+ QFile *file = qobject_cast<QFile *>(this);
+ printf("%p QIODevice::QIODevice(\"%s\") %s\n", this, metaObject()->className(),
+ qPrintable(file ? file->fileName() : QString()));
+#endif
+}
+
+/*!
+ Constructs a QIODevice object with the given \a parent.
+*/
+
+QIODevice::QIODevice(QObject *parent)
+ : QObject(*new QIODevicePrivate, parent)
+{
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::QIODevice(%p \"%s\")\n", this, parent, metaObject()->className());
+#endif
+}
+
+/*! \internal
+*/
+QIODevice::QIODevice(QIODevicePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+#endif
+
+
+/*!
+ The destructor is virtual, and QIODevice is an abstract base
+ class. This destructor does not call close(), but the subclass
+ destructor might. If you are in doubt, call close() before
+ destroying the QIODevice.
+*/
+QIODevice::~QIODevice()
+{
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::~QIODevice()\n", this);
+#endif
+}
+
+/*!
+ Returns true if this device is sequential; otherwise returns
+ false.
+
+ Sequential devices, as opposed to a random-access devices, have no
+ concept of a start, an end, a size, or a current position, and they
+ do not support seeking. You can only read from the device when it
+ reports that data is available. The most common example of a
+ sequential device is a network socket. On Unix, special files such
+ as /dev/zero and fifo pipes are sequential.
+
+ Regular files, on the other hand, do support random access. They
+ have both a size and a current position, and they also support
+ seeking backwards and forwards in the data stream. Regular files
+ are non-sequential.
+
+ \sa bytesAvailable()
+*/
+bool QIODevice::isSequential() const
+{
+ return false;
+}
+
+/*!
+ Returns the mode in which the device has been opened;
+ i.e. ReadOnly or WriteOnly.
+
+ \sa OpenMode
+*/
+QIODevice::OpenMode QIODevice::openMode() const
+{
+ return d_func()->openMode;
+}
+
+/*!
+ Sets the OpenMode of the device to \a openMode. Call this
+ function to set the open mode if the flags change after the device
+ has been opened.
+
+ \sa openMode() OpenMode
+*/
+void QIODevice::setOpenMode(OpenMode openMode)
+{
+ Q_D(QIODevice);
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::setOpenMode(0x%x)\n", this, int(openMode));
+#endif
+ d->openMode = openMode;
+ d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
+ if (!isReadable())
+ d->buffer.clear();
+}
+
+/*!
+ If \a enabled is true, this function sets the \l Text flag on the device;
+ otherwise the \l Text flag is removed. This feature is useful for classes
+ that provide custom end-of-line handling on a QIODevice.
+
+ \sa open(), setOpenMode()
+ */
+void QIODevice::setTextModeEnabled(bool enabled)
+{
+ Q_D(QIODevice);
+ if (enabled)
+ d->openMode |= Text;
+ else
+ d->openMode &= ~Text;
+}
+
+/*!
+ Returns true if the \l Text flag is enabled; otherwise returns false.
+
+ \sa setTextModeEnabled()
+*/
+bool QIODevice::isTextModeEnabled() const
+{
+ return d_func()->openMode & Text;
+}
+
+/*!
+ Returns true if the device is open; otherwise returns false. A
+ device is open if it can be read from and/or written to. By
+ default, this function returns false if openMode() returns
+ \c NotOpen.
+
+ \sa openMode() OpenMode
+*/
+bool QIODevice::isOpen() const
+{
+ return d_func()->openMode != NotOpen;
+}
+
+/*!
+ Returns true if data can be read from the device; otherwise returns
+ false. Use bytesAvailable() to determine how many bytes can be read.
+
+ This is a convenience function which checks if the OpenMode of the
+ device contains the ReadOnly flag.
+
+ \sa openMode() OpenMode
+*/
+bool QIODevice::isReadable() const
+{
+ return (openMode() & ReadOnly) != 0;
+}
+
+/*!
+ Returns true if data can be written to the device; otherwise returns
+ false.
+
+ This is a convenience function which checks if the OpenMode of the
+ device contains the WriteOnly flag.
+
+ \sa openMode() OpenMode
+*/
+bool QIODevice::isWritable() const
+{
+ return (openMode() & WriteOnly) != 0;
+}
+
+/*!
+ Opens the device and sets its OpenMode to \a mode. Returns true if successful;
+ otherwise returns false. This function should be called from any
+ reimplementations of open() or other functions that open the device.
+
+ \sa openMode() OpenMode
+*/
+bool QIODevice::open(OpenMode mode)
+{
+ Q_D(QIODevice);
+ d->openMode = mode;
+ d->pos = (mode & Append) ? size() : qint64(0);
+ d->buffer.clear();
+ d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::open(0x%x)\n", this, quint32(mode));
+#endif
+ return true;
+}
+
+/*!
+ First emits aboutToClose(), then closes the device and sets its
+ OpenMode to NotOpen. The error string is also reset.
+
+ \sa setOpenMode() OpenMode
+*/
+void QIODevice::close()
+{
+ Q_D(QIODevice);
+ if (d->openMode == NotOpen)
+ return;
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::close()\n", this);
+#endif
+
+#ifndef QT_NO_QOBJECT
+ emit aboutToClose();
+#endif
+ d->openMode = NotOpen;
+ d->errorString.clear();
+ d->pos = 0;
+ d->buffer.clear();
+ d->firstRead = true;
+}
+
+/*!
+ For random-access devices, this function returns the position that
+ data is written to or read from. For sequential devices or closed
+ devices, where there is no concept of a "current position", 0 is
+ returned.
+
+ The current read/write position of the device is maintained internally by
+ QIODevice, so reimplementing this function is not necessary. When
+ subclassing QIODevice, use QIODevice::seek() to notify QIODevice about
+ changes in the device position.
+
+ \sa isSequential(), seek()
+*/
+qint64 QIODevice::pos() const
+{
+ Q_D(const QIODevice);
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::pos() == %d\n", this, int(d->pos));
+#endif
+ return d->pos;
+}
+
+/*!
+ For open random-access devices, this function returns the size of the
+ device. For open sequential devices, bytesAvailable() is returned.
+
+ If the device is closed, the size returned will not reflect the actual
+ size of the device.
+
+ \sa isSequential(), pos()
+*/
+qint64 QIODevice::size() const
+{
+ return d_func()->isSequential() ? bytesAvailable() : qint64(0);
+}
+
+/*!
+ For random-access devices, this function sets the current position
+ to \a pos, returning true on success, or false if an error occurred.
+ For sequential devices, the default behavior is to do nothing and
+ return false.
+
+ When subclassing QIODevice, you must call QIODevice::seek() at the
+ start of your function to ensure integrity with QIODevice's
+ built-in buffer. The base implementation always returns true.
+
+ \sa pos(), isSequential()
+*/
+bool QIODevice::seek(qint64 pos)
+{
+ Q_D(QIODevice);
+ if (d->openMode == NotOpen) {
+ qWarning("QIODevice::seek: The device is not open");
+ return false;
+ }
+ if (pos < 0) {
+ qWarning("QIODevice::seek: Invalid pos: %d", int(pos));
+ return false;
+ }
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n",
+ this, int(pos), int(d->pos), d->buffer.size());
+#endif
+
+ qint64 offset = pos - d->pos;
+ if (!d->isSequential()) {
+ d->pos = pos;
+ d->devicePos = pos;
+ }
+
+ if (offset < 0
+ || offset >= qint64(d->buffer.size()))
+ // When seeking backwards, an operation that is only allowed for
+ // random-access devices, the buffer is cleared. The next read
+ // operation will then refill the buffer. We can optimize this, if we
+ // find that seeking backwards becomes a significant performance hit.
+ d->buffer.clear();
+ else if (!d->buffer.isEmpty())
+ d->buffer.skip(int(offset));
+
+#if defined QIODEVICE_DEBUG
+ printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos),
+ d->buffer.size());
+#endif
+ return true;
+}
+
+/*!
+ Returns true if the current read and write position is at the end
+ of the device (i.e. there is no more data available for reading on
+ the device); otherwise returns false.
+
+ For some devices, atEnd() can return true even though there is more data
+ to read. This special case only applies to devices that generate data in
+ direct response to you calling read() (e.g., \c /dev or \c /proc files on
+ Unix and Mac OS X, or console input / \c stdin on all platforms).
+
+ \sa bytesAvailable(), read(), isSequential()
+*/
+bool QIODevice::atEnd() const
+{
+ Q_D(const QIODevice);
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %d\n", this, (d->openMode == NotOpen || d->pos == size()) ? "true" : "false",
+ int(d->openMode), int(d->pos));
+#endif
+ return d->openMode == NotOpen || (d->buffer.isEmpty() && bytesAvailable() == 0);
+}
+
+/*!
+ Seeks to the start of input for random-access devices. Returns
+ true on success; otherwise returns false (for example, if the
+ device is not open).
+
+ Note that when using a QTextStream on a QFile, calling reset() on
+ the QFile will not have the expected result because QTextStream
+ buffers the file. Use the QTextStream::seek() function instead.
+
+ \sa seek()
+*/
+bool QIODevice::reset()
+{
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::reset()\n", this);
+#endif
+ return seek(0);
+}
+
+/*!
+ Returns the number of bytes that are available for reading. This
+ function is commonly used with sequential devices to determine the
+ number of bytes to allocate in a buffer before reading.
+
+ Subclasses that reimplement this function must call the base
+ implementation in order to include the size of QIODevices' buffer. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 1
+
+ \sa bytesToWrite(), readyRead(), isSequential()
+*/
+qint64 QIODevice::bytesAvailable() const
+{
+ Q_D(const QIODevice);
+ if (!d->isSequential())
+ return qMax(size() - d->pos, qint64(0));
+ return d->buffer.size();
+}
+
+/*!
+ For buffered devices, this function returns the number of bytes
+ waiting to be written. For devices with no buffer, this function
+ returns 0.
+
+ \sa bytesAvailable(), bytesWritten(), isSequential()
+*/
+qint64 QIODevice::bytesToWrite() const
+{
+ return qint64(0);
+}
+
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
+/*!
+ Reads at most \a maxSize bytes from the device into \a data, and
+ returns the number of bytes read. If an error occurs, such as when
+ attempting to read from a device opened in WriteOnly mode, this
+ function returns -1.
+
+ 0 is returned when no more data is available for reading. However,
+ reading past the end of the stream is considered an error, so this
+ function returns -1 in those cases (that is, reading on a closed
+ socket or after a process has died).
+
+ \sa readData() readLine() write()
+*/
+qint64 QIODevice::read(char *data, qint64 maxSize)
+{
+ Q_D(QIODevice);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
+ this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
+#endif
+
+ // Short circuit for getChar()
+ if (maxSize == 1) {
+ int chint;
+ while ((chint = d->buffer.getChar()) != -1) {
+ ++(*d->pPos);
+
+ char c = char(uchar(chint));
+ if (c == '\r' && (d->openMode & Text))
+ continue;
+ *data = c;
+#if defined QIODEVICE_DEBUG
+ printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this,
+ int(c), isprint(c) ? c : '?');
+#endif
+ return qint64(1);
+ }
+ }
+
+ CHECK_MAXLEN(read, qint64(-1));
+ qint64 readSoFar = 0;
+ bool moreToRead = true;
+ do {
+ // Try reading from the buffer.
+ int lastReadChunkSize = d->buffer.read(data, maxSize);
+ if (lastReadChunkSize > 0) {
+ *d->pPos += lastReadChunkSize;
+ readSoFar += lastReadChunkSize;
+ // fast exit when satisfied by buffer
+ if (lastReadChunkSize == maxSize && !(d->openMode & Text))
+ return readSoFar;
+
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
+#if defined QIODEVICE_DEBUG
+ printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize,
+ int(readSoFar) - lastReadChunkSize);
+#endif
+ } else {
+ if (d->firstRead) {
+ // this is the first time the file has been read, check it's valid and set up pos pointers
+ // for fast pos updates.
+ CHECK_READABLE(read, qint64(-1));
+ d->firstRead = false;
+ if (d->isSequential()) {
+ d->pPos = &d->seqDumpPos;
+ d->pDevicePos = &d->seqDumpPos;
+ }
+ }
+
+ if (!maxSize)
+ return readSoFar;
+
+ if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
+ // In buffered mode, we try to fill up the QIODevice buffer before
+ // we do anything else.
+ // buffer is empty at this point, try to fill it
+ int bytesToBuffer = QIODEVICE_BUFFERSIZE;
+ char *writePointer = d->buffer.reserve(bytesToBuffer);
+
+ // Make sure the device is positioned correctly.
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(writePointer, bytesToBuffer);
+ d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
+
+ if (readFromDevice > 0) {
+ *d->pDevicePos += readFromDevice;
+#if defined QIODEVICE_DEBUG
+ printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
+#endif
+
+ if (!d->buffer.isEmpty()) {
+ lastReadChunkSize = d->buffer.read(data, maxSize);
+ readSoFar += lastReadChunkSize;
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
+ *d->pPos += lastReadChunkSize;
+#if defined QIODEVICE_DEBUG
+ printf("%p \treading %d bytes from buffer at position %d\n", this,
+ lastReadChunkSize, int(readSoFar));
+#endif
+ }
+ }
+ }
+ }
+
+ // If we need more, try reading from the device.
+ if (maxSize > 0) {
+ // Make sure the device is positioned correctly.
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(data, maxSize);
+#if defined QIODEVICE_DEBUG
+ printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar));
+#endif
+ if (readFromDevice == -1 && readSoFar == 0) {
+ // error and we haven't read anything: return immediately
+ return -1;
+ }
+ if (readFromDevice > 0) {
+ lastReadChunkSize += int(readFromDevice);
+ readSoFar += readFromDevice;
+ data += readFromDevice;
+ maxSize -= readFromDevice;
+ *d->pPos += readFromDevice;
+ *d->pDevicePos += readFromDevice;
+ }
+ }
+ // Best attempt has been made to read data, don't try again except for text mode adjustment below
+ moreToRead = false;
+
+ if (readSoFar && d->openMode & Text) {
+ char *readPtr = data - lastReadChunkSize;
+ const char *endPtr = data;
+
+ if (readPtr < endPtr) {
+ // optimization to avoid initial self-assignment
+ while (*readPtr != '\r') {
+ if (++readPtr == endPtr)
+ return readSoFar;
+ }
+
+ char *writePtr = readPtr;
+
+ while (readPtr < endPtr) {
+ char ch = *readPtr++;
+ if (ch != '\r')
+ *writePtr++ = ch;
+ else {
+ --readSoFar;
+ --data;
+ ++maxSize;
+ }
+ }
+
+ // Make sure we get more data if there is room for more. This
+ // is very important for when someone seeks to the start of a
+ // '\r\n' and reads one character - they should get the '\n'.
+ moreToRead = (readPtr != writePtr);
+ }
+ }
+ } while (moreToRead);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this,
+ int(readSoFar), int(d->pos), d->buffer.size());
+ debugBinaryString(data - readSoFar, readSoFar);
+#endif
+ return readSoFar;
+}
+
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
+/*!
+ \overload
+
+ Reads at most \a maxSize bytes from the device, and returns the
+ data read as a QByteArray.
+
+ 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.
+*/
+QByteArray QIODevice::read(qint64 maxSize)
+{
+ Q_D(QIODevice);
+ QByteArray result;
+
+ CHECK_MAXLEN(read, result);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n",
+ this, int(maxSize), int(d->pos), int(d->buffer.size()));
+#else
+ Q_UNUSED(d);
+#endif
+
+ if (maxSize != qint64(int(maxSize))) {
+ qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
+ maxSize = INT_MAX;
+ }
+
+ qint64 readBytes = 0;
+ if (maxSize) {
+ result.resize(int(maxSize));
+ if (!result.size()) {
+ // If resize fails, read incrementally.
+ qint64 readResult;
+ do {
+ result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE)));
+ readResult = read(result.data() + readBytes, result.size() - readBytes);
+ if (readResult > 0 || readBytes == 0)
+ readBytes += readResult;
+ } while (readResult == QIODEVICE_BUFFERSIZE);
+ } else {
+ readBytes = read(result.data(), result.size());
+ }
+ }
+
+ if (readBytes <= 0)
+ result.clear();
+ else
+ result.resize(int(readBytes));
+
+ return result;
+}
+
+/*!
+ \overload
+
+ Reads all available data from the device, and returns it as a
+ QByteArray.
+
+ 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.
+*/
+QByteArray QIODevice::readAll()
+{
+ Q_D(QIODevice);
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n",
+ this, int(d->pos), int(d->buffer.size()));
+#endif
+
+ QByteArray result;
+ qint64 readBytes = 0;
+
+ // flush internal read buffer
+ if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
+ result = d->buffer.readAll();
+ readBytes = result.size();
+ d->pos += readBytes;
+ }
+
+ qint64 theSize;
+ if (d->isSequential() || (theSize = size()) == 0) {
+ // Size is unknown, read incrementally.
+ qint64 readResult;
+ do {
+ result.resize(result.size() + QIODEVICE_BUFFERSIZE);
+ readResult = read(result.data() + readBytes, result.size() - readBytes);
+ if (readResult > 0 || readBytes == 0)
+ readBytes += readResult;
+ } while (readResult > 0);
+ } else {
+ // Read it all in one go.
+ // If resize fails, don't read anything.
+ result.resize(int(readBytes + theSize - d->pos));
+ readBytes += read(result.data() + readBytes, result.size() - readBytes);
+ }
+
+ if (readBytes <= 0)
+ result.clear();
+ else
+ result.resize(int(readBytes));
+
+ return result;
+}
+
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
+/*!
+ 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
+ occurs, this function returns the length of what could be read, or
+ -1 if nothing was read.
+
+ A terminating '\0' byte is always appended to \a data, so \a
+ maxSize must be larger than 1.
+
+ Data is read until either of the following conditions are met:
+
+ \list
+ \o The first '\n' character is read.
+ \o \a maxSize - 1 bytes are read.
+ \o The end of the device data is detected.
+ \endlist
+
+ For example, the following code reads a line of characters from a
+ file:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 2
+
+ The newline character ('\n') is included in the buffer. If a
+ newline is not encountered before maxSize - 1 bytes are read, a
+ newline will not be inserted into the buffer. On windows newline
+ characters are replaced with '\n'.
+
+ 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()
+*/
+qint64 QIODevice::readLine(char *data, qint64 maxSize)
+{
+ Q_D(QIODevice);
+ if (maxSize < 2) {
+ qWarning("QIODevice::readLine: Called with maxSize < 2");
+ return qint64(-1);
+ }
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::readLine(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
+ this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
+#endif
+
+ // Leave room for a '\0'
+ --maxSize;
+
+ const bool sequential = d->isSequential();
+
+ qint64 readSoFar = 0;
+ if (!d->buffer.isEmpty()) {
+ readSoFar = d->buffer.readLine(data, maxSize);
+ if (!sequential)
+ d->pos += readSoFar;
+#if defined QIODEVICE_DEBUG
+ printf("%p \tread from buffer: %d bytes, last character read: %hhx\n", this,
+ int(readSoFar), data[int(readSoFar) - 1]);
+ if (readSoFar)
+ debugBinaryString(data, int(readSoFar));
+#endif
+#if defined(Q_OS_SYMBIAN)
+ // Open C fgets strips '\r' but readSoFar gets returned as if it was still there
+ if ((d->openMode & Text) &&
+ readSoFar > 1 &&
+ data[readSoFar - 1] == '\0' &&
+ data[readSoFar - 2] == '\n') {
+ --readSoFar;
+ }
+#endif
+ if (readSoFar && data[readSoFar - 1] == '\n') {
+ if (d->openMode & Text) {
+ // QRingBuffer::readLine() isn't Text aware.
+ if (readSoFar > 1 && data[readSoFar - 2] == '\r') {
+ --readSoFar;
+ data[readSoFar - 1] = '\n';
+ }
+ }
+ data[readSoFar] = '\0';
+ return readSoFar;
+ }
+ }
+
+ if (d->pos != d->devicePos && !sequential && !seek(d->pos))
+ return qint64(-1);
+ d->baseReadLineDataCalled = false;
+ qint64 readBytes = readLineData(data + readSoFar, maxSize - readSoFar);
+#if defined QIODEVICE_DEBUG
+ printf("%p \tread from readLineData: %d bytes, readSoFar = %d bytes\n", this,
+ int(readBytes), int(readSoFar));
+ if (readBytes > 0) {
+ debugBinaryString(data, int(readSoFar + readBytes));
+ }
+#endif
+ if (readBytes < 0) {
+ data[readSoFar] = '\0';
+ return readSoFar ? readSoFar : -1;
+ }
+ readSoFar += readBytes;
+ if (!d->baseReadLineDataCalled && !sequential) {
+ d->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);
+ }
+ data[readSoFar] = '\0';
+
+ if (d->openMode & Text) {
+#if defined(Q_OS_SYMBIAN)
+ // Open C fgets strips '\r' but readSoFar gets returned as if it was still there
+ if (readSoFar > 1 && data[readSoFar - 1] == '\0' && data[readSoFar - 2] == '\n') {
+ --readSoFar;
+ }
+#endif
+ if (readSoFar > 1 && data[readSoFar - 1] == '\n' && data[readSoFar - 2] == '\r') {
+ data[readSoFar - 2] = '\n';
+ data[readSoFar - 1] = '\0';
+ --readSoFar;
+ }
+ }
+
+#if defined QIODEVICE_DEBUG
+ printf("%p \treturning %d, d->pos = %d, d->buffer.size() = %d, size() = %d\n",
+ this, int(readSoFar), int(d->pos), d->buffer.size(), int(size()));
+ debugBinaryString(data, int(readSoFar));
+#endif
+ return readSoFar;
+}
+
+/*!
+ \overload
+
+ Reads a line from the device, but no more than \a maxSize characters,
+ and returns the result as a QByteArray.
+
+ 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.
+*/
+QByteArray QIODevice::readLine(qint64 maxSize)
+{
+ Q_D(QIODevice);
+ QByteArray result;
+
+ CHECK_MAXLEN(readLine, result);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n",
+ this, int(maxSize), int(d->pos), int(d->buffer.size()));
+#else
+ Q_UNUSED(d);
+#endif
+
+ if (maxSize > INT_MAX) {
+ qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
+ maxSize = INT_MAX;
+ }
+
+ result.resize(int(maxSize));
+ qint64 readBytes = 0;
+ if (!result.size()) {
+ // If resize fails or maxSize == 0, read incrementally
+ if (maxSize == 0)
+ maxSize = INT_MAX;
+
+ // The first iteration needs to leave an extra byte for the terminating null
+ result.resize(1);
+
+ qint64 readResult;
+ do {
+ result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE)));
+ readResult = readLine(result.data() + readBytes, result.size() - readBytes);
+ if (readResult > 0 || readBytes == 0)
+ readBytes += readResult;
+ } while (readResult == QIODEVICE_BUFFERSIZE
+ && result[int(readBytes - 1)] != '\n');
+ } else
+ readBytes = readLine(result.data(), result.size());
+
+ if (readBytes <= 0)
+ result.clear();
+ else
+ result.resize(readBytes);
+
+ return result;
+}
+
+/*!
+ Reads up to \a maxSize characters into \a data and returns the
+ number of characters read.
+
+ This function is called by readLine(), and provides its base
+ implementation, using getChar(). Buffered devices can improve the
+ performance of readLine() by reimplementing this function.
+
+ readLine() appends a '\0' byte to \a data; readLineData() does not
+ need to do this.
+
+ If you reimplement this function, be careful to return the correct
+ value: it should return the number of bytes read in this line,
+ including the terminating newline, or 0 if there is no line to be
+ read at this point. If an error occurs, it should return -1 if and
+ only if no bytes were read. Reading past EOF is considered an error.
+*/
+qint64 QIODevice::readLineData(char *data, qint64 maxSize)
+{
+ Q_D(QIODevice);
+ qint64 readSoFar = 0;
+ char c;
+ int lastReadReturn = 0;
+ d->baseReadLineDataCalled = true;
+
+ while (readSoFar < maxSize && (lastReadReturn = read(&c, 1)) == 1) {
+ *data++ = c;
+ ++readSoFar;
+ if (c == '\n')
+ break;
+ }
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::readLineData(%p, %d), d->pos = %d, d->buffer.size() = %d, returns %d\n",
+ this, data, int(maxSize), int(d->pos), int(d->buffer.size()), int(readSoFar));
+#endif
+ if (lastReadReturn != 1 && readSoFar == 0)
+ return isSequential() ? lastReadReturn : -1;
+ return readSoFar;
+}
+
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
+/*!
+ Returns true if a complete line of data can be read from the device;
+ otherwise returns false.
+
+ Note that unbuffered devices, which have no way of determining what
+ can be read, always return false.
+
+ This function is often called in conjunction with the readyRead()
+ signal.
+
+ Subclasses that reimplement this function must call the base
+ implementation in order to include the contents of the QIODevice's buffer. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 3
+
+ \sa readyRead(), readLine()
+*/
+bool QIODevice::canReadLine() const
+{
+ return d_func()->buffer.canReadLine();
+}
+
+/*!
+ Writes at most \a maxSize bytes of data from \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 char *data, qint64 maxSize)
+{
+ Q_D(QIODevice);
+ CHECK_WRITABLE(write, qint64(-1));
+ CHECK_MAXLEN(write, qint64(-1));
+
+ const bool sequential = d->isSequential();
+ // Make sure the device is positioned correctly.
+ if (d->pos != d->devicePos && !sequential && !seek(d->pos))
+ return qint64(-1);
+
+#ifdef Q_OS_WIN
+ if (d->openMode & Text) {
+ const char *endOfData = data + maxSize;
+ const char *startOfBlock = data;
+
+ qint64 writtenSoFar = 0;
+
+ forever {
+ const char *endOfBlock = startOfBlock;
+ while (endOfBlock < endOfData && *endOfBlock != '\n')
+ ++endOfBlock;
+
+ qint64 blockSize = endOfBlock - startOfBlock;
+ if (blockSize > 0) {
+ qint64 ret = writeData(startOfBlock, blockSize);
+ if (ret <= 0) {
+ if (writtenSoFar && !sequential)
+ d->buffer.skip(writtenSoFar);
+ return writtenSoFar ? writtenSoFar : ret;
+ }
+ if (!sequential) {
+ d->pos += ret;
+ d->devicePos += ret;
+ }
+ writtenSoFar += ret;
+ }
+
+ if (endOfBlock == endOfData)
+ break;
+
+ qint64 ret = writeData("\r\n", 2);
+ if (ret <= 0) {
+ if (writtenSoFar && !sequential)
+ d->buffer.skip(writtenSoFar);
+ return writtenSoFar ? writtenSoFar : ret;
+ }
+ if (!sequential) {
+ d->pos += ret;
+ d->devicePos += ret;
+ }
+ ++writtenSoFar;
+
+ startOfBlock = endOfBlock + 1;
+ }
+
+ if (writtenSoFar && !sequential)
+ d->buffer.skip(writtenSoFar);
+ return writtenSoFar;
+ }
+#endif
+
+ qint64 written = writeData(data, maxSize);
+ if (written > 0) {
+ if (!sequential) {
+ d->pos += written;
+ d->devicePos += written;
+ }
+ if (!d->buffer.isEmpty() && !sequential)
+ d->buffer.skip(written);
+ }
+ return written;
+}
+
+/*!
+ \since 4.5
+
+ \overload
+
+ Writes data from a zero-terminated string of 8-bit characters to the
+ device. Returns the number of bytes that were actually written, or
+ -1 if an error occurred. This is equivalent to
+ \code
+ ...
+ QIODevice::write(data, qstrlen(data));
+ ...
+ \endcode
+
+ \sa read() writeData()
+*/
+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
+ bytes that were actually written, or -1 if an error occurred.
+
+ \sa read() writeData()
+*/
+
+/*!
+ Puts the character \a c back into the device, and decrements the
+ current position unless the position is 0. This function is
+ usually called to "undo" a getChar() operation, such as when
+ writing a backtracking parser.
+
+ If \a c was not previously read from the device, the behavior is
+ undefined.
+*/
+void QIODevice::ungetChar(char c)
+{
+ Q_D(QIODevice);
+ CHECK_READABLE(read, Q_VOID);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isprint(c) ? c : '?');
+#endif
+
+ d->buffer.ungetChar(c);
+ if (!d->isSequential())
+ --d->pos;
+}
+
+/*! \fn bool QIODevice::putChar(char c)
+
+ Writes the character \a c to the device. Returns true on success;
+ otherwise returns false.
+
+ \sa write() getChar() ungetChar()
+*/
+bool QIODevice::putChar(char c)
+{
+ return d_func()->putCharHelper(c);
+}
+
+/*!
+ \internal
+*/
+bool QIODevicePrivate::putCharHelper(char c)
+{
+ return q_func()->write(&c, 1) == 1;
+}
+
+/*!
+ \internal
+*/
+qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
+{
+ qint64 readBytes = q_func()->read(data, maxSize);
+ if (readBytes <= 0)
+ return readBytes;
+
+ buffer.ungetBlock(data, readBytes);
+ *pPos -= readBytes;
+ return readBytes;
+}
+
+/*!
+ \internal
+*/
+QByteArray QIODevicePrivate::peek(qint64 maxSize)
+{
+ QByteArray result = q_func()->read(maxSize);
+
+ if (result.isEmpty())
+ return result;
+
+ buffer.ungetBlock(result.constData(), result.size());
+ *pPos -= result.size();
+ return result;
+}
+
+/*! \fn bool QIODevice::getChar(char *c)
+
+ Reads one character from the device and stores it in \a c. If \a c
+ is 0, the character is discarded. Returns true on success;
+ otherwise returns false.
+
+ \sa read() putChar() ungetChar()
+*/
+bool QIODevice::getChar(char *c)
+{
+ // readability checked in read()
+ char ch;
+ return (1 == read(c ? c : &ch, 1));
+}
+
+/*!
+ \since 4.1
+
+ Reads at most \a maxSize bytes from the device into \a data, without side
+ effects (i.e., if you call read() after peek(), you will get the same
+ data). Returns the number of bytes read. If an error occurs, such as
+ when attempting to peek a device opened in WriteOnly mode, this function
+ returns -1.
+
+ 0 is returned when no more data is available for reading.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 4
+
+ \sa read()
+*/
+qint64 QIODevice::peek(char *data, qint64 maxSize)
+{
+ return d_func()->peek(data, maxSize);
+}
+
+/*!
+ \since 4.1
+ \overload
+
+ Peeks at most \a maxSize bytes from the device, returning the data peeked
+ as a QByteArray.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qiodevice.cpp 5
+
+ This function has no way of reporting errors; returning an empty
+ QByteArray() can mean either that no data was currently available
+ for peeking, or that an error occurred.
+
+ \sa read()
+*/
+QByteArray QIODevice::peek(qint64 maxSize)
+{
+ return d_func()->peek(maxSize);
+}
+
+/*!
+ Blocks until new data is available for reading and the readyRead()
+ signal has been emitted, or until \a msecs milliseconds have
+ passed. If msecs is -1, this function will not time out.
+
+ Returns true if new data is available for reading; otherwise returns
+ false (if the operation timed out or if an error occurred).
+
+ This function can operate without an event loop. It is
+ useful when writing non-GUI applications and when performing
+ I/O operations in a non-GUI thread.
+
+ If called from within a slot connected to the readyRead() signal,
+ readyRead() will not be reemitted.
+
+ Reimplement this function to provide a blocking API for a custom
+ device. The default implementation does nothing, and returns false.
+
+ \warning Calling this function from the main (GUI) thread
+ might cause your user interface to freeze.
+
+ \sa waitForBytesWritten()
+*/
+bool QIODevice::waitForReadyRead(int msecs)
+{
+ Q_UNUSED(msecs);
+ return false;
+}
+
+/*!
+ For buffered devices, this function waits until a payload of
+ buffered written data has been written to the device and the
+ bytesWritten() signal has been emitted, or until \a msecs
+ milliseconds have passed. If msecs is -1, this function will
+ not time out. For unbuffered devices, it returns immediately.
+
+ Returns true if a payload of data was written to the device;
+ otherwise returns false (i.e. if the operation timed out, or if an
+ error occurred).
+
+ This function can operate without an event loop. It is
+ useful when writing non-GUI applications and when performing
+ I/O operations in a non-GUI thread.
+
+ If called from within a slot connected to the bytesWritten() signal,
+ bytesWritten() will not be reemitted.
+
+ Reimplement this function to provide a blocking API for a custom
+ device. The default implementation does nothing, and returns false.
+
+ \warning Calling this function from the main (GUI) thread
+ might cause your user interface to freeze.
+
+ \sa waitForReadyRead()
+*/
+bool QIODevice::waitForBytesWritten(int msecs)
+{
+ Q_UNUSED(msecs);
+ return false;
+}
+
+/*!
+ Sets the human readable description of the last device error that
+ occurred to \a str.
+
+ \sa errorString()
+*/
+void QIODevice::setErrorString(const QString &str)
+{
+ d_func()->errorString = str;
+}
+
+/*!
+ Returns a human-readable description of the last device error that
+ occurred.
+
+ \sa setErrorString()
+*/
+QString QIODevice::errorString() const
+{
+ Q_D(const QIODevice);
+ if (d->errorString.isEmpty()) {
+#ifdef QT_NO_QOBJECT
+ return QLatin1String(QT_TRANSLATE_NOOP(QIODevice, "Unknown error"));
+#else
+ return tr("Unknown error");
+#endif
+ }
+ return d->errorString;
+}
+
+/*!
+ \fn qint64 QIODevice::readData(char *data, qint64 maxSize)
+
+ Reads up to \a maxSize bytes from the device into \a data, and
+ returns the number of bytes read or -1 if an error occurred.
+
+ If there are no bytes to be read and there can never be more bytes
+ available (examples include socket closed, pipe closed, sub-process
+ finished), this function returns -1.
+
+ This function is called by QIODevice. Reimplement this function
+ when creating a subclass of QIODevice.
+
+ When reimplementing this function it is important that this function
+ reads all the required data before returning. This is required in order
+ for QDataStream to be able to operate on the class. QDataStream assumes
+ all the requested information was read and therefore does not retry reading
+ if there was a problem.
+
+ \sa read() readLine() writeData()
+*/
+
+/*!
+ \fn qint64 QIODevice::writeData(const char *data, qint64 maxSize)
+
+ Writes up to \a maxSize bytes from \a data to the device. Returns
+ the number of bytes written, or -1 if an error occurred.
+
+ This function is called by QIODevice. Reimplement this function
+ when creating a subclass of QIODevice.
+
+ When reimplementing this function it is important that this function
+ writes all the data available before returning. This is required in order
+ for QDataStream to be able to operate on the class. QDataStream assumes
+ all the information was written and therefore does not retry writing if
+ there was a problem.
+
+ \sa read() write()
+*/
+
+/*!
+ \fn QIODevice::Offset QIODevice::status() const
+
+ For device specific error handling, please refer to the
+ individual device documentation.
+
+ \sa qobject_cast()
+*/
+
+/*!
+ \fn QIODevice::Offset QIODevice::at() const
+
+ Use pos() instead.
+*/
+
+/*!
+ \fn bool QIODevice::at(Offset offset)
+
+ Use seek(\a offset) instead.
+*/
+
+/*! \fn int QIODevice::flags() const
+
+ Use openMode() instead.
+*/
+
+/*! \fn int QIODevice::getch()
+
+ Use getChar() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isAsynchronous() const
+
+ This functionality is no longer available. This function always
+ returns true.
+*/
+
+/*!
+ \fn bool QIODevice::isBuffered() const
+
+ Use !(openMode() & QIODevice::Unbuffered) instead.
+*/
+
+/*!
+ \fn bool QIODevice::isCombinedAccess() const
+
+ Use openMode() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isDirectAccess() const
+
+ Use !isSequential() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isInactive() const
+
+ Use isOpen(), isReadable(), or isWritable() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isRaw() const
+
+ Use openMode() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isSequentialAccess() const
+
+ Use isSequential() instead.
+*/
+
+/*!
+ \fn bool QIODevice::isSynchronous() const
+
+ This functionality is no longer available. This function always
+ returns false.
+*/
+
+/*!
+ \fn bool QIODevice::isTranslated() const
+
+ Use openMode() instead.
+*/
+
+/*!
+ \fn bool QIODevice::mode() const
+
+ Use openMode() instead.
+*/
+
+/*! \fn int QIODevice::putch(int ch)
+
+ Use putChar(\a ch) instead.
+*/
+
+/*! \fn int QIODevice::ungetch(int ch)
+
+ Use ungetChar(\a ch) instead.
+*/
+
+/*!
+ \fn quint64 QIODevice::readBlock(char *data, quint64 size)
+
+ Use read(\a data, \a size) instead.
+*/
+
+/*! \fn int QIODevice::state() const
+
+ Use isOpen() instead.
+*/
+
+/*!
+ \fn qint64 QIODevice::writeBlock(const char *data, quint64 size)
+
+ Use write(\a data, \a size) instead.
+*/
+
+/*!
+ \fn qint64 QIODevice::writeBlock(const QByteArray &data)
+
+ Use write(\a data) instead.
+*/
+
+#if defined QT3_SUPPORT
+QIODevice::Status QIODevice::status() const
+{
+#if !defined(QT_NO_QOBJECT)
+ const QFile *f = qobject_cast<const QFile *>(this);
+ if (f) return (int) f->error();
+#endif
+ return isOpen() ? 0 /* IO_Ok */ : 8 /* IO_UnspecifiedError */;
+}
+
+/*!
+ For device specific error handling, please refer to the
+ individual device documentation.
+
+ \sa qobject_cast()
+*/
+void QIODevice::resetStatus()
+{
+#if !defined(QT_NO_QOBJECT)
+ QFile *f = qobject_cast<QFile *>(this);
+ if (f) f->unsetError();
+#endif
+}
+#endif
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug debug, QIODevice::OpenMode modes)
+{
+ debug << "OpenMode(";
+ QStringList modeList;
+ if (modes == QIODevice::NotOpen) {
+ modeList << QLatin1String("NotOpen");
+ } else {
+ if (modes & QIODevice::ReadOnly)
+ modeList << QLatin1String("ReadOnly");
+ if (modes & QIODevice::WriteOnly)
+ modeList << QLatin1String("WriteOnly");
+ if (modes & QIODevice::Append)
+ modeList << QLatin1String("Append");
+ if (modes & QIODevice::Truncate)
+ modeList << QLatin1String("Truncate");
+ if (modes & QIODevice::Text)
+ modeList << QLatin1String("Text");
+ if (modes & QIODevice::Unbuffered)
+ modeList << QLatin1String("Unbuffered");
+ }
+ qSort(modeList);
+ debug << modeList.join(QLatin1String("|"));
+ debug << ')';
+ return debug;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
new file mode 100644
index 0000000000..4bfe77f616
--- /dev/null
+++ b/src/corelib/io/qiodevice.h
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIODEVICE_H
+#define QIODEVICE_H
+
+#ifndef QT_NO_QOBJECT
+#include <QtCore/qobject.h>
+#else
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qscopedpointer.h>
+#endif
+#include <QtCore/qstring.h>
+
+#ifdef open
+#error qiodevice.h must be included before any header file that defines open
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArray;
+class QIODevicePrivate;
+
+class Q_CORE_EXPORT QIODevice
+#ifndef QT_NO_QOBJECT
+ : public QObject
+#endif
+{
+#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
+ };
+ Q_DECLARE_FLAGS(OpenMode, OpenModeFlag)
+
+ QIODevice();
+#ifndef QT_NO_QOBJECT
+ explicit QIODevice(QObject *parent);
+#endif
+ virtual ~QIODevice();
+
+ OpenMode openMode() const;
+
+ void setTextModeEnabled(bool enabled);
+ bool isTextModeEnabled() const;
+
+ bool isOpen() const;
+ bool isReadable() const;
+ bool isWritable() const;
+ virtual bool isSequential() const;
+
+ virtual bool open(OpenMode mode);
+ virtual void close();
+
+ // ### Qt 5: pos() and seek() should not be virtual, and
+ // ### seek() should call a virtual seekData() function.
+ virtual qint64 pos() const;
+ virtual qint64 size() const;
+ virtual bool seek(qint64 pos);
+ virtual bool atEnd() const;
+ virtual bool reset();
+
+ virtual qint64 bytesAvailable() const;
+ virtual qint64 bytesToWrite() const;
+
+ qint64 read(char *data, qint64 maxlen);
+ QByteArray read(qint64 maxlen);
+ QByteArray readAll();
+ qint64 readLine(char *data, qint64 maxlen);
+ QByteArray readLine(qint64 maxlen = 0);
+ virtual bool canReadLine() const;
+
+ 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 peek(char *data, qint64 maxlen);
+ QByteArray peek(qint64 maxlen);
+
+ virtual bool waitForReadyRead(int msecs);
+ virtual bool waitForBytesWritten(int msecs);
+
+ void ungetChar(char c);
+ bool putChar(char c);
+ bool getChar(char *c);
+
+ QString errorString() const;
+
+#ifndef QT_NO_QOBJECT
+Q_SIGNALS:
+ void readyRead();
+ void bytesWritten(qint64 bytes);
+ void aboutToClose();
+ void readChannelFinished();
+#endif
+
+protected:
+#ifdef QT_NO_QOBJECT
+ QIODevice(QIODevicePrivate &dd);
+#else
+ QIODevice(QIODevicePrivate &dd, QObject *parent = 0);
+#endif
+ virtual qint64 readData(char *data, qint64 maxlen) = 0;
+ virtual qint64 readLineData(char *data, qint64 maxlen);
+ virtual qint64 writeData(const char *data, qint64 len) = 0;
+
+ void setOpenMode(OpenMode openMode);
+
+ void setErrorString(const QString &errorString);
+
+#ifdef QT_NO_QOBJECT
+ QScopedPointer<QIODevicePrivate> d_ptr;
+#endif
+
+private:
+ Q_DECLARE_PRIVATE(QIODevice)
+ Q_DISABLE_COPY(QIODevice)
+
+#ifdef QT3_SUPPORT
+public:
+ typedef qint64 Offset;
+
+ inline QT3_SUPPORT int flags() const { return static_cast<int>(openMode()); }
+ inline QT3_SUPPORT int mode() const { return static_cast<int>(openMode()); }
+ inline QT3_SUPPORT int state() const;
+
+ inline QT3_SUPPORT bool isDirectAccess() const { return !isSequential(); }
+ inline QT3_SUPPORT bool isSequentialAccess() const { return isSequential(); }
+ inline QT3_SUPPORT bool isCombinedAccess() const { return false; }
+ inline QT3_SUPPORT bool isBuffered() const { return true; }
+ inline QT3_SUPPORT bool isRaw() const { return false; }
+ inline QT3_SUPPORT bool isSynchronous() const { return true; }
+ inline QT3_SUPPORT bool isAsynchronous() const { return false; }
+ inline QT3_SUPPORT bool isTranslated() const { return (openMode() & Text) != 0; }
+ inline QT3_SUPPORT bool isInactive() const { return !isOpen(); }
+
+ typedef int Status;
+ QT3_SUPPORT Status status() const;
+ QT3_SUPPORT void resetStatus();
+
+ inline QT3_SUPPORT Offset at() const { return pos(); }
+ inline QT3_SUPPORT bool at(Offset offset) { return seek(offset); }
+
+ inline QT3_SUPPORT qint64 readBlock(char *data, quint64 maxlen) { return read(data, maxlen); }
+ inline QT3_SUPPORT qint64 writeBlock(const char *data, quint64 len) { return write(data, len); }
+ inline QT3_SUPPORT qint64 writeBlock(const QByteArray &data) { return write(data); }
+
+ inline QT3_SUPPORT int getch() { char c; return getChar(&c) ? int(uchar(c)) : -1; }
+ inline QT3_SUPPORT int putch(int c) { return putChar(char(c)) ? int(uchar(c)) : -1; }
+ inline QT3_SUPPORT int ungetch(int c) { ungetChar(uchar(c)); return c; }
+#endif
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QIODevice::OpenMode)
+
+#ifdef QT3_SUPPORT
+static QT3_SUPPORT_VARIABLE const uint IO_Direct = 0x0100;
+static QT3_SUPPORT_VARIABLE const uint IO_Sequential = 0x0200;
+static QT3_SUPPORT_VARIABLE const uint IO_Combined = 0x0300;
+static QT3_SUPPORT_VARIABLE const uint IO_TypeMask = 0x0300;
+
+static QT3_SUPPORT_VARIABLE const uint IO_Raw = 0x0000;
+static QT3_SUPPORT_VARIABLE const uint IO_Async = 0x0000;
+
+#define IO_ReadOnly QIODevice::ReadOnly
+#define IO_WriteOnly QIODevice::WriteOnly
+#define IO_ReadWrite QIODevice::ReadWrite
+#define IO_Append QIODevice::Append
+#define IO_Truncate QIODevice::Truncate
+#define IO_Translate QIODevice::Text
+#define IO_ModeMask 0x00ff
+
+static QT3_SUPPORT_VARIABLE const uint IO_Open = 0x1000;
+static QT3_SUPPORT_VARIABLE const uint IO_StateMask = 0xf000;
+
+static QT3_SUPPORT_VARIABLE const uint IO_Ok = 0;
+static QT3_SUPPORT_VARIABLE const uint IO_ReadError = 1;
+static QT3_SUPPORT_VARIABLE const uint IO_WriteError = 2;
+static QT3_SUPPORT_VARIABLE const uint IO_FatalError = 3;
+static QT3_SUPPORT_VARIABLE const uint IO_ResourceError = 4;
+static QT3_SUPPORT_VARIABLE const uint IO_OpenError = 5;
+static QT3_SUPPORT_VARIABLE const uint IO_ConnectError = 5;
+static QT3_SUPPORT_VARIABLE const uint IO_AbortError = 6;
+static QT3_SUPPORT_VARIABLE const uint IO_TimeOutError = 7;
+static QT3_SUPPORT_VARIABLE const uint IO_UnspecifiedError = 8;
+
+inline QT3_SUPPORT int QIODevice::state() const
+{
+ return isOpen() ? 0x1000 : 0;
+}
+#endif
+
+#if !defined(QT_NO_DEBUG_STREAM)
+class QDebug;
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, QIODevice::OpenMode modes);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QIODEVICE_H
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
new file mode 100644
index 0000000000..06de7d7781
--- /dev/null
+++ b/src/corelib/io/qiodevice_p.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIODEVICE_P_H
+#define QIODEVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qiodevice.h"
+#include "QtCore/qbytearray.h"
+#include "QtCore/qobjectdefs.h"
+#include "QtCore/qstring.h"
+#include "private/qringbuffer_p.h"
+#ifndef QT_NO_QOBJECT
+#include "private/qobject_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QIODEVICE_BUFFERSIZE
+#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
+#endif
+
+// This is QIODevice's read buffer, optimized for read(), isEmpty() and getChar()
+class QIODevicePrivateLinearBuffer
+{
+public:
+ QIODevicePrivateLinearBuffer(int) : len(0), first(0), buf(0), capacity(0) {
+ }
+ ~QIODevicePrivateLinearBuffer() {
+ delete [] buf;
+ }
+ void clear() {
+ first = buf;
+ len = 0;
+ }
+ int size() const {
+ return len;
+ }
+ bool isEmpty() const {
+ return len == 0;
+ }
+ void skip(int n) {
+ if (n >= len) {
+ clear();
+ } else {
+ len -= n;
+ first += n;
+ }
+ }
+ int getChar() {
+ if (len == 0)
+ return -1;
+ int ch = uchar(*first);
+ len--;
+ first++;
+ return ch;
+ }
+ int read(char* target, int size) {
+ int r = qMin(size, len);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return r;
+ }
+ char* reserve(int size) {
+ makeSpace(size + len, freeSpaceAtEnd);
+ char* writePtr = first + len;
+ len += size;
+ return writePtr;
+ }
+ void chop(int size) {
+ if (size >= len) {
+ clear();
+ } else {
+ len -= size;
+ }
+ }
+ QByteArray readAll() {
+ char* f = first;
+ int l = len;
+ clear();
+ return QByteArray(f, l);
+ }
+ int readLine(char* target, int size) {
+ int r = qMin(size, len);
+ char* eol = static_cast<char*>(memchr(first, '\n', r));
+ if (eol)
+ r = 1+(eol-first);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return int(r);
+ }
+ bool canReadLine() const {
+ return memchr(first, '\n', len);
+ }
+ void ungetChar(char c) {
+ if (first == buf) {
+ // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
+ makeSpace(len+1, freeSpaceAtStart);
+ }
+ first--;
+ len++;
+ *first = c;
+ }
+ void ungetBlock(const char* block, int size) {
+ if ((first - buf) < size) {
+ // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
+ makeSpace(len + size, freeSpaceAtStart);
+ }
+ first -= size;
+ len += size;
+ memcpy(first, block, size);
+ }
+
+private:
+ enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd};
+ void makeSpace(size_t required, FreeSpacePos where) {
+ size_t newCapacity = qMax(capacity, size_t(QIODEVICE_BUFFERSIZE));
+ while (newCapacity < required)
+ newCapacity *= 2;
+ int moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - len;
+ if (newCapacity > capacity) {
+ // allocate more space
+ char* newBuf = new char[newCapacity];
+ memmove(newBuf + moveOffset, first, len);
+ delete [] buf;
+ buf = newBuf;
+ capacity = newCapacity;
+ } else {
+ // shift any existing data to make space
+ memmove(buf + moveOffset, first, len);
+ }
+ first = buf + moveOffset;
+ }
+
+private:
+ // length of the unread data
+ int len;
+ // start of the unread data
+ char* first;
+ // the allocated buffer
+ char* buf;
+ // allocated buffer size
+ size_t capacity;
+};
+
+class Q_CORE_EXPORT QIODevicePrivate
+#ifndef QT_NO_QOBJECT
+ : public QObjectPrivate
+#endif
+{
+ Q_DECLARE_PUBLIC(QIODevice)
+
+public:
+ QIODevicePrivate();
+ virtual ~QIODevicePrivate();
+
+ QIODevice::OpenMode openMode;
+ QString errorString;
+
+ QIODevicePrivateLinearBuffer buffer;
+ qint64 pos;
+ qint64 devicePos;
+ // these three are for fast position updates during read, avoiding isSequential test
+ qint64 seqDumpPos;
+ qint64 *pPos;
+ qint64 *pDevicePos;
+ bool baseReadLineDataCalled;
+ bool firstRead;
+
+ virtual bool putCharHelper(char c);
+
+ enum AccessMode {
+ Unset,
+ Sequential,
+ RandomAccess
+ };
+ mutable AccessMode accessMode;
+ inline bool isSequential() const
+ {
+ if (accessMode == Unset)
+ accessMode = q_func()->isSequential() ? Sequential : RandomAccess;
+ return accessMode == Sequential;
+ }
+
+ virtual qint64 peek(char *data, qint64 maxSize);
+ virtual QByteArray peek(qint64 maxSize);
+
+#ifdef QT_NO_QOBJECT
+ QIODevice *q_ptr;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QIODEVICE_P_H
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
new file mode 100644
index 0000000000..71cf92db24
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -0,0 +1,545 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnoncontiguousbytedevice_p.h"
+#include <qbuffer.h>
+#include <qdebug.h>
+#include <qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNonContiguousByteDevice
+ \brief A QNonContiguousByteDevice is a representation of a
+ file, array or buffer that allows access with a read pointer.
+ \since 4.6
+
+ \inmodule QtCore
+
+ The goal of this class is to have a data representation that
+ allows us to avoid doing a memcpy as we have to do with QIODevice.
+
+ \sa QNonContiguousByteDeviceFactory
+
+ \internal
+*/
+/*!
+ \fn virtual const char* QNonContiguousByteDevice::readPointer(qint64 maximumLength, qint64 &len)
+
+ Return a byte pointer for at most \a maximumLength bytes of that device.
+ if \a maximumLength is -1, the caller does not care about the length and
+ the device may return what it desires to.
+ The actual number of bytes the pointer is valid for is returned in
+ the \a len variable.
+ \a len will be -1 if EOF or an error occurs.
+ If it was really EOF can then afterwards be checked with atEnd()
+ Returns 0 if it is not possible to read at that position.
+
+ \sa atEnd()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::advanceReadPointer(qint64 amount)
+
+ will advance the internal read pointer by \a amount bytes.
+ The old readPointer is invalid after this call.
+
+ \sa readPointer()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::atEnd()
+
+ Returns true if everything has been read and the read
+ pointer cannot be advanced anymore.
+
+ \sa readPointer(), advanceReadPointer(), reset()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::reset()
+
+ Moves the internal read pointer back to the beginning.
+ Returns false if this was not possible.
+
+ \sa atEnd(), disableReset()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::disableReset()
+
+ Disable the reset() call, e.g. it will always
+ do nothing and return false.
+
+ \sa reset()
+
+ \internal
+*/
+/*!
+ \fn virtual qint64 QNonContiguousByteDevice::size()
+
+ Returns the size of the complete device or -1 if unknown.
+ May also return less/more than what can be actually read with readPointer()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readyRead()
+
+ Emitted when there is data available
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readProgress(qint64 current, qint64 total)
+
+ Emitted when data has been "read" by advancing the read pointer
+
+ \internal
+*/
+
+QNonContiguousByteDevice::QNonContiguousByteDevice() : QObject((QObject*)0), resetDisabled(false)
+{
+}
+
+QNonContiguousByteDevice::~QNonContiguousByteDevice()
+{
+}
+
+void QNonContiguousByteDevice::disableReset()
+{
+ resetDisabled = true;
+}
+
+// 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()
+{
+ 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)));
+}
+
+QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ return arrayImpl->readPointer(maximumLength, len);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::advanceReadPointer(qint64 amount)
+{
+ return arrayImpl->advanceReadPointer(amount);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::atEnd()
+{
+ return arrayImpl->atEnd();
+}
+
+bool QNonContiguousByteDeviceBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+ return arrayImpl->reset();
+}
+
+qint64 QNonContiguousByteDeviceBufferImpl::size()
+{
+ return arrayImpl->size();
+}
+
+QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0)
+{
+ byteArray = ba;
+}
+
+QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceByteArrayImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ if (maximumLength != -1)
+ len = qMin(maximumLength, size() - currentPosition);
+ else
+ len = size() - currentPosition;
+
+ return byteArray->constData() + currentPosition;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::atEnd()
+{
+ return currentPosition >= size();
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+}
+
+qint64 QNonContiguousByteDeviceByteArrayImpl::size()
+{
+ return byteArray->size();
+}
+
+QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
+ : QNonContiguousByteDevice(), currentPosition(0)
+{
+ ringBuffer = rb;
+}
+
+QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceRingBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ const char *returnValue = ringBuffer->readPointerAtPosition(currentPosition, len);
+
+ if (maximumLength != -1)
+ len = qMin(len, maximumLength);
+
+ return returnValue;
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
+{
+ return currentPosition >= size();
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+}
+
+qint64 QNonContiguousByteDeviceRingBufferImpl::size()
+{
+ return ringBuffer->size();
+}
+
+QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d)
+ : QNonContiguousByteDevice(),
+ currentReadBuffer(0), currentReadBufferSize(16*1024),
+ currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0),
+ eof(false)
+{
+ device = d;
+ initialPosition = d->pos();
+ connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+ connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+}
+
+QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl()
+{
+ delete currentReadBuffer;
+}
+
+const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (eof == true) {
+ len = -1;
+ return 0;
+ }
+
+ if (currentReadBuffer == 0)
+ currentReadBuffer = new QByteArray(currentReadBufferSize, '\0'); // lazy alloc
+
+ if (maximumLength == -1)
+ maximumLength = currentReadBufferSize;
+
+ if (currentReadBufferAmount - currentReadBufferPosition > 0) {
+ len = currentReadBufferAmount - currentReadBufferPosition;
+ return currentReadBuffer->data() + currentReadBufferPosition;
+ }
+
+ qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize));
+
+ if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) {
+ eof = true;
+ len = -1;
+ // size was unknown before, emit a readProgress with the final size
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ return 0;
+ }
+
+ currentReadBufferAmount = haveRead;
+ currentReadBufferPosition = 0;
+
+ len = haveRead;
+ return currentReadBuffer->data();
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount)
+{
+ totalAdvancements += amount;
+
+ // normal advancement
+ currentReadBufferPosition += amount;
+
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ else
+ emit readProgress(totalAdvancements, size());
+
+ // advancing over that what has actually been read before
+ if (currentReadBufferPosition > currentReadBufferAmount) {
+ qint64 i = currentReadBufferPosition - currentReadBufferAmount;
+ while (i > 0) {
+ if (device->getChar(0) == false) {
+ emit readProgress(totalAdvancements - i, size());
+ return false; // ### FIXME handle eof
+ }
+ i--;
+ }
+
+ currentReadBufferPosition = 0;
+ currentReadBufferAmount = 0;
+ }
+
+
+ return true;
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::atEnd()
+{
+ return eof == true;
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ if (device->seek(initialPosition)) {
+ eof = false; // assume eof is false, it will be true after a read has been attempted
+ return true;
+ }
+
+ return false;
+}
+
+qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
+{
+ // note that this is different from the size() implementation of QIODevice!
+
+ if (device->isSequential())
+ return -1;
+
+ return device->size() - initialPosition;
+}
+
+QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
+{
+ byteDevice = bd;
+ connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead()));
+
+ open(ReadOnly);
+}
+
+QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice()
+{
+
+}
+
+bool QByteDeviceWrappingIoDevice::isSequential() const
+{
+ return (byteDevice->size() == -1);
+}
+
+bool QByteDeviceWrappingIoDevice::atEnd() const
+{
+ return byteDevice->atEnd();
+}
+
+bool QByteDeviceWrappingIoDevice::reset()
+{
+ return byteDevice->reset();
+}
+
+qint64 QByteDeviceWrappingIoDevice::size() const
+{
+ if (isSequential())
+ return 0;
+
+ return byteDevice->size();
+}
+
+
+qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize)
+{
+ qint64 len;
+ const char *readPointer = byteDevice->readPointer(maxSize, len);
+ if (len == -1)
+ return -1;
+
+ memcpy(data, readPointer, len);
+ byteDevice->advanceReadPointer(len);
+ return len;
+}
+
+qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxSize);
+ return -1;
+}
+
+/*!
+ \class QNonContiguousByteDeviceFactory
+ \since 4.6
+
+ \inmodule QtCore
+
+ Creates a QNonContiguousByteDevice out of a QIODevice,
+ QByteArray etc.
+
+ \sa QNonContiguousByteDevice
+
+ \internal
+*/
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device);
+
+ Create a QNonContiguousByteDevice out of a QIODevice.
+ For QFile, QBuffer and all other QIoDevice, sequential or not.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) {
+ return new 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 new QNonContiguousByteDeviceIoDeviceImpl(device); // FIXME
+}
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer);
+
+ Create a QNonContiguousByteDevice out of a QRingBuffer.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
+{
+ return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer);
+}
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray);
+
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
+{
+ return new QNonContiguousByteDeviceByteArrayImpl(byteArray);
+}
+
+/*!
+ \fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice);
+
+ Wrap the \a byteDevice (possibly again) into a QIODevice.
+
+ \internal
+*/
+QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
+{
+ // ### FIXME if it already has been based on QIoDevice, we could that one out again
+ // and save some calling
+
+ // needed for FTP backend
+
+ return new QByteDeviceWrappingIoDevice(byteDevice);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
new file mode 100644
index 0000000000..5e0b1bbb8f
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNONCONTIGUOUSBYTEDEVICE_H
+#define QNONCONTIGUOUSBYTEDEVICE_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/qobject.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qbuffer.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/QSharedPointer>
+#include "private/qringbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject
+{
+ Q_OBJECT
+public:
+ virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
+ virtual bool advanceReadPointer(qint64 amount) = 0;
+ virtual bool atEnd() = 0;
+ virtual bool reset() = 0;
+ void disableReset();
+ bool isResetDisabled() { return resetDisabled; }
+ virtual qint64 size() = 0;
+
+ virtual ~QNonContiguousByteDevice();
+
+protected:
+ QNonContiguousByteDevice();
+
+
+ bool resetDisabled;
+Q_SIGNALS:
+ void readyRead();
+ void readProgress(qint64 current, qint64 total);
+};
+
+class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
+{
+public:
+ static QNonContiguousByteDevice* create(QIODevice *device);
+ static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QNonContiguousByteDevice* create(QSharedPointer<QRingBuffer> ringBuffer);
+ static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
+};
+
+// the actual implementations
+//
+
+class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba);
+ ~QNonContiguousByteDeviceByteArrayImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QByteArray* byteArray;
+ qint64 currentPosition;
+};
+
+class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb);
+ ~QNonContiguousByteDeviceRingBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QSharedPointer<QRingBuffer> ringBuffer;
+ qint64 currentPosition;
+};
+
+
+class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d);
+ ~QNonContiguousByteDeviceIoDeviceImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QIODevice* device;
+ QByteArray* currentReadBuffer;
+ qint64 currentReadBufferSize;
+ qint64 currentReadBufferAmount;
+ qint64 currentReadBufferPosition;
+ qint64 totalAdvancements;
+ bool eof;
+ qint64 initialPosition;
+};
+
+class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceBufferImpl(QBuffer *b);
+ ~QNonContiguousByteDeviceBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QBuffer* buffer;
+ QByteArray byteArray;
+ QNonContiguousByteDeviceByteArrayImpl* arrayImpl;
+};
+
+// ... and the reverse thing
+class QByteDeviceWrappingIoDevice : public QIODevice
+{
+public:
+ QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd);
+ ~QByteDeviceWrappingIoDevice ();
+ virtual bool isSequential () const;
+ virtual bool atEnd () const;
+ virtual bool reset ();
+ virtual qint64 size () const;
+protected:
+ virtual qint64 readData ( char * data, qint64 maxSize );
+ virtual qint64 writeData ( const char * data, qint64 maxSize );
+
+ QNonContiguousByteDevice *byteDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
new file mode 100644
index 0000000000..a45225f3f7
--- /dev/null
+++ b/src/corelib/io/qprocess.cpp
@@ -0,0 +1,2371 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QPROCESS_DEBUG
+
+#if defined QPROCESS_DEBUG
+#include <qdebug.h>
+#include <qstring.h>
+#include <ctype.h>
+#if !defined(Q_OS_WINCE)
+#include <errno.h>
+#endif
+
+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 <qcoreapplication.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+
+#ifdef Q_WS_WIN
+#include <private/qwineventnotifier_p.h>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#include <e32std.h>
+#endif
+
+#ifndef QT_NO_PROCESS
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QProcessEnvironment
+
+ \brief The QProcessEnvironment class holds the environment variables that
+ can be passed to a program.
+
+ \ingroup io
+ \ingroup misc
+ \mainclass
+ \reentrant
+ \since 4.6
+
+ 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
+ along with QProcess, to set the environment for child processes. It
+ cannot be used to change the current process's environment.
+
+ The environment of the calling process can be obtained using
+ QProcessEnvironment::systemEnvironment().
+
+ On Unix systems, the variable names are case-sensitive. For that reason,
+ this class will not touch the names of the variables. Note as well that
+ Unix environment allows both variable names and contents to contain arbitrary
+ binary data (except for the NUL character), but this is not supported by
+ QProcessEnvironment. This class only supports names and values that are
+ encodable by the current locale settings (see QTextCodec::codecForLocale).
+
+ On Windows, the variable names are case-insensitive. Therefore,
+ QProcessEnvironment will always uppercase the names and do case-insensitive
+ comparisons.
+
+ On Windows CE, the concept of environment does not exist. This class will
+ keep the values set for compatibility with other platforms, but the values
+ set will have no effect on the processes being created.
+
+ \sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment()
+*/
+#ifdef Q_OS_WIN
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
+{ return name.toUpper(); }
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
+{ return QString::fromLocal8Bit(name).toUpper(); }
+static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
+{ return name; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
+{ return value; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
+{ return QString::fromLocal8Bit(value); }
+static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
+{ return value; }
+static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
+{ return value.toLocal8Bit(); }
+#else
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
+{ return name; }
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
+{ return name.toLocal8Bit(); }
+static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
+{ return QString::fromLocal8Bit(name); }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
+{ return value; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
+{ return value.toLocal8Bit(); }
+static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
+{ return QString::fromLocal8Bit(value); }
+static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
+{ return value; }
+#endif
+
+template<> void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
+{
+ if (d && d->ref == 1)
+ return;
+ QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
+ : new QProcessEnvironmentPrivate);
+ x->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = x;
+}
+
+QStringList QProcessEnvironmentPrivate::toList() const
+{
+ QStringList result;
+ QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
+ for ( ; it != end; ++it) {
+ QString data = nameToString(it.key());
+ QString value = valueToString(it.value());
+ data.reserve(data.length() + value.length() + 1);
+ data.append(QLatin1Char('='));
+ data.append(value);
+ result << data;
+ }
+ return result;
+}
+
+QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list)
+{
+ QProcessEnvironment env;
+ QStringList::ConstIterator it = list.constBegin(),
+ end = list.constEnd();
+ for ( ; it != end; ++it) {
+ int pos = it->indexOf(QLatin1Char('='));
+ if (pos < 1)
+ continue;
+
+ QString value = it->mid(pos + 1);
+ QString name = *it;
+ name.truncate(pos);
+ env.insert(name, value);
+ }
+ return env;
+}
+
+QStringList QProcessEnvironmentPrivate::keys() const
+{
+ QStringList result;
+ QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
+ for ( ; it != end; ++it)
+ result << nameToString(it.key());
+ return result;
+}
+
+void QProcessEnvironmentPrivate::insert(const Hash &h)
+{
+ QHash<Unit, Unit>::ConstIterator it = h.constBegin(),
+ end = h.constEnd();
+ for ( ; it != end; ++it)
+ hash.insert(it.key(), it.value());
+}
+
+/*!
+ 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.
+*/
+QProcessEnvironment::QProcessEnvironment()
+ : d(0)
+{
+}
+
+/*!
+ Frees the resources associated with this QProcessEnvironment object.
+*/
+QProcessEnvironment::~QProcessEnvironment()
+{
+}
+
+/*!
+ Creates a QProcessEnvironment object that is a copy of \a other.
+*/
+QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Copies the contents of the \a other QProcessEnvironment object into this
+ one.
+*/
+QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const
+
+ Returns true if this and the \a other QProcessEnvironment objects are different.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns true if this and the \a other QProcessEnvironment objects 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
+ platforms where the environment is case-sensitive.
+
+ \sa operator!=(), contains()
+*/
+bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const
+{
+ return d == other.d || (d && other.d && d->hash == other.d->hash);
+}
+
+/*!
+ Returns true if this QProcessEnvironment object is empty: that is
+ there are no key=value pairs set.
+
+ \sa clear(), systemEnvironment(), insert()
+*/
+bool QProcessEnvironment::isEmpty() const
+{
+ return d ? d->hash.isEmpty() : true;
+}
+
+/*!
+ Removes all key=value pairs from this QProcessEnvironment object, making
+ it empty.
+
+ \sa isEmpty(), systemEnvironment()
+*/
+void QProcessEnvironment::clear()
+{
+ if (d)
+ d->hash.clear();
+}
+
+/*!
+ Returns true if the environment variable of name \a name is found in
+ this QProcessEnvironment object.
+
+ On Windows, variable names are case-insensitive, so the key is converted
+ to uppercase before searching. On other systems, names are case-sensitive
+ so no trasformation is applied.
+
+ \sa insert(), value()
+*/
+bool QProcessEnvironment::contains(const QString &name) const
+{
+ return d ? d->hash.contains(prepareName(name)) : false;
+}
+
+/*!
+ Inserts the environment variable of name \a name and contents \a value
+ into this QProcessEnvironment object. If that variable already existed,
+ it is replaced by the new value.
+
+ On Windows, variable names are case-insensitive, so this function always
+ uppercases the variable name before inserting. On other systems, names
+ are case-sensitive, so no transformation is applied.
+
+ On most systems, inserting a variable with no contents will have the
+ same effect for applications as if the variable had not been set at all.
+ However, to guarantee that there are no incompatibilities, to remove a
+ variable, please use the remove() function.
+
+ \sa contains(), remove(), value()
+*/
+void QProcessEnvironment::insert(const QString &name, const QString &value)
+{
+ // d detaches from null
+ d->hash.insert(prepareName(name), prepareValue(value));
+}
+
+/*!
+ Removes the environment variable identified by \a name from this
+ QProcessEnvironment object. If that variable did not exist before,
+ nothing happens.
+
+ On Windows, variable names are case-insensitive, so the key is converted
+ to uppercase before searching. On other systems, names are case-sensitive
+ so no trasformation is applied.
+
+ \sa contains(), insert(), value()
+*/
+void QProcessEnvironment::remove(const QString &name)
+{
+ if (d)
+ d->hash.remove(prepareName(name));
+}
+
+/*!
+ Searches this QProcessEnvironment object for a variable identified by
+ \a name and returns its value. If the variable is not found in this object,
+ then \a defaultValue is returned instead.
+
+ On Windows, variable names are case-insensitive, so the key is converted
+ to uppercase before searching. On other systems, names are case-sensitive
+ so no trasformation is applied.
+
+ \sa contains(), insert(), remove()
+*/
+QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const
+{
+ if (!d)
+ return defaultValue;
+
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name));
+ if (it == d->hash.constEnd())
+ return defaultValue;
+
+ return valueToString(it.value());
+}
+
+/*!
+ Converts this QProcessEnvironment object into a list of strings, one for
+ each environment variable that is set. The environment variable's name
+ and its value are separated by an equal character ('=').
+
+ The QStringList contents returned by this function are suitable for use
+ with the QProcess::setEnvironment function. However, it is recommended
+ to use QProcess::setProcessEnvironment instead since that will avoid
+ unnecessary copying of the data.
+
+ \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(),
+ QProcess::setEnvironment()
+*/
+QStringList QProcessEnvironment::toStringList() const
+{
+ return d ? d->toList() : QStringList();
+}
+
+/*!
+ \since 4.8
+
+ Returns a list containing all the variable names in this QProcessEnvironment
+ object.
+*/
+QStringList QProcessEnvironment::keys() const
+{
+ return d ? d->keys() : QStringList();
+}
+
+/*!
+ \overload
+ \since 4.8
+
+ Inserts the contents of \a e in this QProcessEnvironment object. Variables in
+ this object that also exist in \a e will be overwritten.
+*/
+void QProcessEnvironment::insert(const QProcessEnvironment &e)
+{
+ if (!e.d)
+ return;
+
+ // d detaches from null
+ d->insert(e.d->hash);
+}
+
+void QProcessPrivate::Channel::clear()
+{
+ switch (type) {
+ case PipeSource:
+ Q_ASSERT(process);
+ process->stdinChannel.type = Normal;
+ process->stdinChannel.process = 0;
+ break;
+ case PipeSink:
+ Q_ASSERT(process);
+ process->stdoutChannel.type = Normal;
+ process->stdoutChannel.process = 0;
+ break;
+ }
+
+ type = Normal;
+ file.clear();
+ process = 0;
+}
+
+/*! \fn bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
+
+\internal
+ */
+
+/*!
+ \class QProcess
+
+ \brief The QProcess class is used to start external programs and
+ to communicate with them.
+
+ \ingroup io
+
+ \reentrant
+
+ \section1 Running a Process
+
+ To start a process, pass the name and command line arguments of
+ the program you want to run as arguments to start(). Arguments
+ are supplied as individual strings in a QStringList.
+
+ For example, the following code snippet runs the analog clock
+ example in the Motif style on X11 platforms by passing strings
+ containing "-style" and "motif" as two items in the list of
+ arguments:
+
+ \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 0
+ \dots
+ \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 1
+ \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 2
+
+ QProcess then enters the \l Starting state, and when the program
+ has started, QProcess enters the \l Running state and emits
+ started().
+
+ QProcess allows you to treat a process as a sequential I/O
+ device. You can write to and read from the process just as you
+ would access a network connection using QTcpSocket. You can then
+ write to the process's standard input by calling write(), and
+ read the standard output by calling read(), readLine(), and
+ getChar(). Because it inherits QIODevice, QProcess can also be
+ used as an input source for QXmlReader, or for generating data to
+ be uploaded using QFtp.
+
+ \note On Windows CE and Symbian, reading and writing to a process
+ is not supported.
+
+ When the process exits, QProcess reenters the \l NotRunning state
+ (the initial state), and emits finished().
+
+ The finished() signal provides the exit code and exit status of
+ the process as arguments, and you can also call exitCode() to
+ obtain the exit code of the last process that finished, and
+ exitStatus() to obtain its exit status. If an error occurs at
+ any point in time, QProcess will emit the error() signal. You
+ can also call error() to find the type of error that occurred
+ last, and state() to find the current process state.
+
+ \section1 Communicating via Channels
+
+ Processes have two predefined output channels: The standard
+ output channel (\c stdout) supplies regular console output, and
+ the standard error channel (\c stderr) usually supplies the
+ errors that are printed by the process. These channels represent
+ two separate streams of data. You can toggle between them by
+ calling setReadChannel(). QProcess emits readyRead() when data is
+ available on the current read channel. It also emits
+ readyReadStandardOutput() when new standard output data is
+ available, and when new standard error data is available,
+ readyReadStandardError() is emitted. Instead of calling read(),
+ readLine(), or getChar(), you can explicitly read all data from
+ either of the two channels by calling readAllStandardOutput() or
+ readAllStandardError().
+
+ The terminology for the channels can be misleading. Be aware that
+ the process's output channels correspond to QProcess's
+ \e read channels, whereas the process's input channels correspond
+ to QProcess's \e write channels. This is because what we read
+ using QProcess is the process's output, and what we write becomes
+ the process's input.
+
+ QProcess can merge the two output channels, so that standard
+ output and standard error data from the running process both use
+ the standard output channel. Call setProcessChannelMode() with
+ MergedChannels before starting the process to activative
+ this feature. You also have the option of forwarding the output of
+ the running process to the calling, main process, by passing
+ ForwardedChannels as the argument.
+
+ Certain processes need special environment settings in order to
+ operate. You can set environment variables for your process by
+ calling setEnvironment(). To set a working directory, call
+ setWorkingDirectory(). By default, processes are run in the
+ current working directory of the calling process.
+
+ \note On Symbian, setting environment or working directory
+ is not supported. The working directory will always be the private
+ directory of the running process.
+
+ \section1 Synchronous Process API
+
+ QProcess provides a set of functions which allow it to be used
+ without an event loop, by suspending the calling thread until
+ certain signals are emitted:
+
+ \list
+ \o waitForStarted() blocks until the process has started.
+
+ \o waitForReadyRead() blocks until new data is
+ available for reading on the current read channel.
+
+ \o waitForBytesWritten() blocks until one payload of
+ data has been written to the process.
+
+ \o waitForFinished() blocks until the process has finished.
+ \endlist
+
+ Calling these functions from the main thread (the thread that
+ calls QApplication::exec()) may cause your user interface to
+ freeze.
+
+ The following example runs \c gzip to compress the string "Qt
+ rocks!", without an event loop:
+
+ \snippet doc/src/snippets/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.
+
+ \section1 Symbian Platform Security Requirements
+
+ On Symbian, processes which use the functions kill() or terminate()
+ must have the \c PowerMgmt platform security capability. If the client
+ process lacks this capability, these functions will fail.
+
+ Platform security capabilities are added via the
+ \l{qmake-variable-reference.html#target-capability}{TARGET.CAPABILITY}
+ qmake variable.
+
+ \sa QBuffer, QFile, QTcpSocket
+*/
+
+/*!
+ \enum QProcess::ProcessChannel
+
+ This enum describes the process channels used by the running process.
+ Pass one of these values to setReadChannel() to set the
+ current read channel of QProcess.
+
+ \value StandardOutput The standard output (stdout) of the running
+ process.
+
+ \value StandardError The standard error (stderr) of the running
+ process.
+
+ \sa setReadChannel()
+*/
+
+/*!
+ \enum QProcess::ProcessChannelMode
+
+ This enum describes the process channel modes of QProcess. Pass
+ one of these values to setProcessChannelMode() to set the
+ current read channel mode.
+
+ \value SeparateChannels QProcess manages the output of the
+ running process, keeping standard output and standard error data
+ in separate internal buffers. You can select the QProcess's
+ current read channel by calling setReadChannel(). This is the
+ default channel mode of QProcess.
+
+ \value MergedChannels QProcess merges the output of the running
+ 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.
+
+ \value ForwardedChannels QProcess forwards the output of the
+ running process onto the main process. Anything the child process
+ writes to its standard output and standard error will be written
+ to the standard output and standard error of the main process.
+
+ \sa setProcessChannelMode()
+*/
+
+/*!
+ \enum QProcess::ProcessError
+
+ This enum describes the different types of errors that are
+ reported by QProcess.
+
+ \value FailedToStart The process failed to start. Either the
+ invoked program is missing, or you may have insufficient
+ permissions to invoke the program.
+
+ \value Crashed The process crashed some time after starting
+ successfully.
+
+ \value Timedout The last waitFor...() function timed out. The
+ state of QProcess is unchanged, and you can try calling
+ waitFor...() again.
+
+ \value WriteError An error occurred when attempting to write to the
+ process. For example, the process may not be running, or it may
+ have closed its input channel.
+
+ \value ReadError An error occurred when attempting to read from
+ the process. For example, the process may not be running.
+
+ \value UnknownError An unknown error occurred. This is the default
+ return value of error().
+
+ \sa error()
+*/
+
+/*!
+ \enum QProcess::ProcessState
+
+ This enum describes the different states of QProcess.
+
+ \value NotRunning The process is not running.
+
+ \value Starting The process is starting, but the program has not
+ yet been invoked.
+
+ \value Running The process is running and is ready for reading and
+ writing.
+
+ \sa state()
+*/
+
+/*!
+ \enum QProcess::ExitStatus
+
+ This enum describes the different exit statuses of QProcess.
+
+ \value NormalExit The process exited normally.
+
+ \value CrashExit The process crashed.
+
+ \sa exitStatus()
+*/
+
+/*!
+ \fn void QProcess::error(QProcess::ProcessError error)
+
+ This signal is emitted when an error occurs with the process. The
+ specified \a error describes the type of error that occurred.
+*/
+
+/*!
+ \fn void QProcess::started()
+
+ This signal is emitted by QProcess when the process has started,
+ and state() returns \l Running.
+*/
+
+/*!
+ \fn void QProcess::stateChanged(QProcess::ProcessState newState)
+
+ This signal is emitted whenever the state of QProcess changes. The
+ \a newState argument is the state QProcess changed to.
+*/
+
+/*!
+ \fn void QProcess::finished(int exitCode)
+ \obsolete
+ \overload
+
+ Use finished(int exitCode, QProcess::ExitStatus status) instead.
+*/
+
+/*!
+ \fn void QProcess::finished(int exitCode, QProcess::ExitStatus exitStatus)
+
+ This signal is emitted when the process finishes. \a exitCode is the exit
+ code of the process, and \a exitStatus is the exit status. After the
+ process has finished, the buffers in QProcess are still intact. You can
+ still read any data that the process may have written before it finished.
+
+ \sa exitStatus()
+*/
+
+/*!
+ \fn void QProcess::readyReadStandardOutput()
+
+ This signal is emitted when the process has made new data
+ available through its standard output channel (\c stdout). It is
+ emitted regardless of the current \l{readChannel()}{read channel}.
+
+ \sa readAllStandardOutput(), readChannel()
+*/
+
+/*!
+ \fn void QProcess::readyReadStandardError()
+
+ This signal is emitted when the process has made new data
+ available through its standard error channel (\c stderr). It is
+ emitted regardless of the current \l{readChannel()}{read
+ channel}.
+
+ \sa readAllStandardError(), readChannel()
+*/
+
+/*! \internal
+*/
+QProcessPrivate::QProcessPrivate()
+{
+ processChannel = QProcess::StandardOutput;
+ processChannelMode = QProcess::SeparateChannels;
+ processError = QProcess::UnknownError;
+ processState = QProcess::NotRunning;
+ pid = 0;
+ sequenceNumber = 0;
+ exitCode = 0;
+ exitStatus = QProcess::NormalExit;
+ startupSocketNotifier = 0;
+ deathNotifier = 0;
+ notifier = 0;
+ pipeWriter = 0;
+ childStartedPipe[0] = INVALID_Q_PIPE;
+ childStartedPipe[1] = INVALID_Q_PIPE;
+ deathPipe[0] = INVALID_Q_PIPE;
+ deathPipe[1] = INVALID_Q_PIPE;
+ exitCode = 0;
+ crashed = false;
+ dying = false;
+ emittedReadyRead = false;
+ emittedBytesWritten = false;
+#ifdef Q_WS_WIN
+ pipeWriter = 0;
+ processFinishedNotifier = 0;
+#endif // Q_WS_WIN
+#ifdef Q_OS_UNIX
+ serial = 0;
+#endif
+#ifdef Q_OS_SYMBIAN
+ symbianProcess = NULL;
+ processLaunched = false;
+#endif
+}
+
+/*! \internal
+*/
+QProcessPrivate::~QProcessPrivate()
+{
+ if (stdinChannel.process)
+ stdinChannel.process->stdoutChannel.clear();
+ if (stdoutChannel.process)
+ stdoutChannel.process->stdinChannel.clear();
+}
+
+/*! \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 (processFinishedNotifier) {
+ processFinishedNotifier->setEnabled(false);
+ qDeleteInEventHandler(processFinishedNotifier);
+ processFinishedNotifier = 0;
+ }
+
+#endif
+ pid = 0;
+ sequenceNumber = 0;
+ dying = false;
+
+ if (stdoutChannel.notifier) {
+ stdoutChannel.notifier->setEnabled(false);
+ qDeleteInEventHandler(stdoutChannel.notifier);
+ stdoutChannel.notifier = 0;
+ }
+ if (stderrChannel.notifier) {
+ stderrChannel.notifier->setEnabled(false);
+ qDeleteInEventHandler(stderrChannel.notifier);
+ stderrChannel.notifier = 0;
+ }
+ if (stdinChannel.notifier) {
+ stdinChannel.notifier->setEnabled(false);
+ qDeleteInEventHandler(stdinChannel.notifier);
+ stdinChannel.notifier = 0;
+ }
+ if (startupSocketNotifier) {
+ startupSocketNotifier->setEnabled(false);
+ qDeleteInEventHandler(startupSocketNotifier);
+ startupSocketNotifier = 0;
+ }
+ if (deathNotifier) {
+ deathNotifier->setEnabled(false);
+ qDeleteInEventHandler(deathNotifier);
+ deathNotifier = 0;
+ }
+ if (notifier) {
+ qDeleteInEventHandler(notifier);
+ notifier = 0;
+ }
+ destroyPipe(stdoutChannel.pipe);
+ destroyPipe(stderrChannel.pipe);
+ destroyPipe(stdinChannel.pipe);
+ destroyPipe(childStartedPipe);
+ destroyPipe(deathPipe);
+#ifdef Q_OS_UNIX
+ serial = 0;
+#endif
+#ifdef Q_OS_SYMBIAN
+ if (symbianProcess) {
+ symbianProcess->Close();
+ delete symbianProcess;
+ symbianProcess = NULL;
+ }
+#endif
+}
+
+/*! \internal
+*/
+bool QProcessPrivate::_q_canReadStandardOutput()
+{
+ Q_Q(QProcess);
+ qint64 available = bytesAvailableFromStdout();
+ if (available == 0) {
+ if (stdoutChannel.notifier)
+ stdoutChannel.notifier->setEnabled(false);
+ destroyPipe(stdoutChannel.pipe);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available");
+#endif
+ return false;
+ }
+
+ char *ptr = outputReadBuffer.reserve(available);
+ qint64 readBytes = readFromStdout(ptr, available);
+ if (readBytes == -1) {
+ processError = QProcess::ReadError;
+ q->setErrorString(QProcess::tr("Error reading from process"));
+ emit q->error(processError);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process");
+#endif
+ return false;
+ }
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
+ int(readBytes));
+#endif
+
+ if (stdoutChannel.closed) {
+ outputReadBuffer.chop(readBytes);
+ return false;
+ }
+
+ outputReadBuffer.chop(available - readBytes);
+
+ bool didRead = false;
+ if (readBytes == 0) {
+ if (stdoutChannel.notifier)
+ stdoutChannel.notifier->setEnabled(false);
+ } else if (processChannel == QProcess::StandardOutput) {
+ didRead = true;
+ if (!emittedReadyRead) {
+ emittedReadyRead = true;
+ emit q->readyRead();
+ emittedReadyRead = false;
+ }
+ }
+ emit q->readyReadStandardOutput();
+ return didRead;
+}
+
+/*! \internal
+*/
+bool QProcessPrivate::_q_canReadStandardError()
+{
+ Q_Q(QProcess);
+ qint64 available = bytesAvailableFromStderr();
+ if (available == 0) {
+ if (stderrChannel.notifier)
+ stderrChannel.notifier->setEnabled(false);
+ destroyPipe(stderrChannel.pipe);
+ return false;
+ }
+
+ char *ptr = errorReadBuffer.reserve(available);
+ qint64 readBytes = readFromStderr(ptr, available);
+ if (readBytes == -1) {
+ processError = QProcess::ReadError;
+ q->setErrorString(QProcess::tr("Error reading from process"));
+ emit q->error(processError);
+ return false;
+ }
+ if (stderrChannel.closed) {
+ errorReadBuffer.chop(readBytes);
+ return false;
+ }
+
+ errorReadBuffer.chop(available - readBytes);
+
+ bool didRead = false;
+ if (readBytes == 0) {
+ if (stderrChannel.notifier)
+ stderrChannel.notifier->setEnabled(false);
+ } else if (processChannel == QProcess::StandardError) {
+ didRead = true;
+ if (!emittedReadyRead) {
+ emittedReadyRead = true;
+ emit q->readyRead();
+ emittedReadyRead = false;
+ }
+ }
+ emit q->readyReadStandardError();
+ return didRead;
+}
+
+/*! \internal
+*/
+bool QProcessPrivate::_q_canWrite()
+{
+ Q_Q(QProcess);
+ if (stdinChannel.notifier)
+ stdinChannel.notifier->setEnabled(false);
+
+ if (writeBuffer.isEmpty()) {
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
+#endif
+ return false;
+ }
+
+ qint64 written = writeToStdin(writeBuffer.readPointer(),
+ writeBuffer.nextDataBlockSize());
+ if (written < 0) {
+ destroyPipe(stdinChannel.pipe);
+ processError = QProcess::WriteError;
+ q->setErrorString(QProcess::tr("Error writing to process"));
+ emit q->error(processError);
+ return false;
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written));
+#endif
+
+ if (written != 0) {
+ writeBuffer.free(written);
+ if (!emittedBytesWritten) {
+ emittedBytesWritten = true;
+ emit q->bytesWritten(written);
+ emittedBytesWritten = false;
+ }
+ }
+ if (stdinChannel.notifier && !writeBuffer.isEmpty())
+ stdinChannel.notifier->setEnabled(true);
+ if (writeBuffer.isEmpty() && stdinChannel.closed)
+ closeWriteChannel();
+ return true;
+}
+
+/*! \internal
+*/
+bool QProcessPrivate::_q_processDied()
+{
+ Q_Q(QProcess);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::_q_processDied()");
+#endif
+#ifdef Q_OS_UNIX
+ if (!waitForDeadChild())
+ return false;
+#endif
+#ifdef Q_OS_WIN
+ if (processFinishedNotifier)
+ processFinishedNotifier->setEnabled(false);
+#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 error(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();
+
+ if (crashed) {
+ exitStatus = QProcess::CrashExit;
+ processError = QProcess::Crashed;
+ q->setErrorString(QProcess::tr("Process crashed"));
+ emit q->error(processError);
+ }
+
+ bool wasRunning = (processState == QProcess::Running);
+
+ cleanup();
+
+ if (wasRunning) {
+ // we received EOF now:
+ emit q->readChannelFinished();
+ // in the future:
+ //emit q->standardOutputClosed();
+ //emit q->standardErrorClosed();
+
+ emit q->finished(exitCode);
+ emit q->finished(exitCode, exitStatus);
+ }
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::_q_processDied() process is dead");
+#endif
+ return true;
+}
+
+/*! \internal
+*/
+bool QProcessPrivate::_q_startupNotification()
+{
+ Q_Q(QProcess);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::startupNotification()");
+#endif
+
+ if (startupSocketNotifier)
+ startupSocketNotifier->setEnabled(false);
+ if (processStarted()) {
+ q->setProcessState(QProcess::Running);
+ emit q->started();
+ return true;
+ }
+
+ q->setProcessState(QProcess::NotRunning);
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+#ifdef Q_OS_UNIX
+ // make sure the process manager removes this entry
+ waitForDeadChild();
+ findExitCode();
+#endif
+ cleanup();
+ return false;
+}
+
+/*! \internal
+*/
+void QProcessPrivate::closeWriteChannel()
+{
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::closeWriteChannel()");
+#endif
+ if (stdinChannel.notifier) {
+ extern void qDeleteInEventHandler(QObject *o);
+ stdinChannel.notifier->setEnabled(false);
+ if (stdinChannel.notifier) {
+ qDeleteInEventHandler(stdinChannel.notifier);
+ stdinChannel.notifier = 0;
+ }
+ }
+#ifdef Q_OS_WIN
+ // ### Find a better fix, feeding the process little by little
+ // instead.
+ flushPipeWriter();
+#endif
+ destroyPipe(stdinChannel.pipe);
+}
+
+/*!
+ Constructs a QProcess object with the given \a parent.
+*/
+QProcess::QProcess(QObject *parent)
+ : QIODevice(*new QProcessPrivate, parent)
+{
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::QProcess(%p)", parent);
+#endif
+}
+
+/*!
+ Destructs the QProcess object, i.e., killing the process.
+
+ Note that this function will not return until the process is
+ terminated.
+*/
+QProcess::~QProcess()
+{
+ Q_D(QProcess);
+ if (d->processState != NotRunning) {
+ qWarning("QProcess: Destroyed while process is still running.");
+ kill();
+ waitForFinished();
+ }
+#ifdef Q_OS_UNIX
+ // make sure the process manager removes this entry
+ d->findExitCode();
+#endif
+ d->cleanup();
+}
+
+/*!
+ \obsolete
+ Returns the read channel mode of the QProcess. This function is
+ equivalent to processChannelMode()
+
+ \sa processChannelMode()
+*/
+QProcess::ProcessChannelMode QProcess::readChannelMode() const
+{
+ return processChannelMode();
+}
+
+/*!
+ \obsolete
+
+ Use setProcessChannelMode(\a mode) instead.
+
+ \sa setProcessChannelMode()
+*/
+void QProcess::setReadChannelMode(ProcessChannelMode mode)
+{
+ setProcessChannelMode(mode);
+}
+
+/*!
+ \since 4.2
+
+ Returns the channel mode of the QProcess standard output and
+ standard error channels.
+
+ \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel()
+*/
+QProcess::ProcessChannelMode QProcess::processChannelMode() const
+{
+ Q_D(const QProcess);
+ return d->processChannelMode;
+}
+
+/*!
+ \since 4.2
+
+ Sets the channel mode of the QProcess standard output and standard
+ error channels to the \a mode specified.
+ This mode will be used the next time start() is called. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0
+
+ \sa processChannelMode(), ProcessChannelMode, setReadChannel()
+*/
+void QProcess::setProcessChannelMode(ProcessChannelMode mode)
+{
+ Q_D(QProcess);
+ d->processChannelMode = mode;
+}
+
+/*!
+ Returns the current read channel of the QProcess.
+
+ \sa setReadChannel()
+*/
+QProcess::ProcessChannel QProcess::readChannel() const
+{
+ Q_D(const QProcess);
+ return d->processChannel;
+}
+
+/*!
+ Sets the current read channel of the QProcess to the given \a
+ channel. The current input channel is used by the functions
+ read(), readAll(), readLine(), and getChar(). It also determines
+ which channel triggers QProcess to emit readyRead().
+
+ \sa readChannel()
+*/
+void QProcess::setReadChannel(ProcessChannel channel)
+{
+ Q_D(QProcess);
+ if (d->processChannel != channel) {
+ QByteArray buf = d->buffer.readAll();
+ if (d->processChannel == QProcess::StandardOutput) {
+ for (int i = buf.size() - 1; i >= 0; --i)
+ d->outputReadBuffer.ungetChar(buf.at(i));
+ } else {
+ for (int i = buf.size() - 1; i >= 0; --i)
+ d->errorReadBuffer.ungetChar(buf.at(i));
+ }
+ }
+ d->processChannel = channel;
+}
+
+/*!
+ Closes the read channel \a channel. After calling this function,
+ QProcess will no longer receive data on the channel. Any data that
+ has already been received is still available for reading.
+
+ Call this function to save memory, if you are not interested in
+ the output of the process.
+
+ \sa closeWriteChannel(), setReadChannel()
+*/
+void QProcess::closeReadChannel(ProcessChannel channel)
+{
+ Q_D(QProcess);
+
+ if (channel == StandardOutput)
+ d->stdoutChannel.closed = true;
+ else
+ d->stderrChannel.closed = true;
+}
+
+/*!
+ Schedules the write channel of QProcess to be closed. The channel
+ will close once all data has been written to the process. After
+ calling this function, any attempts to write to the process will
+ fail.
+
+ Closing the write channel is necessary for programs that read
+ input data until the channel has been closed. For example, the
+ program "more" is used to display text data in a console on both
+ Unix and Windows. But it will not display the text data until
+ QProcess's write channel has been closed. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 1
+
+ The write channel is implicitly opened when start() is called.
+
+ \sa closeReadChannel()
+*/
+void QProcess::closeWriteChannel()
+{
+ Q_D(QProcess);
+ d->stdinChannel.closed = true; // closing
+ if (d->writeBuffer.isEmpty())
+ d->closeWriteChannel();
+}
+
+/*!
+ \since 4.2
+
+ Redirects the process' standard input to the file indicated by \a
+ fileName. When an input redirection is in place, the QProcess
+ object will be in read-only mode (calling write() will result in
+ error).
+
+ If the file \a fileName does not exist at the moment start() is
+ called or is not readable, starting the process will fail.
+
+ Calling setStandardInputFile() after the process has started has no
+ effect.
+
+ \sa setStandardOutputFile(), setStandardErrorFile(),
+ setStandardOutputProcess()
+*/
+void QProcess::setStandardInputFile(const QString &fileName)
+{
+ Q_D(QProcess);
+ d->stdinChannel = fileName;
+}
+
+/*!
+ \since 4.2
+
+ Redirects the process' standard output to the file \a
+ fileName. When the redirection is in place, the standard output
+ read channel is closed: reading from it using read() will always
+ fail, as will readAllStandardOutput().
+
+ If the file \a fileName doesn't exist at the moment start() is
+ called, it will be created. If it cannot be created, the starting
+ will fail.
+
+ If the file exists and \a mode is QIODevice::Truncate, the file
+ will be truncated. Otherwise (if \a mode is QIODevice::Append),
+ the file will be appended to.
+
+ Calling setStandardOutputFile() after the process has started has
+ no effect.
+
+ \sa setStandardInputFile(), setStandardErrorFile(),
+ setStandardOutputProcess()
+*/
+void QProcess::setStandardOutputFile(const QString &fileName, OpenMode mode)
+{
+ Q_ASSERT(mode == Append || mode == Truncate);
+ Q_D(QProcess);
+
+ d->stdoutChannel = fileName;
+ d->stdoutChannel.append = mode == Append;
+}
+
+/*!
+ \since 4.2
+
+ Redirects the process' standard error to the file \a
+ fileName. When the redirection is in place, the standard error
+ read channel is closed: reading from it using read() will always
+ fail, as will readAllStandardError(). The file will be appended to
+ if \a mode is Append, otherwise, it will be truncated.
+
+ See setStandardOutputFile() for more information on how the file
+ is opened.
+
+ Note: if setProcessChannelMode() was called with an argument of
+ QProcess::MergedChannels, this function has no effect.
+
+ \sa setStandardInputFile(), setStandardOutputFile(),
+ setStandardOutputProcess()
+*/
+void QProcess::setStandardErrorFile(const QString &fileName, OpenMode mode)
+{
+ Q_ASSERT(mode == Append || mode == Truncate);
+ Q_D(QProcess);
+
+ d->stderrChannel = fileName;
+ d->stderrChannel.append = mode == Append;
+}
+
+/*!
+ \since 4.2
+
+ Pipes the standard output stream of this process to the \a
+ destination process' standard input.
+
+ The following shell command:
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 2
+
+ Can be accomplished with QProcesses with the following code:
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 3
+*/
+void QProcess::setStandardOutputProcess(QProcess *destination)
+{
+ QProcessPrivate *dfrom = d_func();
+ QProcessPrivate *dto = destination->d_func();
+ dfrom->stdoutChannel.pipeTo(dto);
+ dto->stdinChannel.pipeFrom(dfrom);
+}
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+
+/*!
+ \since 4.7
+
+ Returns the additional native command line arguments for the program.
+
+ \note This function is available only on the Windows and Symbian
+ platforms.
+
+ \sa setNativeArguments()
+*/
+QString QProcess::nativeArguments() const
+{
+ Q_D(const QProcess);
+ return d->nativeArguments;
+}
+
+/*!
+ \since 4.7
+ \overload
+
+ Sets additional native command line \a arguments for the program.
+
+ On operating systems where the system API for passing command line
+ \a arguments to a subprocess natively uses a single string, one can
+ conceive command lines which cannot be passed via QProcess's portable
+ list-based API. In such cases this function must be used to set a
+ string which is \e appended to the string composed from the usual
+ argument list, with a delimiting space.
+
+ \note This function is available only on the Windows and Symbian
+ platforms.
+
+ \sa nativeArguments()
+*/
+void QProcess::setNativeArguments(const QString &arguments)
+{
+ Q_D(QProcess);
+ d->nativeArguments = arguments;
+}
+
+#endif
+
+/*!
+ If QProcess has been assigned a working directory, this function returns
+ the working directory that the QProcess will enter before the program has
+ started. Otherwise, (i.e., no directory has been assigned,) an empty
+ string is returned, and QProcess will use the application's current
+ working directory instead.
+
+ \sa setWorkingDirectory()
+*/
+QString QProcess::workingDirectory() const
+{
+ Q_D(const QProcess);
+ return d->workingDirectory;
+}
+
+/*!
+ Sets the working directory to \a dir. QProcess will start the
+ process in this directory. The default behavior is to start the
+ process in the working directory of the calling process.
+
+ \note The working directory setting is ignored on Symbian;
+ the private directory of the process is considered its working
+ directory.
+
+ \sa workingDirectory(), start()
+*/
+void QProcess::setWorkingDirectory(const QString &dir)
+{
+ Q_D(QProcess);
+ d->workingDirectory = dir;
+}
+
+/*!
+ Returns the native process identifier for the running process, if
+ available. If no process is currently running, 0 is returned.
+*/
+Q_PID QProcess::pid() const
+{
+ Q_D(const QProcess);
+ return d->pid;
+}
+
+/*! \reimp
+
+ This function operates on the current read channel.
+
+ \sa readChannel(), setReadChannel()
+*/
+bool QProcess::canReadLine() const
+{
+ Q_D(const QProcess);
+ const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
+ ? &d->errorReadBuffer
+ : &d->outputReadBuffer;
+ return readBuffer->canReadLine() || QIODevice::canReadLine();
+}
+
+/*!
+ Closes all communication with the process and kills it. After calling this
+ function, QProcess will no longer emit readyRead(), and data can no
+ longer be read or written.
+*/
+void QProcess::close()
+{
+ emit aboutToClose();
+ while (waitForBytesWritten(-1))
+ ;
+ kill();
+ waitForFinished(-1);
+ QIODevice::close();
+}
+
+/*! \reimp
+
+ Returns true if the process is not running, and no more data is available
+ for reading; otherwise returns false.
+*/
+bool QProcess::atEnd() const
+{
+ Q_D(const QProcess);
+ const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
+ ? &d->errorReadBuffer
+ : &d->outputReadBuffer;
+ return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
+}
+
+/*! \reimp
+*/
+bool QProcess::isSequential() const
+{
+ return true;
+}
+
+/*! \reimp
+*/
+qint64 QProcess::bytesAvailable() const
+{
+ Q_D(const QProcess);
+ const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
+ ? &d->errorReadBuffer
+ : &d->outputReadBuffer;
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
+ (d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
+#endif
+ return readBuffer->size() + QIODevice::bytesAvailable();
+}
+
+/*! \reimp
+*/
+qint64 QProcess::bytesToWrite() const
+{
+ Q_D(const QProcess);
+ qint64 size = d->writeBuffer.size();
+#ifdef Q_OS_WIN
+ size += d->pipeWriterBytesToWrite();
+#endif
+ return size;
+}
+
+/*!
+ Returns the type of error that occurred last.
+
+ \sa state()
+*/
+QProcess::ProcessError QProcess::error() const
+{
+ Q_D(const QProcess);
+ return d->processError;
+}
+
+/*!
+ Returns the current state of the process.
+
+ \sa stateChanged(), error()
+*/
+QProcess::ProcessState QProcess::state() const
+{
+ Q_D(const QProcess);
+ return d->processState;
+}
+
+/*!
+ \deprecated
+ Sets the environment that QProcess will use when starting a process to the
+ \a environment specified which consists of a list of key=value pairs.
+
+ For example, the following code adds the \c{C:\\BIN} directory to the list of
+ executable paths (\c{PATHS}) on Windows:
+
+ \snippet doc/src/snippets/qprocess-environment/main.cpp 0
+
+ \note This function is less efficient than the setProcessEnvironment()
+ function.
+
+ \sa environment(), setProcessEnvironment(), systemEnvironment()
+*/
+void QProcess::setEnvironment(const QStringList &environment)
+{
+ setProcessEnvironment(QProcessEnvironmentPrivate::fromList(environment));
+}
+
+/*!
+ \deprecated
+ Returns the environment that QProcess will use when starting a
+ process, or an empty QStringList if no environment has been set
+ using setEnvironment() or setEnvironmentHash(). If no environment
+ has been set, the environment of the calling process will be used.
+
+ \note The environment settings are ignored on Windows CE and Symbian,
+ as there is no concept of an environment.
+
+ \sa processEnvironment(), setEnvironment(), systemEnvironment()
+*/
+QStringList QProcess::environment() const
+{
+ Q_D(const QProcess);
+ return d->environment.toStringList();
+}
+
+/*!
+ \since 4.6
+ Sets the environment that QProcess will use when starting a process to the
+ \a environment object.
+
+ For example, the following code adds the \c{C:\\BIN} directory to the list of
+ executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}:
+
+ \snippet doc/src/snippets/qprocess-environment/main.cpp 1
+
+ Note how, on Windows, environment variable names are case-insensitive.
+
+ \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), setEnvironment()
+*/
+void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)
+{
+ Q_D(QProcess);
+ d->environment = environment;
+}
+
+/*!
+ \since 4.6
+ Returns the environment that QProcess will use when starting a
+ 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.
+
+ \note The environment settings are ignored on Windows CE,
+ as there is no concept of an environment.
+
+ \sa setProcessEnvironment(), setEnvironment(), QProcessEnvironment::isEmpty()
+*/
+QProcessEnvironment QProcess::processEnvironment() const
+{
+ Q_D(const QProcess);
+ return d->environment;
+}
+
+/*!
+ Blocks until the process has started and the started() signal has
+ been emitted, or until \a msecs milliseconds have passed.
+
+ Returns true if the process was started successfully; otherwise
+ returns false (if the operation timed out or if an error
+ occurred).
+
+ This function can operate without an event loop. It is
+ useful when writing non-GUI applications and when performing
+ I/O operations in a non-GUI thread.
+
+ \warning Calling this function from the main (GUI) thread
+ might cause your user interface to freeze.
+
+ If msecs is -1, this function will not time out.
+
+ \sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished()
+*/
+bool QProcess::waitForStarted(int msecs)
+{
+ Q_D(QProcess);
+ if (d->processState == QProcess::Starting) {
+ if (!d->waitForStarted(msecs))
+ return false;
+ setProcessState(QProcess::Running);
+ emit started();
+ }
+ return d->processState == QProcess::Running;
+}
+
+/*! \reimp
+*/
+bool QProcess::waitForReadyRead(int msecs)
+{
+ Q_D(QProcess);
+
+ if (d->processState == QProcess::NotRunning)
+ return false;
+ if (d->processChannel == QProcess::StandardOutput && d->stdoutChannel.closed)
+ return false;
+ if (d->processChannel == QProcess::StandardError && d->stderrChannel.closed)
+ return false;
+ return d->waitForReadyRead(msecs);
+}
+
+/*! \reimp
+*/
+bool QProcess::waitForBytesWritten(int msecs)
+{
+ Q_D(QProcess);
+ if (d->processState == QProcess::NotRunning)
+ return false;
+ if (d->processState == QProcess::Starting) {
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+ bool started = waitForStarted(msecs);
+ if (!started)
+ return false;
+ if (msecs != -1)
+ msecs -= stopWatch.elapsed();
+ }
+
+ return d->waitForBytesWritten(msecs);
+}
+
+/*!
+ Blocks until the process has finished and the finished() signal
+ has been emitted, or until \a msecs milliseconds have passed.
+
+ Returns true if the process finished; otherwise returns false (if
+ the operation timed out, if an error occurred, or if this QProcess
+ is already finished).
+
+ This function can operate without an event loop. It is
+ useful when writing non-GUI applications and when performing
+ I/O operations in a non-GUI thread.
+
+ \warning Calling this function from the main (GUI) thread
+ might cause your user interface to freeze.
+
+ If msecs is -1, this function will not time out.
+
+ \sa finished(), waitForStarted(), waitForReadyRead(), waitForBytesWritten()
+*/
+bool QProcess::waitForFinished(int msecs)
+{
+ Q_D(QProcess);
+ if (d->processState == QProcess::NotRunning)
+ return false;
+ if (d->processState == QProcess::Starting) {
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+ bool started = waitForStarted(msecs);
+ if (!started)
+ return false;
+ if (msecs != -1)
+ msecs -= stopWatch.elapsed();
+ }
+
+ return d->waitForFinished(msecs);
+}
+
+/*!
+ Sets the current state of the QProcess to the \a state specified.
+
+ \sa state()
+*/
+void QProcess::setProcessState(ProcessState state)
+{
+ Q_D(QProcess);
+ if (d->processState == state)
+ return;
+ d->processState = state;
+ emit stateChanged(state);
+}
+
+/*!
+ This function is called in the child process context just before the
+ program is executed on Unix or Mac OS X (i.e., after \e fork(), but before
+ \e execve()). Reimplement this function to do last minute initialization
+ of the child process. Example:
+
+ \snippet doc/src/snippets/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 Mac OS X
+ only. On Windows, it is not called.
+*/
+void QProcess::setupChildProcess()
+{
+}
+
+/*! \reimp
+*/
+qint64 QProcess::readData(char *data, qint64 maxlen)
+{
+ Q_D(QProcess);
+ QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
+ ? &d->errorReadBuffer
+ : &d->outputReadBuffer;
+
+ if (maxlen == 1 && !readBuffer->isEmpty()) {
+ int c = readBuffer->getChar();
+ if (c == -1) {
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::readData(%p \"%s\", %d) == -1",
+ data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
+#endif
+ return -1;
+ }
+ *data = (char) c;
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::readData(%p \"%s\", %d) == 1",
+ data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
+#endif
+ return 1;
+ }
+
+ qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen));
+ qint64 readSoFar = 0;
+ while (readSoFar < bytesToRead) {
+ const char *ptr = readBuffer->readPointer();
+ int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar,
+ readBuffer->nextDataBlockSize());
+ memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ readSoFar += bytesToReadFromThisBlock;
+ readBuffer->free(bytesToReadFromThisBlock);
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::readData(%p \"%s\", %lld) == %lld",
+ data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar);
+#endif
+ if (!readSoFar && d->processState == QProcess::NotRunning)
+ return -1; // EOF
+ return readSoFar;
+}
+
+/*! \reimp
+*/
+qint64 QProcess::writeData(const char *data, qint64 len)
+{
+ Q_D(QProcess);
+
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(data);
+ Q_UNUSED(len);
+ d->processError = QProcess::WriteError;
+ setErrorString(tr("Error writing to process"));
+ emit error(d->processError);
+ return -1;
+#endif
+
+ 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 (len == 1) {
+ d->writeBuffer.putChar(*data);
+ if (d->stdinChannel.notifier)
+ d->stdinChannel.notifier->setEnabled(true);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)",
+ data, qt_prettyDebug(data, len, 16).constData(), len);
+#endif
+ return 1;
+ }
+
+ char *dest = d->writeBuffer.reserve(len);
+ memcpy(dest, 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, 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
+ QByteArray.
+
+ \sa readyReadStandardOutput(), readAllStandardError(), readChannel(), setReadChannel()
+*/
+QByteArray QProcess::readAllStandardOutput()
+{
+ ProcessChannel tmp = readChannel();
+ setReadChannel(StandardOutput);
+ QByteArray data = readAll();
+ setReadChannel(tmp);
+ return data;
+}
+
+/*!
+ Regardless of the current read channel, this function returns all
+ data available from the standard error of the process as a
+ QByteArray.
+
+ \sa readyReadStandardError(), readAllStandardOutput(), readChannel(), setReadChannel()
+*/
+QByteArray QProcess::readAllStandardError()
+{
+ ProcessChannel tmp = readChannel();
+ setReadChannel(StandardError);
+ QByteArray data = readAll();
+ setReadChannel(tmp);
+ return data;
+}
+
+/*!
+ Starts the given \a program in a new process, if none is already
+ running, passing the command line arguments in \a arguments. The OpenMode
+ is set to \a mode.
+
+ The QProcess object will immediately enter the Starting state. If the
+ process starts successfully, QProcess will emit started(); otherwise,
+ error() will be emitted. If the QProcess object is already running a
+ process, a warning may be printed at the console, and the existing
+ process will continue running.
+
+ \note Processes are started asynchronously, which means the started()
+ and error() 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.
+
+ \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
+
+ \sa pid(), started(), waitForStarted()
+*/
+void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
+{
+ Q_D(QProcess);
+ if (d->processState != NotRunning) {
+ qWarning("QProcess::start: Process is already running");
+ return;
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
+#endif
+
+ d->outputReadBuffer.clear();
+ d->errorReadBuffer.clear();
+
+ if (d->stdinChannel.type != QProcessPrivate::Channel::Normal)
+ mode &= ~WriteOnly; // not open for writing
+ if (d->stdoutChannel.type != QProcessPrivate::Channel::Normal &&
+ (d->stderrChannel.type != QProcessPrivate::Channel::Normal ||
+ d->processChannelMode == MergedChannels))
+ mode &= ~ReadOnly; // not open for reading
+ if (mode == 0)
+ mode = Unbuffered;
+ QIODevice::open(mode);
+
+ d->stdinChannel.closed = false;
+ d->stdoutChannel.closed = false;
+ d->stderrChannel.closed = false;
+
+ d->program = program;
+ d->arguments = arguments;
+
+ d->exitCode = 0;
+ d->exitStatus = NormalExit;
+ d->processError = QProcess::UnknownError;
+ d->errorString.clear();
+ d->startProcess();
+}
+
+
+static QStringList parseCombinedArgString(const QString &program)
+{
+ QStringList args;
+ QString tmp;
+ int quoteCount = 0;
+ bool inQuote = false;
+
+ // handle quoting. tokens can be surrounded by double quotes
+ // "hello world". three consecutive double quotes represent
+ // the quote character itself.
+ for (int i = 0; i < program.size(); ++i) {
+ if (program.at(i) == QLatin1Char('"')) {
+ ++quoteCount;
+ if (quoteCount == 3) {
+ // third consecutive quote
+ quoteCount = 0;
+ tmp += program.at(i);
+ }
+ continue;
+ }
+ if (quoteCount) {
+ if (quoteCount == 1)
+ inQuote = !inQuote;
+ quoteCount = 0;
+ }
+ if (!inQuote && program.at(i).isSpace()) {
+ if (!tmp.isEmpty()) {
+ args += tmp;
+ tmp.clear();
+ }
+ } else {
+ tmp += program.at(i);
+ }
+ }
+ if (!tmp.isEmpty())
+ args += tmp;
+
+ return args;
+}
+
+/*!
+ \overload
+
+ Starts the program \a program in a new process, if one is not already
+ running. \a program 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 doc/src/snippets/code/src_corelib_io_qprocess.cpp 5
+
+ The \a program string can also contain quotes, to ensure that arguments
+ containing spaces are correctly supplied to the new process. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 6
+
+ If the QProcess object is already running a process, a warning may be
+ printed at the console, and the existing process will continue running.
+
+ Note that, on Windows, quotes need to be both escaped and quoted.
+ For example, the above code would be specified in the following
+ way to ensure that \c{"My Documents"} is used as the argument to
+ the \c dir executable:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 7
+
+ The OpenMode is set to \a mode.
+*/
+void QProcess::start(const QString &program, OpenMode mode)
+{
+ QStringList args = parseCombinedArgString(program);
+ if (args.isEmpty()) {
+ Q_D(QProcess);
+ d->processError = QProcess::FailedToStart;
+ setErrorString(tr("No program defined"));
+ emit error(d->processError);
+ return;
+ }
+
+ QString prog = args.first();
+ args.removeFirst();
+
+ start(prog, args, mode);
+}
+
+/*!
+ Attempts to terminate the process.
+
+ The process may not exit as a result of calling this function (it is given
+ the chance to prompt the user for any unsaved files, etc).
+
+ On Windows, terminate() posts a WM_CLOSE message to all toplevel windows
+ of the process and then to the main thread of the process itself. On Unix
+ and Mac OS X the SIGTERM signal is sent.
+
+ Console applications on Windows that do not run an event loop, or whose
+ event loop does not handle the WM_CLOSE message, can only be terminated by
+ calling kill().
+
+ On Symbian, this function requires platform security capability
+ \c PowerMgmt. If absent, the process will panic with KERN-EXEC 46.
+
+ \note Terminating running processes from other processes will typically
+ cause a panic in Symbian due to platform security.
+
+ \sa {Symbian Platform Security Requirements}
+ \sa kill()
+*/
+void QProcess::terminate()
+{
+ Q_D(QProcess);
+ d->terminateProcess();
+}
+
+/*!
+ Kills the current process, causing it to exit immediately.
+
+ On Windows, kill() uses TerminateProcess, and on Unix and Mac OS X, the
+ SIGKILL signal is sent to the process.
+
+ On Symbian, this function requires platform security capability
+ \c PowerMgmt. If absent, the process will panic with KERN-EXEC 46.
+
+ \note Killing running processes from other processes will typically
+ cause a panic in Symbian due to platform security.
+
+ \sa {Symbian Platform Security Requirements}
+ \sa terminate()
+*/
+void QProcess::kill()
+{
+ Q_D(QProcess);
+ d->killProcess();
+}
+
+/*!
+ Returns the exit code of the last process that finished.
+*/
+int QProcess::exitCode() const
+{
+ Q_D(const QProcess);
+ return d->exitCode;
+}
+
+/*!
+ \since 4.1
+
+ Returns the exit status of the last process that finished.
+
+ On Windows, if the process was terminated with TerminateProcess()
+ from another application this function will still return NormalExit
+ unless the exit code is less than 0.
+*/
+QProcess::ExitStatus QProcess::exitStatus() const
+{
+ Q_D(const QProcess);
+ return d->exitStatus;
+}
+
+/*!
+ Starts the program \a program with the arguments \a arguments in a
+ new process, waits for it to finish, and then returns the exit
+ code of the process. Any data the new process writes to the
+ console is forwarded to the calling process.
+
+ The environment and working directory are inherited from the calling
+ process.
+
+ On Windows, arguments that contain spaces are wrapped in quotes.
+
+ If the process cannot be started, -2 is returned. If the process
+ crashes, -1 is returned. Otherwise, the process' exit code is
+ returned.
+*/
+int QProcess::execute(const QString &program, const QStringList &arguments)
+{
+ QProcess process;
+ process.setReadChannelMode(ForwardedChannels);
+ process.start(program, arguments);
+ if (!process.waitForFinished(-1))
+ return -2;
+ return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1;
+}
+
+/*!
+ \overload
+
+ Starts the program \a program in a new process. \a program is a
+ single string of text containing both the program name and its
+ arguments. The arguments are separated by one or more spaces.
+*/
+int QProcess::execute(const QString &program)
+{
+ QProcess process;
+ process.setReadChannelMode(ForwardedChannels);
+ process.start(program);
+ if (!process.waitForFinished(-1))
+ return -2;
+ return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1;
+}
+
+/*!
+ Starts the program \a program with the arguments \a arguments in a
+ new process, and detaches from it. Returns true on success;
+ otherwise returns false. If the calling process exits, the
+ detached process will continue to live.
+
+ Note that arguments that contain spaces are not passed to the
+ process as separate arguments.
+
+ \bold{Unix:} The started process will run in its own session and act
+ like a daemon.
+
+ \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
+ The started process will run as a regular standalone process.
+
+ The process will be started in the directory \a workingDirectory.
+
+ If the function is successful then *\a pid is set to the process
+ identifier of the started process.
+*/
+bool QProcess::startDetached(const QString &program,
+ const QStringList &arguments,
+ const QString &workingDirectory,
+ qint64 *pid)
+{
+ return QProcessPrivate::startDetached(program,
+ arguments,
+ workingDirectory,
+ pid);
+}
+
+/*!
+ Starts the program \a program with the given \a arguments in a
+ new process, and detaches from it. Returns true on success;
+ otherwise returns false. If the calling process exits, the
+ detached process will continue to live.
+
+ \note Arguments that contain spaces are not passed to the
+ process as separate arguments.
+
+ \bold{Unix:} The started process will run in its own session and act
+ like a daemon.
+
+ \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
+ The started process will run as a regular standalone process.
+*/
+bool QProcess::startDetached(const QString &program,
+ const QStringList &arguments)
+{
+ return QProcessPrivate::startDetached(program, arguments);
+}
+
+/*!
+ \overload
+
+ Starts the program \a program in a new process. \a program is a
+ single string of text containing both the program name and its
+ arguments. The arguments are separated by one or more spaces.
+
+ The \a program string can also contain quotes, to ensure that arguments
+ containing spaces are correctly supplied to the new process.
+*/
+bool QProcess::startDetached(const QString &program)
+{
+ QStringList args = parseCombinedArgString(program);
+ if (args.isEmpty())
+ return false;
+
+ QString prog = args.first();
+ args.removeFirst();
+
+ return QProcessPrivate::startDetached(prog, args);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#elif defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) || (defined(Q_OS_MAC) && defined(QT_NO_CORESERVICES))
+ 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
+
+ Returns the environment of the calling process as a list of
+ key=value pairs. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
+
+ This function does not cache the system environment. Therefore, it's
+ possible to obtain an updated version of the environment if low-level C
+ library functions like \tt setenv ot \tt putenv have been called.
+
+ However, note that repeated calls to this function will recreate the
+ list of environment variables, which is a non-trivial operation.
+
+ \note For new code, it is recommended to use QProcessEvironment::systemEnvironment()
+
+ \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
+*/
+QStringList QProcess::systemEnvironment()
+{
+ QStringList tmp;
+ char *entry = 0;
+ int count = 0;
+ while ((entry = environ[count++]))
+ tmp << QString::fromLocal8Bit(entry);
+ return tmp;
+}
+
+/*!
+ \since 4.6
+
+ \brief The systemEnvironment function returns the environment of
+ the calling process.
+
+ It is returned as a QProcessEnvironment. This function does not
+ cache the system environment. Therefore, it's possible to obtain
+ an updated version of the environment if low-level C library
+ functions like \tt setenv ot \tt putenv have been called.
+
+ However, note that repeated calls to this function will recreate the
+ QProcessEnvironment object, which is a non-trivial operation.
+
+ \sa QProcess::systemEnvironment()
+*/
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+ const char *entry;
+ for (int count = 0; (entry = environ[count]); ++count) {
+ const char *equal = strchr(entry, '=');
+ if (!equal)
+ continue;
+
+ QByteArray name(entry, equal - entry);
+ QByteArray value(equal + 1);
+ env.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value));
+ }
+ return env;
+}
+
+/*!
+ \typedef Q_PID
+ \relates QProcess
+
+ Typedef for the identifiers used to represent processes on the underlying
+ platform. On Unix and Symbian, this corresponds to \l qint64; on Windows, it
+ corresponds to \c{_PROCESS_INFORMATION*}.
+
+ \sa QProcess::pid()
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qprocess.cpp"
+
+#endif // QT_NO_PROCESS
+
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
new file mode 100644
index 0000000000..664992f7e2
--- /dev/null
+++ b/src/corelib/io/qprocess.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROCESS_H
+#define QPROCESS_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_PROCESS
+
+#if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)) || defined(qdoc)
+typedef qint64 Q_PID;
+#else
+QT_END_NAMESPACE
+typedef struct _PROCESS_INFORMATION *Q_PID;
+QT_BEGIN_NAMESPACE
+#endif
+
+class QProcessPrivate;
+class QProcessEnvironmentPrivate;
+
+class Q_CORE_EXPORT QProcessEnvironment
+{
+public:
+ QProcessEnvironment();
+ QProcessEnvironment(const QProcessEnvironment &other);
+ ~QProcessEnvironment();
+ QProcessEnvironment &operator=(const QProcessEnvironment &other);
+
+ bool operator==(const QProcessEnvironment &other) const;
+ inline bool operator!=(const QProcessEnvironment &other) const
+ { return !(*this == other); }
+
+ bool isEmpty() const;
+ void clear();
+
+ bool contains(const QString &name) const;
+ void insert(const QString &name, const QString &value);
+ void remove(const QString &name);
+ QString value(const QString &name, const QString &defaultValue = QString()) const;
+
+ QStringList toStringList() const;
+
+ QStringList keys() const;
+
+ void insert(const QProcessEnvironment &e);
+
+ static QProcessEnvironment systemEnvironment();
+
+private:
+ friend class QProcessPrivate;
+ friend class QProcessEnvironmentPrivate;
+ QSharedDataPointer<QProcessEnvironmentPrivate> d;
+};
+
+class Q_CORE_EXPORT QProcess : public QIODevice
+{
+ Q_OBJECT
+public:
+ enum ProcessError {
+ FailedToStart, //### file not found, resource error
+ Crashed,
+ Timedout,
+ ReadError,
+ WriteError,
+ UnknownError
+ };
+ enum ProcessState {
+ NotRunning,
+ Starting,
+ Running
+ };
+ enum ProcessChannel {
+ StandardOutput,
+ StandardError
+ };
+ enum ProcessChannelMode {
+ SeparateChannels,
+ MergedChannels,
+ ForwardedChannels
+ };
+ enum ExitStatus {
+ NormalExit,
+ CrashExit
+ };
+
+ explicit QProcess(QObject *parent = 0);
+ virtual ~QProcess();
+
+ void start(const QString &program, const QStringList &arguments, OpenMode mode = ReadWrite);
+ void start(const QString &program, OpenMode mode = ReadWrite);
+
+ ProcessChannelMode readChannelMode() const;
+ void setReadChannelMode(ProcessChannelMode mode);
+ ProcessChannelMode processChannelMode() const;
+ void setProcessChannelMode(ProcessChannelMode mode);
+
+ ProcessChannel readChannel() const;
+ void setReadChannel(ProcessChannel channel);
+
+ void closeReadChannel(ProcessChannel channel);
+ void closeWriteChannel();
+
+ void setStandardInputFile(const QString &fileName);
+ void setStandardOutputFile(const QString &fileName, OpenMode mode = Truncate);
+ void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate);
+ void setStandardOutputProcess(QProcess *destination);
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ QString nativeArguments() const;
+ void setNativeArguments(const QString &arguments);
+#endif
+
+ QString workingDirectory() const;
+ void setWorkingDirectory(const QString &dir);
+
+ void setEnvironment(const QStringList &environment);
+ QStringList environment() const;
+ void setProcessEnvironment(const QProcessEnvironment &environment);
+ QProcessEnvironment processEnvironment() const;
+
+ 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;
+
+ bool waitForStarted(int msecs = 30000);
+ bool waitForReadyRead(int msecs = 30000);
+ bool waitForBytesWritten(int msecs = 30000);
+ bool waitForFinished(int msecs = 30000);
+
+ QByteArray readAllStandardOutput();
+ QByteArray readAllStandardError();
+
+ int exitCode() const;
+ QProcess::ExitStatus exitStatus() const;
+
+ // QIODevice
+ qint64 bytesAvailable() const;
+ qint64 bytesToWrite() const;
+ bool isSequential() const;
+ bool canReadLine() const;
+ void close();
+ bool atEnd() const;
+
+ static int execute(const QString &program, const QStringList &arguments);
+ static int execute(const QString &program);
+
+ static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory,
+ qint64 *pid = 0);
+ static bool startDetached(const QString &program, const QStringList &arguments);
+ static bool startDetached(const QString &program);
+
+ static QStringList systemEnvironment();
+
+public Q_SLOTS:
+ void terminate();
+ void kill();
+
+Q_SIGNALS:
+ void started();
+ void finished(int exitCode);
+ void finished(int exitCode, QProcess::ExitStatus exitStatus);
+ void error(QProcess::ProcessError error);
+ void stateChanged(QProcess::ProcessState state);
+
+ void readyReadStandardOutput();
+ void readyReadStandardError();
+
+protected:
+ void setProcessState(ProcessState state);
+
+ virtual void setupChildProcess();
+
+ // QIODevice
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
+private:
+ Q_DECLARE_PRIVATE(QProcess)
+ Q_DISABLE_COPY(QProcess)
+
+ Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput())
+ Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardError())
+ Q_PRIVATE_SLOT(d_func(), bool _q_canWrite())
+ Q_PRIVATE_SLOT(d_func(), bool _q_startupNotification())
+ Q_PRIVATE_SLOT(d_func(), bool _q_processDied())
+ Q_PRIVATE_SLOT(d_func(), void _q_notified())
+ friend class QProcessManager;
+};
+
+#endif // QT_NO_PROCESS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROCESS_H
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
new file mode 100644
index 0000000000..7bfcb311f9
--- /dev/null
+++ b/src/corelib/io/qprocess_p.h
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROCESS_P_H
+#define QPROCESS_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/qprocess.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qhash.h"
+#include "QtCore/qshareddata.h"
+#include "private/qringbuffer_p.h"
+#include "private/qiodevice_p.h"
+
+#ifdef Q_OS_WIN
+#include "QtCore/qt_windows.h"
+typedef HANDLE Q_PIPE;
+#define INVALID_Q_PIPE INVALID_HANDLE_VALUE
+#else
+typedef int Q_PIPE;
+#define INVALID_Q_PIPE -1
+#endif
+
+#ifndef QT_NO_PROCESS
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+class QWindowsPipeWriter;
+class QWinEventNotifier;
+class QTimer;
+#if defined(Q_OS_SYMBIAN)
+class RProcess;
+#endif
+
+class QProcessEnvironmentPrivate: public QSharedData
+{
+public:
+#ifdef Q_OS_WIN
+ typedef QString Unit;
+#else
+ typedef QByteArray Unit;
+#endif
+ typedef QHash<Unit, Unit> Hash;
+ Hash hash;
+
+ static QProcessEnvironment fromList(const QStringList &list);
+ QStringList toList() const;
+ QStringList keys() const;
+ void insert(const Hash &hash);
+};
+
+class QProcessPrivate : public QIODevicePrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QProcess)
+
+ struct Channel {
+ enum ProcessChannelType {
+ Normal = 0,
+ PipeSource = 1,
+ PipeSink = 2,
+ Redirect = 3
+ // if you add "= 4" here, increase the number of bits below
+ };
+
+ Channel() : process(0), notifier(0), type(Normal), closed(false), append(false)
+ {
+ pipe[0] = INVALID_Q_PIPE;
+ pipe[1] = INVALID_Q_PIPE;
+ }
+
+ void clear();
+
+ Channel &operator=(const QString &fileName)
+ {
+ clear();
+ file = fileName;
+ type = fileName.isEmpty() ? Normal : Redirect;
+ return *this;
+ }
+
+ void pipeTo(QProcessPrivate *other)
+ {
+ clear();
+ process = other;
+ type = PipeSource;
+ }
+
+ void pipeFrom(QProcessPrivate *other)
+ {
+ clear();
+ process = other;
+ type = PipeSink;
+ }
+
+ QString file;
+ QProcessPrivate *process;
+ QSocketNotifier *notifier;
+ Q_PIPE pipe[2];
+
+ unsigned type : 2;
+ bool closed : 1;
+ bool append : 1;
+ };
+
+ QProcessPrivate();
+ virtual ~QProcessPrivate();
+
+ // private slots
+ bool _q_canReadStandardOutput();
+ bool _q_canReadStandardError();
+ bool _q_canWrite();
+ bool _q_startupNotification();
+ bool _q_processDied();
+ void _q_notified();
+
+ QProcess::ProcessChannel processChannel;
+ QProcess::ProcessChannelMode processChannelMode;
+ QProcess::ProcessError processError;
+ QProcess::ProcessState processState;
+ QString workingDirectory;
+ Q_PID pid;
+ int sequenceNumber;
+
+ bool dying;
+ bool emittedReadyRead;
+ bool emittedBytesWritten;
+
+ Channel stdinChannel;
+ Channel stdoutChannel;
+ Channel stderrChannel;
+ bool createChannel(Channel &channel);
+ void closeWriteChannel();
+
+ QString program;
+ QStringList arguments;
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ QString nativeArguments;
+#endif
+ QProcessEnvironment environment;
+
+ QRingBuffer outputReadBuffer;
+ QRingBuffer errorReadBuffer;
+ QRingBuffer writeBuffer;
+
+ Q_PIPE childStartedPipe[2];
+ Q_PIPE deathPipe[2];
+ void destroyPipe(Q_PIPE pipe[2]);
+
+ QSocketNotifier *startupSocketNotifier;
+ QSocketNotifier *deathNotifier;
+
+ // the wonderful windows notifier
+ QTimer *notifier;
+ QWindowsPipeWriter *pipeWriter;
+ QWinEventNotifier *processFinishedNotifier;
+
+ void startProcess();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
+#endif
+ bool processStarted();
+ void terminateProcess();
+ void killProcess();
+ void findExitCode();
+#ifdef Q_OS_UNIX
+ bool waitForDeadChild();
+#endif
+#ifdef Q_OS_WIN
+ void flushPipeWriter();
+ qint64 pipeWriterBytesToWrite() const;
+#endif
+
+ static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(),
+ qint64 *pid = 0);
+
+ int exitCode;
+ QProcess::ExitStatus exitStatus;
+ bool crashed;
+#ifdef Q_OS_UNIX
+ int serial;
+#endif
+
+ bool waitForStarted(int msecs = 30000);
+ bool waitForReadyRead(int msecs = 30000);
+ bool waitForBytesWritten(int msecs = 30000);
+ bool waitForFinished(int msecs = 30000);
+ bool waitForWrite(int msecs = 30000);
+
+ qint64 bytesAvailableFromStdout() const;
+ qint64 bytesAvailableFromStderr() const;
+ qint64 readFromStdout(char *data, qint64 maxlen);
+ qint64 readFromStderr(char *data, qint64 maxlen);
+ qint64 writeToStdin(const char *data, qint64 maxlen);
+
+ void cleanup();
+#ifdef Q_OS_UNIX
+ static void initializeProcessManager();
+#endif
+
+#ifdef Q_OS_SYMBIAN
+ bool processLaunched;
+ RProcess* symbianProcess;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PROCESS
+
+#endif // QPROCESS_P_H
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp
new file mode 100644
index 0000000000..8a74c7b4a2
--- /dev/null
+++ b/src/corelib/io/qprocess_symbian.cpp
@@ -0,0 +1,1067 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QPROCESS_DEBUG
+
+#ifdef QPROCESS_DEBUG
+#include "qdebug.h"
+#define QPROCESS_DEBUG_PRINT(args...) qDebug(args);
+#else
+#define QPROCESS_DEBUG_PRINT(args...)
+#endif
+
+#ifndef QT_NO_PROCESS
+
+#define QPROCESS_ASSERT(check, panicReason, args...) \
+ if (!(check)) { \
+ qWarning(args); \
+ User::Panic(KQProcessPanic, panicReason); \
+ }
+
+#include <exception>
+#include <e32base.h>
+#include <e32std.h>
+#include <stdio.h>
+#include "qplatformdefs.h"
+
+#include "qdir.h"
+#include "qstring.h"
+#include "qprocess.h"
+#include "qprocess_p.h"
+#include "private/qeventdispatcher_symbian_p.h"
+
+#include <private/qthread_p.h>
+#include <qmutex.h>
+#include <qmap.h>
+#include <qsocketnotifier.h>
+
+#include <errno.h>
+
+
+QT_BEGIN_NAMESPACE
+
+_LIT(KQProcessManagerThreadName, "QProcManThread");
+_LIT(KQProcessPanic, "QPROCESS");
+enum TQProcessPanic {
+ EProcessManagerMediatorRunError = 1,
+ EProcessManagerMediatorInactive = 2,
+ EProcessManagerMediatorNotPending = 3,
+ EProcessManagerMediatorInvalidCmd = 4,
+ EProcessManagerMediatorCreationFailed = 5,
+ EProcessManagerMediatorThreadOpenFailed = 6,
+ EProcessManagerMediatorNullObserver = 7,
+ EProcessActiveRunError = 10,
+ EProcessActiveNullParameter = 11,
+ EProcessManagerMutexCreationFail = 20,
+ EProcessManagerThreadCreationFail = 21,
+ EProcessManagerSchedulerCreationFail = 22,
+ EProcessManagerNullParam = 23
+};
+
+// Forward declarations
+class QProcessManager;
+
+
+// Active object to listen for child process death
+class QProcessActive : public CActive
+{
+public:
+ static QProcessActive *construct(QProcess *process,
+ RProcess **proc,
+ int serial,
+ int deathPipe);
+
+ virtual ~QProcessActive();
+
+ void start();
+ void stop();
+
+ bool error();
+
+protected:
+
+ // Inherited from CActive
+ void RunL();
+ TInt RunError(TInt aError);
+ void DoCancel();
+
+ QProcessActive();
+
+private:
+
+ QProcess *process;
+ RProcess **pproc;
+ int serial;
+ int deathPipe;
+ bool errorValue;
+};
+
+// Active object to communicate synchronously with process manager thread
+class QProcessManagerMediator : public CActive
+{
+public:
+ static QProcessManagerMediator *construct();
+
+ virtual ~QProcessManagerMediator();
+
+ bool add(QProcessActive *processObserver);
+ void remove(QProcessActive *processObserver);
+ void terminate();
+
+protected:
+
+ enum Commands {
+ ENoCommand,
+ EAdd,
+ ERemove,
+ ETerminate
+ };
+
+ // Inherited from CActive
+ void RunL();
+ TInt RunError(TInt aError);
+ void DoCancel();
+
+ QProcessManagerMediator();
+
+ bool notify(QProcessActive *processObserver, Commands command);
+
+private:
+ QProcessActive *currentObserver;
+ Commands currentCommand;
+
+ RThread processManagerThread;
+};
+
+// Process manager manages child process death listeners.
+//
+// Note: Because QProcess can be used outside event loop, we cannot be guaranteed
+// an active scheduler exists for us to add our process death listener objects.
+// We can't just install active scheduler on the calling thread, as that would block it
+// if we want to actually use it, so a separate manager thread is required.
+class QProcessManager
+{
+public:
+ QProcessManager();
+ ~QProcessManager();
+
+ void startThread();
+
+ TInt run(void *param);
+ bool add(QProcess *process);
+ void remove(QProcess *process);
+
+ inline void setMediator(QProcessManagerMediator *newMediator) {
+ mediator = newMediator;
+ };
+
+private:
+ inline void lock() {
+ managerMutex.Wait();
+ };
+ inline void unlock() {
+ managerMutex.Signal();
+ };
+
+ QMap<int, QProcessActive *> children;
+ QProcessManagerMediator *mediator;
+ RMutex managerMutex;
+ bool threadStarted;
+ RThread managerThread;
+};
+
+static bool qt_rprocess_running(RProcess *proc)
+{
+ if (proc && proc->Handle()) {
+ TExitType et = proc->ExitType();
+ if (et == EExitPending)
+ return true;
+ }
+
+ return false;
+}
+
+static void qt_create_symbian_commandline(
+ const QStringList &arguments, const QString &nativeArguments, QString &commandLine)
+{
+ for (int i = 0; i < arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // in the case of \" already being in the string the \ must also be escaped
+ tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
+ // escape a single " because the arguments will be parsed
+ tmp.replace(QLatin1String("\""), QLatin1String("\\\""));
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\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\"
+ QString endQuote(QLatin1String("\""));
+ int i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
+ --i;
+ endQuote += QLatin1String("\\");
+ }
+ commandLine += QLatin1String("\"") + tmp.left(i) + endQuote + QLatin1Char(' ');
+ } else {
+ commandLine += tmp + QLatin1Char(' ');
+ }
+ }
+
+ if (!nativeArguments.isEmpty())
+ commandLine += nativeArguments;
+ else if (!commandLine.isEmpty()) // Chop the extra trailing space if any arguments were appended
+ commandLine.chop(1);
+}
+
+static TInt qt_create_symbian_process(RProcess **proc,
+ const QString &programName, const QStringList &arguments, const QString &nativeArguments)
+{
+ RProcess *newProc = NULL;
+ newProc = new RProcess();
+
+ if (!newProc)
+ return KErrNoMemory;
+
+ QString commandLine;
+ qt_create_symbian_commandline(arguments, nativeArguments, commandLine);
+
+ TPtrC program_ptr(reinterpret_cast<const TText*>(programName.constData()));
+ TPtrC cmdline_ptr(reinterpret_cast<const TText*>(commandLine.constData()));
+
+ TInt err = newProc->Create(program_ptr, cmdline_ptr);
+
+ if (err == KErrNotFound) {
+ // Strip path from program name and try again (i.e. try from default location "\sys\bin")
+ int index = programName.lastIndexOf(QDir::separator());
+ int index2 = programName.lastIndexOf(QChar(QLatin1Char('/')));
+ index = qMax(index, index2);
+
+ if (index != -1 && programName.length() >= index) {
+ QString strippedName;
+ strippedName = programName.mid(index + 1);
+ QPROCESS_DEBUG_PRINT("qt_create_symbian_process() Executable '%s' not found, trying stripped version '%s'",
+ qPrintable(programName), qPrintable(strippedName));
+
+ TPtrC stripped_ptr(reinterpret_cast<const TText*>(strippedName.constData()));
+ err = newProc->Create(stripped_ptr, cmdline_ptr);
+
+ if (err != KErrNone) {
+ QPROCESS_DEBUG_PRINT("qt_create_symbian_process() Unable to create process '%s': %d",
+ qPrintable(strippedName), err);
+ }
+ }
+ }
+
+ if (err == KErrNone)
+ *proc = newProc;
+ else
+ delete newProc;
+
+ return err;
+}
+
+static qint64 qt_native_read(int fd, char *data, qint64 maxlen)
+{
+ qint64 ret = 0;
+ do {
+ ret = ::read(fd, data, maxlen);
+ } while (ret == -1 && errno == EINTR);
+
+ QPROCESS_DEBUG_PRINT("qt_native_read(): fd: %d, result: %d, errno = %d", fd, (int)ret, errno);
+
+ return ret;
+}
+
+static qint64 qt_native_write(int fd, const char *data, qint64 len)
+{
+ qint64 ret = 0;
+ do {
+ ret = ::write(fd, data, len);
+ } while (ret == -1 && errno == EINTR);
+
+ QPROCESS_DEBUG_PRINT("qt_native_write(): fd: %d, result: %d, errno = %d", fd, (int)ret, errno);
+
+ return ret;
+}
+
+static void qt_native_close(int fd)
+{
+ int ret;
+ do {
+ ret = ::close(fd);
+ } while (ret == -1 && errno == EINTR);
+}
+
+static void qt_create_pipe(int *pipe)
+{
+ if (pipe[0] != -1)
+ qt_native_close(pipe[0]);
+ if (pipe[1] != -1)
+ qt_native_close(pipe[1]);
+ if (::pipe(pipe) != 0) {
+ qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
+ pipe, qPrintable(qt_error_string(errno)));
+ } else {
+ QPROCESS_DEBUG_PRINT("qt_create_pipe(): Created pipe %d - %d", pipe[0], pipe[1]);
+ }
+}
+
+// Called from ProcessManagerThread
+QProcessActive *QProcessActive::construct(QProcess *process,
+ RProcess **proc,
+ int serial,
+ int deathPipe)
+{
+ QPROCESS_ASSERT((process || proc || *proc),
+ EProcessActiveNullParameter,
+ "QProcessActive::construct(): process (0x%x), proc (0x%x) or *proc == NULL, not creating an instance", process, proc)
+
+ QProcessActive *newInstance = new QProcessActive();
+
+ if (!newInstance) {
+ QPROCESS_DEBUG_PRINT("QProcessActive::construct(): Failed to create new instance");
+ } else {
+ newInstance->process = process;
+ newInstance->pproc = proc;
+ newInstance->serial = serial;
+ newInstance->deathPipe = deathPipe;
+ newInstance->errorValue = false;
+ }
+
+ return newInstance;
+}
+
+// Called from ProcessManagerThread
+QProcessActive::QProcessActive()
+ : CActive(CActive::EPriorityStandard)
+{
+ // Nothing to do
+}
+
+// Called from main thread
+QProcessActive::~QProcessActive()
+{
+ process = NULL;
+ pproc = NULL;
+}
+
+// Called from ProcessManagerThread
+void QProcessActive::start()
+{
+ if (qt_rprocess_running(*pproc)) {
+ CActiveScheduler::Add(this);
+ (*pproc)->Logon(iStatus);
+ SetActive();
+ QPROCESS_DEBUG_PRINT("QProcessActive::start(): Started monitoring for process exit.");
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessActive::start(): Process doesn't exist or is already dead");
+ // Assume process has already died
+ qt_native_write(deathPipe, "", 1);
+ errorValue = true;
+ }
+}
+
+// Called from ProcessManagerThread
+void QProcessActive::stop()
+{
+ QPROCESS_DEBUG_PRINT("QProcessActive::stop()");
+
+ // Remove this from scheduler (also cancels the request)
+ Deque();
+}
+
+bool QProcessActive::error()
+{
+ return errorValue;
+}
+
+// Called from ProcessManagerThread
+void QProcessActive::RunL()
+{
+ // If this method gets executed, the monitored process has died
+
+ // Notify main thread
+ qt_native_write(deathPipe, "", 1);
+ QPROCESS_DEBUG_PRINT("QProcessActive::RunL() sending death notice to %d", deathPipe);
+}
+
+// Called from ProcessManagerThread
+TInt QProcessActive::RunError(TInt aError)
+{
+ Q_UNUSED(aError);
+ // Handle RunL leave (should never happen)
+ QPROCESS_ASSERT(0, EProcessActiveRunError, "QProcessActive::RunError(): Should never get here!")
+ return 0;
+}
+
+// Called from ProcessManagerThread
+void QProcessActive::DoCancel()
+{
+ QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel()");
+
+ if (qt_rprocess_running(*pproc)) {
+ (*pproc)->LogonCancel(iStatus);
+ QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel(): Stopped monitoring for process exit.");
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel(): Process doesn't exist");
+ }
+}
+
+
+// Called from ProcessManagerThread
+QProcessManagerMediator *QProcessManagerMediator::construct()
+{
+ QProcessManagerMediator *newInstance = new QProcessManagerMediator;
+ TInt err(KErrNone);
+
+ newInstance->currentCommand = ENoCommand;
+ newInstance->currentObserver = NULL;
+
+ if (newInstance) {
+ err = newInstance->processManagerThread.Open(newInstance->processManagerThread.Id());
+ QPROCESS_ASSERT((err == KErrNone),
+ EProcessManagerMediatorThreadOpenFailed,
+ "QProcessManagerMediator::construct(): Failed to open processManagerThread (err:%d)", err)
+ } else {
+ QPROCESS_ASSERT(0,
+ EProcessManagerMediatorCreationFailed,
+ "QProcessManagerMediator::construct(): Failed to open construct mediator")
+ }
+
+ // Activate mediator
+ CActiveScheduler::Add(newInstance);
+ newInstance->iStatus = KRequestPending;
+ newInstance->SetActive();
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::construct(): new instance successfully created and activated");
+
+ return newInstance;
+}
+
+// Called from ProcessManagerThread
+QProcessManagerMediator::QProcessManagerMediator()
+ : CActive(CActive::EPriorityStandard)
+{
+ // Nothing to do
+}
+
+// Called from main thread
+QProcessManagerMediator::~QProcessManagerMediator()
+{
+ processManagerThread.Close();
+ currentCommand = ENoCommand;
+ currentObserver = NULL;
+}
+
+// Called from main thread
+bool QProcessManagerMediator::add(QProcessActive *processObserver)
+{
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::add()");
+ return notify(processObserver, EAdd);
+}
+
+// Called from main thread
+void QProcessManagerMediator::remove(QProcessActive *processObserver)
+{
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::remove()");
+ notify(processObserver, ERemove);
+}
+
+// Called from main thread
+void QProcessManagerMediator::terminate()
+{
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::terminate()");
+ notify(NULL, ETerminate);
+}
+
+// Called from main thread
+bool QProcessManagerMediator::notify(QProcessActive *processObserver, Commands command)
+{
+ bool success(true);
+
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Command: %d, processObserver: 0x%x", command, processObserver);
+
+ QPROCESS_ASSERT((command == ETerminate || processObserver),
+ EProcessManagerMediatorNullObserver,
+ "QProcessManagerMediator::Notify(): NULL processObserver not allowed for command: %d", command)
+
+ QPROCESS_ASSERT(IsActive(),
+ EProcessManagerMediatorInactive,
+ "QProcessManagerMediator::Notify(): Mediator is not active!")
+
+ QPROCESS_ASSERT(iStatus == KRequestPending,
+ EProcessManagerMediatorNotPending,
+ "QProcessManagerMediator::Notify(): Mediator request not pending!")
+
+ currentObserver = processObserver;
+ currentCommand = command;
+
+ // Sync with process manager thread
+ TRequestStatus pmStatus;
+ processManagerThread.Rendezvous(pmStatus);
+
+ // Complete request -> RunL will run in the process manager thread
+ TRequestStatus *status = &iStatus;
+ processManagerThread.RequestComplete(status, command);
+
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Waiting process manager to complete...");
+ User::WaitForRequest(pmStatus);
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Wait over");
+
+ if (currentObserver) {
+ success = !(currentObserver->error());
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): success = %d", success);
+ }
+
+ currentObserver = NULL;
+ currentCommand = ENoCommand;
+
+ return success;
+}
+
+// Called from ProcessManagerThread
+void QProcessManagerMediator::RunL()
+{
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::RunL(): currentCommand: %d, iStatus: %d", currentCommand, iStatus.Int());
+ switch (currentCommand) {
+ case EAdd:
+ currentObserver->start();
+ break;
+ case ERemove:
+ currentObserver->stop();
+ break;
+ case ETerminate:
+ Deque();
+ CActiveScheduler::Stop();
+ return;
+ default:
+ QPROCESS_ASSERT(0,
+ EProcessManagerMediatorInvalidCmd,
+ "QProcessManagerMediator::RunL(): Invalid command!")
+ break;
+ }
+
+ iStatus = KRequestPending;
+ SetActive();
+
+ // Notify main thread that we are done
+ RThread::Rendezvous(KErrNone);
+}
+
+// Called from ProcessManagerThread
+TInt QProcessManagerMediator::RunError(TInt aError)
+{
+ Q_UNUSED(aError);
+ // Handle RunL leave (should never happen)
+ QPROCESS_ASSERT(0,
+ EProcessManagerMediatorRunError,
+ "QProcessManagerMediator::RunError(): Should never get here!")
+ return 0;
+}
+
+// Called from ProcessManagerThread
+void QProcessManagerMediator::DoCancel()
+{
+ QPROCESS_DEBUG_PRINT("QProcessManagerMediator::DoCancel()");
+ TRequestStatus *status = &iStatus;
+ processManagerThread.RequestComplete(status, KErrCancel);
+}
+
+Q_GLOBAL_STATIC(QProcessManager, processManager)
+
+TInt processManagerThreadFunction(TAny *param)
+{
+ QPROCESS_ASSERT(param,
+ EProcessManagerNullParam,
+ "processManagerThreadFunction(): NULL param")
+
+ QProcessManager *manager = reinterpret_cast<QProcessManager*>(param);
+
+ CActiveScheduler *scheduler = new CQtActiveScheduler();
+
+ QPROCESS_ASSERT(scheduler,
+ EProcessManagerSchedulerCreationFail,
+ "processManagerThreadFunction(): Scheduler creation failed")
+
+ CActiveScheduler::Install(scheduler);
+
+ //Creating mediator also adds it to scheduler and activates it. Failure will panic.
+ manager->setMediator(QProcessManagerMediator::construct());
+ RThread::Rendezvous(KErrNone);
+
+ CActiveScheduler::Start();
+
+ CActiveScheduler::Install(NULL);
+ delete scheduler;
+
+ return KErrNone;
+}
+
+QProcessManager::QProcessManager()
+ : mediator(NULL), threadStarted(false)
+{
+ TInt err = managerMutex.CreateLocal();
+
+ QPROCESS_ASSERT(err == KErrNone,
+ EProcessManagerMutexCreationFail,
+ "QProcessManager::QProcessManager(): Failed to create new managerMutex (err: %d)", err)
+}
+
+QProcessManager::~QProcessManager()
+{
+ QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager()");
+
+ // Check if manager thread is still alive. If this destructor is ran as part of global
+ // static cleanup, manager thread will most likely be terminated by kernel at this point,
+ // so trying to delete QProcessActives and QProcessMediators will panic as they
+ // will still be active. They can also no longer be canceled as the thread is already gone.
+ // In case manager thread has already died, we simply do nothing and let the deletion of
+ // the main heap at process exit take care of stray objects.
+
+ if (managerThread.Handle() && managerThread.ExitType() == EExitPending) {
+ // Cancel death listening for all child processes
+ if (mediator) {
+ QMap<int, QProcessActive *>::Iterator it = children.begin();
+ while (it != children.end()) {
+ // Remove all monitors
+ QProcessActive *active = it.value();
+ mediator->remove(active);
+
+ QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process");
+ ++it;
+ }
+
+ // Terminate process manager thread.
+ mediator->terminate();
+ delete mediator;
+ }
+
+ qDeleteAll(children.values());
+ children.clear();
+ }
+
+ managerThread.Close();
+ managerMutex.Close();
+}
+
+void QProcessManager::startThread()
+{
+ lock();
+
+ if (!threadStarted) {
+ TInt err = managerThread.Create(KQProcessManagerThreadName,
+ processManagerThreadFunction,
+ 0x5000,
+ (RAllocator*)NULL,
+ (TAny*)this,
+ EOwnerProcess);
+
+ QPROCESS_ASSERT(err == KErrNone,
+ EProcessManagerThreadCreationFail,
+ "QProcessManager::startThread(): Failed to create new managerThread (err:%d)", err)
+
+ threadStarted = true;
+
+ // Manager thread must start running before we continue, so sync with rendezvous
+ TRequestStatus status;
+ managerThread.Rendezvous(status);
+ managerThread.Resume();
+ User::WaitForRequest(status);
+ }
+
+ unlock();
+}
+
+static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
+
+bool QProcessManager::add(QProcess *process)
+{
+ QPROCESS_ASSERT(process,
+ EProcessManagerNullParam,
+ "QProcessManager::add(): Failed to add QProcessActive to ProcessManager - NULL process")
+
+ lock();
+
+ int serial = idCounter.fetchAndAddRelaxed(1);
+ process->d_func()->serial = serial;
+
+ QPROCESS_DEBUG_PRINT("QProcessManager::add(): serial: %d, deathPipe: %d - %d, symbianProcess: 0x%x", serial, process->d_func()->deathPipe[0], process->d_func()->deathPipe[1], process->d_func()->symbianProcess);
+
+ QProcessActive *newActive =
+ QProcessActive::construct(process,
+ &(process->d_func()->symbianProcess),
+ serial,
+ process->d_func()->deathPipe[1]);
+
+ if (newActive) {
+ if (mediator->add(newActive)) {
+ children.insert(serial, newActive);
+ unlock();
+ return true;
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessManager::add(): Failed to add QProcessActive to ProcessManager");
+ delete newActive;
+ }
+ }
+
+ unlock();
+
+ return false;
+}
+
+void QProcessManager::remove(QProcess *process)
+{
+ QPROCESS_ASSERT(process,
+ EProcessManagerNullParam,
+ "QProcessManager::remove(): Failed to remove QProcessActive from ProcessManager - NULL process")
+
+ lock();
+
+ int serial = process->d_func()->serial;
+ QProcessActive *active = children.value(serial);
+ if (!active) {
+ unlock();
+ return;
+ }
+
+ mediator->remove(active);
+
+ children.remove(serial);
+ delete active;
+
+ unlock();
+}
+
+void QProcessPrivate::destroyPipe(int *pipe)
+{
+ if (pipe[1] != -1) {
+ qt_native_close(pipe[1]);
+ pipe[1] = -1;
+ }
+ if (pipe[0] != -1) {
+ qt_native_close(pipe[0]);
+ pipe[0] = -1;
+ }
+}
+
+bool QProcessPrivate::createChannel(Channel &channel)
+{
+ Q_UNUSED(channel);
+ // No channels used
+ return false;
+}
+
+void QProcessPrivate::startProcess()
+{
+ Q_Q(QProcess);
+
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess()");
+
+ // Start the process (platform dependent)
+ q->setProcessState(QProcess::Starting);
+
+ processManager()->startThread();
+
+ qt_create_pipe(deathPipe);
+ if (threadData->eventDispatcher) {
+ deathNotifier = new QSocketNotifier(deathPipe[0],
+ QSocketNotifier::Read, q);
+ QObject::connect(deathNotifier, SIGNAL(activated(int)),
+ q, SLOT(_q_processDied()));
+ }
+
+ TInt err = qt_create_symbian_process(&symbianProcess, program, arguments, nativeArguments);
+
+ if (err == KErrNone) {
+ pid = symbianProcess->Id().Id();
+
+ ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK);
+
+ if (!processManager()->add(q)) {
+ qWarning("QProcessPrivate::startProcess(): Failed to start monitoring for process death.");
+ err = KErrNoMemory;
+ }
+ }
+
+ if (err != KErrNone) {
+ // Cleanup, report error and return
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess() Process open failed, err: %d, '%s'", err, qPrintable(program));
+ q->setProcessState(QProcess::NotRunning);
+ processError = QProcess::FailedToStart;
+ q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "Resource error (qt_create_symbian_process failure)")));
+ emit q->error(processError);
+ cleanup();
+ return;
+ }
+
+ processLaunched = true;
+
+ symbianProcess->Resume();
+
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess(): this: 0x%x, pid: %ld", this, pid);
+
+ // Notify child start
+ _q_startupNotification();
+
+}
+
+bool QProcessPrivate::processStarted()
+{
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::processStarted() == %s", processLaunched ? "true" : "false");
+
+ // Since we cannot get information whether process has actually been launched
+ // or not in Symbian, we need to fake it. Assume process is started if launch was
+ // successful.
+
+ return processLaunched;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStdout() const
+{
+ // In Symbian, stdout is not supported
+ return 0;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStderr() const
+{
+ // In Symbian, stderr is not supported
+ return 0;
+}
+
+qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ // In Symbian, stdout is not supported
+ return 0;
+}
+
+qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ // In Symbian, stderr is not supported
+ return 0;
+}
+
+qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ // In Symbian, stdin is not supported
+ return 0;
+}
+
+void QProcessPrivate::terminateProcess()
+{
+ // Needs PowerMgmt capability if process has been started; will panic kern-exec 46 otherwise.
+ // Always works if process is not yet started.
+ if (qt_rprocess_running(symbianProcess)) {
+ symbianProcess->Terminate(0);
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::terminateProcess(), Process not running");
+ }
+}
+
+void QProcessPrivate::killProcess()
+{
+ // Needs PowerMgmt capability if process has been started; will panic kern-exec 46 otherwise.
+ // Always works if process is not yet started.
+ if (qt_rprocess_running(symbianProcess)) {
+ symbianProcess->Kill(0);
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::killProcess(), Process not running");
+ }
+}
+
+bool QProcessPrivate::waitForStarted(int msecs)
+{
+ Q_UNUSED(msecs);
+ // Since we can get no actual feedback from process beyond its death,
+ // assume that started has already been emitted if process has been launched
+ return processLaunched;
+}
+
+bool QProcessPrivate::waitForReadyRead(int msecs)
+{
+ // Functionality not supported in Symbian
+ Q_UNUSED(msecs);
+ return false;
+}
+
+bool QProcessPrivate::waitForBytesWritten(int msecs)
+{
+ // Functionality not supported in Symbian
+ Q_UNUSED(msecs);
+ return false;
+}
+
+bool QProcessPrivate::waitForFinished(int msecs)
+{
+ Q_Q(QProcess);
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished(%d)", msecs);
+
+ TRequestStatus timerStatus = KErrNone;
+ TRequestStatus logonStatus = KErrNone;
+ bool timeoutOccurred = false;
+
+ // Logon to process to observe its death
+ if (qt_rprocess_running(symbianProcess)) {
+ symbianProcess->Logon(logonStatus);
+
+ if (msecs < 0) {
+ // If timeout is negative, there is no timeout
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Waiting (just logon)...");
+ User::WaitForRequest(logonStatus);
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Wait completed");
+ } else {
+ // Create timer
+ RTimer timer;
+ timer.CreateLocal();
+ TTimeIntervalMicroSeconds32 interval(msecs*1000);
+ timer.After(timerStatus, interval);
+
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Waiting (logon + timer)...");
+ User::WaitForRequest(logonStatus, timerStatus);
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Wait completed");
+
+ if (logonStatus != KRequestPending) {
+ timer.Cancel();
+ User::WaitForRequest(timerStatus);
+ } else {
+ timeoutOccurred = true;
+ symbianProcess->LogonCancel(logonStatus);
+ User::WaitForRequest(logonStatus);
+ }
+ timer.Close();
+ }
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished(), qt_rprocess_running returned false");
+ }
+
+ if (timeoutOccurred) {
+ processError = QProcess::Timedout;
+ q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "Process operation timed out")));
+ return false;
+ }
+
+ _q_processDied();
+
+ return true;
+}
+
+bool QProcessPrivate::waitForWrite(int msecs)
+{
+ // Functionality not supported in Symbian
+ Q_UNUSED(msecs);
+ return false;
+}
+
+// Deceptively named function. Exit code is actually got in waitForDeadChild().
+void QProcessPrivate::findExitCode()
+{
+ Q_Q(QProcess);
+ processManager()->remove(q);
+}
+
+bool QProcessPrivate::waitForDeadChild()
+{
+ Q_Q(QProcess);
+
+ // read a byte from the death pipe
+ char c;
+ qt_native_read(deathPipe[0], &c, 1);
+
+ if (symbianProcess && symbianProcess->Handle()) {
+ TExitType et = symbianProcess->ExitType();
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForDeadChild() symbianProcess->ExitType: %d", et);
+ if (et != EExitPending) {
+ processManager()->remove(q);
+ exitCode = symbianProcess->ExitReason();
+ crashed = (et == EExitPanic);
+#if defined QPROCESS_DEBUG
+ TExitCategoryName catName = symbianProcess->ExitCategory();
+ qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
+ << exitCode << ", crashed:" << crashed
+ << ", category:" << QString((const QChar *)catName.Ptr());
+#endif
+ } else {
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForDeadChild() not dead!");
+ }
+ }
+
+ return true;
+}
+
+void QProcessPrivate::_q_notified()
+{
+ // Nothing to do in Symbian
+}
+
+bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
+{
+ QPROCESS_DEBUG_PRINT("QProcessPrivate::startDetached()");
+ Q_UNUSED(workingDirectory);
+
+ RProcess *newProc = NULL;
+
+ TInt err = qt_create_symbian_process(&newProc, program, arguments, QString());
+
+ if (err == KErrNone) {
+ if (pid)
+ *pid = newProc->Id().Id();
+
+ newProc->Resume();
+ newProc->Close();
+ delete newProc;
+ return true;
+ }
+
+ return false;
+}
+
+
+void QProcessPrivate::initializeProcessManager()
+{
+ (void) processManager();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
new file mode 100644
index 0000000000..3af9b46df8
--- /dev/null
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -0,0 +1,1297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QPROCESS_DEBUG
+#include "qdebug.h"
+
+#ifndef QT_NO_PROCESS
+
+#if defined QPROCESS_DEBUG
+#include "qstring.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:
+ QString tmp;
+ tmp.sprintf("\\%o", c);
+ out += tmp.toLatin1();
+ }
+ }
+
+ if (len < maxSize)
+ out += "...";
+
+ return out;
+}
+QT_END_NAMESPACE
+#endif
+
+#include "qplatformdefs.h"
+
+#include "qprocess.h"
+#include "qprocess_p.h"
+#include "private/qcore_unix_p.h"
+
+#ifdef Q_OS_MAC
+#include <private/qcore_mac_p.h>
+#endif
+
+#include <private/qcoreapplication_p.h>
+#include <private/qthread_p.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qlist.h>
+#include <qhash.h>
+#include <qmutex.h>
+#include <qsemaphore.h>
+#include <qsocketnotifier.h>
+#include <qthread.h>
+#include <qelapsedtimer.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+// POSIX requires PIPE_BUF to be 512 or larger
+// so we will use 512
+static const int errorBufferMax = 512;
+
+#ifdef Q_OS_INTEGRITY
+static inline char *strdup(const char *data)
+{
+ return qstrdup(data);
+}
+#endif
+
+static int qt_qprocess_deadChild_pipe[2];
+static struct sigaction qt_sa_old_sigchld_handler;
+static void qt_sa_sigchld_handler(int signum)
+{
+ qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
+#if defined (QPROCESS_DEBUG)
+ fprintf(stderr, "*** SIGCHLD\n");
+#endif
+
+ // load it as volatile
+ void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
+ if (oldAction && oldAction != SIG_IGN)
+ oldAction(signum);
+}
+
+static inline void add_fd(int &nfds, int fd, fd_set *fdset)
+{
+ FD_SET(fd, fdset);
+ if ((fd) > nfds)
+ nfds = fd;
+}
+
+struct QProcessInfo {
+ QProcess *process;
+ int deathPipe;
+ int exitResult;
+ pid_t pid;
+ int serialNumber;
+};
+
+class QProcessManager : public QThread
+{
+ Q_OBJECT
+public:
+ QProcessManager();
+ ~QProcessManager();
+
+ void run();
+ void catchDeadChildren();
+ void add(pid_t pid, QProcess *process);
+ void remove(QProcess *process);
+ void lock();
+ void unlock();
+
+private:
+ QMutex mutex;
+ QHash<int, QProcessInfo *> children;
+};
+
+
+Q_GLOBAL_STATIC(QMutex, processManagerGlobalMutex)
+
+static QProcessManager *processManager() {
+ // The constructor of QProcessManager should be called only once
+ // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager
+ QMutex *mutex = processManagerGlobalMutex();
+ QMutexLocker locker(mutex);
+ static QProcessManager processManager;
+ return &processManager;
+}
+
+QProcessManager::QProcessManager()
+{
+#if defined (QPROCESS_DEBUG)
+ qDebug() << "QProcessManager::QProcessManager()";
+#endif
+ // initialize the dead child pipe and make it non-blocking. in the
+ // extremely unlikely event that the pipe fills up, we do not under any
+ // circumstances want to block.
+ qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK);
+
+ // set up the SIGCHLD handler, which writes a single byte to the dead
+ // child pipe every time a child dies.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = qt_sa_sigchld_handler;
+ action.sa_flags = SA_NOCLDSTOP;
+ ::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
+}
+
+QProcessManager::~QProcessManager()
+{
+ // notify the thread that we're shutting down.
+ qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1);
+ qt_safe_close(qt_qprocess_deadChild_pipe[1]);
+ wait();
+
+ // on certain unixes, closing the reading end of the pipe will cause
+ // select in run() to block forever, rather than return with EBADF.
+ qt_safe_close(qt_qprocess_deadChild_pipe[0]);
+
+ qt_qprocess_deadChild_pipe[0] = -1;
+ qt_qprocess_deadChild_pipe[1] = -1;
+
+ qDeleteAll(children.values());
+ children.clear();
+
+ struct sigaction currentAction;
+ ::sigaction(SIGCHLD, 0, &currentAction);
+ if (currentAction.sa_handler == qt_sa_sigchld_handler) {
+ ::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
+ }
+}
+
+void QProcessManager::run()
+{
+ forever {
+ fd_set readset;
+ FD_ZERO(&readset);
+ FD_SET(qt_qprocess_deadChild_pipe[0], &readset);
+
+#if defined (QPROCESS_DEBUG)
+ qDebug() << "QProcessManager::run() waiting for children to die";
+#endif
+
+ // block forever, or until activity is detected on the dead child
+ // pipe. the only other peers are the SIGCHLD signal handler, and the
+ // QProcessManager destructor.
+ int nselect = select(qt_qprocess_deadChild_pipe[0] + 1, &readset, 0, 0, 0);
+ if (nselect < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+
+ // empty only one byte from the pipe, even though several SIGCHLD
+ // signals may have been delivered in the meantime, to avoid race
+ // conditions.
+ char c;
+ if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@')
+ break;
+
+ // catch any and all children that we can.
+ catchDeadChildren();
+ }
+}
+
+void QProcessManager::catchDeadChildren()
+{
+ QMutexLocker locker(&mutex);
+
+ // try to catch all children whose pid we have registered, and whose
+ // deathPipe is still valid (i.e, we have not already notified it).
+ QHash<int, QProcessInfo *>::Iterator it = children.begin();
+ while (it != children.end()) {
+ // notify all children that they may have died. they need to run
+ // waitpid() in their own thread.
+ QProcessInfo *info = it.value();
+ qt_safe_write(info->deathPipe, "", 1);
+
+#if defined (QPROCESS_DEBUG)
+ qDebug() << "QProcessManager::run() sending death notice to" << info->process;
+#endif
+ ++it;
+ }
+}
+
+static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
+
+void QProcessManager::add(pid_t pid, QProcess *process)
+{
+#if defined (QPROCESS_DEBUG)
+ qDebug() << "QProcessManager::add() adding pid" << pid << "process" << process;
+#endif
+
+ // insert a new info structure for this process
+ QProcessInfo *info = new QProcessInfo;
+ info->process = process;
+ info->deathPipe = process->d_func()->deathPipe[1];
+ info->exitResult = 0;
+ info->pid = pid;
+
+ int serial = idCounter.fetchAndAddRelaxed(1);
+ process->d_func()->serial = serial;
+ children.insert(serial, info);
+}
+
+void QProcessManager::remove(QProcess *process)
+{
+ QMutexLocker locker(&mutex);
+
+ int serial = process->d_func()->serial;
+ QProcessInfo *info = children.take(serial);
+#if defined (QPROCESS_DEBUG)
+ if (info)
+ qDebug() << "QProcessManager::remove() removing pid" << info->pid << "process" << info->process;
+#endif
+ delete info;
+}
+
+void QProcessManager::lock()
+{
+ mutex.lock();
+}
+
+void QProcessManager::unlock()
+{
+ mutex.unlock();
+}
+
+static void qt_create_pipe(int *pipe)
+{
+ if (pipe[0] != -1)
+ qt_safe_close(pipe[0]);
+ if (pipe[1] != -1)
+ qt_safe_close(pipe[1]);
+ if (qt_safe_pipe(pipe) != 0) {
+ qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
+ pipe, qPrintable(qt_error_string(errno)));
+ }
+}
+
+void QProcessPrivate::destroyPipe(int *pipe)
+{
+ if (pipe[1] != -1) {
+ qt_safe_close(pipe[1]);
+ pipe[1] = -1;
+ }
+ if (pipe[0] != -1) {
+ qt_safe_close(pipe[0]);
+ pipe[0] = -1;
+ }
+}
+
+/*
+ Create the pipes to a QProcessPrivate::Channel.
+
+ This function must be called in order: stdin, stdout, stderr
+*/
+bool QProcessPrivate::createChannel(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
+ qt_create_pipe(channel.pipe);
+
+ // create the socket notifiers
+ if (threadData->eventDispatcher) {
+ if (&channel == &stdinChannel) {
+ channel.notifier = new QSocketNotifier(channel.pipe[1],
+ QSocketNotifier::Write, q);
+ channel.notifier->setEnabled(false);
+ QObject::connect(channel.notifier, SIGNAL(activated(int)),
+ q, SLOT(_q_canWrite()));
+ } else {
+ channel.notifier = new QSocketNotifier(channel.pipe[0],
+ QSocketNotifier::Read, q);
+ const char *receiver;
+ if (&channel == &stdoutChannel)
+ receiver = SLOT(_q_canReadStandardOutput());
+ else
+ receiver = SLOT(_q_canReadStandardError());
+ QObject::connect(channel.notifier, SIGNAL(activated(int)),
+ q, receiver);
+ }
+ }
+
+ return true;
+ } else if (channel.type == Channel::Redirect) {
+ // we're redirecting the channel to/from a file
+ QByteArray fname = QFile::encodeName(channel.file);
+
+ if (&channel == &stdinChannel) {
+ // try to open in read-only mode
+ channel.pipe[1] = -1;
+ if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1)
+ return true; // success
+
+ q->setErrorString(QProcess::tr("Could not open input redirection for reading"));
+ } else {
+ int mode = O_WRONLY | O_CREAT;
+ if (channel.append)
+ mode |= O_APPEND;
+ else
+ mode |= O_TRUNC;
+
+ channel.pipe[0] = -1;
+ if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1)
+ return true; // success
+
+ q->setErrorString(QProcess::tr("Could not open output redirection for writing"));
+ }
+
+ // could not open file
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+ cleanup();
+ return false;
+ } else {
+ Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
+
+ Channel *source;
+ Channel *sink;
+
+ if (channel.type == Channel::PipeSource) {
+ // we are the source
+ source = &channel;
+ sink = &channel.process->stdinChannel;
+
+ Q_ASSERT(source == &stdoutChannel);
+ Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
+ } else {
+ // we are the sink;
+ source = &channel.process->stdoutChannel;
+ sink = &channel;
+
+ Q_ASSERT(sink == &stdinChannel);
+ Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
+ }
+
+ if (source->pipe[1] != INVALID_Q_PIPE || sink->pipe[0] != INVALID_Q_PIPE) {
+ // already created, do nothing
+ return true;
+ } else {
+ Q_ASSERT(source->pipe[0] == INVALID_Q_PIPE && source->pipe[1] == INVALID_Q_PIPE);
+ Q_ASSERT(sink->pipe[0] == INVALID_Q_PIPE && sink->pipe[1] == INVALID_Q_PIPE);
+
+ Q_PIPE pipe[2] = { -1, -1 };
+ qt_create_pipe(pipe);
+ sink->pipe[0] = pipe[0];
+ source->pipe[1] = pipe[1];
+
+ return true;
+ }
+ }
+}
+
+static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment, int *envc)
+{
+ *envc = 0;
+ if (environment.isEmpty())
+ return 0;
+
+ // if LD_LIBRARY_PATH exists in the current environment, but
+ // not in the environment list passed by the programmer, then
+ // copy it over.
+#if defined(Q_OS_MAC)
+ static const char libraryPath[] = "DYLD_LIBRARY_PATH";
+#else
+ static const char libraryPath[] = "LD_LIBRARY_PATH";
+#endif
+ const QByteArray envLibraryPath = qgetenv(libraryPath);
+ bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
+ !environment.contains(libraryPath);
+
+ char **envp = new char *[environment.count() + 2];
+ envp[environment.count()] = 0;
+ envp[environment.count() + 1] = 0;
+
+ QHash<QByteArray, QByteArray>::ConstIterator it = environment.constBegin();
+ const QHash<QByteArray, QByteArray>::ConstIterator end = environment.constEnd();
+ for ( ; it != end; ++it) {
+ QByteArray key = it.key();
+ QByteArray value = it.value();
+ key.reserve(key.length() + 1 + value.length());
+ key.append('=');
+ key.append(value);
+
+ envp[(*envc)++] = ::strdup(key.constData());
+ }
+
+ if (needToAddLibraryPath)
+ envp[(*envc)++] = ::strdup(QByteArray(QByteArray(libraryPath) + '=' +
+ envLibraryPath).constData());
+ return envp;
+}
+
+// under QNX RTOS we have to use vfork() when multithreading
+inline pid_t qt_fork()
+{
+#if defined(Q_OS_QNX)
+ return vfork();
+#else
+ return fork();
+#endif
+}
+
+#ifdef Q_OS_MAC
+Q_GLOBAL_STATIC(QMutex, cfbundleMutex);
+#endif
+
+void QProcessPrivate::startProcess()
+{
+ Q_Q(QProcess);
+
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::startProcess()");
+#endif
+
+ processManager()->start();
+
+ // Initialize pipes
+ if (!createChannel(stdinChannel) ||
+ !createChannel(stdoutChannel) ||
+ !createChannel(stderrChannel))
+ return;
+ qt_create_pipe(childStartedPipe);
+ qt_create_pipe(deathPipe);
+
+ if (threadData->eventDispatcher) {
+ startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
+ QSocketNotifier::Read, q);
+ QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),
+ q, SLOT(_q_startupNotification()));
+
+ deathNotifier = new QSocketNotifier(deathPipe[0],
+ QSocketNotifier::Read, q);
+ QObject::connect(deathNotifier, SIGNAL(activated(int)),
+ q, SLOT(_q_processDied()));
+ }
+
+ // 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] = 0;
+
+ // Encode the program name.
+ QByteArray encodedProgramName = QFile::encodeName(program);
+#ifdef Q_OS_MAC
+ // allow invoking of .app bundles on the Mac.
+ QFileInfo fileInfo(QString::fromUtf8(encodedProgramName.constData()));
+ if (encodedProgramName.endsWith(".app") && 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.
+ QMutexLocker lock(cfbundleMutex());
+ QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
+ url = CFBundleCopyExecutableURL(bundle);
+ }
+ if (url) {
+ QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ encodedProgramName += "/Contents/MacOS/" + static_cast<QString>(str).toUtf8();
+ }
+ }
+#endif
+
+ // Add the program name to the argument list.
+ char *dupProgramName = ::strdup(encodedProgramName.constData());
+ argv[0] = dupProgramName;
+
+ // Add every argument to the list
+ for (int i = 0; i < arguments.count(); ++i) {
+ QString arg = arguments.at(i);
+#ifdef Q_OS_MAC
+ // Mac OS X uses UTF8 for exec, regardless of the system locale.
+ argv[i + 1] = ::strdup(arg.toUtf8().constData());
+#else
+ argv[i + 1] = ::strdup(arg.toLocal8Bit().constData());
+#endif
+ }
+
+ // Duplicate the environment.
+ int envc = 0;
+ char **envp = 0;
+ if (environment.d.constData())
+ envp = _q_dupEnvironment(environment.d.constData()->hash, &envc);
+
+ // Encode the working directory if it's non-empty, otherwise just pass 0.
+ const char *workingDirPtr = 0;
+ QByteArray encodedWorkingDirectory;
+ if (!workingDirectory.isEmpty()) {
+ encodedWorkingDirectory = QFile::encodeName(workingDirectory);
+ workingDirPtr = encodedWorkingDirectory.constData();
+ }
+
+ // If the program does not specify a path, generate a list of possible
+ // locations for the binary using the PATH environment variable.
+ char **path = 0;
+ int pathc = 0;
+ if (!program.contains(QLatin1Char('/'))) {
+ const QString pathEnv = QString::fromLocal8Bit(::getenv("PATH"));
+ if (!pathEnv.isEmpty()) {
+ QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
+ if (!pathEntries.isEmpty()) {
+ pathc = pathEntries.size();
+ path = new char *[pathc + 1];
+ path[pathc] = 0;
+
+ for (int k = 0; k < pathEntries.size(); ++k) {
+ QByteArray tmp = QFile::encodeName(pathEntries.at(k));
+ if (!tmp.endsWith('/')) tmp += '/';
+ tmp += encodedProgramName;
+ path[k] = ::strdup(tmp.constData());
+ }
+ }
+ }
+ }
+
+ // Start the process manager, and fork off the child process.
+ processManager()->lock();
+ pid_t childPid = qt_fork();
+ int lastForkErrno = errno;
+ if (childPid != 0) {
+ // Clean up duplicated memory.
+ free(dupProgramName);
+ for (int i = 1; i <= arguments.count(); ++i)
+ free(argv[i]);
+ for (int i = 0; i < envc; ++i)
+ free(envp[i]);
+ for (int i = 0; i < pathc; ++i)
+ free(path[i]);
+ delete [] argv;
+ delete [] envp;
+ delete [] path;
+ }
+ if (childPid < 0) {
+ // Cleanup, report error and return
+#if defined (QPROCESS_DEBUG)
+ qDebug("qt_fork failed: %s", qPrintable(qt_error_string(lastForkErrno)));
+#endif
+ processManager()->unlock();
+ q->setProcessState(QProcess::NotRunning);
+ processError = QProcess::FailedToStart;
+ q->setErrorString(QProcess::tr("Resource error (fork failure): %1").arg(qt_error_string(lastForkErrno)));
+ emit q->error(processError);
+ cleanup();
+ return;
+ }
+
+ // Start the child.
+ if (childPid == 0) {
+ execChild(workingDirPtr, path, argv, envp);
+ ::_exit(-1);
+ }
+
+ // Register the child. In the mean time, we can get a SIGCHLD, so we need
+ // to keep the lock held to avoid a race to catch the child.
+ processManager()->add(childPid, q);
+ pid = Q_PID(childPid);
+ processManager()->unlock();
+
+ // parent
+ // close the ends we don't use and make all pipes non-blocking
+ ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK);
+ qt_safe_close(childStartedPipe[1]);
+ childStartedPipe[1] = -1;
+
+ if (stdinChannel.pipe[0] != -1) {
+ qt_safe_close(stdinChannel.pipe[0]);
+ stdinChannel.pipe[0] = -1;
+ }
+
+ if (stdinChannel.pipe[1] != -1)
+ ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK);
+
+ if (stdoutChannel.pipe[1] != -1) {
+ qt_safe_close(stdoutChannel.pipe[1]);
+ stdoutChannel.pipe[1] = -1;
+ }
+
+ if (stdoutChannel.pipe[0] != -1)
+ ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK);
+
+ if (stderrChannel.pipe[1] != -1) {
+ qt_safe_close(stderrChannel.pipe[1]);
+ stderrChannel.pipe[1] = -1;
+ }
+ if (stderrChannel.pipe[0] != -1)
+ ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK);
+}
+
+void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp)
+{
+ ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
+
+ Q_Q(QProcess);
+
+ // copy the stdin socket (without closing on exec)
+ qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0);
+
+ // copy the stdout and stderr if asked to
+ if (processChannelMode != QProcess::ForwardedChannels) {
+ qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0);
+
+ // merge stdout and stderr if asked to
+ if (processChannelMode == QProcess::MergedChannels) {
+ qt_safe_dup2(fileno(stdout), fileno(stderr), 0);
+ } else {
+ qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0);
+ }
+ }
+
+ // make sure this fd is closed if execvp() succeeds
+ qt_safe_close(childStartedPipe[0]);
+
+ // enter the working directory
+ if (workingDir)
+ QT_CHDIR(workingDir);
+
+ // this is a virtual call, and it base behavior is to do nothing.
+ q->setupChildProcess();
+
+ // execute the process
+ if (!envp) {
+ qt_safe_execvp(argv[0], argv);
+ } else {
+ if (path) {
+ char **arg = path;
+ while (*arg) {
+ argv[0] = *arg;
+#if defined (QPROCESS_DEBUG)
+ fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);
+#endif
+ qt_safe_execve(argv[0], argv, envp);
+ ++arg;
+ }
+ } else {
+#if defined (QPROCESS_DEBUG)
+ fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
+#endif
+ qt_safe_execve(argv[0], argv, envp);
+ }
+ }
+
+ // notify failure
+ QString error = qt_error_string(errno);
+#if defined (QPROCESS_DEBUG)
+ fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", qPrintable(error));
+#endif
+ qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar));
+ qt_safe_close(childStartedPipe[1]);
+ childStartedPipe[1] = -1;
+}
+
+bool QProcessPrivate::processStarted()
+{
+ ushort buf[errorBufferMax];
+ int i = qt_safe_read(childStartedPipe[0], &buf, sizeof buf);
+ if (startupSocketNotifier) {
+ startupSocketNotifier->setEnabled(false);
+ startupSocketNotifier->deleteLater();
+ startupSocketNotifier = 0;
+ }
+ qt_safe_close(childStartedPipe[0]);
+ childStartedPipe[0] = -1;
+
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false");
+#endif
+
+ // did we read an error message?
+ if (i > 0)
+ q_func()->setErrorString(QString((const QChar *)buf, i / sizeof(QChar)));
+
+ return i <= 0;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStdout() const
+{
+ int nbytes = 0;
+ qint64 available = 0;
+ if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
+ available = (qint64) nbytes;
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);
+#endif
+ return available;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStderr() const
+{
+ int nbytes = 0;
+ qint64 available = 0;
+ if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
+ available = (qint64) nbytes;
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);
+#endif
+ return available;
+}
+
+qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
+{
+ qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
+ data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
+#endif
+ return bytesRead;
+}
+
+qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+{
+ qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
+ data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
+#endif
+ return bytesRead;
+}
+
+static void qt_ignore_sigpipe()
+{
+ // Set to ignore SIGPIPE once only.
+ static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (atom.testAndSetRelaxed(0, 1)) {
+ struct sigaction noaction;
+ memset(&noaction, 0, sizeof(noaction));
+ noaction.sa_handler = SIG_IGN;
+ ::sigaction(SIGPIPE, &noaction, 0);
+ }
+}
+
+qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+{
+ qt_ignore_sigpipe();
+
+ qint64 written = qt_safe_write(stdinChannel.pipe[1], data, maxlen);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld",
+ data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written);
+ if (written == -1)
+ qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno)));
+#endif
+ // If the O_NONBLOCK flag is set and If some data can be written without blocking
+ // the process, write() will transfer what it can and return the number of bytes written.
+ // Otherwise, it will return -1 and set errno to EAGAIN
+ if (written == -1 && errno == EAGAIN)
+ written = 0;
+ return written;
+}
+
+void QProcessPrivate::terminateProcess()
+{
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::killProcess()");
+#endif
+ if (pid)
+ ::kill(pid_t(pid), SIGTERM);
+}
+
+void QProcessPrivate::killProcess()
+{
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::killProcess()");
+#endif
+ if (pid)
+ ::kill(pid_t(pid), SIGKILL);
+}
+
+static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
+{
+ if (timeout < 0)
+ return qt_safe_select(nfds, fdread, fdwrite, 0, 0);
+
+ struct timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ return qt_safe_select(nfds, fdread, fdwrite, 0, &tv);
+}
+
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int qt_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1)
+ return -1;
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+bool QProcessPrivate::waitForStarted(int msecs)
+{
+ Q_Q(QProcess);
+
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs,
+ childStartedPipe[0]);
+#endif
+
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(childStartedPipe[0], &fds);
+ if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) {
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs);
+#endif
+ return false;
+ }
+
+ bool startedEmitted = _q_startupNotification();
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForStarted() == %s", startedEmitted ? "true" : "false");
+#endif
+ return startedEmitted;
+}
+
+bool QProcessPrivate::waitForReadyRead(int msecs)
+{
+ Q_Q(QProcess);
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForReadyRead(%d)", msecs);
+#endif
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ forever {
+ fd_set fdread;
+ fd_set fdwrite;
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+
+ int nfds = deathPipe[0];
+ FD_SET(deathPipe[0], &fdread);
+
+ if (processState == QProcess::Starting)
+ add_fd(nfds, childStartedPipe[0], &fdread);
+
+ if (stdoutChannel.pipe[0] != -1)
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
+ if (stderrChannel.pipe[0] != -1)
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
+
+ if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
+
+ int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
+ if (ret < 0) {
+ break;
+ }
+ if (ret == 0) {
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+ }
+
+ if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
+ if (!_q_startupNotification())
+ return false;
+ }
+
+ bool readyReadEmitted = false;
+ if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
+ bool canRead = _q_canReadStandardOutput();
+ if (processChannel == QProcess::StandardOutput && canRead)
+ readyReadEmitted = true;
+ }
+ if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
+ bool canRead = _q_canReadStandardError();
+ if (processChannel == QProcess::StandardError && canRead)
+ readyReadEmitted = true;
+ }
+ if (readyReadEmitted)
+ return true;
+
+ if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
+ _q_canWrite();
+
+ if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
+ if (_q_processDied())
+ return false;
+ }
+ }
+ return false;
+}
+
+bool QProcessPrivate::waitForBytesWritten(int msecs)
+{
+ Q_Q(QProcess);
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForBytesWritten(%d)", msecs);
+#endif
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ while (!writeBuffer.isEmpty()) {
+ fd_set fdread;
+ fd_set fdwrite;
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+
+ int nfds = deathPipe[0];
+ FD_SET(deathPipe[0], &fdread);
+
+ if (processState == QProcess::Starting)
+ add_fd(nfds, childStartedPipe[0], &fdread);
+
+ if (stdoutChannel.pipe[0] != -1)
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
+ if (stderrChannel.pipe[0] != -1)
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
+
+
+ if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
+
+ int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
+ if (ret < 0) {
+ break;
+ }
+
+ if (ret == 0) {
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+ }
+
+ if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
+ if (!_q_startupNotification())
+ return false;
+ }
+
+ if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
+ return _q_canWrite();
+
+ if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
+ _q_canReadStandardOutput();
+
+ if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
+ _q_canReadStandardError();
+
+ if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
+ if (_q_processDied())
+ return false;
+ }
+ }
+
+ return false;
+}
+
+bool QProcessPrivate::waitForFinished(int msecs)
+{
+ Q_Q(QProcess);
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+#endif
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ forever {
+ fd_set fdread;
+ fd_set fdwrite;
+ int nfds = -1;
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+
+ if (processState == QProcess::Starting)
+ add_fd(nfds, childStartedPipe[0], &fdread);
+
+ if (stdoutChannel.pipe[0] != -1)
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
+ if (stderrChannel.pipe[0] != -1)
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
+
+ if (processState == QProcess::Running)
+ add_fd(nfds, deathPipe[0], &fdread);
+
+ if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
+
+ int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
+ if (ret < 0) {
+ break;
+ }
+ if (ret == 0) {
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+ }
+
+ if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
+ if (!_q_startupNotification())
+ return false;
+ }
+ if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
+ _q_canWrite();
+
+ if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
+ _q_canReadStandardOutput();
+
+ if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
+ _q_canReadStandardError();
+
+ if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
+ if (_q_processDied())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QProcessPrivate::waitForWrite(int msecs)
+{
+ fd_set fdwrite;
+ FD_ZERO(&fdwrite);
+ FD_SET(stdinChannel.pipe[1], &fdwrite);
+ return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
+}
+
+void QProcessPrivate::findExitCode()
+{
+ Q_Q(QProcess);
+ processManager()->remove(q);
+}
+
+bool QProcessPrivate::waitForDeadChild()
+{
+ Q_Q(QProcess);
+
+ // read a byte from the death pipe
+ char c;
+ qt_safe_read(deathPipe[0], &c, 1);
+
+ // check if our process is dead
+ int exitStatus;
+ if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) {
+ processManager()->remove(q);
+ crashed = !WIFEXITED(exitStatus);
+ exitCode = WEXITSTATUS(exitStatus);
+#if defined QPROCESS_DEBUG
+ qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
+ << exitCode << ", crashed?" << crashed;
+#endif
+ return true;
+ }
+#if defined QPROCESS_DEBUG
+ qDebug() << "QProcessPrivate::waitForDeadChild() not dead!";
+#endif
+ return false;
+}
+
+void QProcessPrivate::_q_notified()
+{
+}
+
+bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
+{
+ processManager()->start();
+
+ QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
+
+ // To catch the startup of the child
+ int startedPipe[2];
+ qt_safe_pipe(startedPipe);
+ // To communicate the pid of the child
+ int pidPipe[2];
+ qt_safe_pipe(pidPipe);
+
+ pid_t childPid = qt_fork();
+ if (childPid == 0) {
+ struct sigaction noaction;
+ memset(&noaction, 0, sizeof(noaction));
+ noaction.sa_handler = SIG_IGN;
+ ::sigaction(SIGPIPE, &noaction, 0);
+
+ ::setsid();
+
+ qt_safe_close(startedPipe[0]);
+ qt_safe_close(pidPipe[0]);
+
+ pid_t doubleForkPid = qt_fork();
+ if (doubleForkPid == 0) {
+ qt_safe_close(pidPipe[1]);
+
+ if (!encodedWorkingDirectory.isEmpty())
+ QT_CHDIR(encodedWorkingDirectory.constData());
+
+ char **argv = new char *[arguments.size() + 2];
+ for (int i = 0; i < arguments.size(); ++i) {
+#ifdef Q_OS_MAC
+ argv[i + 1] = ::strdup(arguments.at(i).toUtf8().constData());
+#else
+ argv[i + 1] = ::strdup(arguments.at(i).toLocal8Bit().constData());
+#endif
+ }
+ argv[arguments.size() + 1] = 0;
+
+ if (!program.contains(QLatin1Char('/'))) {
+ const QString path = QString::fromLocal8Bit(::getenv("PATH"));
+ if (!path.isEmpty()) {
+ QStringList pathEntries = path.split(QLatin1Char(':'));
+ for (int k = 0; k < pathEntries.size(); ++k) {
+ QByteArray tmp = QFile::encodeName(pathEntries.at(k));
+ if (!tmp.endsWith('/')) tmp += '/';
+ tmp += QFile::encodeName(program);
+ argv[0] = tmp.data();
+ qt_safe_execv(argv[0], argv);
+ }
+ }
+ } else {
+ QByteArray tmp = QFile::encodeName(program);
+ argv[0] = tmp.data();
+ qt_safe_execv(argv[0], argv);
+ }
+
+ struct sigaction noaction;
+ memset(&noaction, 0, sizeof(noaction));
+ noaction.sa_handler = SIG_IGN;
+ ::sigaction(SIGPIPE, &noaction, 0);
+
+ // '\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, 0);
+
+ // '\2' means internal error
+ char c = '\2';
+ qt_safe_write(startedPipe[1], &c, 1);
+ }
+
+ qt_safe_close(startedPipe[1]);
+ qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
+ QT_CHDIR("/");
+ ::_exit(1);
+ }
+
+ qt_safe_close(startedPipe[1]);
+ qt_safe_close(pidPipe[1]);
+
+ if (childPid == -1) {
+ qt_safe_close(startedPipe[0]);
+ qt_safe_close(pidPipe[0]);
+ return false;
+ }
+
+ char reply = '\0';
+ int startResult = qt_safe_read(startedPipe[0], &reply, 1);
+ int result;
+ qt_safe_close(startedPipe[0]);
+ qt_safe_waitpid(childPid, &result, 0);
+ bool success = (startResult != -1 && reply == '\0');
+ 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;
+ }
+ }
+ qt_safe_close(pidPipe[0]);
+ return success;
+}
+
+void QProcessPrivate::initializeProcessManager()
+{
+ (void) processManager();
+}
+
+QT_END_NAMESPACE
+
+#include "qprocess_unix.moc"
+
+#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
new file mode 100644
index 0000000000..625ed9853f
--- /dev/null
+++ b/src/corelib/io/qprocess_win.cpp
@@ -0,0 +1,855 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qprocess.h"
+#include "qprocess_p.h"
+#include "qwindowspipewriter_p.h"
+
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <private/qwineventnotifier_p.h>
+#include <private/qthread_p.h>
+#include <qdebug.h>
+
+#include "private/qfsfileengine_p.h" // for longFileName
+
+
+#ifndef QT_NO_PROCESS
+
+QT_BEGIN_NAMESPACE
+
+//#define QPROCESS_DEBUG
+
+#define NOTIFYTIMEOUT 100
+
+static void qt_create_pipe(Q_PIPE *pipe, bool in)
+{
+ // Open the pipes. Make non-inheritable copies of input write and output
+ // read handles to avoid non-closable handles (this is done by the
+ // DuplicateHandle() call).
+
+#if !defined(Q_OS_WINCE)
+ SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };
+
+ HANDLE tmpHandle;
+ if (in) { // stdin
+ if (!CreatePipe(&pipe[0], &tmpHandle, &secAtt, 1024 * 1024))
+ return;
+ if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(),
+ &pipe[1], 0, FALSE, DUPLICATE_SAME_ACCESS))
+ return;
+ } else { // stdout or stderr
+ if (!CreatePipe(&tmpHandle, &pipe[1], &secAtt, 1024 * 1024))
+ return;
+ if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(),
+ &pipe[0], 0, FALSE, DUPLICATE_SAME_ACCESS))
+ return;
+ }
+
+ CloseHandle(tmpHandle);
+#else
+ Q_UNUSED(pipe);
+ Q_UNUSED(in);
+#endif
+}
+
+/*
+ Create the pipes to a QProcessPrivate::Channel.
+
+ This function must be called in order: stdin, stdout, stderr
+*/
+bool QProcessPrivate::createChannel(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);
+ }
+
+ if (channel.type == Channel::Normal) {
+ // we're piping this channel to our own process
+ qt_create_pipe(channel.pipe, &channel == &stdinChannel);
+
+ return true;
+ } else if (channel.type == Channel::Redirect) {
+ // we're redirecting the channel to/from a file
+ SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+
+ if (&channel == &stdinChannel) {
+ // try to open in read-only mode
+ channel.pipe[1] = INVALID_Q_PIPE;
+ channel.pipe[0] =
+ CreateFile((const wchar_t*)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &secAtt,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (channel.pipe[0] != INVALID_Q_PIPE)
+ return true;
+
+ q->setErrorString(QProcess::tr("Could not open input redirection for reading"));
+ } else {
+ // open in write mode
+ channel.pipe[0] = INVALID_Q_PIPE;
+ channel.pipe[1] =
+ CreateFile((const wchar_t *)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &secAtt,
+ channel.append ? OPEN_ALWAYS : CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (channel.pipe[1] != INVALID_Q_PIPE) {
+ if (channel.append) {
+ SetFilePointer(channel.pipe[1], 0, NULL, FILE_END);
+ }
+ return true;
+ }
+
+ q->setErrorString(QProcess::tr("Could not open output redirection for writing"));
+ }
+
+ // could not open file
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+ cleanup();
+ return false;
+ } else {
+ Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
+
+ Channel *source;
+ Channel *sink;
+
+ if (channel.type == Channel::PipeSource) {
+ // we are the source
+ source = &channel;
+ sink = &channel.process->stdinChannel;
+
+ 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
+ sink->pipe[0] = source->pipe[0];
+ source->pipe[0] = INVALID_Q_PIPE;
+
+ return true;
+ } else {
+ // we are the sink;
+ source = &channel.process->stdoutChannel;
+ sink = &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
+ source->pipe[1] = sink->pipe[1];
+ sink->pipe[1] = INVALID_Q_PIPE;
+
+ return true;
+ }
+ }
+}
+
+void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
+{
+ if (pipe[0] == stdinChannel.pipe[0] && pipe[1] == stdinChannel.pipe[1] && pipeWriter) {
+ delete pipeWriter;
+ pipeWriter = 0;
+ }
+
+ if (pipe[0] != INVALID_Q_PIPE) {
+ CloseHandle(pipe[0]);
+ pipe[0] = INVALID_Q_PIPE;
+ }
+ if (pipe[1] != INVALID_Q_PIPE) {
+ CloseHandle(pipe[1]);
+ pipe[1] = INVALID_Q_PIPE;
+ }
+}
+
+
+static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+{
+ 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('\\'));
+
+ // add the prgram as the first arg ... it works better
+ args = programName + QLatin1Char(' ');
+ }
+
+ for (int i=0; i<arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // in the case of \" already being in the string the \ must also be escaped
+ tmp.replace( QLatin1String("\\\""), QLatin1String("\\\\\"") );
+ // escape a single " because the arguments will be parsed
+ tmp.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\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\"
+ QString endQuote(QLatin1Char('\"'));
+ int i = tmp.length();
+ while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) {
+ --i;
+ endQuote += QLatin1Char('\\');
+ }
+ args += QLatin1String(" \"") + tmp.left(i) + endQuote;
+ } else {
+ args += QLatin1Char(' ') + tmp;
+ }
+ }
+ return args;
+}
+
+static QByteArray qt_create_environment(const QHash<QString, QString> &environment)
+{
+ QByteArray envlist;
+ if (!environment.isEmpty()) {
+ QHash<QString, QString> copy = environment;
+
+ // add PATH if necessary (for DLL loading)
+ if (!copy.contains(QLatin1String("PATH"))) {
+ QByteArray path = qgetenv("PATH");
+ if (!path.isEmpty())
+ copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path));
+ }
+
+ // add systemroot if needed
+ if (!copy.contains(QLatin1String("SYSTEMROOT"))) {
+ QByteArray systemRoot = qgetenv("SYSTEMROOT");
+ if (!systemRoot.isEmpty())
+ copy.insert(QLatin1String("SYSTEMROOT"), QString::fromLocal8Bit(systemRoot));
+ }
+
+ int pos = 0;
+ QHash<QString, QString>::ConstIterator it = copy.constBegin(),
+ end = copy.constEnd();
+
+ static const wchar_t equal = L'=';
+ static const wchar_t nul = L'\0';
+
+ 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);
+
+ tmpSize = it.key().length() * sizeof(wchar_t);
+ memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data()+pos, &equal, sizeof(wchar_t));
+ pos += sizeof(wchar_t);
+
+ tmpSize = it.value().length() * sizeof(wchar_t);
+ memcpy(envlist.data()+pos, it.value().utf16(), 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;
+}
+
+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 (!createChannel(stdinChannel) ||
+ !createChannel(stdoutChannel) ||
+ !createChannel(stderrChannel))
+ return;
+
+#if defined(Q_OS_WINCE)
+ QString args = qt_create_commandline(QString(), arguments);
+#else
+ QString args = qt_create_commandline(program, arguments);
+ QByteArray envlist;
+ if (environment.d.constData())
+ envlist = qt_create_environment(environment.d.constData()->hash);
+#endif
+ if (!nativeArguments.isEmpty()) {
+ if (!args.isEmpty())
+ args += QLatin1Char(' ');
+ args += nativeArguments;
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug("Creating process");
+ qDebug(" program : [%s]", program.toLatin1().constData());
+ qDebug(" args : %s", args.toLatin1().constData());
+ qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
+#endif
+
+#if defined(Q_OS_WINCE)
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, 0, 0, 0, 0, pid);
+#else
+ DWORD dwCreationFlags = 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]
+ };
+ success = CreateProcess(0, (wchar_t*)args.utf16(),
+ 0, 0, TRUE, dwCreationFlags,
+ environment.isEmpty() ? 0 : envlist.data(),
+ workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(),
+ &startupInfo, pid);
+ if (!success) {
+ // Capture the error string before we do CloseHandle below
+ q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string()));
+ }
+
+ if (stdinChannel.pipe[0] != INVALID_Q_PIPE) {
+ CloseHandle(stdinChannel.pipe[0]);
+ stdinChannel.pipe[0] = INVALID_Q_PIPE;
+ }
+ if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) {
+ CloseHandle(stdoutChannel.pipe[1]);
+ stdoutChannel.pipe[1] = INVALID_Q_PIPE;
+ }
+ if (stderrChannel.pipe[1] != INVALID_Q_PIPE) {
+ CloseHandle(stderrChannel.pipe[1]);
+ stderrChannel.pipe[1] = INVALID_Q_PIPE;
+ }
+#endif // Q_OS_WINCE
+
+ if (!success) {
+ cleanup();
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+ q->setProcessState(QProcess::NotRunning);
+ return;
+ }
+
+ q->setProcessState(QProcess::Running);
+ // User can call kill()/terminate() from the stateChanged() slot
+ // so check before proceeding
+ if (!pid)
+ return;
+
+ if (threadData->eventDispatcher) {
+ processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
+ QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
+ processFinishedNotifier->setEnabled(true);
+ notifier = new QTimer(q);
+ QObject::connect(notifier, SIGNAL(timeout()), q, SLOT(_q_notified()));
+ notifier->start(NOTIFYTIMEOUT);
+ }
+
+ // give the process a chance to start ...
+ Sleep(SLEEPMIN * 2);
+ _q_startupNotification();
+}
+
+bool QProcessPrivate::processStarted()
+{
+ return processState == QProcess::Running;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStdout() const
+{
+ if (stdoutChannel.pipe[0] == INVALID_Q_PIPE)
+ return 0;
+
+ DWORD bytesAvail = 0;
+#if !defined(Q_OS_WINCE)
+ PeekNamedPipe(stdoutChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
+#endif
+ if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
+ QByteArray buf(bytesAvail, 0);
+ DWORD bytesRead = 0;
+ if (ReadFile(stdoutChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (hStdout) {
+ DWORD bytesWritten = 0;
+ WriteFile(hStdout, buf.data(), bytesRead, &bytesWritten, 0);
+ }
+ }
+ bytesAvail = 0;
+ }
+#endif
+ return bytesAvail;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStderr() const
+{
+ if (stderrChannel.pipe[0] == INVALID_Q_PIPE)
+ return 0;
+
+ DWORD bytesAvail = 0;
+#if !defined(Q_OS_WINCE)
+ PeekNamedPipe(stderrChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
+#endif
+ if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
+ QByteArray buf(bytesAvail, 0);
+ DWORD bytesRead = 0;
+ if (ReadFile(stderrChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
+ HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
+ if (hStderr) {
+ DWORD bytesWritten = 0;
+ WriteFile(hStderr, buf.data(), bytesRead, &bytesWritten, 0);
+ }
+ }
+ bytesAvail = 0;
+ }
+#endif
+ return bytesAvail;
+}
+
+qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
+{
+ DWORD read = qMin(maxlen, bytesAvailableFromStdout());
+ DWORD bytesRead = 0;
+
+ if (read > 0 && !ReadFile(stdoutChannel.pipe[0], data, read, &bytesRead, 0))
+ return -1;
+ return bytesRead;
+}
+
+qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+{
+ DWORD read = qMin(maxlen, bytesAvailableFromStderr());
+ DWORD bytesRead = 0;
+
+ if (read > 0 && !ReadFile(stderrChannel.pipe[0], data, read, &bytesRead, 0))
+ return -1;
+ return bytesRead;
+}
+
+
+static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
+{
+ DWORD currentProcId = 0;
+ GetWindowThreadProcessId(hwnd, &currentProcId);
+ if (currentProcId == (DWORD)procId)
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+
+ return TRUE;
+}
+
+void QProcessPrivate::terminateProcess()
+{
+ if (pid) {
+ EnumWindows(qt_terminateApp, (LPARAM)pid->dwProcessId);
+ PostThreadMessage(pid->dwThreadId, WM_CLOSE, 0, 0);
+ }
+}
+
+void QProcessPrivate::killProcess()
+{
+ if (pid)
+ TerminateProcess(pid->hProcess, 0xf291);
+}
+
+bool QProcessPrivate::waitForStarted(int)
+{
+ Q_Q(QProcess);
+
+ if (processStarted())
+ return true;
+
+ if (processError == QProcess::FailedToStart)
+ return false;
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+bool QProcessPrivate::waitForReadyRead(int msecs)
+{
+ Q_Q(QProcess);
+
+#if defined(Q_OS_WINCE)
+ processError = QProcess::ReadError;
+ q->setErrorString(QProcess::tr("Error reading from process"));
+ emit q->error(processError);
+ return false;
+#endif
+
+ QIncrementalSleepTimer timer(msecs);
+
+ forever {
+ if (!writeBuffer.isEmpty() && !_q_canWrite())
+ return false;
+ if (pipeWriter && pipeWriter->waitForWrite(0))
+ timer.resetIncrements();
+ bool readyReadEmitted = false;
+ if (bytesAvailableFromStdout() != 0) {
+ readyReadEmitted = _q_canReadStandardOutput() ? true : readyReadEmitted;
+ timer.resetIncrements();
+ }
+
+ if (bytesAvailableFromStderr() != 0) {
+ readyReadEmitted = _q_canReadStandardError() ? true : readyReadEmitted;
+ timer.resetIncrements();
+ }
+
+ if (readyReadEmitted)
+ return true;
+
+ if (!pid)
+ return false;
+ if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
+ // find the return value if there is noew data to read
+ _q_processDied();
+ return false;
+ }
+
+ Sleep(timer.nextSleepTime());
+ if (timer.hasTimedOut())
+ break;
+ }
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+bool QProcessPrivate::waitForBytesWritten(int msecs)
+{
+ Q_Q(QProcess);
+
+#if defined(Q_OS_WINCE)
+ processError = QProcess::ReadError;
+ q->setErrorString(QProcess::tr("Error reading from process"));
+ emit q->error(processError);
+ return false;
+#endif
+
+ QIncrementalSleepTimer timer(msecs);
+
+ forever {
+ // Check if we have any data pending: the pipe writer has
+ // bytes waiting to written, or it has written data since the
+ // last time we called pipeWriter->waitForWrite().
+ bool pendingDataInPipe = pipeWriter && (pipeWriter->bytesToWrite() || pipeWriter->hadWritten());
+
+ // If we don't have pending data, and our write buffer is
+ // empty, we fail.
+ if (!pendingDataInPipe && writeBuffer.isEmpty())
+ 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;
+ }
+
+ // 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 pipeWriter is now dead, that means _q_canWrite()
+ // destroyed the writer after it successfully wrote the last
+ // batch.
+ if (!pipeWriter || pipeWriter->waitForWrite(0))
+ return true;
+
+ // If we wouldn't write anything, check if we can read stdout.
+ if (bytesAvailableFromStdout() != 0) {
+ _q_canReadStandardOutput();
+ timer.resetIncrements();
+ }
+
+ // Check if we can read stderr.
+ if (bytesAvailableFromStderr() != 0) {
+ _q_canReadStandardError();
+ timer.resetIncrements();
+ }
+
+ // 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 (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
+ _q_processDied();
+ return false;
+ }
+
+ // Only wait for as long as we've been asked.
+ if (timer.hasTimedOut())
+ break;
+ }
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+
+bool QProcessPrivate::waitForFinished(int msecs)
+{
+ Q_Q(QProcess);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+#endif
+
+ QIncrementalSleepTimer timer(msecs);
+
+ forever {
+ if (!writeBuffer.isEmpty() && !_q_canWrite())
+ return false;
+ if (pipeWriter && pipeWriter->waitForWrite(0))
+ timer.resetIncrements();
+
+ if (bytesAvailableFromStdout() != 0) {
+ _q_canReadStandardOutput();
+ timer.resetIncrements();
+ }
+
+ if (bytesAvailableFromStderr() != 0) {
+ _q_canReadStandardError();
+ timer.resetIncrements();
+ }
+
+ if (!pid)
+ return true;
+
+ if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
+ _q_processDied();
+ return true;
+ }
+
+ if (timer.hasTimedOut())
+ break;
+ }
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+
+void QProcessPrivate::findExitCode()
+{
+ DWORD theExitCode;
+ if (GetExitCodeProcess(pid->hProcess, &theExitCode)) {
+ exitCode = theExitCode;
+ //### for now we assume a crash if exit code is less than -1 or the magic number
+ crashed = (exitCode == 0xf291 || (int)exitCode < 0);
+ }
+}
+
+void QProcessPrivate::flushPipeWriter()
+{
+ if (pipeWriter && pipeWriter->bytesToWrite() > 0) {
+ pipeWriter->waitForWrite(ULONG_MAX);
+ }
+}
+
+qint64 QProcessPrivate::pipeWriterBytesToWrite() const
+{
+ return pipeWriter ? pipeWriter->bytesToWrite() : qint64(0);
+}
+
+qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+{
+ Q_Q(QProcess);
+
+#if defined(Q_OS_WINCE)
+ processError = QProcess::WriteError;
+ q->setErrorString(QProcess::tr("Error writing to process"));
+ emit q->error(processError);
+ return -1;
+#endif
+
+ if (!pipeWriter) {
+ pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
+ pipeWriter->start();
+ }
+
+ return pipeWriter->write(data, maxlen);
+}
+
+bool QProcessPrivate::waitForWrite(int msecs)
+{
+ Q_Q(QProcess);
+
+ if (!pipeWriter || pipeWriter->waitForWrite(msecs))
+ return true;
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+void QProcessPrivate::_q_notified()
+{
+ notifier->stop();
+
+ if (!writeBuffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0)))
+ _q_canWrite();
+
+ if (bytesAvailableFromStdout())
+ _q_canReadStandardOutput();
+
+ if (bytesAvailableFromStderr())
+ _q_canReadStandardError();
+
+ if (processState != QProcess::NotRunning)
+ notifier->start(NOTIFYTIMEOUT);
+}
+
+bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(workingDir);
+ QString args = qt_create_commandline(QString(), arguments);
+#else
+ QString args = qt_create_commandline(program, arguments);
+#endif
+
+ bool success = false;
+
+ PROCESS_INFORMATION pinfo;
+
+#if defined(Q_OS_WINCE)
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
+#else
+ STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ success = CreateProcess(0, (wchar_t*)args.utf16(),
+ 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
+ workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
+ &startupInfo, &pinfo);
+#endif // Q_OS_WINCE
+
+ if (success) {
+ CloseHandle(pinfo.hThread);
+ CloseHandle(pinfo.hProcess);
+ if (pid)
+ *pid = pinfo.dwProcessId;
+ }
+
+ return success;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
new file mode 100644
index 0000000000..cd8c1a3076
--- /dev/null
+++ b/src/corelib/io/qresource.cpp
@@ -0,0 +1,1496 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qresource.h"
+#include "qresource_p.h"
+#include "qresource_iterator_p.h"
+#include "qset.h"
+#include "qhash.h"
+#include "qmutex.h"
+#include "qdebug.h"
+#include "qlocale.h"
+#include "qglobal.h"
+#include "qvector.h"
+#include "qdatetime.h"
+#include "qbytearray.h"
+#include "qstringlist.h"
+#include <qshareddata.h>
+#include <qplatformdefs.h>
+#include "private/qabstractfileengine_p.h"
+
+#ifdef Q_OS_UNIX
+# include "private/qcore_unix_p.h"
+#endif
+
+//#define DEBUG_RESOURCE_MATCH
+
+#if defined(Q_OS_VXWORKS)
+# if defined(m_data)
+# undef m_data
+# endif
+# if defined(m_len)
+# undef m_len
+# endif
+#endif
+
+QT_BEGIN_NAMESPACE
+
+
+class QStringSplitter
+{
+public:
+ QStringSplitter(const QString &s)
+ : m_string(s), m_data(m_string.constData()), m_len(s.length()), m_pos(0)
+ {
+ m_splitChar = QLatin1Char('/');
+ }
+
+ inline bool hasNext() {
+ while (m_pos < m_len && m_data[m_pos] == m_splitChar)
+ ++m_pos;
+ return m_pos < m_len;
+ }
+
+ inline QStringRef next() {
+ int start = m_pos;
+ while (m_pos < m_len && m_data[m_pos] != m_splitChar)
+ ++m_pos;
+ return QStringRef(&m_string, start, m_pos - start);
+ }
+
+ QString m_string;
+ const QChar *m_data;
+ QChar m_splitChar;
+ int m_len;
+ int m_pos;
+};
+
+
+//resource glue
+class QResourceRoot
+{
+ enum Flags
+ {
+ Compressed = 0x01,
+ Directory = 0x02
+ };
+ const uchar *tree, *names, *payloads;
+ inline int findOffset(int node) const { return node * 14; } //sizeof each tree element
+ int hash(int node) const;
+ QString name(int node) const;
+ short flags(int node) const;
+public:
+ mutable QAtomicInt ref;
+
+ inline QResourceRoot(): tree(0), names(0), payloads(0) {}
+ inline QResourceRoot(const uchar *t, const uchar *n, const uchar *d) { setSource(t, n, d); }
+ virtual ~QResourceRoot() { }
+ int findNode(const QString &path, const QLocale &locale=QLocale()) const;
+ inline bool isContainer(int node) const { return flags(node) & Directory; }
+ inline bool isCompressed(int node) const { return flags(node) & Compressed; }
+ const uchar *data(int node, qint64 *size) const;
+ QStringList children(int node) const;
+ virtual QString mappingRoot() const { return QString(); }
+ bool mappingRootSubdir(const QString &path, QString *match=0) const;
+ inline bool operator==(const QResourceRoot &other) const
+ { return tree == other.tree && names == other.names && payloads == other.payloads; }
+ inline bool operator!=(const QResourceRoot &other) const
+ { return !operator==(other); }
+ enum ResourceRootType { Resource_Builtin, Resource_File, Resource_Buffer };
+ virtual ResourceRootType type() const { return Resource_Builtin; }
+
+protected:
+ inline void setSource(const uchar *t, const uchar *n, const uchar *d) {
+ tree = t;
+ names = n;
+ payloads = d;
+ }
+};
+
+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("//")))
+ path.remove(0, 1);
+ return path;
+}
+
+Q_DECLARE_TYPEINFO(QResourceRoot, Q_MOVABLE_TYPE);
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, resourceMutex, (QMutex::Recursive))
+
+typedef QList<QResourceRoot*> ResourceList;
+Q_GLOBAL_STATIC(ResourceList, resourceList)
+
+Q_GLOBAL_STATIC(QStringList, resourceSearchPaths)
+
+/*!
+ \class QResource
+ \brief The QResource class provides an interface for reading directly from resources.
+
+ \ingroup io
+
+ \reentrant
+ \since 4.2
+
+ QResource is an object that represents a set of data (and possibly
+ children) relating to a single resource entity. QResource gives direct
+ access to the bytes in their raw format. In this way direct access
+ allows reading data without buffer copying or indirection. Indirection
+ is often useful when interacting with the resource entity as if it is a
+ file, this can be achieved with QFile. The data and children behind a
+ QResource are normally compiled into an application/library, but it is
+ also possible to load a resource at runtime. When loaded at run time
+ the resource file will be loaded as one big set of data and then given
+ out in pieces via references into the resource tree.
+
+ A QResource can either be loaded with an absolute path, either treated
+ as a file system rooted with a \c{/} character, or in resource notation
+ rooted with a \c{:} character. A relative resource can also be opened
+ which will be found in the list of paths returned by QDir::searchPaths().
+
+ A QResource that is representing a file will have data backing it, this
+ data can possibly be compressed, in which case qUncompress() must be
+ used to access the real data; this happens implicitly when accessed
+ through a QFile. A QResource that is representing a directory will have
+ only children and no data.
+
+ \section1 Dynamic Resource Loading
+
+ A resource can be left out of an application's binary and loaded when
+ it is needed at run-time by using the registerResource() function. The
+ resource file passed into registerResource() must be a binary resource
+ as created by rcc. Further information about binary resources can be
+ found in \l{The Qt Resource System} documentation.
+
+ This can often be useful when loading a large set of application icons
+ that may change based on a setting, or that can be edited by a user and
+ later recreated. The resource is immediately loaded into memory, either
+ as a result of a single file read operation, or as a memory mapped file.
+
+ This approach can prove to be a significant performance gain as only a
+ single file will be loaded, and pieces of data will be given out via the
+ path requested in setFileName().
+
+ The unregisterResource() function removes a reference to a particular
+ file. If there are QResources that currently reference resources related
+ to the unregistered file, they will continue to be valid but the resource
+ file itself will be removed from the resource roots, and thus no further
+ QResource can be created pointing into this resource data. The resource
+ itself will be unmapped from memory when the last QResource that points
+ to it is destroyed.
+
+ \sa {The Qt Resource System}, QFile, QDir, QFileInfo
+*/
+
+class QResourcePrivate {
+public:
+ inline QResourcePrivate(QResource *_q) : q_ptr(_q) { clear(); }
+ inline ~QResourcePrivate() { clear(); }
+
+ void ensureInitialized() const;
+ void ensureChildren() const;
+
+ bool load(const QString &file);
+ void clear();
+
+ QLocale locale;
+ QString fileName, absoluteFilePath;
+ QList<QResourceRoot*> related;
+ uint container : 1;
+ mutable uint compressed : 1;
+ mutable qint64 size;
+ mutable const uchar *data;
+ mutable QStringList children;
+
+ QResource *q_ptr;
+ Q_DECLARE_PUBLIC(QResource)
+};
+
+void
+QResourcePrivate::clear()
+{
+ absoluteFilePath.clear();
+ compressed = 0;
+ data = 0;
+ size = 0;
+ children.clear();
+ container = 0;
+ for(int i = 0; i < related.size(); ++i) {
+ QResourceRoot *root = related.at(i);
+ if(!root->ref.deref())
+ delete root;
+ }
+ related.clear();
+}
+
+bool
+QResourcePrivate::load(const QString &file)
+{
+ related.clear();
+ QMutexLocker lock(resourceMutex());
+ const ResourceList *list = resourceList();
+ QString cleaned = cleanPath(file);
+ 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()) {
+ container = res->isContainer(node);
+ if(!container) {
+ data = res->data(node, &size);
+ compressed = res->isCompressed(node);
+ } else {
+ data = 0;
+ size = 0;
+ compressed = 0;
+ }
+ } 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)) {
+ container = true;
+ data = 0;
+ size = 0;
+ compressed = 0;
+ res->ref.ref();
+ related.append(res);
+ }
+ }
+ return !related.isEmpty();
+}
+
+void
+QResourcePrivate::ensureInitialized() const
+{
+ if(!related.isEmpty())
+ return;
+ QResourcePrivate *that = const_cast<QResourcePrivate *>(this);
+ if(fileName == QLatin1String(":"))
+ that->fileName += QLatin1Char('/');
+ that->absoluteFilePath = fileName;
+ if(!that->absoluteFilePath.startsWith(QLatin1Char(':')))
+ that->absoluteFilePath.prepend(QLatin1Char(':'));
+
+ QString path = fileName;
+ if(path.startsWith(QLatin1Char(':')))
+ path = path.mid(1);
+
+ if(path.startsWith(QLatin1Char('/'))) {
+ that->load(path);
+ } else {
+ QMutexLocker 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;
+ }
+ }
+ }
+}
+
+void
+QResourcePrivate::ensureChildren() const
+{
+ ensureInitialized();
+ if(!children.isEmpty() || !container || related.isEmpty())
+ return;
+
+ QString path = absoluteFilePath, k;
+ if(path.startsWith(QLatin1Char(':')))
+ path = path.mid(1);
+ QSet<QString> kids;
+ QString cleaned = cleanPath(path);
+ for(int i = 0; i < related.size(); ++i) {
+ QResourceRoot *res = related.at(i);
+ if(res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
+ if(!kids.contains(k)) {
+ children += k;
+ kids.insert(k);
+ }
+ } else {
+ const int node = res->findNode(cleaned);
+ if(node != -1) {
+ QStringList related_children = res->children(node);
+ for(int kid = 0; kid < related_children.size(); ++kid) {
+ k = related_children.at(kid);
+ if(!kids.contains(k)) {
+ children += k;
+ kids.insert(k);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*!
+ Constructs a QResource pointing to \a file. \a locale is used to
+ load a specific localization of a resource data.
+
+ \sa QFileInfo, QDir::searchPaths(), setFileName(), setLocale()
+*/
+
+QResource::QResource(const QString &file, const QLocale &locale) : d_ptr(new QResourcePrivate(this))
+{
+ Q_D(QResource);
+ d->fileName = file;
+ d->locale = locale;
+}
+
+/*!
+ Releases the resources of the QResource object.
+*/
+QResource::~QResource()
+{
+}
+
+/*!
+ Sets a QResource to only load the localization of resource to for \a
+ locale. If a resource for the specific locale is not found then the
+ C locale is used.
+
+ \sa setFileName()
+*/
+
+void QResource::setLocale(const QLocale &locale)
+{
+ Q_D(QResource);
+ d->clear();
+ d->locale = locale;
+}
+
+/*!
+ Returns the locale used to locate the data for the QResource.
+*/
+
+QLocale QResource::locale() const
+{
+ Q_D(const QResource);
+ return d->locale;
+}
+
+/*!
+ Sets a QResource to point to \a file. \a file can either be absolute,
+ in which case it is opened directly, if relative then the file will be
+ tried to be found in QDir::searchPaths().
+
+ \sa absoluteFilePath()
+*/
+
+void QResource::setFileName(const QString &file)
+{
+ Q_D(QResource);
+ d->clear();
+ d->fileName = file;
+}
+
+/*!
+ Returns the full path to the file that this QResource represents as it
+ was passed.
+
+ \sa absoluteFilePath()
+*/
+
+QString QResource::fileName() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->fileName;
+}
+
+/*!
+ Returns the real path that this QResource represents, if the resource
+ was found via the QDir::searchPaths() it will be indicated in the path.
+
+ \sa fileName()
+*/
+
+QString QResource::absoluteFilePath() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->absoluteFilePath;
+}
+
+/*!
+ Returns true if the resource really exists in the resource hierarchy,
+ false otherwise.
+
+*/
+
+bool QResource::isValid() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return !d->related.isEmpty();
+}
+
+/*!
+ \fn bool QResource::isFile() const
+
+ Returns true if the resource represents a file and thus has data
+ backing it, false if it represents a directory.
+
+ \sa isDir()
+*/
+
+
+/*!
+ Returns true if the resource represents a file and the data backing it
+ is in a compressed format, false otherwise.
+
+ \sa data(), isFile()
+*/
+
+bool QResource::isCompressed() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->compressed;
+}
+
+/*!
+ Returns the size of the data backing the resource.
+
+ \sa data(), isFile()
+*/
+
+qint64 QResource::size() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->size;
+}
+
+/*!
+ Returns direct access to a read only segment of data that this resource
+ represents. If the resource is compressed the data returns is
+ compressed and qUncompress() must be used to access the data. If the
+ resource is a directory 0 is returned.
+
+ \sa size(), isCompressed(), isFile()
+*/
+
+const uchar *QResource::data() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->data;
+}
+
+/*!
+ Returns true if the resource represents a directory and thus may have
+ children() in it, false if it represents a file.
+
+ \sa isFile()
+*/
+
+bool QResource::isDir() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->container;
+}
+
+/*!
+ Returns a list of all resources in this directory, if the resource
+ represents a file the list will be empty.
+
+ \sa isDir()
+*/
+
+QStringList QResource::children() const
+{
+ Q_D(const QResource);
+ d->ensureChildren();
+ return d->children;
+}
+
+/*!
+ \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 /) [%s]",
+ path.toLocal8Bit().data());
+ return;
+ }
+ QMutexLocker 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()
+{
+ QMutexLocker lock(resourceMutex());
+ return *resourceSearchPaths();
+}
+
+inline int QResourceRoot::hash(int node) const
+{
+ if(!node) //root
+ return 0;
+ const int offset = findOffset(node);
+ int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ name_offset += 2; //jump past name length
+ return (names[name_offset+0] << 24) + (names[name_offset+1] << 16) +
+ (names[name_offset+2] << 8) + (names[name_offset+3] << 0);
+}
+inline QString QResourceRoot::name(int node) const
+{
+ if(!node) // root
+ return QString();
+ const int offset = findOffset(node);
+
+ QString ret;
+ int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ const short name_length = (names[name_offset+0] << 8) +
+ (names[name_offset+1] << 0);
+ name_offset += 2;
+ name_offset += 4; //jump past hash
+
+ ret.resize(name_length);
+ QChar *strData = ret.data();
+ for(int i = 0; i < name_length*2; i+=2) {
+ QChar c(names[name_offset+i+1], names[name_offset+i]);
+ *strData = c;
+ ++strData;
+ }
+ return ret;
+}
+
+int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
+{
+ QString path = _path;
+ {
+ QString root = mappingRoot();
+ if(!root.isEmpty()) {
+ if(root == path) {
+ path = QLatin1Char('/');
+ } 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('/');
+ }
+ }
+ }
+#ifdef DEBUG_RESOURCE_MATCH
+ qDebug() << "!!!!" << "START" << path << locale.country() << locale.language();
+#endif
+
+ if(path == QLatin1String("/"))
+ return 0;
+
+ //the root node is always first
+ int child_count = (tree[6] << 24) + (tree[7] << 16) +
+ (tree[8] << 8) + (tree[9] << 0);
+ int child = (tree[10] << 24) + (tree[11] << 16) +
+ (tree[12] << 8) + (tree[13] << 0);
+
+ //now iterate up the tree
+ int node = -1;
+
+ QStringSplitter splitter(path);
+ while (child_count && splitter.hasNext()) {
+ QStringRef segment = splitter.next();
+
+#ifdef DEBUG_RESOURCE_MATCH
+ qDebug() << " CHILDREN" << segment;
+ for(int j = 0; j < child_count; ++j) {
+ qDebug() << " " << child+j << " :: " << name(child+j);
+ }
+#endif
+ const int h = qHash(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 int sub_node_hash = hash(child+sub_node);
+ if(h == sub_node_hash)
+ break;
+ else if(h < sub_node_hash)
+ r = sub_node - 1;
+ else
+ l = sub_node;
+ sub_node = (l + r + 1) / 2;
+ }
+ sub_node += child;
+
+ //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
+ --sub_node;
+ 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
+
+ const short flags = (tree[offset+0] << 8) +
+ (tree[offset+1] << 0);
+ offset += 2;
+
+ if(!splitter.hasNext()) {
+ if(!(flags & Directory)) {
+ const short country = (tree[offset+0] << 8) +
+ (tree[offset+1] << 0);
+ offset += 2;
+
+ const short language = (tree[offset+0] << 8) +
+ (tree[offset+1] << 0);
+ offset += 2;
+#ifdef DEBUG_RESOURCE_MATCH
+ qDebug() << " " << "LOCALE" << country << language;
+#endif
+ if(country == locale.country() && 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)) {
+ node = sub_node;
+ }
+ continue;
+ } else {
+#ifdef DEBUG_RESOURCE_MATCH
+ qDebug() << "!!!!" << "FINISHED" << __LINE__ << sub_node;
+#endif
+
+ return sub_node;
+ }
+ }
+
+ if(!(flags & Directory))
+ return -1;
+
+ child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ offset += 4;
+ child = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ break;
+ }
+ }
+ }
+ if(!found)
+ break;
+ }
+#ifdef DEBUG_RESOURCE_MATCH
+ qDebug() << "!!!!" << "FINISHED" << __LINE__ << node;
+#endif
+ return node;
+}
+short QResourceRoot::flags(int node) const
+{
+ if(node == -1)
+ return 0;
+ const int offset = findOffset(node) + 4; //jump past name
+ return (tree[offset+0] << 8) + (tree[offset+1] << 0);
+}
+const uchar *QResourceRoot::data(int node, qint64 *size) const
+{
+ if(node == -1) {
+ *size = 0;
+ return 0;
+ }
+ int offset = findOffset(node) + 4; //jump past name
+
+ const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);
+ offset += 2;
+
+ offset += 4; //jump past locale
+
+ if(!(flags & Directory)) {
+ const int data_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ const uint data_length = (payloads[data_offset+0] << 24) + (payloads[data_offset+1] << 16) +
+ (payloads[data_offset+2] << 8) + (payloads[data_offset+3] << 0);
+ const uchar *ret = payloads+data_offset+4;
+ *size = data_length;
+ return ret;
+ }
+ *size = 0;
+ return 0;
+}
+QStringList QResourceRoot::children(int node) const
+{
+ if(node == -1)
+ return QStringList();
+ int offset = findOffset(node) + 4; //jump past name
+
+ const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);
+ offset += 2;
+
+ QStringList ret;
+ if(flags & Directory) {
+ const int child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ offset += 4;
+ const int child_off = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
+ (tree[offset+2] << 8) + (tree[offset+3] << 0);
+ for(int i = child_off; i < child_off+child_count; ++i)
+ ret << name(i);
+ }
+ return ret;
+}
+bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const
+{
+ const QString root = mappingRoot();
+ if(!root.isEmpty()) {
+ const QStringList root_segments = root.split(QLatin1Char('/'), QString::SkipEmptyParts),
+ path_segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ if(path_segments.size() <= root_segments.size()) {
+ int matched = 0;
+ for(int i = 0; i < path_segments.size(); ++i) {
+ if(root_segments[i] != path_segments[i])
+ break;
+ ++matched;
+ }
+ if(matched == path_segments.size()) {
+ if(match && root_segments.size() > matched)
+ *match = root_segments.at(matched);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
+ const unsigned char *name, const unsigned char *data)
+{
+ QMutexLocker lock(resourceMutex());
+ if(version == 0x01 && resourceList()) {
+ bool found = false;
+ QResourceRoot res(tree, name, data);
+ for(int i = 0; i < resourceList()->size(); ++i) {
+ if(*resourceList()->at(i) == res) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ QResourceRoot *root = new QResourceRoot(tree, name, data);
+ root->ref.ref();
+ resourceList()->append(root);
+ }
+ return true;
+ }
+ return false;
+}
+
+Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tree,
+ const unsigned char *name, const unsigned char *data)
+{
+ QMutexLocker lock(resourceMutex());
+ if(version == 0x01 && resourceList()) {
+ QResourceRoot res(tree, name, data);
+ for(int i = 0; i < resourceList()->size(); ) {
+ if(*resourceList()->at(i) == res) {
+ QResourceRoot *root = resourceList()->takeAt(i);
+ if(!root->ref.deref())
+ delete root;
+ } else {
+ ++i;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+//run time resource creation
+
+class QDynamicBufferResourceRoot: public QResourceRoot
+{
+ QString root;
+ const uchar *buffer;
+
+public:
+ inline QDynamicBufferResourceRoot(const QString &_root) : root(_root), buffer(0) { }
+ inline ~QDynamicBufferResourceRoot() { }
+ inline const uchar *mappingBuffer() const { return buffer; }
+ virtual QString mappingRoot() const { return root; }
+ virtual ResourceRootType type() const { return Resource_Buffer; }
+
+ bool registerSelf(const uchar *b) {
+ //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') {
+ return false;
+ }
+ offset += 4;
+
+ const int version = (b[offset+0] << 24) + (b[offset+1] << 16) +
+ (b[offset+2] << 8) + (b[offset+3] << 0);
+ offset += 4;
+
+ const int tree_offset = (b[offset+0] << 24) + (b[offset+1] << 16) +
+ (b[offset+2] << 8) + (b[offset+3] << 0);
+ offset += 4;
+
+ const int data_offset = (b[offset+0] << 24) + (b[offset+1] << 16) +
+ (b[offset+2] << 8) + (b[offset+3] << 0);
+ offset += 4;
+
+ const int name_offset = (b[offset+0] << 24) + (b[offset+1] << 16) +
+ (b[offset+2] << 8) + (b[offset+3] << 0);
+ offset += 4;
+
+ if(version == 0x01) {
+ buffer = b;
+ setSource(b+tree_offset, b+name_offset, b+data_offset);
+ return true;
+ }
+ return false;
+ }
+};
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined (Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+#define QT_USE_MMAP
+#endif
+
+// most of the headers below are already included in qplatformdefs.h
+// also this lacks Large File support but that's probably irrelevant
+#if defined(QT_USE_MMAP)
+// for mmap
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <sys/mman.h>
+#include <errno.h>
+QT_END_INCLUDE_NAMESPACE
+#endif
+
+
+
+class QDynamicFileResourceRoot: public QDynamicBufferResourceRoot
+{
+ QString fileName;
+ // for mmap'ed files, this is what needs to be unmapped.
+ uchar *unmapPointer;
+ unsigned int unmapLength;
+
+public:
+ inline QDynamicFileResourceRoot(const QString &_root) : QDynamicBufferResourceRoot(_root), unmapPointer(0), unmapLength(0) { }
+ ~QDynamicFileResourceRoot() {
+#if defined(QT_USE_MMAP)
+ if (unmapPointer) {
+ munmap((char*)unmapPointer, unmapLength);
+ unmapPointer = 0;
+ unmapLength = 0;
+ } else
+#endif
+ {
+ delete [] (uchar *)mappingBuffer();
+ }
+ }
+ QString mappingFile() const { return fileName; }
+ virtual ResourceRootType type() const { return Resource_File; }
+
+ bool registerSelf(const QString &f) {
+ bool fromMM = false;
+ uchar *data = 0;
+ unsigned int data_len = 0;
+
+#ifdef QT_USE_MMAP
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef MAP_FAILED
+#define MAP_FAILED -1
+#endif
+
+ int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
+#if defined(Q_OS_WIN)
+ _S_IREAD | _S_IWRITE
+#else
+ 0666
+#endif
+ );
+ if (fd >= 0) {
+ QT_STATBUF st;
+ if (!QT_FSTAT(fd, &st)) {
+ uchar *ptr;
+ ptr = reinterpret_cast<uchar *>(
+ mmap(0, st.st_size, // any address, whole file
+ PROT_READ, // read-only memory
+ MAP_FILE | MAP_PRIVATE, // swap-backed map from file
+ fd, 0)); // from offset 0 of fd
+ if (ptr && ptr != reinterpret_cast<uchar *>(MAP_FAILED)) {
+ data = ptr;
+ data_len = st.st_size;
+ fromMM = true;
+ }
+ }
+ ::close(fd);
+ }
+#endif // QT_USE_MMAP
+ if(!data) {
+ QFile file(f);
+ if (!file.exists())
+ return false;
+ data_len = file.size();
+ data = new uchar[data_len];
+
+ bool ok = false;
+ if (file.open(QIODevice::ReadOnly))
+ ok = (data_len == (uint)file.read((char*)data, data_len));
+ if (!ok) {
+ delete [] data;
+ data = 0;
+ data_len = 0;
+ return false;
+ }
+ fromMM = false;
+ }
+ if(data && QDynamicBufferResourceRoot::registerSelf(data)) {
+ if(fromMM) {
+ unmapPointer = data;
+ unmapLength = data_len;
+ }
+ fileName = f;
+ return true;
+ }
+ return false;
+ }
+};
+
+static QString qt_resource_fixResourceRoot(QString r) {
+ if(!r.isEmpty()) {
+ if(r.startsWith(QLatin1Char(':')))
+ r = r.mid(1);
+ if(!r.isEmpty())
+ r = QDir::cleanPath(r);
+ }
+ return r;
+}
+
+
+/*!
+ \fn bool QResource::registerResource(const QString &rccFileName, const QString &mapRoot)
+
+ Registers the resource with the given \a rccFileName at the location in the
+ resource tree specified by \a mapRoot, and returns true if the file is
+ successfully opened; otherwise returns false.
+
+ \sa unregisterResource()
+*/
+
+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 [%s] must be rooted in an absolute path (start with /) [%s]",
+ rccFilename.toLocal8Bit().data(), resourceRoot.toLocal8Bit().data());
+ return false;
+ }
+
+ QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(r);
+ if(root->registerSelf(rccFilename)) {
+ root->ref.ref();
+ QMutexLocker lock(resourceMutex());
+ resourceList()->append(root);
+ return true;
+ }
+ delete root;
+ return false;
+}
+
+/*!
+ \fn bool QResource::unregisterResource(const QString &rccFileName, const QString &mapRoot)
+
+ Unregisters the resource with the given \a rccFileName at the location in
+ the resource tree specified by \a mapRoot, and returns true if the
+ resource is successfully unloaded and no references exist for the
+ resource; otherwise returns false.
+
+ \sa registerResource()
+*/
+
+bool
+QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
+{
+ QString r = qt_resource_fixResourceRoot(resourceRoot);
+
+ QMutexLocker lock(resourceMutex());
+ ResourceList *list = resourceList();
+ 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(root->mappingFile() == rccFilename && root->mappingRoot() == r) {
+ resourceList()->removeAt(i);
+ if(!root->ref.deref()) {
+ delete root;
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+
+/*!
+ \fn bool QResource::registerResource(const uchar *rccData, const QString &mapRoot)
+ \since 4.3
+
+ Registers the resource with the given \a rccData at the location in the
+ resource tree specified by \a mapRoot, and returns true if the file is
+ successfully opened; otherwise returns false.
+
+ \warning The data must remain valid throughout the life of any QFile
+ that may reference the resource data.
+
+ \sa unregisterResource()
+*/
+
+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 /) [%s]",
+ rccData, resourceRoot.toLocal8Bit().data());
+ return false;
+ }
+
+ QDynamicBufferResourceRoot *root = new QDynamicBufferResourceRoot(r);
+ if(root->registerSelf(rccData)) {
+ root->ref.ref();
+ QMutexLocker lock(resourceMutex());
+ resourceList()->append(root);
+ return true;
+ }
+ delete root;
+ return false;
+}
+
+/*!
+ \fn bool QResource::unregisterResource(const uchar *rccData, const QString &mapRoot)
+ \since 4.3
+
+ Unregisters the resource with the given \a rccData at the location in the
+ resource tree specified by \a mapRoot, and returns true if the resource is
+ successfully unloaded and no references exist into the resource; otherwise returns false.
+
+ \sa registerResource()
+*/
+
+bool
+QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot)
+{
+ QString r = qt_resource_fixResourceRoot(resourceRoot);
+
+ QMutexLocker lock(resourceMutex());
+ ResourceList *list = resourceList();
+ 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(root->mappingBuffer() == rccData && root->mappingRoot() == r) {
+ resourceList()->removeAt(i);
+ if(!root->ref.deref()) {
+ delete root;
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+//resource engine
+class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate
+{
+protected:
+ Q_DECLARE_PUBLIC(QResourceFileEngine)
+private:
+ uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
+ bool unmap(uchar *ptr);
+ qint64 offset;
+ QResource resource;
+ QByteArray uncompressed;
+protected:
+ QResourceFileEnginePrivate() : offset(0) { }
+};
+
+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;
+}
+
+QResourceFileEngine::QResourceFileEngine(const QString &file) :
+ QAbstractFileEngine(*new QResourceFileEnginePrivate)
+{
+ Q_D(QResourceFileEngine);
+ d->resource.setFileName(file);
+ if(d->resource.isCompressed() && d->resource.size()) {
+#ifndef QT_NO_COMPRESS
+ d->uncompressed = qUncompress(d->resource.data(), d->resource.size());
+#else
+ Q_ASSERT(!"QResourceFileEngine::open: Qt built without support for compression");
+#endif
+ }
+}
+
+QResourceFileEngine::~QResourceFileEngine()
+{
+}
+
+void QResourceFileEngine::setFileName(const QString &file)
+{
+ Q_D(QResourceFileEngine);
+ d->resource.setFileName(file);
+}
+
+bool QResourceFileEngine::open(QIODevice::OpenMode flags)
+{
+ Q_D(QResourceFileEngine);
+ if (d->resource.fileName().isEmpty()) {
+ qWarning("QResourceFileEngine::open: Missing file name");
+ return false;
+ }
+ if(flags & QIODevice::WriteOnly)
+ return false;
+ if(!d->resource.isValid())
+ return false;
+ return true;
+}
+
+bool QResourceFileEngine::close()
+{
+ Q_D(QResourceFileEngine);
+ d->offset = 0;
+ d->uncompressed.clear();
+ return true;
+}
+
+bool QResourceFileEngine::flush()
+{
+ return true;
+}
+
+qint64 QResourceFileEngine::read(char *data, qint64 len)
+{
+ Q_D(QResourceFileEngine);
+ if(len > size()-d->offset)
+ len = size()-d->offset;
+ if(len <= 0)
+ return 0;
+ if(d->resource.isCompressed())
+ memcpy(data, d->uncompressed.constData()+d->offset, len);
+ else
+ 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);
+ if(!d->resource.isValid())
+ return 0;
+ if(d->resource.isCompressed())
+ return d->uncompressed.size();
+ return d->resource.size();
+}
+
+qint64 QResourceFileEngine::pos() const
+{
+ Q_D(const QResourceFileEngine);
+ return d->offset;
+}
+
+bool QResourceFileEngine::atEnd() const
+{
+ Q_D(const QResourceFileEngine);
+ if(!d->resource.isValid())
+ return true;
+ return d->offset == size();
+}
+
+bool QResourceFileEngine::seek(qint64 pos)
+{
+ Q_D(QResourceFileEngine);
+ if(!d->resource.isValid())
+ return false;
+
+ 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 = 0;
+ if(!d->resource.isValid())
+ return ret;
+
+ 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) {
+ ret |= ExistsFlag;
+ if(d->resource.absoluteFilePath() == QLatin1String(":/"))
+ 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 (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('/'));
+ if (slash == -1)
+ return QLatin1String(":");
+ else if (slash <= 1)
+ return QLatin1String(":/");
+ return path.left(slash);
+
+ } else if(file == CanonicalName || file == CanonicalPathName) {
+ const QString absoluteFilePath = d->resource.absoluteFilePath();
+ if(file == CanonicalPathName) {
+ const int slash = absoluteFilePath.lastIndexOf(QLatin1Char('/'));
+ if (slash != -1)
+ return absoluteFilePath.left(slash);
+ }
+ return absoluteFilePath;
+ }
+ return d->resource.fileName();
+}
+
+bool QResourceFileEngine::isRelativePath() const
+{
+ return false;
+}
+
+uint QResourceFileEngine::ownerId(FileOwner) const
+{
+ static const uint nobodyID = (uint) -2;
+ return nobodyID;
+}
+
+QString QResourceFileEngine::owner(FileOwner) const
+{
+ return QString();
+}
+
+QDateTime QResourceFileEngine::fileTime(FileTime) const
+{
+ return QDateTime();
+}
+
+/*!
+ \internal
+*/
+QAbstractFileEngine::Iterator *QResourceFileEngine::beginEntryList(QDir::Filters filters,
+ const QStringList &filterNames)
+{
+ return new QResourceFileEngineIterator(filters, filterNames);
+}
+
+/*!
+ \internal
+*/
+QAbstractFileEngine::Iterator *QResourceFileEngine::endEntryList()
+{
+ return 0;
+}
+
+bool QResourceFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
+{
+ Q_D(QResourceFileEngine);
+ if (extension == MapExtension) {
+ const MapExtensionOption *options = (MapExtensionOption*)(option);
+ MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
+ returnValue->address = d->map(options->offset, options->size, options->flags);
+ return (returnValue->address != 0);
+ }
+ if (extension == UnMapExtension) {
+ UnMapExtensionOption *options = (UnMapExtensionOption*)option;
+ return d->unmap(options->address);
+ }
+ return false;
+}
+
+bool QResourceFileEngine::supportsExtension(Extension extension) const
+{
+ return (extension == UnMapExtension || extension == MapExtension);
+}
+
+uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
+{
+ Q_Q(QResourceFileEngine);
+ Q_UNUSED(flags);
+ if (offset < 0 || size <= 0 || !resource.isValid() || offset + size > resource.size()) {
+ q->setError(QFile::UnspecifiedError, QString());
+ return 0;
+ }
+ uchar *address = const_cast<uchar *>(resource.data());
+ return (address + offset);
+}
+
+bool QResourceFileEnginePrivate::unmap(uchar *ptr)
+{
+ Q_UNUSED(ptr);
+ return true;
+}
+
+Q_CORE_EXPORT void qInitResourceIO() { } // ### Qt 5: remove
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
new file mode 100644
index 0000000000..ba993c4361
--- /dev/null
+++ b/src/corelib/io/qresource.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRESOURCE_H
+#define QRESOURCE_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qlocale.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QResourcePrivate;
+
+class Q_CORE_EXPORT QResource
+{
+public:
+ QResource(const QString &file=QString(), const QLocale &locale=QLocale());
+ ~QResource();
+
+ void setFileName(const QString &file);
+ QString fileName() const;
+ QString absoluteFilePath() const;
+
+ void setLocale(const QLocale &locale);
+ QLocale locale() const;
+
+ bool isValid() const;
+
+ bool isCompressed() const;
+ qint64 size() const;
+ const uchar *data() const;
+
+ static void addSearchPath(const QString &path);
+ static QStringList searchPaths();
+
+ static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
+ static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());
+
+ static bool registerResource(const uchar *rccData, const QString &resourceRoot=QString());
+ static bool unregisterResource(const uchar *rccData, const QString &resourceRoot=QString());
+
+protected:
+ friend class QResourceFileEngine;
+ friend class QResourceFileEngineIterator;
+ bool isDir() const;
+ inline bool isFile() const { return !isDir(); }
+ QStringList children() const;
+
+protected:
+ QScopedPointer<QResourcePrivate> d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QResource)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QRESOURCE_H
diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp
new file mode 100644
index 0000000000..b49f228248
--- /dev/null
+++ b/src/corelib/io/qresource_iterator.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qresource.h"
+#include "qresource_iterator_p.h"
+
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+QResourceFileEngineIterator::QResourceFileEngineIterator(QDir::Filters filters,
+ const QStringList &filterNames)
+ : QAbstractFileEngineIterator(filters, filterNames), index(-1)
+{
+}
+
+QResourceFileEngineIterator::~QResourceFileEngineIterator()
+{
+}
+
+QString QResourceFileEngineIterator::next()
+{
+ if (!hasNext())
+ return QString();
+ ++index;
+ return currentFilePath();
+}
+
+bool QResourceFileEngineIterator::hasNext() const
+{
+ if (index == -1) {
+ // Lazy initialization of the iterator
+ QResource resource(path());
+ if (!resource.isValid())
+ return false;
+
+ // Initialize and move to the next entry.
+ entries = resource.children();
+ index = 0;
+ }
+
+ return index < entries.size();
+}
+
+QString QResourceFileEngineIterator::currentFileName() const
+{
+ if (index <= 0 || index > entries.size())
+ return QString();
+ return entries.at(index - 1);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h
new file mode 100644
index 0000000000..2f647a6695
--- /dev/null
+++ b/src/corelib/io/qresource_iterator_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRESOURCE_ITERATOR_P_H
+#define QRESOURCE_ITERATOR_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 "qabstractfileengine.h"
+#include "qdir.h"
+
+QT_BEGIN_NAMESPACE
+
+class QResourceFileEngineIteratorPrivate;
+class QResourceFileEngineIterator : public QAbstractFileEngineIterator
+{
+public:
+ QResourceFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
+ ~QResourceFileEngineIterator();
+
+ QString next();
+ bool hasNext() const;
+
+ QString currentFileName() const;
+
+private:
+ mutable QStringList entries;
+ mutable int index;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
new file mode 100644
index 0000000000..b7218c9377
--- /dev/null
+++ b/src/corelib/io/qresource_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRESOURCE_P_H
+#define QRESOURCE_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/qabstractfileengine.h"
+
+QT_BEGIN_NAMESPACE
+
+class QResourceFileEnginePrivate;
+class QResourceFileEngine : public QAbstractFileEngine
+{
+private:
+ Q_DECLARE_PRIVATE(QResourceFileEngine)
+public:
+ explicit QResourceFileEngine(const QString &path);
+ ~QResourceFileEngine();
+
+ virtual void setFileName(const QString &file);
+
+ virtual bool open(QIODevice::OpenMode flags) ;
+ virtual bool close();
+ virtual bool flush();
+ virtual qint64 size() const;
+ virtual qint64 pos() const;
+ virtual bool atEnd() const;
+ virtual bool seek(qint64);
+ virtual qint64 read(char *data, qint64 maxlen);
+ virtual qint64 write(const char *data, qint64 len);
+
+ virtual bool remove();
+ virtual bool copy(const QString &newName);
+ virtual bool rename(const QString &newName);
+ virtual bool link(const QString &newName);
+
+ virtual bool isSequential() const;
+
+ virtual bool isRelativePath() const;
+
+ virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
+ virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
+
+ virtual bool setSize(qint64 size);
+
+ virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+
+ virtual bool caseSensitive() const;
+
+ virtual FileFlags fileFlags(FileFlags type) const;
+
+ virtual bool setPermissions(uint perms);
+
+ virtual QString fileName(QAbstractFileEngine::FileName file) const;
+
+ virtual uint ownerId(FileOwner) const;
+ virtual QString owner(FileOwner) const;
+
+ virtual QDateTime fileTime(FileTime time) const;
+
+ virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
+ virtual Iterator *endEntryList();
+
+ bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
+ bool supportsExtension(Extension extension) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QRESOURCE_P_H
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
new file mode 100644
index 0000000000..b084ca5d62
--- /dev/null
+++ b/src/corelib/io/qsettings.cpp
@@ -0,0 +1,3843 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdebug.h>
+#include "qplatformdefs.h"
+#include "qsettings.h"
+
+#ifndef QT_NO_SETTINGS
+
+#include "qsettings_p.h"
+#include "qcache.h"
+#include "qfile.h"
+#include "qdir.h"
+#include "qfileinfo.h"
+#include "qmutex.h"
+#include "qlibraryinfo.h"
+#include "qtemporaryfile.h"
+
+#ifndef QT_NO_TEXTCODEC
+# include "qtextcodec.h"
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+#include "qsize.h"
+#include "qpoint.h"
+#include "qrect.h"
+#endif // !QT_NO_GEOM_VARIANT
+
+#ifndef QT_NO_QOBJECT
+#include "qcoreapplication.h"
+
+#ifdef Q_OS_WIN // for homedirpath reading from registry
+#include "qt_windows.h"
+#include <private/qsystemlibrary_p.h>
+
+#endif // Q_OS_WIN
+#endif // QT_NO_QOBJECT
+
+#ifdef Q_OS_VXWORKS
+# include <ioLib.h>
+#endif
+
+#include <stdlib.h>
+
+#ifndef CSIDL_COMMON_APPDATA
+#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data
+#endif
+
+#ifndef CSIDL_APPDATA
+#define CSIDL_APPDATA 0x001a // <username>\Application Data
+#endif
+
+#ifdef Q_AUTOTEST_EXPORT
+# define Q_AUTOTEST_EXPORT_HELPER Q_AUTOTEST_EXPORT
+#else
+# define Q_AUTOTEST_EXPORT_HELPER static
+#endif
+
+// ************************************************************************
+// QConfFile
+
+/*
+ QConfFile objects are explicitly shared within the application.
+ This ensures that modification to the settings done through one
+ QSettings object are immediately reflected in other setting
+ objects of the same application.
+*/
+
+QT_BEGIN_NAMESPACE
+
+struct QConfFileCustomFormat
+{
+ QString extension;
+ QSettings::ReadFunc readFunc;
+ QSettings::WriteFunc writeFunc;
+ Qt::CaseSensitivity caseSensitivity;
+};
+
+typedef QHash<QString, QConfFile *> ConfFileHash;
+typedef QCache<QString, QConfFile> ConfFileCache;
+typedef QHash<int, QString> PathHash;
+typedef QVector<QConfFileCustomFormat> CustomFormatVector;
+
+Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc)
+Q_GLOBAL_STATIC(ConfFileCache, unusedCacheFunc)
+Q_GLOBAL_STATIC(PathHash, pathHashFunc)
+Q_GLOBAL_STATIC(CustomFormatVector, customFormatVectorFunc)
+Q_GLOBAL_STATIC(QMutex, globalMutex)
+static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
+
+#ifndef Q_OS_WIN
+inline bool qt_isEvilFsTypeName(const char *name)
+{
+ return (qstrncmp(name, "nfs", 3) == 0
+ || qstrncmp(name, "autofs", 6) == 0
+ || qstrncmp(name, "cachefs", 7) == 0);
+}
+
+#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include <sys/param.h>
+# include <sys/mount.h>
+QT_END_INCLUDE_NAMESPACE
+
+Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
+{
+ struct statfs buf;
+ if (fstatfs(handle, &buf) != 0)
+ return false;
+ return qt_isEvilFsTypeName(buf.f_fstypename);
+}
+
+#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include <sys/vfs.h>
+# ifdef QT_LINUXBASE
+ // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
+# include <sys/statfs.h>
+# endif
+QT_END_INCLUDE_NAMESPACE
+# ifndef NFS_SUPER_MAGIC
+# define NFS_SUPER_MAGIC 0x00006969
+# endif
+# ifndef AUTOFS_SUPER_MAGIC
+# define AUTOFS_SUPER_MAGIC 0x00000187
+# endif
+# ifndef AUTOFSNG_SUPER_MAGIC
+# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
+# endif
+
+Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
+{
+ struct statfs buf;
+ if (fstatfs(handle, &buf) != 0)
+ return false;
+ return buf.f_type == NFS_SUPER_MAGIC
+ || buf.f_type == AUTOFS_SUPER_MAGIC
+ || buf.f_type == AUTOFSNG_SUPER_MAGIC;
+}
+
+#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
+ || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
+ || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include <sys/statvfs.h>
+QT_END_INCLUDE_NAMESPACE
+
+Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
+{
+ struct statvfs buf;
+ if (fstatvfs(handle, &buf) != 0)
+ return false;
+#if defined(Q_OS_NETBSD)
+ return qt_isEvilFsTypeName(buf.f_fstypename);
+#else
+ return qt_isEvilFsTypeName(buf.f_basetype);
+#endif
+}
+#else
+Q_AUTOTEST_EXPORT_HELPER inline bool qIsLikelyToBeNfs(int /* handle */)
+{
+ return true;
+}
+#endif
+
+static bool unixLock(int handle, int lockType)
+{
+ /*
+ NFS hangs on the fcntl() call below when statd or lockd isn't
+ running. There's no way to detect this. Our work-around for
+ now is to disable locking when we detect NFS (or AutoFS or
+ CacheFS, which are probably wrapping NFS).
+ */
+ if (qIsLikelyToBeNfs(handle))
+ return false;
+
+ struct flock fl;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = lockType;
+ return fcntl(handle, F_SETLKW, &fl) == 0;
+}
+#endif
+
+QConfFile::QConfFile(const QString &fileName, bool _userPerms)
+ : name(fileName), size(0), ref(1), userPerms(_userPerms)
+{
+ usedHashFunc()->insert(name, this);
+}
+
+QConfFile::~QConfFile()
+{
+ if (usedHashFunc())
+ usedHashFunc()->remove(name);
+}
+
+ParsedSettingsMap QConfFile::mergedKeyMap() const
+{
+ ParsedSettingsMap result = originalKeys;
+ ParsedSettingsMap::const_iterator i;
+
+ for (i = removedKeys.begin(); i != removedKeys.end(); ++i)
+ result.remove(i.key());
+ for (i = addedKeys.begin(); i != addedKeys.end(); ++i)
+ result.insert(i.key(), i.value());
+ return result;
+}
+
+bool QConfFile::isWritable() const
+{
+ QFileInfo fileInfo(name);
+
+#ifndef QT_NO_TEMPORARYFILE
+ if (fileInfo.exists()) {
+#endif
+ QFile file(name);
+ return file.open(QFile::ReadWrite);
+#ifndef QT_NO_TEMPORARYFILE
+ } else {
+ // Create the directories to the file.
+ QDir dir(fileInfo.absolutePath());
+ if (!dir.exists()) {
+ if (!dir.mkpath(dir.absolutePath()))
+ return false;
+ }
+
+ // we use a temporary file to avoid race conditions
+ QTemporaryFile file(name);
+ return file.open();
+ }
+#endif
+}
+
+QConfFile *QConfFile::fromName(const QString &fileName, bool _userPerms)
+{
+ QString absPath = QFileInfo(fileName).absoluteFilePath();
+
+ ConfFileHash *usedHash = usedHashFunc();
+ ConfFileCache *unusedCache = unusedCacheFunc();
+
+ QConfFile *confFile = 0;
+ QMutexLocker locker(globalMutex());
+
+ if (!(confFile = usedHash->value(absPath))) {
+ if ((confFile = unusedCache->take(absPath)))
+ usedHash->insert(absPath, confFile);
+ }
+ if (confFile) {
+ confFile->ref.ref();
+ return confFile;
+ }
+ return new QConfFile(absPath, _userPerms);
+}
+
+void QConfFile::clearCache()
+{
+ QMutexLocker locker(globalMutex());
+ unusedCacheFunc()->clear();
+}
+
+// ************************************************************************
+// QSettingsPrivate
+
+QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
+ : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true),
+ pendingChanges(false), status(QSettings::NoError)
+{
+}
+
+QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application)
+ : format(format), scope(scope), organizationName(organization), applicationName(application),
+ iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
+{
+}
+
+QSettingsPrivate::~QSettingsPrivate()
+{
+}
+
+QString QSettingsPrivate::actualKey(const QString &key) const
+{
+ QString n = normalizedKey(key);
+ Q_ASSERT_X(!n.isEmpty(), "QSettings", "empty key");
+ n.prepend(groupPrefix);
+ return n;
+}
+
+/*
+ Returns a string that never starts nor ends with a slash (or an
+ empty string). Examples:
+
+ "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 result = key;
+
+ 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;
+ }
+ ++i; // leave the slash alone
+ }
+
+after_loop:
+ if (!result.isEmpty())
+ result.truncate(i - 1); // remove the trailing slash
+ return result;
+}
+
+// see also qsettings_win.cpp and qsettings_mac.cpp
+
+#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
+QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application)
+{
+ return new QConfFileSettingsPrivate(format, scope, organization, application);
+}
+#endif
+
+#if !defined(Q_OS_WIN)
+QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
+{
+ return new QConfFileSettingsPrivate(fileName, format);
+}
+#endif
+
+void QSettingsPrivate::processChild(QString key, ChildSpec spec, QMap<QString, QString> &result)
+{
+ if (spec != AllKeys) {
+ int slashPos = key.indexOf(QLatin1Char('/'));
+ if (slashPos == -1) {
+ if (spec != ChildKeys)
+ return;
+ } else {
+ if (spec != ChildGroups)
+ return;
+ key.truncate(slashPos);
+ }
+ }
+ result.insert(key, QString());
+}
+
+void QSettingsPrivate::beginGroupOrArray(const QSettingsGroup &group)
+{
+ groupStack.push(group);
+ if (!group.name().isEmpty()) {
+ groupPrefix += group.name();
+ groupPrefix += QLatin1Char('/');
+ }
+}
+
+/*
+ We only set an error if there isn't one set already. This way the user always gets the
+ first error that occurred. We always allow clearing errors.
+*/
+
+void QSettingsPrivate::setStatus(QSettings::Status status) const
+{
+ if (status == QSettings::NoError || this->status == QSettings::NoError)
+ this->status = status;
+}
+
+void QSettingsPrivate::update()
+{
+ flush();
+ pendingChanges = false;
+}
+
+void QSettingsPrivate::requestUpdate()
+{
+ if (!pendingChanges) {
+ pendingChanges = true;
+#ifndef QT_NO_QOBJECT
+ Q_Q(QSettings);
+ QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
+#else
+ update();
+#endif
+ }
+}
+
+QStringList QSettingsPrivate::variantListToStringList(const QVariantList &l)
+{
+ QStringList result;
+ QVariantList::const_iterator it = l.constBegin();
+ for (; it != l.constEnd(); ++it)
+ result.append(variantToString(*it));
+ return result;
+}
+
+QVariant QSettingsPrivate::stringListToVariantList(const QStringList &l)
+{
+ QStringList outStringList = l;
+ for (int i = 0; i < outStringList.count(); ++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 {
+ QVariantList variantList;
+ for (int j = 0; j < l.count(); ++j)
+ variantList.append(stringToVariant(l.at(j)));
+ return variantList;
+ }
+ }
+ }
+ return outStringList;
+}
+
+QString QSettingsPrivate::variantToString(const QVariant &v)
+{
+ QString result;
+
+ switch (v.type()) {
+ case QVariant::Invalid:
+ result = QLatin1String("@Invalid()");
+ break;
+
+ case QVariant::ByteArray: {
+ QByteArray a = v.toByteArray();
+ result = QLatin1String("@ByteArray(");
+ result += QString::fromLatin1(a.constData(), a.size());
+ result += QLatin1Char(')');
+ break;
+ }
+
+ case QVariant::String:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Bool:
+ case QVariant::Double:
+ case QVariant::KeySequence: {
+ result = v.toString();
+ if (result.startsWith(QLatin1Char('@')))
+ result.prepend(QLatin1Char('@'));
+ break;
+ }
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Rect: {
+ QRect r = qvariant_cast<QRect>(v);
+ result += QLatin1String("@Rect(");
+ result += QString::number(r.x());
+ result += QLatin1Char(' ');
+ result += QString::number(r.y());
+ result += QLatin1Char(' ');
+ result += QString::number(r.width());
+ result += QLatin1Char(' ');
+ result += QString::number(r.height());
+ result += QLatin1Char(')');
+ break;
+ }
+ case QVariant::Size: {
+ QSize s = qvariant_cast<QSize>(v);
+ result += QLatin1String("@Size(");
+ result += QString::number(s.width());
+ result += QLatin1Char(' ');
+ result += QString::number(s.height());
+ result += QLatin1Char(')');
+ break;
+ }
+ case QVariant::Point: {
+ QPoint p = qvariant_cast<QPoint>(v);
+ result += QLatin1String("@Point(");
+ result += QString::number(p.x());
+ result += QLatin1Char(' ');
+ result += QString::number(p.y());
+ result += QLatin1Char(')');
+ break;
+ }
+#endif // !QT_NO_GEOM_VARIANT
+
+ default: {
+#ifndef QT_NO_DATASTREAM
+ QByteArray a;
+ {
+ QDataStream s(&a, QIODevice::WriteOnly);
+ s.setVersion(QDataStream::Qt_4_0);
+ s << v;
+ }
+
+ result = QLatin1String("@Variant(");
+ result += QString::fromLatin1(a.constData(), a.size());
+ result += QLatin1Char(')');
+#else
+ Q_ASSERT(!"QSettings: Cannot save custom types without QDataStream support");
+#endif
+ break;
+ }
+ }
+
+ return result;
+}
+
+
+QVariant QSettingsPrivate::stringToVariant(const QString &s)
+{
+ if (s.startsWith(QLatin1Char('@'))) {
+ if (s.endsWith(QLatin1Char(')'))) {
+ if (s.startsWith(QLatin1String("@ByteArray("))) {
+ return QVariant(s.toLatin1().mid(11, s.size() - 12));
+ } else if (s.startsWith(QLatin1String("@Variant("))) {
+#ifndef QT_NO_DATASTREAM
+ QByteArray a(s.toLatin1().mid(9));
+ QDataStream stream(&a, QIODevice::ReadOnly);
+ stream.setVersion(QDataStream::Qt_4_0);
+ QVariant result;
+ stream >> result;
+ return result;
+#else
+ Q_ASSERT(!"QSettings: Cannot load custom types without QDataStream support");
+#endif
+#ifndef QT_NO_GEOM_VARIANT
+ } else if (s.startsWith(QLatin1String("@Rect("))) {
+ 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("))) {
+ 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("))) {
+ 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()")) {
+ return QVariant();
+ }
+
+ }
+ if (s.startsWith(QLatin1String("@@")))
+ return QVariant(s.mid(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) {
+ 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 == '.') {
+ result += (char)ch;
+ } else if (ch <= 0xFF) {
+ result += '%';
+ result += hexDigits[ch / 16];
+ result += hexDigits[ch % 16];
+ } else {
+ result += "%U";
+ QByteArray hexCode;
+ for (int i = 0; i < 4; ++i) {
+ hexCode.prepend(hexDigits[ch % 16]);
+ ch >>= 4;
+ }
+ result += hexCode;
+ }
+ }
+}
+
+bool QSettingsPrivate::iniUnescapedKey(const QByteArray &key, int from, int to, QString &result)
+{
+ bool lowercaseOnly = true;
+ int i = from;
+ result.reserve(result.length() + (to - from));
+ while (i < to) {
+ int ch = (uchar)key.at(i);
+
+ if (ch == '\\') {
+ result += QLatin1Char('/');
+ ++i;
+ continue;
+ }
+
+ if (ch != '%' || i == to - 1) {
+ if (uint(ch - 'A') <= 'Z' - 'A') // only for ASCII
+ lowercaseOnly = false;
+ result += QLatin1Char(ch);
+ ++i;
+ continue;
+ }
+
+ int numDigits = 2;
+ int firstDigitPos = i + 1;
+
+ ch = key.at(i + 1);
+ if (ch == 'U') {
+ ++firstDigitPos;
+ numDigits = 4;
+ }
+
+ if (firstDigitPos + numDigits > to) {
+ result += QLatin1Char('%');
+ // ### missing U
+ ++i;
+ continue;
+ }
+
+ bool ok;
+ ch = key.mid(firstDigitPos, numDigits).toInt(&ok, 16);
+ if (!ok) {
+ result += QLatin1Char('%');
+ // ### missing U
+ ++i;
+ continue;
+ }
+
+ QChar qch(ch);
+ if (qch.isUpper())
+ lowercaseOnly = false;
+ result += qch;
+ i = firstDigitPos + numDigits;
+ }
+ return lowercaseOnly;
+}
+
+void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result, QTextCodec *codec)
+{
+ bool needsQuotes = false;
+ bool escapeNextIfDigit = false;
+ int i;
+ int startPos = result.size();
+
+ result.reserve(startPos + str.size() * 3 / 2);
+ for (i = 0; i < str.size(); ++i) {
+ uint ch = str.at(i).unicode();
+ if (ch == ';' || ch == ',' || ch == '=')
+ needsQuotes = true;
+
+ if (escapeNextIfDigit
+ && ((ch >= '0' && ch <= '9')
+ || (ch >= 'a' && ch <= 'f')
+ || (ch >= 'A' && ch <= 'F'))) {
+ result += "\\x";
+ result += QByteArray::number(ch, 16);
+ continue;
+ }
+
+ escapeNextIfDigit = false;
+
+ switch (ch) {
+ case '\0':
+ result += "\\0";
+ escapeNextIfDigit = true;
+ break;
+ case '\a':
+ result += "\\a";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ case '\v':
+ result += "\\v";
+ break;
+ case '"':
+ case '\\':
+ result += '\\';
+ result += (char)ch;
+ break;
+ default:
+ if (ch <= 0x1F || (ch >= 0x7F && !codec)) {
+ result += "\\x";
+ result += QByteArray::number(ch, 16);
+ escapeNextIfDigit = true;
+#ifndef QT_NO_TEXTCODEC
+ } else if (codec) {
+ // slow
+ result += codec->fromUnicode(str.at(i));
+#endif
+ } else {
+ result += (char)ch;
+ }
+ }
+ }
+
+ if (needsQuotes
+ || (startPos < result.size() && (result.at(startPos) == ' '
+ || result.at(result.size() - 1) == ' '))) {
+ result.insert(startPos, '"');
+ result += '"';
+ }
+}
+
+inline static void iniChopTrailingSpaces(QString &str)
+{
+ int n = str.size() - 1;
+ QChar ch;
+ while (n >= 0 && ((ch = str.at(n)) == QLatin1Char(' ') || ch == QLatin1Char('\t')))
+ str.truncate(n--);
+}
+
+void QSettingsPrivate::iniEscapedStringList(const QStringList &strs, QByteArray &result, QTextCodec *codec)
+{
+ if (strs.isEmpty()) {
+ /*
+ We need to distinguish between empty lists and one-item
+ lists that contain an empty string. Ideally, we'd have a
+ @EmptyList() symbol but that would break compatibility
+ with Qt 4.0. @Invalid() stands for QVariant(), and
+ QVariant().toStringList() returns an empty QStringList,
+ so we're in good shape.
+
+ ### Qt 5: Use a nicer syntax, e.g. @List, for variant lists
+ */
+ result += "@Invalid()";
+ } else {
+ for (int i = 0; i < strs.size(); ++i) {
+ if (i != 0)
+ result += ", ";
+ iniEscapedString(strs.at(i), result, codec);
+ }
+ }
+}
+
+bool QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, int to,
+ QString &stringResult, QStringList &stringListResult,
+ QTextCodec *codec)
+{
+ static const char escapeCodes[][2] =
+ {
+ { 'a', '\a' },
+ { 'b', '\b' },
+ { 'f', '\f' },
+ { 'n', '\n' },
+ { 'r', '\r' },
+ { 't', '\t' },
+ { 'v', '\v' },
+ { '"', '"' },
+ { '?', '?' },
+ { '\'', '\'' },
+ { '\\', '\\' }
+ };
+ static const int numEscapeCodes = sizeof(escapeCodes) / sizeof(escapeCodes[0]);
+
+ bool isStringList = false;
+ bool inQuotedString = false;
+ bool currentValueIsQuoted = false;
+ int escapeVal = 0;
+ int i = from;
+ char ch;
+
+StSkipSpaces:
+ while (i < to && ((ch = str.at(i)) == ' ' || ch == '\t'))
+ ++i;
+ // fallthrough
+
+StNormal:
+ while (i < to) {
+ switch (str.at(i)) {
+ case '\\':
+ ++i;
+ if (i >= to)
+ goto end;
+
+ ch = str.at(i++);
+ for (int j = 0; j < numEscapeCodes; ++j) {
+ if (ch == escapeCodes[j][0]) {
+ stringResult += QLatin1Char(escapeCodes[j][1]);
+ goto StNormal;
+ }
+ }
+
+ if (ch == 'x') {
+ escapeVal = 0;
+
+ if (i >= to)
+ goto end;
+
+ ch = str.at(i);
+ if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))
+ goto StHexEscape;
+ } else if (ch >= '0' && ch <= '7') {
+ escapeVal = ch - '0';
+ goto StOctEscape;
+ } else if (ch == '\n' || ch == '\r') {
+ if (i < to) {
+ 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)
+ ++i;
+ }
+ } else {
+ // the character is skipped
+ }
+ break;
+ case '"':
+ ++i;
+ currentValueIsQuoted = true;
+ inQuotedString = !inQuotedString;
+ if (!inQuotedString)
+ goto StSkipSpaces;
+ break;
+ case ',':
+ if (!inQuotedString) {
+ if (!currentValueIsQuoted)
+ iniChopTrailingSpaces(stringResult);
+ if (!isStringList) {
+ isStringList = true;
+ stringListResult.clear();
+ stringResult.squeeze();
+ }
+ stringListResult.append(stringResult);
+ stringResult.clear();
+ currentValueIsQuoted = false;
+ ++i;
+ goto StSkipSpaces;
+ }
+ // fallthrough
+ default: {
+ int j = i + 1;
+ while (j < to) {
+ ch = str.at(j);
+ if (ch == '\\' || ch == '"' || ch == ',')
+ break;
+ ++j;
+ }
+
+#ifndef QT_NO_TEXTCODEC
+ if (codec) {
+ stringResult += codec->toUnicode(str.constData() + i, j - i);
+ } else
+#endif
+ {
+ int n = stringResult.size();
+ stringResult.resize(n + (j - i));
+ QChar *resultData = stringResult.data() + n;
+ for (int k = i; k < j; ++k)
+ *resultData++ = QLatin1Char(str.at(k));
+ }
+ i = j;
+ }
+ }
+ }
+ goto end;
+
+StHexEscape:
+ if (i >= to) {
+ stringResult += QChar(escapeVal);
+ goto end;
+ }
+
+ ch = str.at(i);
+ if (ch >= 'a')
+ ch -= 'a' - 'A';
+ if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
+ escapeVal <<= 4;
+ escapeVal += strchr(hexDigits, ch) - hexDigits;
+ ++i;
+ goto StHexEscape;
+ } else {
+ stringResult += QChar(escapeVal);
+ goto StNormal;
+ }
+
+StOctEscape:
+ if (i >= to) {
+ stringResult += QChar(escapeVal);
+ goto end;
+ }
+
+ ch = str.at(i);
+ if (ch >= '0' && ch <= '7') {
+ escapeVal <<= 3;
+ escapeVal += ch - '0';
+ ++i;
+ goto StOctEscape;
+ } else {
+ stringResult += QChar(escapeVal);
+ goto StNormal;
+ }
+
+end:
+ if (!currentValueIsQuoted)
+ iniChopTrailingSpaces(stringResult);
+ if (isStringList)
+ stringListResult.append(stringResult);
+ return isStringList;
+}
+
+QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
+{
+ int l = s.length();
+ Q_ASSERT(l > 0);
+ Q_ASSERT(s.at(idx) == QLatin1Char('('));
+ Q_ASSERT(s.at(l - 1) == QLatin1Char(')'));
+
+ QStringList result;
+ QString item;
+
+ for (++idx; idx < l; ++idx) {
+ QChar c = s.at(idx);
+ if (c == QLatin1Char(')')) {
+ Q_ASSERT(idx == l - 1);
+ result.append(item);
+ } else if (c == QLatin1Char(' ')) {
+ result.append(item);
+ item.clear();
+ } else {
+ item.append(c);
+ }
+ }
+
+ return result;
+}
+
+// ************************************************************************
+// QConfFileSettingsPrivate
+
+/*
+ If we don't have the permission to read the file, returns false.
+ If the file doesn't exist, returns true.
+*/
+static bool checkAccess(const QString &name)
+{
+ QFileInfo fileInfo(name);
+
+ if (fileInfo.exists()) {
+ QFile file(name);
+ // if the file exists but we can't open it, report an error
+ return file.open(QFile::ReadOnly);
+ } else {
+ return true;
+ }
+}
+
+void QConfFileSettingsPrivate::initFormat()
+{
+ extension = (format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini");
+ readFunc = 0;
+ writeFunc = 0;
+#if defined(Q_OS_MAC)
+ caseSensitivity = (format == QSettings::NativeFormat) ? Qt::CaseSensitive : IniCaseSensitivity;
+#else
+ caseSensitivity = IniCaseSensitivity;
+#endif
+
+ if (format > QSettings::IniFormat) {
+ QMutexLocker locker(globalMutex());
+ const CustomFormatVector *customFormatVector = customFormatVectorFunc();
+
+ int i = (int)format - (int)QSettings::CustomFormat1;
+ if (i >= 0 && i < customFormatVector->size()) {
+ QConfFileCustomFormat info = customFormatVector->at(i);
+ extension = info.extension;
+ readFunc = info.readFunc;
+ writeFunc = info.writeFunc;
+ caseSensitivity = info.caseSensitivity;
+ }
+ }
+}
+
+void QConfFileSettingsPrivate::initAccess()
+{
+ bool readAccess = false;
+ if (confFiles[spec]) {
+ readAccess = checkAccess(confFiles[spec]->name);
+ if (format > QSettings::IniFormat) {
+ if (!readFunc)
+ readAccess = false;
+ }
+ }
+
+ if (!readAccess)
+ setStatus(QSettings::AccessError);
+
+ sync(); // loads the files the first time
+}
+
+#ifdef Q_OS_WIN
+static QString windowsConfigPath(int type)
+{
+ QString result;
+
+#ifndef QT_NO_QOBJECT
+ // We can't use QLibrary if there is QT_NO_QOBJECT is defined
+ // This only happens when bootstrapping qmake.
+#ifndef Q_OS_WINCE
+ QSystemLibrary library(QLatin1String("shell32"));
+#else
+ QSystemLibrary library(QLatin1String("coredll"));
+#endif // Q_OS_WINCE
+ typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL);
+ GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
+ if (SHGetSpecialFolderPath) {
+ wchar_t path[MAX_PATH];
+ SHGetSpecialFolderPath(0, path, type, FALSE);
+ result = QString::fromWCharArray(path);
+ }
+
+#endif // QT_NO_QOBJECT
+
+ if (result.isEmpty()) {
+ switch (type) {
+#ifndef Q_OS_WINCE
+ case CSIDL_COMMON_APPDATA:
+ result = QLatin1String("C:\\temp\\qt-common");
+ break;
+ case CSIDL_APPDATA:
+ result = QLatin1String("C:\\temp\\qt-user");
+ break;
+#else
+ case CSIDL_COMMON_APPDATA:
+ result = QLatin1String("\\Temp\\qt-common");
+ break;
+ case CSIDL_APPDATA:
+ result = QLatin1String("\\Temp\\qt-user");
+ break;
+#endif
+ default:
+ ;
+ }
+ }
+
+ return result;
+}
+#endif // Q_OS_WIN
+
+static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope)
+{
+ return int((uint(format) << 1) | uint(scope == QSettings::SystemScope));
+}
+
+static void initDefaultPaths(QMutexLocker *locker)
+{
+ PathHash *pathHash = pathHashFunc();
+ QString homePath = QDir::homePath();
+ QString systemPath;
+
+ locker->unlock();
+
+ /*
+ QLibraryInfo::location() uses QSettings, so in order to
+ avoid a dead-lock, we can't hold the global mutex while
+ calling it.
+ */
+ systemPath = QLibraryInfo::location(QLibraryInfo::SettingsPath);
+ systemPath += QLatin1Char('/');
+
+ locker->relock();
+ if (pathHash->isEmpty()) {
+ /*
+ Lazy initialization of pathHash. We initialize the
+ IniFormat paths and (on Unix) the NativeFormat paths.
+ (The NativeFormat paths are not configurable for the
+ Windows registry and the Mac CFPreferences.)
+ */
+#ifdef Q_OS_WIN
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope),
+ windowsConfigPath(CSIDL_APPDATA) + QDir::separator());
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
+ windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
+#else
+ QString userPath;
+ char *env = getenv("XDG_CONFIG_HOME");
+ if (env == 0) {
+ userPath = homePath;
+ userPath += QLatin1Char('/');
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ userPath += QLatin1String("Settings");
+#else
+ userPath += QLatin1String(".config");
+#endif
+ } else if (*env == '/') {
+ userPath = QLatin1String(env);
+ } else {
+ userPath = homePath;
+ userPath += QLatin1Char('/');
+ userPath += QLatin1String(env);
+ }
+ userPath += QLatin1Char('/');
+
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath);
+#ifndef Q_OS_MAC
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath);
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath);
+#endif
+#endif
+ }
+}
+
+static QString getPath(QSettings::Format format, QSettings::Scope scope)
+{
+ Q_ASSERT((int)QSettings::NativeFormat == 0);
+ Q_ASSERT((int)QSettings::IniFormat == 1);
+
+ QMutexLocker locker(globalMutex());
+ PathHash *pathHash = pathHashFunc();
+ if (pathHash->isEmpty())
+ initDefaultPaths(&locker);
+
+ QString result = pathHash->value(pathHashKey(format, scope));
+ if (!result.isEmpty())
+ return result;
+
+ // fall back on INI path
+ return pathHash->value(pathHashKey(QSettings::IniFormat, scope));
+}
+
+QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
+ QSettings::Scope scope,
+ const QString &organization,
+ const QString &application)
+ : QSettingsPrivate(format, scope, organization, application),
+ nextPosition(0x40000000) // big positive number
+{
+ int i;
+ initFormat();
+
+ QString org = organization;
+ if (org.isEmpty()) {
+ setStatus(QSettings::AccessError);
+ org = QLatin1String("Unknown Organization");
+ }
+
+ QString appFile = org + QDir::separator() + application + extension;
+ QString orgFile = org + extension;
+
+ if (scope == QSettings::UserScope) {
+ QString userPath = getPath(format, QSettings::UserScope);
+ if (!application.isEmpty())
+ confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true));
+ confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true));
+ }
+
+ QString systemPath = getPath(format, QSettings::SystemScope);
+ if (!application.isEmpty())
+ confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false));
+ confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false));
+
+ for (i = 0; i < NumConfFiles; ++i) {
+ if (confFiles[i]) {
+ spec = i;
+ break;
+ }
+ }
+
+ initAccess();
+}
+
+QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
+ QSettings::Format format)
+ : QSettingsPrivate(format),
+ nextPosition(0x40000000) // big positive number
+{
+ initFormat();
+
+ confFiles[0].reset(QConfFile::fromName(fileName, true));
+
+ initAccess();
+}
+
+QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
+{
+ QMutexLocker locker(globalMutex());
+ ConfFileHash *usedHash = usedHashFunc();
+ ConfFileCache *unusedCache = unusedCacheFunc();
+
+ for (int i = 0; i < NumConfFiles; ++i) {
+ if (confFiles[i] && !confFiles[i]->ref.deref()) {
+ if (confFiles[i]->size == 0) {
+ delete confFiles[i].take();
+ } else {
+ if (usedHash)
+ usedHash->remove(confFiles[i]->name);
+ if (unusedCache) {
+ QT_TRY {
+ // compute a better size?
+ unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
+ 10 + (confFiles[i]->originalKeys.size() / 4));
+ confFiles[i].take();
+ } QT_CATCH(...) {
+ // out of memory. Do not cache the file.
+ delete confFiles[i].take();
+ }
+ } else {
+ // unusedCache is gone - delete the entry to prevent a memory leak
+ delete confFiles[i].take();
+ }
+ }
+ }
+ // prevent the ScopedPointer to deref it again.
+ confFiles[i].take();
+ }
+}
+
+void QConfFileSettingsPrivate::remove(const QString &key)
+{
+ QConfFile *confFile = confFiles[spec].data();
+ if (!confFile)
+ return;
+
+ QSettingsKey theKey(key, caseSensitivity);
+ QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity);
+ QMutexLocker locker(&confFile->mutex);
+
+ ensureSectionParsed(confFile, theKey);
+ ensureSectionParsed(confFile, prefix);
+
+ ParsedSettingsMap::iterator 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);
+ while (j != confFile->originalKeys.constEnd() && j.key().startsWith(prefix)) {
+ confFile->removedKeys.insert(j.key(), QVariant());
+ ++j;
+ }
+ if (confFile->originalKeys.contains(theKey))
+ confFile->removedKeys.insert(theKey, QVariant());
+}
+
+void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
+{
+ QConfFile *confFile = confFiles[spec].data();
+ if (!confFile)
+ return;
+
+ QSettingsKey theKey(key, caseSensitivity, nextPosition++);
+ QMutexLocker locker(&confFile->mutex);
+ confFile->removedKeys.remove(theKey);
+ confFile->addedKeys.insert(theKey, value);
+}
+
+bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
+{
+ QSettingsKey theKey(key, caseSensitivity);
+ ParsedSettingsMap::const_iterator j;
+ bool found = false;
+
+ for (int i = 0; i < NumConfFiles; ++i) {
+ if (QConfFile *confFile = confFiles[i].data()) {
+ QMutexLocker locker(&confFile->mutex);
+
+ if (!confFile->addedKeys.isEmpty()) {
+ j = confFile->addedKeys.constFind(theKey);
+ found = (j != confFile->addedKeys.constEnd());
+ }
+ if (!found) {
+ ensureSectionParsed(confFile, theKey);
+ j = confFile->originalKeys.constFind(theKey);
+ found = (j != confFile->originalKeys.constEnd()
+ && !confFile->removedKeys.contains(theKey));
+ }
+
+ if (found && value)
+ *value = *j;
+
+ if (found)
+ return true;
+ if (!fallbacks)
+ break;
+ }
+ }
+ return false;
+}
+
+QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
+{
+ QMap<QString, QString> result;
+ ParsedSettingsMap::const_iterator j;
+
+ QSettingsKey thePrefix(prefix, caseSensitivity);
+ int startPos = prefix.size();
+
+ for (int i = 0; i < NumConfFiles; ++i) {
+ if (QConfFile *confFile = confFiles[i].data()) {
+ QMutexLocker locker(&confFile->mutex);
+
+ if (thePrefix.isEmpty()) {
+ ensureAllSectionsParsed(confFile);
+ } 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(j.key().originalCaseKey().mid(startPos), spec, result);
+ ++j;
+ }
+
+ j = const_cast<const ParsedSettingsMap *>(
+ &confFile->addedKeys)->lowerBound(thePrefix);
+ while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ processChild(j.key().originalCaseKey().mid(startPos), spec, result);
+ ++j;
+ }
+
+ if (!fallbacks)
+ break;
+ }
+ }
+ return result.keys();
+}
+
+void QConfFileSettingsPrivate::clear()
+{
+ QConfFile *confFile = confFiles[spec].data();
+ if (!confFile)
+ return;
+
+ QMutexLocker locker(&confFile->mutex);
+ ensureAllSectionsParsed(confFile);
+ confFile->addedKeys.clear();
+ confFile->removedKeys = confFile->originalKeys;
+}
+
+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 (int i = 0; i < NumConfFiles; ++i) {
+ QConfFile *confFile = confFiles[i].data();
+ if (confFile) {
+ QMutexLocker locker(&confFile->mutex);
+ syncConfFile(i);
+ }
+ }
+}
+
+void QConfFileSettingsPrivate::flush()
+{
+ sync();
+}
+
+QString QConfFileSettingsPrivate::fileName() const
+{
+ QConfFile *confFile = confFiles[spec].data();
+ if (!confFile)
+ return QString();
+ return confFile->name;
+}
+
+bool QConfFileSettingsPrivate::isWritable() const
+{
+ if (format > QSettings::IniFormat && !writeFunc)
+ return false;
+
+ QConfFile *confFile = confFiles[spec].data();
+ if (!confFile)
+ return false;
+
+ return confFile->isWritable();
+}
+
+void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
+{
+ QConfFile *confFile = confFiles[confFileNo].data();
+ bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
+ bool ok;
+
+ /*
+ We can often optimize the read-only case, if the file on disk
+ hasn't changed.
+ */
+ if (readOnly) {
+ QFileInfo fileInfo(confFile->name);
+ if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified())
+ return;
+ }
+
+ /*
+ Open the configuration file and try to use it using a named
+ semaphore on Windows and an advisory lock on Unix-based
+ systems. This protect us against other QSettings instances
+ trying to access the same file from other threads or
+ processes.
+
+ As it stands now, the locking mechanism doesn't work for
+ .plist files.
+ */
+ QFile file(confFile->name);
+ bool createFile = !file.exists();
+ if (!readOnly && confFile->isWritable())
+ file.open(QFile::ReadWrite);
+ if (!file.isOpen())
+ file.open(QFile::ReadOnly);
+
+#ifdef Q_OS_WIN
+ HANDLE readSemaphore = 0;
+ HANDLE writeSemaphore = 0;
+ static const int FileLockSemMax = 50;
+ int numReadLocks = readOnly ? 1 : FileLockSemMax;
+
+ if (file.isOpen()) {
+ // Acquire the write lock if we will be writing
+ if (!readOnly) {
+ QString writeSemName = QLatin1String("QSettingsWriteSem ");
+ writeSemName.append(file.fileName());
+
+ writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
+
+ if (writeSemaphore) {
+ WaitForSingleObject(writeSemaphore, INFINITE);
+ } else {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+ }
+
+ // Acquire all the read locks if we will be writing, to make sure nobody
+ // reads while we're writing. If we are only reading, acquire a single
+ // read lock.
+ QString readSemName(QLatin1String("QSettingsReadSem "));
+ readSemName.append(file.fileName());
+
+ readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
+
+ if (readSemaphore) {
+ for (int i = 0; i < numReadLocks; ++i)
+ WaitForSingleObject(readSemaphore, INFINITE);
+ } else {
+ setStatus(QSettings::AccessError);
+ if (writeSemaphore != 0) {
+ ReleaseSemaphore(writeSemaphore, 1, 0);
+ CloseHandle(writeSemaphore);
+ }
+ return;
+ }
+ }
+#else
+ if (file.isOpen())
+ unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK);
+#endif
+
+ // If we have created the file, apply the file perms
+ if (file.isOpen()) {
+ if (createFile) {
+ QFile::Permissions perms = file.permissions() | QFile::ReadOwner | QFile::WriteOwner;
+ if (!confFile->userPerms)
+ perms |= QFile::ReadGroup | QFile::ReadOther;
+ file.setPermissions(perms);
+ }
+ }
+
+ /*
+ We hold the lock. Let's reread the file if it has changed
+ since last time we read it.
+ */
+ QFileInfo fileInfo(confFile->name);
+ bool mustReadFile = true;
+
+ if (!readOnly)
+ mustReadFile = (confFile->size != fileInfo.size()
+ || (confFile->size != 0 && confFile->timeStamp != fileInfo.lastModified()));
+
+ if (mustReadFile) {
+ confFile->unparsedIniSections.clear();
+ confFile->originalKeys.clear();
+
+ /*
+ Files that we can't read (because of permissions or
+ because they don't exist) are treated as empty files.
+ */
+ if (file.isReadable() && fileInfo.size() != 0) {
+#ifdef Q_OS_MAC
+ if (format == QSettings::NativeFormat) {
+ ok = readPlistFile(confFile->name, &confFile->originalKeys);
+ } else
+#endif
+ {
+ if (format <= QSettings::IniFormat) {
+ QByteArray data = file.readAll();
+ ok = readIniFile(data, &confFile->unparsedIniSections);
+ } else {
+ if (readFunc) {
+ QSettings::SettingsMap tempNewKeys;
+ ok = readFunc(file, tempNewKeys);
+
+ if (ok) {
+ QSettings::SettingsMap::const_iterator i = tempNewKeys.constBegin();
+ while (i != tempNewKeys.constEnd()) {
+ confFile->originalKeys.insert(QSettingsKey(i.key(),
+ caseSensitivity),
+ i.value());
+ ++i;
+ }
+ }
+ } else {
+ ok = false;
+ }
+ }
+ }
+
+ if (!ok)
+ setStatus(QSettings::FormatError);
+ }
+
+ confFile->size = fileInfo.size();
+ confFile->timeStamp = fileInfo.lastModified();
+ }
+
+ /*
+ We also need to save the file. We still hold the file lock,
+ so everything is under control.
+ */
+ if (!readOnly) {
+ ensureAllSectionsParsed(confFile);
+ ParsedSettingsMap mergedKeys = confFile->mergedKeyMap();
+
+ if (file.isWritable()) {
+#ifdef Q_OS_MAC
+ if (format == QSettings::NativeFormat) {
+ ok = writePlistFile(confFile->name, mergedKeys);
+ } else
+#endif
+ {
+ file.seek(0);
+ file.resize(0);
+
+ if (format <= QSettings::IniFormat) {
+ ok = writeIniFile(file, mergedKeys);
+ if (!ok) {
+ // try to restore old data; might work if the disk was full and the new data
+ // was larger than the old data
+ file.seek(0);
+ file.resize(0);
+ writeIniFile(file, confFile->originalKeys);
+ }
+ } else {
+ if (writeFunc) {
+ QSettings::SettingsMap tempOriginalKeys;
+
+ ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
+ while (i != mergedKeys.constEnd()) {
+ tempOriginalKeys.insert(i.key(), i.value());
+ ++i;
+ }
+ ok = writeFunc(file, tempOriginalKeys);
+ } else {
+ ok = false;
+ }
+ }
+ }
+ } else {
+ ok = false;
+ }
+
+ if (ok) {
+ confFile->unparsedIniSections.clear();
+ confFile->originalKeys = mergedKeys;
+ confFile->addedKeys.clear();
+ confFile->removedKeys.clear();
+
+ QFileInfo fileInfo(confFile->name);
+ confFile->size = fileInfo.size();
+ confFile->timeStamp = fileInfo.lastModified();
+ } else {
+ setStatus(QSettings::AccessError);
+ }
+ }
+
+ /*
+ Release the file lock.
+ */
+#ifdef Q_OS_WIN
+ if (readSemaphore != 0) {
+ ReleaseSemaphore(readSemaphore, numReadLocks, 0);
+ CloseHandle(readSemaphore);
+ }
+ if (writeSemaphore != 0) {
+ ReleaseSemaphore(writeSemaphore, 1, 0);
+ CloseHandle(writeSemaphore);
+ }
+#endif
+}
+
+enum { Space = 0x1, Special = 0x2 };
+
+static const char charTraits[256] =
+{
+ // Space: '\t', '\n', '\r', ' '
+ // Special: '\n', '\r', '"', ';', '=', '\\'
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, Space | Special, 0, 0, Space | Special, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Space, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, Special, 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, Special, 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, 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
+};
+
+bool QConfFileSettingsPrivate::readIniLine(const QByteArray &data, int &dataPos,
+ int &lineStart, int &lineLen, int &equalsPos)
+{
+ int dataLen = data.length();
+ bool inQuotes = false;
+
+ equalsPos = -1;
+
+ lineStart = dataPos;
+ while (lineStart < dataLen && (charTraits[uint(uchar(data.at(lineStart)))] & Space))
+ ++lineStart;
+
+ int i = lineStart;
+ while (i < dataLen) {
+ while (!(charTraits[uint(uchar(data.at(i)))] & Special)) {
+ if (++i == dataLen)
+ goto break_out_of_outer_loop;
+ }
+
+ char ch = data.at(i++);
+ if (ch == '=') {
+ if (!inQuotes && equalsPos == -1)
+ equalsPos = i - 1;
+ } else if (ch == '\n' || ch == '\r') {
+ if (i == lineStart + 1) {
+ ++lineStart;
+ } else if (!inQuotes) {
+ --i;
+ goto break_out_of_outer_loop;
+ }
+ } else if (ch == '\\') {
+ if (i < dataLen) {
+ char ch = data.at(i++);
+ if (i < dataLen) {
+ char ch2 = data.at(i);
+ // \n, \r, \r\n, and \n\r are legitimate line terminators in INI files
+ if ((ch == '\n' && ch2 == '\r') || (ch == '\r' && ch2 == '\n'))
+ ++i;
+ }
+ }
+ } else if (ch == '"') {
+ inQuotes = !inQuotes;
+ } else {
+ Q_ASSERT(ch == ';');
+
+ if (i == lineStart + 1) {
+ char ch;
+ while (i < dataLen && ((ch = data.at(i) != '\n') && ch != '\r'))
+ ++i;
+ lineStart = i;
+ } else if (!inQuotes) {
+ --i;
+ goto break_out_of_outer_loop;
+ }
+ }
+ }
+
+break_out_of_outer_loop:
+ dataPos = i;
+ lineLen = i - lineStart;
+ return lineLen > 0;
+}
+
+/*
+ Returns false on parse error. However, as many keys are read as
+ 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,
+ UnparsedSettingsMap *unparsedIniSections)
+{
+#define FLUSH_CURRENT_SECTION() \
+ { \
+ QByteArray &sectionData = (*unparsedIniSections)[QSettingsKey(currentSection, \
+ IniCaseSensitivity, \
+ sectionPosition)]; \
+ if (!sectionData.isEmpty()) \
+ sectionData.append('\n'); \
+ sectionData += data.mid(currentSectionStart, lineStart - currentSectionStart); \
+ sectionPosition = ++position; \
+ }
+
+ QString currentSection;
+ int currentSectionStart = 0;
+ int dataPos = 0;
+ int lineStart;
+ int lineLen;
+ int equalsPos;
+ int position = 0;
+ int sectionPosition = 0;
+ bool ok = true;
+
+ while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
+ char ch = data.at(lineStart);
+ if (ch == '[') {
+ FLUSH_CURRENT_SECTION();
+
+ // this is a section
+ QByteArray iniSection;
+ int idx = data.indexOf(']', lineStart);
+ if (idx == -1 || idx >= lineStart + lineLen) {
+ ok = false;
+ iniSection = data.mid(lineStart + 1, lineLen - 1);
+ } else {
+ iniSection = data.mid(lineStart + 1, idx - lineStart - 1);
+ }
+
+ iniSection = iniSection.trimmed();
+
+ if (qstricmp(iniSection, "general") == 0) {
+ currentSection.clear();
+ } else {
+ if (qstricmp(iniSection, "%general") == 0) {
+ currentSection = QLatin1String(iniSection.constData() + 1);
+ } else {
+ currentSection.clear();
+ iniUnescapedKey(iniSection, 0, iniSection.size(), currentSection);
+ }
+ currentSection += QLatin1Char('/');
+ }
+ currentSectionStart = dataPos;
+ }
+ ++position;
+ }
+
+ Q_ASSERT(lineStart == data.length());
+ FLUSH_CURRENT_SECTION();
+
+ return ok;
+
+#undef FLUSH_CURRENT_SECTION
+}
+
+bool QConfFileSettingsPrivate::readIniSection(const QSettingsKey &section, const QByteArray &data,
+ ParsedSettingsMap *settingsMap, QTextCodec *codec)
+{
+ QStringList strListValue;
+ bool sectionIsLowercase = (section == section.originalCaseKey());
+ int equalsPos;
+
+ bool ok = true;
+ int dataPos = 0;
+ int lineStart;
+ int lineLen;
+ int position = section.originalKeyPosition();
+
+ while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
+ char ch = data.at(lineStart);
+ Q_ASSERT(ch != '[');
+
+ if (equalsPos == -1) {
+ if (ch != ';')
+ ok = false;
+ continue;
+ }
+
+ int keyEnd = equalsPos;
+ while (keyEnd > lineStart && ((ch = data.at(keyEnd - 1)) == ' ' || ch == '\t'))
+ --keyEnd;
+ int valueStart = equalsPos + 1;
+
+ QString key = section.originalCaseKey();
+ bool keyIsLowercase = (iniUnescapedKey(data, lineStart, keyEnd, key) && sectionIsLowercase);
+
+ QString strValue;
+ strValue.reserve(lineLen - (valueStart - lineStart));
+ bool isStringList = iniUnescapedStringList(data, valueStart, lineStart + lineLen,
+ strValue, strListValue, codec);
+ QVariant variant;
+ if (isStringList) {
+ variant = stringListToVariantList(strListValue);
+ } else {
+ variant = 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);
+ ++position;
+ }
+
+ return ok;
+}
+
+class QSettingsIniKey : public QString
+{
+public:
+ inline QSettingsIniKey() : position(-1) {}
+ inline QSettingsIniKey(const QString &str, int pos = -1) : QString(str), position(pos) {}
+
+ int position;
+};
+
+static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
+{
+ if (k1.position != k2.position)
+ return k1.position < k2.position;
+ return static_cast<const QString &>(k1) < static_cast<const QString &>(k2);
+}
+
+typedef QMap<QSettingsIniKey, QVariant> IniKeyMap;
+
+struct QSettingsIniSection
+{
+ int position;
+ IniKeyMap keyMap;
+
+ inline QSettingsIniSection() : position(-1) {}
+};
+
+typedef QMap<QString, QSettingsIniSection> IniMap;
+
+/*
+ This would be more straightforward if we didn't try to remember the original
+ key order in the .ini file, but we do.
+*/
+bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSettingsMap &map)
+{
+ IniMap iniMap;
+ IniMap::const_iterator i;
+
+#ifdef Q_OS_WIN
+ const char * const eol = "\r\n";
+#else
+ const char eol = '\n';
+#endif
+
+ for (ParsedSettingsMap::const_iterator j = map.constBegin(); j != map.constEnd(); ++j) {
+ QString section;
+ QSettingsIniKey key(j.key().originalCaseKey(), j.key().originalKeyPosition());
+ int slashPos;
+
+ if ((slashPos = key.indexOf(QLatin1Char('/'))) != -1) {
+ section = key.left(slashPos);
+ key.remove(0, slashPos + 1);
+ }
+
+ QSettingsIniSection &iniSection = iniMap[section];
+
+ // -1 means infinity
+ if (uint(key.position) < uint(iniSection.position))
+ iniSection.position = key.position;
+ iniSection.keyMap[key] = j.value();
+ }
+
+ const int sectionCount = iniMap.size();
+ QVector<QSettingsIniKey> sections;
+ sections.reserve(sectionCount);
+ for (i = iniMap.constBegin(); i != iniMap.constEnd(); ++i)
+ sections.append(QSettingsIniKey(i.key(), i.value().position));
+ qSort(sections);
+
+ bool writeError = false;
+ for (int j = 0; !writeError && j < sectionCount; ++j) {
+ i = iniMap.constFind(sections.at(j));
+ Q_ASSERT(i != iniMap.constEnd());
+
+ QByteArray realSection;
+
+ iniEscapedKey(i.key(), realSection);
+
+ if (realSection.isEmpty()) {
+ realSection = "[General]";
+ } else if (qstricmp(realSection, "general") == 0) {
+ realSection = "[%General]";
+ } else {
+ realSection.prepend('[');
+ realSection.append(']');
+ }
+
+ if (j != 0)
+ realSection.prepend(eol);
+ realSection += eol;
+
+ device.write(realSection);
+
+ const IniKeyMap &ents = i.value().keyMap;
+ for (IniKeyMap::const_iterator j = ents.constBegin(); j != ents.constEnd(); ++j) {
+ QByteArray block;
+ iniEscapedKey(j.key(), block);
+ block += '=';
+
+ const QVariant &value = j.value();
+
+ /*
+ The size() != 1 trick is necessary because
+ QVariant(QString("foo")).toList() returns an empty
+ list, not a list containing "foo".
+ */
+ if (value.type() == QVariant::StringList
+ || (value.type() == QVariant::List && value.toList().size() != 1)) {
+ iniEscapedStringList(variantListToStringList(value.toList()), block, iniCodec);
+ } else {
+ iniEscapedString(variantToString(value), block, iniCodec);
+ }
+ block += eol;
+ if (device.write(block) == -1) {
+ writeError = true;
+ break;
+ }
+ }
+ }
+ return !writeError;
+}
+
+void QConfFileSettingsPrivate::ensureAllSectionsParsed(QConfFile *confFile) const
+{
+ UnparsedSettingsMap::const_iterator i = confFile->unparsedIniSections.constBegin();
+ const UnparsedSettingsMap::const_iterator end = confFile->unparsedIniSections.constEnd();
+
+ for (; i != end; ++i) {
+ if (!QConfFileSettingsPrivate::readIniSection(i.key(), i.value(), &confFile->originalKeys, iniCodec))
+ setStatus(QSettings::FormatError);
+ }
+ confFile->unparsedIniSections.clear();
+}
+
+void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
+ const QSettingsKey &key) const
+{
+ if (confFile->unparsedIniSections.isEmpty())
+ return;
+
+ UnparsedSettingsMap::iterator i;
+
+ int indexOfSlash = key.indexOf(QLatin1Char('/'));
+ if (indexOfSlash != -1) {
+ i = confFile->unparsedIniSections.upperBound(key);
+ if (i == confFile->unparsedIniSections.begin())
+ return;
+ --i;
+ if (i.key().isEmpty() || !key.startsWith(i.key()))
+ return;
+ } else {
+ i = confFile->unparsedIniSections.begin();
+ if (i == confFile->unparsedIniSections.end() || !i.key().isEmpty())
+ return;
+ }
+
+ if (!QConfFileSettingsPrivate::readIniSection(i.key(), i.value(), &confFile->originalKeys, iniCodec))
+ setStatus(QSettings::FormatError);
+ confFile->unparsedIniSections.erase(i);
+}
+
+/*!
+ \class QSettings
+ \brief The QSettings class provides persistent platform-independent application settings.
+
+ \ingroup io
+
+ \reentrant
+
+ Users normally expect an application to remember its settings
+ (window sizes and positions, options, etc.) across sessions. This
+ information is often stored in the system registry on Windows,
+ and in XML preferences files on Mac OS X. On Unix systems, in the
+ absence of a standard, many applications (including the KDE
+ applications) use INI text files.
+
+ QSettings is an abstraction around these technologies, enabling
+ you to save and restore application settings in a portable
+ manner. It also supports \l{registerFormat()}{custom storage
+ formats}.
+
+ QSettings's API is based on QVariant, allowing you to save
+ most value-based types, such as QString, QRect, and QImage,
+ with the minimum of effort.
+
+ If all you need is a non-persistent memory-based structure,
+ consider using QMap<QString, QVariant> instead.
+
+ \tableofcontents section1
+
+ \section1 Basic Usage
+
+ When creating a QSettings object, you must pass the name of your
+ company or organization as well as the name of your application.
+ For example, if your product is called Star Runner and your
+ company is called MySoft, you would construct the QSettings
+ object as follows:
+
+ \snippet doc/src/snippets/settings/settings.cpp 0
+
+ QSettings objects can be created either on the stack or on
+ the heap (i.e. using \c new). Constructing and destroying a
+ QSettings object is very fast.
+
+ If you use QSettings from many places in your application, you
+ might want to specify the organization name and the application
+ name using QCoreApplication::setOrganizationName() and
+ QCoreApplication::setApplicationName(), and then use the default
+ QSettings constructor:
+
+ \snippet doc/src/snippets/settings/settings.cpp 1
+ \snippet doc/src/snippets/settings/settings.cpp 2
+ \snippet doc/src/snippets/settings/settings.cpp 3
+ \dots
+ \snippet doc/src/snippets/settings/settings.cpp 4
+
+ (Here, we also specify the organization's Internet domain. When
+ the Internet domain is set, it is used on Mac OS X instead of the
+ organization name, since Mac OS X applications conventionally use
+ Internet domains to identify themselves. If no domain is set, a
+ fake domain is derived from the organization name. See the
+ \l{Platform-Specific Notes} below for details.)
+
+ QSettings stores settings. Each setting consists of a QString
+ that specifies the setting's name (the \e key) and a QVariant
+ that stores the data associated with the key. To write a setting,
+ use setValue(). For example:
+
+ \snippet doc/src/snippets/settings/settings.cpp 5
+
+ If there already exists a setting with the same key, the existing
+ value is overwritten by the new value. For efficiency, the
+ changes may not be saved to permanent storage immediately. (You
+ can always call sync() to commit your changes.)
+
+ You can get a setting's value back using value():
+
+ \snippet doc/src/snippets/settings/settings.cpp 6
+
+ If there is no setting with the specified name, QSettings
+ returns a null QVariant (which can be converted to the integer 0).
+ You can specify another default value by passing a second
+ argument to value():
+
+ \snippet doc/src/snippets/settings/settings.cpp 7
+
+ To test whether a given key exists, call contains(). To remove
+ the setting associated with a key, call remove(). To obtain the
+ list of all keys, call allKeys(). To remove all keys, call
+ clear().
+
+ \section1 QVariant and GUI Types
+
+ Because QVariant is part of the \l QtCore library, it cannot provide
+ conversion functions to data types such as QColor, QImage, and
+ QPixmap, which are part of \l QtGui. In other words, there is no
+ \c toColor(), \c toImage(), or \c toPixmap() functions in QVariant.
+
+ Instead, you can use the QVariant::value() or the qVariantValue()
+ template function. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 0
+
+ The inverse conversion (e.g., from QColor to QVariant) is
+ automatic for all data types supported by QVariant, including
+ GUI-related types:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 1
+
+ Custom types registered using qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() can be stored using QSettings.
+
+ \section1 Section and Key Syntax
+
+ Setting keys can contain any Unicode characters. The Windows
+ registry and INI files use case-insensitive keys, whereas the
+ Carbon Preferences API on Mac OS X uses case-sensitive keys. To
+ avoid portability problems, follow these simple rules:
+
+ \list 1
+ \o Always refer to the same key using the same case. For example,
+ if you refer to a key as "text fonts" in one place in your
+ code, don't refer to it as "Text Fonts" somewhere else.
+
+ \o Avoid key names that are identical except for the case. For
+ example, if you have a key called "MainWindow", don't try to
+ save another key as "mainwindow".
+
+ \o Do not use slashes ('/' and '\\') in section or key names; the
+ backslash character is used to separate sub keys (see below). On
+ windows '\\' are converted by QSettings to '/', which makes
+ them identical.
+ \endlist
+
+ You can form hierarchical keys using the '/' character as a
+ separator, similar to Unix file paths. For example:
+
+ \snippet doc/src/snippets/settings/settings.cpp 8
+ \snippet doc/src/snippets/settings/settings.cpp 9
+ \snippet doc/src/snippets/settings/settings.cpp 10
+
+ If you want to save or restore many settings with the same
+ prefix, you can specify the prefix using beginGroup() and call
+ endGroup() at the end. Here's the same example again, but this
+ time using the group mechanism:
+
+ \snippet doc/src/snippets/settings/settings.cpp 11
+ \codeline
+ \snippet doc/src/snippets/settings/settings.cpp 12
+
+ If a group is set using beginGroup(), the behavior of most
+ functions changes consequently. Groups can be set recursively.
+
+ In addition to groups, QSettings also supports an "array"
+ concept. See beginReadArray() and beginWriteArray() for details.
+
+ \section1 Fallback Mechanism
+
+ Let's assume that you have created a QSettings object with the
+ organization name MySoft and the application name Star Runner.
+ When you look up a value, up to four locations are searched in
+ that order:
+
+ \list 1
+ \o a user-specific location for the Star Runner application
+ \o a user-specific location for all applications by MySoft
+ \o a system-wide location for the Star Runner application
+ \o a system-wide location for all applications by MySoft
+ \endlist
+
+ (See \l{Platform-Specific Notes} below for information on what
+ these locations are on the different platforms supported by Qt.)
+
+ If a key cannot be found in the first location, the search goes
+ on in the second location, and so on. This enables you to store
+ system-wide or organization-wide settings and to override them on
+ a per-user or per-application basis. To turn off this mechanism,
+ call setFallbacksEnabled(false).
+
+ Although keys from all four locations are available for reading,
+ only the first file (the user-specific location for the
+ application at hand) is accessible for writing. To write to any
+ of the other files, omit the application name and/or specify
+ QSettings::SystemScope (as opposed to QSettings::UserScope, the
+ default).
+
+ Let's see with an example:
+
+ \snippet doc/src/snippets/settings/settings.cpp 13
+ \snippet doc/src/snippets/settings/settings.cpp 14
+
+ The table below summarizes which QSettings objects access
+ which location. "\bold{X}" means that the location is the main
+ location associated to the QSettings object and is used both
+ for reading and for writing; "o" means that the location is used
+ as a fallback when reading.
+
+ \table
+ \header \o Locations \o \c{obj1} \o \c{obj2} \o \c{obj3} \o \c{obj4}
+ \row \o 1. User, Application \o \bold{X} \o \o \o
+ \row \o 2. User, Organization \o o \o \bold{X} \o \o
+ \row \o 3. System, Application \o o \o \o \bold{X} \o
+ \row \o 4. System, Organization \o o \o o \o o \o \bold{X}
+ \endtable
+
+ The beauty of this mechanism is that it works on all platforms
+ supported by Qt and that it still gives you a lot of flexibility,
+ without requiring you to specify any file names or registry
+ paths.
+
+ If you want to use INI files on all platforms instead of the
+ native API, you can pass QSettings::IniFormat as the first
+ argument to the QSettings constructor, followed by the scope, the
+ organization name, and the application name:
+
+ \snippet doc/src/snippets/settings/settings.cpp 15
+
+ The \l{tools/settingseditor}{Settings Editor} example lets you
+ experiment with different settings location and with fallbacks
+ turned on or off.
+
+ \section1 Restoring the State of a GUI Application
+
+ QSettings is often used to store the state of a GUI
+ application. The following example illustrates how to use QSettings
+ to save and restore the geometry of an application's main window.
+
+ \snippet doc/src/snippets/settings/settings.cpp 16
+ \codeline
+ \snippet doc/src/snippets/settings/settings.cpp 17
+
+ See \l{Window Geometry} for a discussion on why it is better to
+ call QWidget::resize() and QWidget::move() rather than QWidget::setGeometry()
+ to restore a window's geometry.
+
+ The \c readSettings() and \c writeSettings() functions must be
+ called from the main window's constructor and close event handler
+ as follows:
+
+ \snippet doc/src/snippets/settings/settings.cpp 18
+ \dots
+ \snippet doc/src/snippets/settings/settings.cpp 19
+ \snippet doc/src/snippets/settings/settings.cpp 20
+ \codeline
+ \snippet doc/src/snippets/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
+ distinct QSettings object in different threads
+ simultaneously. This guarantee stands even when the QSettings
+ objects refer to the same files on disk (or to the same entries
+ in the system registry). If a setting is modified through one
+ QSettings object, the change will immediately be visible in
+ any other QSettings objects that operate on the same location
+ and that live in the same process.
+
+ QSettings can safely be used from different processes (which can
+ be different instances of your application running at the same
+ time or different applications altogether) to read and write to
+ the same system locations. It uses advisory file locking and a
+ smart merging algorithm to ensure data integrity. Note that sync()
+ imports changes made by other processes (in addition to writing
+ the changes from this QSettings).
+
+ \section1 Platform-Specific Notes
+
+ \section2 Locations Where Application Settings Are Stored
+
+ As mentioned in the \l{Fallback Mechanism} section, QSettings
+ stores settings for an application in up to four locations,
+ depending on whether the settings are user-specific or
+ system-wide and whether the settings are application-specific
+ or organization-wide. For simplicity, we're assuming the
+ organization is called MySoft and the application is called Star
+ Runner.
+
+ On Unix systems, if the file format is NativeFormat, the
+ following files are used by default:
+
+ \list 1
+ \o \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf})
+ \o \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf})
+ \o \c{/etc/xdg/MySoft/Star Runner.conf}
+ \o \c{/etc/xdg/MySoft.conf}
+ \endlist
+
+ On Mac OS X versions 10.2 and 10.3, these files are used by
+ default:
+
+ \list 1
+ \o \c{$HOME/Library/Preferences/com.MySoft.Star Runner.plist}
+ \o \c{$HOME/Library/Preferences/com.MySoft.plist}
+ \o \c{/Library/Preferences/com.MySoft.Star Runner.plist}
+ \o \c{/Library/Preferences/com.MySoft.plist}
+ \endlist
+
+ On Windows, NativeFormat settings are stored in the following
+ registry paths:
+
+ \list 1
+ \o \c{HKEY_CURRENT_USER\Software\MySoft\Star Runner}
+ \o \c{HKEY_CURRENT_USER\Software\MySoft}
+ \o \c{HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner}
+ \o \c{HKEY_LOCAL_MACHINE\Software\MySoft}
+ \endlist
+
+ \note On Windows, for 32-bit programs running in WOW64 mode, settings are
+ stored in the following registry path:
+ \c{HKEY_LOCAL_MACHINE\Software\WOW6432node}.
+
+ If the file format is IniFormat, the following files are
+ used on Unix and Mac OS X:
+
+ \list 1
+ \o \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini})
+ \o \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini})
+ \o \c{/etc/xdg/MySoft/Star Runner.ini}
+ \o \c{/etc/xdg/MySoft.ini}
+ \endlist
+
+ On Windows, the following files are used:
+
+ \list 1
+ \o \c{%APPDATA%\MySoft\Star Runner.ini}
+ \o \c{%APPDATA%\MySoft.ini}
+ \o \c{%COMMON_APPDATA%\MySoft\Star Runner.ini}
+ \o \c{%COMMON_APPDATA%\MySoft.ini}
+ \endlist
+
+ The \c %APPDATA% path is usually \tt{C:\\Documents and
+ Settings\\\e{User Name}\\Application Data}; the \c
+ %COMMON_APPDATA% path is usually \tt{C:\\Documents and
+ Settings\\All Users\\Application Data}.
+
+ The paths for the \c .ini and \c .conf files can be changed using
+ setPath(). On Unix and Mac OS X, the user can override them by by
+ setting the \c XDG_CONFIG_HOME environment variable; see
+ setPath() for details.
+
+ \section2 Accessing INI and .plist Files Directly
+
+ Sometimes you do want to access settings stored in a specific
+ file or registry path. On all platforms, if you want to read an
+ INI file directly, you can use the QSettings constructor that
+ takes a file name as first argument and pass QSettings::IniFormat
+ as second argument. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 2
+
+ You can then use the QSettings object to read and write settings
+ in the file.
+
+ On Mac OS X, you can access XML-based \c .plist files by passing
+ QSettings::NativeFormat as second argument. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 3
+
+ \section2 Accessing the Windows Registry Directly
+
+ On Windows, QSettings lets you access settings that have been
+ written with QSettings (or settings in a supported format, e.g., string
+ data) in the system registry. This is done by constructing a QSettings
+ object with a path in the registry and QSettings::NativeFormat.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 4
+
+ All the registry entries that appear under the specified path can
+ be read or written through the QSettings object as usual (using
+ forward slashes instead of backslashes). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 5
+
+ Note that the backslash character is, as mentioned, used by
+ QSettings to separate subkeys. As a result, you cannot read or
+ write windows registry entries that contain slashes or
+ backslashes; you should use a native windows API if you need to do
+ so.
+
+ \section2 Accessing Common Registry Settings on Windows
+
+ On Windows, it is possible for a key to have both a value and subkeys.
+ Its default value is accessed by using "Default" or "." in
+ place of a subkey:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 6
+
+ On other platforms than Windows, "Default" and "." would be
+ treated as regular subkeys.
+
+ \section2 Platform Limitations
+
+ While QSettings attempts to smooth over the differences between
+ the different supported platforms, there are still a few
+ differences that you should be aware of when porting your
+ application:
+
+ \list
+ \o The Windows system registry has the following limitations: A
+ subkey may not exceed 255 characters, an entry's value may
+ not exceed 16,383 characters, and all the values of a key may
+ not exceed 65,535 characters. One way to work around these
+ limitations is to store the settings using the IniFormat
+ instead of the NativeFormat.
+
+ \o On Mac OS X, allKeys() will return some extra keys for global
+ settings that apply to all applications. These keys can be
+ read using value() but cannot be changed, only shadowed.
+ Calling setFallbacksEnabled(false) will hide these global
+ settings.
+
+ \o On Mac OS X, the CFPreferences API used by QSettings expects
+ Internet domain names rather than organization names. To
+ provide a uniform API, QSettings derives a fake domain name
+ from the organization name (unless the organization name
+ already is a domain name, e.g. OpenOffice.org). The algorithm
+ appends ".com" to the company name and replaces spaces and
+ other illegal characters with hyphens. If you want to specify
+ a different domain name, call
+ QCoreApplication::setOrganizationDomain(),
+ QCoreApplication::setOrganizationName(), and
+ QCoreApplication::setApplicationName() in your \c main()
+ function and then use the default QSettings constructor.
+ Another solution is to use preprocessor directives, for
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 7
+
+ \o On Unix and Mac OS X systems, the advisory file locking is disabled
+ if NFS (or AutoFS or CacheFS) is detected to work around a bug in the
+ NFS fcntl() implementation, which hangs forever if statd or lockd aren't
+ running. Also, the locking isn't performed when accessing \c .plist
+ files.
+
+ \endlist
+
+ \sa QVariant, QSessionManager, {Settings Editor Example}, {Application Example}
+*/
+
+/*! \enum QSettings::Status
+
+ The following status values are possible:
+
+ \value NoError No error occurred.
+ \value AccessError An access error occurred (e.g. trying to write to a read-only file).
+ \value FormatError A format error occurred (e.g. loading a malformed INI file).
+
+ \sa status()
+*/
+
+/*! \enum QSettings::Format
+
+ This enum type specifies the storage format used by QSettings.
+
+ \value NativeFormat Store the settings using the most
+ appropriate storage format for the platform.
+ On Windows, this means the system registry;
+ on Mac OS X, this means the CFPreferences
+ API; on Unix, this means textual
+ configuration files in INI format.
+ \value IniFormat Store the settings in INI files.
+ \value InvalidFormat Special value returned by registerFormat().
+ \omitvalue CustomFormat1
+ \omitvalue CustomFormat2
+ \omitvalue CustomFormat3
+ \omitvalue CustomFormat4
+ \omitvalue CustomFormat5
+ \omitvalue CustomFormat6
+ \omitvalue CustomFormat7
+ \omitvalue CustomFormat8
+ \omitvalue CustomFormat9
+ \omitvalue CustomFormat10
+ \omitvalue CustomFormat11
+ \omitvalue CustomFormat12
+ \omitvalue CustomFormat13
+ \omitvalue CustomFormat14
+ \omitvalue CustomFormat15
+ \omitvalue CustomFormat16
+
+ On Unix, NativeFormat and IniFormat mean the same thing, except
+ that the file extension is different (\c .conf for NativeFormat,
+ \c .ini for IniFormat).
+
+ The INI file format is a Windows file format that Qt supports on
+ all platforms. In the absence of an INI standard, we try to
+ follow what Microsoft does, with the following exceptions:
+
+ \list
+ \o If you store types that QVariant can't convert to QString
+ (e.g., QPoint, QRect, and QSize), Qt uses an \c{@}-based
+ syntax to encode the type. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 8
+
+ To minimize compatibility issues, any \c @ that doesn't
+ appear at the first position in the value or that isn't
+ followed by a Qt type (\c Point, \c Rect, \c Size, etc.) is
+ treated as a normal character.
+
+ \o Although backslash is a special character in INI files, most
+ Windows applications don't escape backslashes (\c{\}) in file
+ paths:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 9
+
+ QSettings always treats backslash as a special character and
+ provides no API for reading or writing such entries.
+
+ \o The INI file format has severe restrictions on the syntax of
+ a key. Qt works around this by using \c % as an escape
+ character in keys. In addition, if you save a top-level
+ setting (a key with no slashes in it, e.g., "someKey"), it
+ will appear in the INI file's "General" section. To avoid
+ overwriting other keys, if you save something using the a key
+ such as "General/someKey", the key will be located in the
+ "%General" section, \e not in the "General" section.
+
+ \o Following the philosophy that we should be liberal in what
+ we accept and conservative in what we generate, QSettings
+ will accept Latin-1 encoded INI files, but generate pure
+ ASCII files, where non-ASCII values are encoded using standard
+ INI escape sequences. To make the INI files more readable (but
+ potentially less compatible), call setIniCodec().
+ \endlist
+
+ \sa registerFormat(), setPath()
+*/
+
+/*! \enum QSettings::Scope
+
+ This enum specifies whether settings are user-specific or shared
+ by all users of the same system.
+
+ \value UserScope Store settings in a location specific to the
+ current user (e.g., in the user's home
+ directory).
+ \value SystemScope Store settings in a global location, so that
+ all users on the same machine access the same
+ set of settings.
+ \omitvalue User
+ \omitvalue Global
+
+ \sa setPath()
+*/
+
+#ifndef QT_NO_QOBJECT
+/*!
+ Constructs a QSettings object for accessing settings of the
+ application called \a application from the organization called \a
+ organization, and with parent \a parent.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 10
+
+ The scope is set to QSettings::UserScope, and the format is
+ set to QSettings::NativeFormat (i.e. calling setDefaultFormat()
+ before calling this constructor has no effect).
+
+ \sa setDefaultFormat(), {Fallback Mechanism}
+*/
+QSettings::QSettings(const QString &organization, const QString &application, QObject *parent)
+ : QObject(*QSettingsPrivate::create(NativeFormat, UserScope, organization, application),
+ parent)
+{
+}
+
+/*!
+ Constructs a QSettings object for accessing settings of the
+ application called \a application from the organization called \a
+ organization, and with parent \a parent.
+
+ If \a scope is QSettings::UserScope, the QSettings object searches
+ user-specific settings first, before it searches system-wide
+ settings as a fallback. If \a scope is QSettings::SystemScope, the
+ QSettings object ignores user-specific settings and provides
+ access to system-wide settings.
+
+ The storage format is set to QSettings::NativeFormat (i.e. calling
+ setDefaultFormat() before calling this constructor has no effect).
+
+ If no application name is given, the QSettings object will
+ only access the organization-wide \l{Fallback Mechanism}{locations}.
+
+ \sa setDefaultFormat()
+*/
+QSettings::QSettings(Scope scope, const QString &organization, const QString &application,
+ QObject *parent)
+ : QObject(*QSettingsPrivate::create(NativeFormat, scope, organization, application), parent)
+{
+}
+
+/*!
+ Constructs a QSettings object for accessing settings of the
+ application called \a application from the organization called
+ \a organization, and with parent \a parent.
+
+ If \a scope is QSettings::UserScope, the QSettings object searches
+ user-specific settings first, before it searches system-wide
+ settings as a fallback. If \a scope is
+ QSettings::SystemScope, the QSettings object ignores user-specific
+ settings and provides access to system-wide settings.
+
+ If \a format is QSettings::NativeFormat, the native API is used for
+ storing settings. If \a format is QSettings::IniFormat, the INI format
+ is used.
+
+ If no application name is given, the QSettings object will
+ only access the organization-wide \l{Fallback Mechanism}{locations}.
+*/
+QSettings::QSettings(Format format, Scope scope, const QString &organization,
+ const QString &application, QObject *parent)
+ : QObject(*QSettingsPrivate::create(format, scope, organization, application), parent)
+{
+}
+
+/*!
+ Constructs a QSettings object for accessing the settings
+ stored in the file called \a fileName, with parent \a parent. If
+ the file doesn't already exist, it is created.
+
+ If \a format is QSettings::NativeFormat, the meaning of \a
+ fileName depends on the platform. On Unix, \a fileName is the
+ name of an INI file. On Mac OS X, \a fileName is the name of a
+ \c .plist file. On Windows, \a fileName is a path in the system
+ registry.
+
+ If \a format is QSettings::IniFormat, \a fileName is the name of an INI
+ file.
+
+ \warning This function is provided for convenience. It works well for
+ accessing INI or \c .plist files generated by Qt, but might fail on some
+ syntaxes found in such files originated by other programs. In particular,
+ be aware of the following limitations:
+
+ \list
+ \o QSettings provides no way of reading INI "path" entries, i.e., entries
+ with unescaped slash characters. (This is because these entries are
+ ambiguous and cannot be resolved automatically.)
+ \o In INI files, QSettings uses the \c @ character as a metacharacter in some
+ contexts, to encode Qt-specific data types (e.g., \c @Rect), and might
+ therefore misinterpret it when it occurs in pure INI files.
+ \endlist
+
+ \sa fileName()
+*/
+QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
+ : QObject(*QSettingsPrivate::create(fileName, format), parent)
+{
+}
+
+/*!
+ Constructs a QSettings object for accessing settings of the
+ application and organization set previously with a call to
+ QCoreApplication::setOrganizationName(),
+ QCoreApplication::setOrganizationDomain(), and
+ QCoreApplication::setApplicationName().
+
+ The scope is QSettings::UserScope and the format is
+ defaultFormat() (QSettings::NativeFormat by default).
+ Use setDefaultFormat() before calling this constructor
+ to change the default format used by this constructor.
+
+ The code
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 11
+
+ is equivalent to
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 12
+
+ If QCoreApplication::setOrganizationName() and
+ QCoreApplication::setApplicationName() has not been previously
+ called, the QSettings object will not be able to read or write
+ any settings, and status() will return AccessError.
+
+ On Mac OS X, if both a name and an Internet domain are specified
+ for the organization, the domain is preferred over the name. On
+ other platforms, the name is preferred over the domain.
+
+ \sa QCoreApplication::setOrganizationName(),
+ QCoreApplication::setOrganizationDomain(),
+ QCoreApplication::setApplicationName(),
+ setDefaultFormat()
+*/
+QSettings::QSettings(QObject *parent)
+ : QObject(*QSettingsPrivate::create(globalDefaultFormat, UserScope,
+#ifdef Q_OS_MAC
+ QCoreApplication::organizationDomain().isEmpty()
+ ? QCoreApplication::organizationName()
+ : QCoreApplication::organizationDomain()
+#else
+ QCoreApplication::organizationName().isEmpty()
+ ? QCoreApplication::organizationDomain()
+ : QCoreApplication::organizationName()
+#endif
+ , QCoreApplication::applicationName()),
+ parent)
+{
+}
+
+#else
+QSettings::QSettings(const QString &organization, const QString &application)
+ : d_ptr(QSettingsPrivate::create(globalDefaultFormat, QSettings::UserScope, organization, application))
+{
+ d_ptr->q_ptr = this;
+}
+
+QSettings::QSettings(Scope scope, const QString &organization, const QString &application)
+ : d_ptr(QSettingsPrivate::create(globalDefaultFormat, scope, organization, application))
+{
+ d_ptr->q_ptr = this;
+}
+
+QSettings::QSettings(Format format, Scope scope, const QString &organization,
+ const QString &application)
+ : d_ptr(QSettingsPrivate::create(format, scope, organization, application))
+{
+ d_ptr->q_ptr = this;
+}
+
+QSettings::QSettings(const QString &fileName, Format format)
+ : d_ptr(QSettingsPrivate::create(fileName, format))
+{
+ d_ptr->q_ptr = this;
+}
+#endif
+
+/*!
+ Destroys the QSettings object.
+
+ Any unsaved changes will eventually be written to permanent
+ storage.
+
+ \sa sync()
+*/
+QSettings::~QSettings()
+{
+ Q_D(QSettings);
+ if (d->pendingChanges) {
+ QT_TRY {
+ d->flush();
+ } QT_CATCH(...) {
+ ; // ok. then don't flush but at least don't throw in the destructor
+ }
+ }
+}
+
+/*!
+ Removes all entries in the primary location associated to this
+ QSettings object.
+
+ Entries in fallback locations are not removed.
+
+ If you only want to remove the entries in the current group(),
+ use remove("") instead.
+
+ \sa remove(), setFallbacksEnabled()
+*/
+void QSettings::clear()
+{
+ Q_D(QSettings);
+ d->clear();
+ d->requestUpdate();
+}
+
+/*!
+ Writes any unsaved changes to permanent storage, and reloads any
+ settings that have been changed in the meantime by another
+ application.
+
+ This function is called automatically from QSettings's destructor and
+ by the event loop at regular intervals, so you normally don't need to
+ call it yourself.
+
+ \sa status()
+*/
+void QSettings::sync()
+{
+ Q_D(QSettings);
+ d->sync();
+}
+
+/*!
+ Returns the path where settings written using this QSettings
+ object are stored.
+
+ On Windows, if the format is QSettings::NativeFormat, the return value
+ is a system registry path, not a file path.
+
+ \sa isWritable(), format()
+*/
+QString QSettings::fileName() const
+{
+ Q_D(const QSettings);
+ return d->fileName();
+}
+
+/*!
+ \since 4.4
+
+ Returns the format used for storing the settings.
+
+ \sa defaultFormat(), fileName(), scope(), organizationName(), applicationName()
+*/
+QSettings::Format QSettings::format() const
+{
+ Q_D(const QSettings);
+ return d->format;
+}
+
+/*!
+ \since 4.4
+
+ Returns the scope used for storing the settings.
+
+ \sa format(), organizationName(), applicationName()
+*/
+QSettings::Scope QSettings::scope() const
+{
+ Q_D(const QSettings);
+ return d->scope;
+}
+
+/*!
+ \since 4.4
+
+ Returns the organization name used for storing the settings.
+
+ \sa QCoreApplication::organizationName(), format(), scope(), applicationName()
+*/
+QString QSettings::organizationName() const
+{
+ Q_D(const QSettings);
+ return d->organizationName;
+}
+
+/*!
+ \since 4.4
+
+ Returns the application name used for storing the settings.
+
+ \sa QCoreApplication::applicationName(), format(), scope(), organizationName()
+*/
+QString QSettings::applicationName() const
+{
+ Q_D(const QSettings);
+ return d->applicationName;
+}
+
+#ifndef QT_NO_TEXTCODEC
+
+/*!
+ \since 4.5
+
+ Sets the codec for accessing INI files (including \c .conf files on Unix)
+ to \a codec. The codec is used for decoding any data that is read from
+ the INI file, and for encoding any data that is written to the file. By
+ default, no codec is used, and non-ASCII characters are encoded using
+ standard INI escape sequences.
+
+ \warning The codec must be set immediately after creating the QSettings
+ object, before accessing any data.
+
+ \sa iniCodec()
+*/
+void QSettings::setIniCodec(QTextCodec *codec)
+{
+ Q_D(QSettings);
+ d->iniCodec = codec;
+}
+
+/*!
+ \since 4.5
+ \overload
+
+ Sets the codec for accessing INI files (including \c .conf files on Unix)
+ to the QTextCodec for the encoding specified by \a codecName. Common
+ values for \c codecName include "ISO 8859-1", "UTF-8", and "UTF-16".
+ If the encoding isn't recognized, nothing happens.
+
+ \sa QTextCodec::codecForName()
+*/
+void QSettings::setIniCodec(const char *codecName)
+{
+ Q_D(QSettings);
+ if (QTextCodec *codec = QTextCodec::codecForName(codecName))
+ d->iniCodec = codec;
+}
+
+/*!
+ \since 4.5
+
+ Returns the codec that is used for accessing INI files. By default,
+ no codec is used, so a null pointer is returned.
+*/
+
+QTextCodec *QSettings::iniCodec() const
+{
+ Q_D(const QSettings);
+ return d->iniCodec;
+}
+
+#endif // QT_NO_TEXTCODEC
+
+/*!
+ Returns a status code indicating the first error that was met by
+ QSettings, or QSettings::NoError if no error occurred.
+
+ Be aware that QSettings delays performing some operations. For this
+ reason, you might want to call sync() to ensure that the data stored
+ in QSettings is written to disk before calling status().
+
+ \sa sync()
+*/
+QSettings::Status QSettings::status() const
+{
+ Q_D(const QSettings);
+ return d->status;
+}
+
+/*!
+ Appends \a prefix to the current group.
+
+ The current group is automatically prepended to all keys
+ specified to QSettings. In addition, query functions such as
+ childGroups(), childKeys(), and allKeys() are based on the group.
+ By default, no group is set.
+
+ Groups are useful to avoid typing in the same setting paths over
+ and over. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 13
+
+ This will set the value of three settings:
+
+ \list
+ \o \c mainwindow/size
+ \o \c mainwindow/fullScreen
+ \o \c outputpanel/visible
+ \endlist
+
+ Call endGroup() to reset the current group to what it was before
+ the corresponding beginGroup() call. Groups can be nested.
+
+ \sa endGroup(), group()
+*/
+void QSettings::beginGroup(const QString &prefix)
+{
+ Q_D(QSettings);
+ d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix)));
+}
+
+/*!
+ Resets the group to what it was before the corresponding
+ beginGroup() call.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 14
+
+ \sa beginGroup(), group()
+*/
+void QSettings::endGroup()
+{
+ Q_D(QSettings);
+ if (d->groupStack.isEmpty()) {
+ qWarning("QSettings::endGroup: No matching beginGroup()");
+ return;
+ }
+
+ QSettingsGroup group = d->groupStack.pop();
+ int len = group.toString().size();
+ if (len > 0)
+ d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
+
+ if (group.isArray())
+ qWarning("QSettings::endGroup: Expected endArray() instead");
+}
+
+/*!
+ Returns the current group.
+
+ \sa beginGroup(), endGroup()
+*/
+QString QSettings::group() const
+{
+ Q_D(const QSettings);
+ return d->groupPrefix.left(d->groupPrefix.size() - 1);
+}
+
+/*!
+ Adds \a prefix to the current group and starts reading from an
+ array. Returns the size of the array.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 15
+
+ Use beginWriteArray() to write the array in the first place.
+
+ \sa beginWriteArray(), endArray(), setArrayIndex()
+*/
+int QSettings::beginReadArray(const QString &prefix)
+{
+ Q_D(QSettings);
+ d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), false));
+ return value(QLatin1String("size")).toInt();
+}
+
+/*!
+ Adds \a prefix to the current group and starts writing an array
+ of size \a size. If \a size is -1 (the default), it is automatically
+ determined based on the indexes of the entries written.
+
+ If you have many occurrences of a certain set of keys, you can
+ use arrays to make your life easier. For example, let's suppose
+ that you want to save a variable-length list of user names and
+ passwords. You could then write:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 16
+
+ The generated keys will have the form
+
+ \list
+ \o \c logins/size
+ \o \c logins/1/userName
+ \o \c logins/1/password
+ \o \c logins/2/userName
+ \o \c logins/2/password
+ \o \c logins/3/userName
+ \o \c logins/3/password
+ \o ...
+ \endlist
+
+ To read back an array, use beginReadArray().
+
+ \sa beginReadArray(), endArray(), setArrayIndex()
+*/
+void QSettings::beginWriteArray(const QString &prefix, int size)
+{
+ Q_D(QSettings);
+ d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), size < 0));
+
+ if (size < 0)
+ remove(QLatin1String("size"));
+ else
+ setValue(QLatin1String("size"), size);
+}
+
+/*!
+ Closes the array that was started using beginReadArray() or
+ beginWriteArray().
+
+ \sa beginReadArray(), beginWriteArray()
+*/
+void QSettings::endArray()
+{
+ Q_D(QSettings);
+ if (d->groupStack.isEmpty()) {
+ qWarning("QSettings::endArray: No matching beginArray()");
+ return;
+ }
+
+ QSettingsGroup group = d->groupStack.top();
+ int 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());
+
+ if (!group.isArray())
+ qWarning("QSettings::endArray: Expected endGroup() instead");
+}
+
+/*!
+ Sets the current array index to \a i. Calls to functions such as
+ setValue(), value(), remove(), and contains() will operate on the
+ array entry at that index.
+
+ You must call beginReadArray() or beginWriteArray() before you
+ can call this function.
+*/
+void QSettings::setArrayIndex(int i)
+{
+ Q_D(QSettings);
+ if (d->groupStack.isEmpty() || !d->groupStack.top().isArray()) {
+ qWarning("QSettings::setArrayIndex: Missing beginArray()");
+ return;
+ }
+
+ QSettingsGroup &top = d->groupStack.top();
+ int len = top.toString().size();
+ top.setArrayIndex(qMax(i, 0));
+ d->groupPrefix.replace(d->groupPrefix.size() - len - 1, len, top.toString());
+}
+
+/*!
+ Returns a list of all keys, including subkeys, that can be read
+ using the QSettings object.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 17
+
+ If a group is set using beginGroup(), only the keys in the group
+ are returned, without the group prefix:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 18
+
+ \sa childGroups(), childKeys()
+*/
+QStringList QSettings::allKeys() const
+{
+ Q_D(const QSettings);
+ return d->children(d->groupPrefix, QSettingsPrivate::AllKeys);
+}
+
+/*!
+ Returns a list of all top-level keys that can be read using the
+ QSettings object.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 19
+
+ If a group is set using beginGroup(), the top-level keys in that
+ group are returned, without the group prefix:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 20
+
+ You can navigate through the entire setting hierarchy using
+ childKeys() and childGroups() recursively.
+
+ \sa childGroups(), allKeys()
+*/
+QStringList QSettings::childKeys() const
+{
+ Q_D(const QSettings);
+ return d->children(d->groupPrefix, QSettingsPrivate::ChildKeys);
+}
+
+/*!
+ Returns a list of all key top-level groups that contain keys that
+ can be read using the QSettings object.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 21
+
+ If a group is set using beginGroup(), the first-level keys in
+ that group are returned, without the group prefix.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 22
+
+ You can navigate through the entire setting hierarchy using
+ childKeys() and childGroups() recursively.
+
+ \sa childKeys(), allKeys()
+*/
+QStringList QSettings::childGroups() const
+{
+ Q_D(const QSettings);
+ return d->children(d->groupPrefix, QSettingsPrivate::ChildGroups);
+}
+
+/*!
+ Returns true if settings can be written using this QSettings
+ object; returns false otherwise.
+
+ One reason why isWritable() might return false is if
+ QSettings operates on a read-only file.
+
+ \warning This function is not perfectly reliable, because the
+ file permissions can change at any time.
+
+ \sa fileName(), status(), sync()
+*/
+bool QSettings::isWritable() const
+{
+ Q_D(const QSettings);
+ return d->isWritable();
+}
+
+/*!
+
+ Sets the value of setting \a key to \a value. If the \a key already
+ exists, the previous value is overwritten.
+
+ Note that the Windows registry and INI files use case-insensitive
+ keys, whereas the Carbon Preferences API on Mac OS X uses
+ case-sensitive keys. To avoid portability problems, see the
+ \l{Section and Key Syntax} rules.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 23
+
+ \sa value(), remove(), contains()
+*/
+void QSettings::setValue(const QString &key, const QVariant &value)
+{
+ Q_D(QSettings);
+ QString k = d->actualKey(key);
+ d->set(k, value);
+ d->requestUpdate();
+}
+
+/*!
+ Removes the setting \a key and any sub-settings of \a key.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 24
+
+ Be aware that if one of the fallback locations contains a setting
+ with the same key, that setting will be visible after calling
+ remove().
+
+ If \a key is an empty string, all keys in the current group() are
+ removed. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 25
+
+ Note that the Windows registry and INI files use case-insensitive
+ keys, whereas the Carbon Preferences API on Mac OS X uses
+ case-sensitive keys. To avoid portability problems, see the
+ \l{Section and Key Syntax} rules.
+
+ \sa setValue(), value(), contains()
+*/
+void QSettings::remove(const QString &key)
+{
+ Q_D(QSettings);
+ /*
+ We cannot use actualKey(), because remove() supports empty
+ keys. The code is also tricky because of slash handling.
+ */
+ QString theKey = d->normalizedKey(key);
+ if (theKey.isEmpty())
+ theKey = group();
+ else
+ theKey.prepend(d->groupPrefix);
+
+ if (theKey.isEmpty()) {
+ d->clear();
+ } else {
+ d->remove(theKey);
+ }
+ d->requestUpdate();
+}
+
+/*!
+ Returns true if there exists a setting called \a key; returns
+ false otherwise.
+
+ If a group is set using beginGroup(), \a key is taken to be
+ relative to that group.
+
+ Note that the Windows registry and INI files use case-insensitive
+ keys, whereas the Carbon Preferences API on Mac OS X uses
+ case-sensitive keys. To avoid portability problems, see the
+ \l{Section and Key Syntax} rules.
+
+ \sa value(), setValue()
+*/
+bool QSettings::contains(const QString &key) const
+{
+ Q_D(const QSettings);
+ QString k = d->actualKey(key);
+ return d->get(k, 0);
+}
+
+/*!
+ Sets whether fallbacks are enabled to \a b.
+
+ By default, fallbacks are enabled.
+
+ \sa fallbacksEnabled()
+*/
+void QSettings::setFallbacksEnabled(bool b)
+{
+ Q_D(QSettings);
+ d->fallbacks = !!b;
+}
+
+/*!
+ Returns true if fallbacks are enabled; returns false otherwise.
+
+ By default, fallbacks are enabled.
+
+ \sa setFallbacksEnabled()
+*/
+bool QSettings::fallbacksEnabled() const
+{
+ Q_D(const QSettings);
+ return d->fallbacks;
+}
+
+#ifndef QT_NO_QOBJECT
+/*!
+ \reimp
+*/
+bool QSettings::event(QEvent *event)
+{
+ Q_D(QSettings);
+ if (event->type() == QEvent::UpdateRequest) {
+ d->update();
+ return true;
+ }
+ return QObject::event(event);
+}
+#endif
+
+/*!
+ Returns the value for setting \a key. If the setting doesn't
+ exist, returns \a defaultValue.
+
+ If no default value is specified, a default QVariant is
+ returned.
+
+ Note that the Windows registry and INI files use case-insensitive
+ keys, whereas the Carbon Preferences API on Mac OS X uses
+ case-sensitive keys. To avoid portability problems, see the
+ \l{Section and Key Syntax} rules.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 26
+
+ \sa setValue(), contains(), remove()
+*/
+QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+ Q_D(const QSettings);
+ QVariant result = defaultValue;
+ QString k = d->actualKey(key);
+ d->get(k, &result);
+ return result;
+}
+
+/*!
+ \since 4.4
+
+ Sets the default file format to the given \a format, which is used
+ for storing settings for the QSettings(QObject *) constructor.
+
+ If no default format is set, QSettings::NativeFormat is used. See
+ the documentation for the QSettings constructor you are using to
+ see if that constructor will ignore this function.
+
+ \sa format()
+*/
+void QSettings::setDefaultFormat(Format format)
+{
+ globalDefaultFormat = format;
+}
+
+/*!
+ \since 4.4
+
+ Returns default file format used for storing settings for the QSettings(QObject *) constructor.
+ If no default format is set, QSettings::NativeFormat is used.
+
+ \sa format()
+*/
+QSettings::Format QSettings::defaultFormat()
+{
+ return globalDefaultFormat;
+}
+
+/*!
+ \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
+}
+
+/*!
+ \since 4.1
+
+ Sets the path used for storing settings for the given \a format
+ and \a scope, to \a path. The \a format can be a custom format.
+
+ The table below summarizes the default values:
+
+ \table
+ \header \o Platform \o Format \o Scope \o Path
+ \row \o{1,2} Windows \o{1,2} IniFormat \o UserScope \o \c %APPDATA%
+ \row \o SystemScope \o \c %COMMON_APPDATA%
+ \row \o{1,2} Unix \o{1,2} NativeFormat, IniFormat \o UserScope \o \c $HOME/.config
+ \row \o SystemScope \o \c /etc/xdg
+ \row \o{1,2} Qt for Embedded Linux \o{1,2} NativeFormat, IniFormat \o UserScope \o \c $HOME/Settings
+ \row \o SystemScope \o \c /etc/xdg
+ \row \o{1,2} Mac OS X \o{1,2} IniFormat \o UserScope \o \c $HOME/.config
+ \row \o SystemScope \o \c /etc/xdg
+ \endtable
+
+ The default UserScope paths on Unix and Mac OS X (\c
+ $HOME/.config or $HOME/Settings) can be overridden by the user by setting the
+ \c XDG_CONFIG_HOME environment variable. The default SystemScope
+ paths on Unix and Mac OS X (\c /etc/xdg) can be overridden when
+ building the Qt library using the \c configure script's \c
+ --sysconfdir flag (see QLibraryInfo for details).
+
+ Setting the NativeFormat paths on Windows and Mac OS X has no
+ effect.
+
+ \warning This function doesn't affect existing QSettings objects.
+
+ \sa registerFormat()
+*/
+void QSettings::setPath(Format format, Scope scope, const QString &path)
+{
+ QMutexLocker locker(globalMutex());
+ PathHash *pathHash = pathHashFunc();
+ if (pathHash->isEmpty())
+ initDefaultPaths(&locker);
+ pathHash->insert(pathHashKey(format, scope), path + QDir::separator());
+}
+
+/*!
+ \typedef QSettings::SettingsMap
+
+ Typedef for QMap<QString, QVariant>.
+
+ \sa registerFormat()
+*/
+
+/*!
+ \typedef QSettings::ReadFunc
+
+ Typedef for a pointer to a function with the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 27
+
+ \c ReadFunc is used in \c registerFormat() as a pointer to a function
+ that reads a set of key/value pairs. \c ReadFunc should read all the
+ options in one pass, and return all the settings in the \c SettingsMap
+ container, which is initially empty.
+
+ \sa WriteFunc, registerFormat()
+*/
+
+/*!
+ \typedef QSettings::WriteFunc
+
+ Typedef for a pointer to a function with the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 28
+
+ \c WriteFunc is used in \c registerFormat() as a pointer to a function
+ that writes a set of key/value pairs. \c WriteFunc is only called once,
+ so you need to output the settings in one go.
+
+ \sa ReadFunc, registerFormat()
+*/
+
+/*!
+ \since 4.1
+ \threadsafe
+
+ Registers a custom storage format. On success, returns a special
+ Format value that can then be passed to the QSettings constructor.
+ On failure, returns InvalidFormat.
+
+ The \a extension is the file
+ extension associated to the format (without the '.').
+
+ The \a readFunc and \a writeFunc parameters are pointers to
+ functions that read and write a set of key/value pairs. The
+ QIODevice parameter to the read and write functions is always
+ opened in binary mode (i.e., without the QIODevice::Text flag).
+
+ The \a caseSensitivity parameter specifies whether keys are case
+ sensitive or not. This makes a difference when looking up values
+ using QSettings. The default is case sensitive.
+
+ By default, if you use one of the constructors that work in terms
+ of an organization name and an application name, the file system
+ locations used are the same as for IniFormat. Use setPath() to
+ specify other locations.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 29
+
+ \sa setPath()
+*/
+QSettings::Format QSettings::registerFormat(const QString &extension, ReadFunc readFunc,
+ WriteFunc writeFunc,
+ Qt::CaseSensitivity caseSensitivity)
+{
+#ifdef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
+ Q_ASSERT(caseSensitivity == Qt::CaseSensitive);
+#endif
+
+ QMutexLocker locker(globalMutex());
+ CustomFormatVector *customFormatVector = customFormatVectorFunc();
+ int index = customFormatVector->size();
+ if (index == 16) // the QSettings::Format enum has room for 16 custom formats
+ return QSettings::InvalidFormat;
+
+ QConfFileCustomFormat info;
+ info.extension = QLatin1Char('.');
+ info.extension += extension;
+ info.readFunc = readFunc;
+ info.writeFunc = writeFunc;
+ info.caseSensitivity = caseSensitivity;
+ customFormatVector->append(info);
+
+ return QSettings::Format((int)QSettings::CustomFormat1 + index);
+}
+
+#ifdef QT3_SUPPORT
+void QSettings::setPath_helper(Scope scope, const QString &organization, const QString &application)
+{
+ Q_D(QSettings);
+ if (d->pendingChanges)
+ d->flush();
+ QSettingsPrivate *oldPriv = d;
+ QSettingsPrivate *newPriv = QSettingsPrivate::create(oldPriv->format, scope, organization, application);
+ static_cast<QObjectPrivate &>(*newPriv) = static_cast<QObjectPrivate &>(*oldPriv); // copy the QObject stuff over (hack)
+ d_ptr.reset(newPriv);
+}
+
+/*! \fn bool QSettings::writeEntry(const QString &key, bool value)
+
+ Sets the value of setting \a key to \a value.
+
+ Use setValue() instead.
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, double value)
+
+ \overload
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, int value)
+
+ \overload
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, const char *value)
+
+ \overload
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, const QString &value)
+
+ \overload
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value)
+
+ \overload
+*/
+
+/*! \fn bool QSettings::writeEntry(const QString &key, const QStringList &value, QChar separator)
+
+ \overload
+
+ Use setValue(\a key, \a value) instead. You don't need \a separator.
+*/
+
+/*! \fn QStringList QSettings::readListEntry(const QString &key, bool *ok = 0)
+
+ Returns the value of setting \a key converted to a QStringList.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ QStringList list = settings.readListEntry("recentFiles", &ok);
+ \newcode
+ bool ok = settings.contains("recentFiles");
+ QStringList list = settings.value("recentFiles").toStringList();
+ \endcode
+*/
+
+/*! \fn QStringList QSettings::readListEntry(const QString &key, QChar separator, bool *ok)
+
+ Returns the value of setting \a key converted to a QStringList.
+ \a separator is ignored.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ QStringList list = settings.readListEntry("recentFiles", ":", &ok);
+ \newcode
+ bool ok = settings.contains("recentFiles");
+ QStringList list = settings.value("recentFiles").toStringList();
+ \endcode
+*/
+
+/*! \fn QString QSettings::readEntry(const QString &key, const QString &defaultValue, bool *ok)
+
+ Returns the value for setting \a key converted to a QString. If
+ the setting doesn't exist, returns \a defaultValue.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ QString str = settings.readEntry("userName", "administrator", &ok);
+ \newcode
+ bool ok = settings.contains("userName");
+ QString str = settings.value("userName", "administrator").toString();
+ \endcode
+*/
+
+/*! \fn int QSettings::readNumEntry(const QString &key, int defaultValue, bool *ok)
+
+ Returns the value for setting \a key converted to an \c int. If
+ the setting doesn't exist, returns \a defaultValue.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ int max = settings.readNumEntry("maxConnections", 30, &ok);
+ \newcode
+ bool ok = settings.contains("maxConnections");
+ int max = settings.value("maxConnections", 30).toInt();
+ \endcode
+*/
+
+/*! \fn double QSettings::readDoubleEntry(const QString &key, double defaultValue, bool *ok)
+
+ Returns the value for setting \a key converted to a \c double. If
+ the setting doesn't exist, returns \a defaultValue.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ double pi = settings.readDoubleEntry("pi", 3.141592, &ok);
+ \newcode
+ bool ok = settings.contains("pi");
+ double pi = settings.value("pi", 3.141592).toDouble();
+ \endcode
+*/
+
+/*! \fn bool QSettings::readBoolEntry(const QString &key, bool defaultValue, bool *ok)
+
+ Returns the value for setting \a key converted to a \c bool. If
+ the setting doesn't exist, returns \a defaultValue.
+
+ If \a ok is not 0, *\a{ok} is set to true if the key exists,
+ otherwise *\a{ok} is set to false.
+
+ Use value() instead.
+
+ \oldcode
+ bool ok;
+ bool grid = settings.readBoolEntry("showGrid", true, &ok);
+ \newcode
+ bool ok = settings.contains("showGrid");
+ bool grid = settings.value("showGrid", true).toBool();
+ \endcode
+*/
+
+/*! \fn bool QSettings::removeEntry(const QString &key)
+
+ Use remove() instead.
+*/
+
+/*! \enum QSettings::System
+ \compat
+
+ \value Unix Unix systems (X11 and Embedded Linux)
+ \value Windows Microsoft Windows systems
+ \value Mac Mac OS X systems
+
+ \sa insertSearchPath(), removeSearchPath()
+*/
+
+/*! \fn void QSettings::insertSearchPath(System system, const QString &path)
+
+ This function is implemented as a no-op. It is provided for
+ source compatibility with Qt 3. The new QSettings class has no
+ concept of "search path".
+*/
+
+/*! \fn void QSettings::removeSearchPath(System system, const QString &path)
+
+ This function is implemented as a no-op. It is provided for
+ source compatibility with Qt 3. The new QSettings class has no
+ concept of "search path".
+*/
+
+/*! \fn void QSettings::setPath(const QString &organization, const QString &application, \
+ Scope scope)
+
+ Specifies the \a organization, \a application, and \a scope to
+ use by the QSettings object.
+
+ Use the appropriate constructor instead, with QSettings::UserScope
+ instead of QSettings::User and QSettings::SystemScope instead of
+ QSettings::Global.
+
+ \oldcode
+ QSettings settings;
+ settings.setPath("twikimaster.com", "Kanooth", QSettings::Global);
+ \newcode
+ QSettings settings(QSettings::SystemScope, "twikimaster.com", "Kanooth");
+ \endcode
+*/
+
+/*! \fn void QSettings::resetGroup()
+
+ Sets the current group to be the empty string.
+
+ Use endGroup() instead (possibly multiple times).
+
+ \oldcode
+ QSettings settings;
+ settings.beginGroup("mainWindow");
+ settings.beginGroup("leftPanel");
+ ...
+ settings.resetGroup();
+ \newcode
+ QSettings settings;
+ settings.beginGroup("mainWindow");
+ settings.beginGroup("leftPanel");
+ ...
+ settings.endGroup();
+ settings.endGroup();
+ \endcode
+*/
+
+/*! \fn QStringList QSettings::entryList(const QString &key) const
+
+ Returns a list of all sub-keys of \a key.
+
+ Use childKeys() instead.
+
+ \oldcode
+ QSettings settings;
+ QStringList keys = settings.entryList("cities");
+ ...
+ \newcode
+ QSettings settings;
+ settings.beginGroup("cities");
+ QStringList keys = settings.childKeys();
+ ...
+ settings.endGroup();
+ \endcode
+*/
+
+/*! \fn QStringList QSettings::subkeyList(const QString &key) const
+
+ Returns a list of all sub-keys of \a key.
+
+ Use childGroups() instead.
+
+ \oldcode
+ QSettings settings;
+ QStringList groups = settings.entryList("cities");
+ ...
+ \newcode
+ QSettings settings;
+ settings.beginGroup("cities");
+ QStringList groups = settings.childKeys();
+ ...
+ settings.endGroup();
+ \endcode
+*/
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SETTINGS
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
new file mode 100644
index 0000000000..b62446ee3b
--- /dev/null
+++ b/src/corelib/io/qsettings.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSETTINGS_H
+#define QSETTINGS_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+QT_END_NAMESPACE
+
+#ifndef QT_NO_SETTINGS
+
+#ifdef QT3_SUPPORT
+#include <QtCore/qstringlist.h>
+#endif
+
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Status // we seem to pick up a macro Status --> int somewhere
+#undef Status
+#endif
+
+class QIODevice;
+class QSettingsPrivate;
+
+#ifndef QT_NO_QOBJECT
+class Q_CORE_EXPORT QSettings : public QObject
+#else
+class Q_CORE_EXPORT QSettings
+#endif
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#else
+ QScopedPointer<QSettingsPrivate> d_ptr;
+#endif
+ Q_DECLARE_PRIVATE(QSettings)
+
+public:
+ enum Status {
+ NoError = 0,
+ AccessError,
+ FormatError
+ };
+
+ enum Format {
+ NativeFormat,
+ IniFormat,
+
+ InvalidFormat = 16,
+ CustomFormat1,
+ CustomFormat2,
+ CustomFormat3,
+ CustomFormat4,
+ CustomFormat5,
+ CustomFormat6,
+ CustomFormat7,
+ CustomFormat8,
+ CustomFormat9,
+ CustomFormat10,
+ CustomFormat11,
+ CustomFormat12,
+ CustomFormat13,
+ CustomFormat14,
+ CustomFormat15,
+ CustomFormat16
+ };
+
+ enum Scope {
+ UserScope,
+ SystemScope
+#ifdef QT3_SUPPORT
+ ,
+ User = UserScope,
+ Global = SystemScope
+#endif
+ };
+
+#ifndef QT_NO_QOBJECT
+ explicit QSettings(const QString &organization,
+ const QString &application = QString(), QObject *parent = 0);
+ QSettings(Scope scope, const QString &organization,
+ const QString &application = QString(), QObject *parent = 0);
+ QSettings(Format format, Scope scope, const QString &organization,
+ const QString &application = QString(), QObject *parent = 0);
+ QSettings(const QString &fileName, Format format, QObject *parent = 0);
+ explicit QSettings(QObject *parent = 0);
+#else
+ explicit QSettings(const QString &organization,
+ const QString &application = QString());
+ QSettings(Scope scope, const QString &organization,
+ const QString &application = QString());
+ QSettings(Format format, Scope scope, const QString &organization,
+ const QString &application = QString());
+ QSettings(const QString &fileName, Format format);
+#endif
+ ~QSettings();
+
+ void clear();
+ void sync();
+ Status status() const;
+
+ void beginGroup(const QString &prefix);
+ void endGroup();
+ QString group() const;
+
+ int beginReadArray(const QString &prefix);
+ void beginWriteArray(const QString &prefix, int size = -1);
+ void endArray();
+ void setArrayIndex(int i);
+
+ QStringList allKeys() const;
+ QStringList childKeys() const;
+ QStringList childGroups() const;
+ bool isWritable() const;
+
+ void setValue(const QString &key, const QVariant &value);
+ QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+
+ void remove(const QString &key);
+ bool contains(const QString &key) const;
+
+ void setFallbacksEnabled(bool b);
+ bool fallbacksEnabled() const;
+
+ QString fileName() const;
+ Format format() const;
+ Scope scope() const;
+ QString organizationName() const;
+ QString applicationName() const;
+
+#ifndef QT_NO_TEXTCODEC
+ void setIniCodec(QTextCodec *codec);
+ void setIniCodec(const char *codecName);
+ QTextCodec *iniCodec() const;
+#endif
+
+ static void setDefaultFormat(Format format);
+ static Format defaultFormat();
+ static void setSystemIniPath(const QString &dir); // ### remove in 5.0 (use setPath() instead)
+ static void setUserIniPath(const QString &dir); // ### remove in 5.0 (use setPath() instead)
+ static void setPath(Format format, Scope scope, const QString &path);
+
+ typedef QMap<QString, QVariant> SettingsMap;
+ typedef bool (*ReadFunc)(QIODevice &device, SettingsMap &map);
+ typedef bool (*WriteFunc)(QIODevice &device, const SettingsMap &map);
+
+ static Format registerFormat(const QString &extension, ReadFunc readFunc, WriteFunc writeFunc,
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool writeEntry(const QString &key, bool value)
+ { setValue(key, value); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, double value)
+ { setValue(key, value); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, int value)
+ { setValue(key, value); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, const char *value)
+ { setValue(key, QString::fromAscii(value)); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, const QString &value)
+ { setValue(key, value); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, const QStringList &value)
+ { setValue(key, value); return isWritable(); }
+ inline QT3_SUPPORT bool writeEntry(const QString &key, const QStringList &value, QChar separator)
+ { setValue(key, value.join(QString(separator))); return isWritable(); }
+ inline QT3_SUPPORT QStringList readListEntry(const QString &key, bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ return value(key).toStringList();
+ }
+ inline QT3_SUPPORT QStringList readListEntry(const QString &key, QChar separator, bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ QString str = value(key).toString();
+ if (str.isEmpty())
+ return QStringList();
+ return str.split(separator);
+ }
+ inline QT3_SUPPORT QString readEntry(const QString &key, const QString &defaultValue = QString(),
+ bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ return value(key, defaultValue).toString();
+ }
+ inline QT3_SUPPORT int readNumEntry(const QString &key, int defaultValue = 0, bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ return value(key, defaultValue).toInt();
+ }
+ inline QT3_SUPPORT double readDoubleEntry(const QString &key, double defaultValue = 0,
+ bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ return value(key, defaultValue).toDouble();
+ }
+ inline QT3_SUPPORT bool readBoolEntry(const QString &key, bool defaultValue = false,
+ bool *ok = 0)
+ {
+ if (ok)
+ *ok = contains(key);
+ return value(key, defaultValue).toBool();
+ }
+ inline QT3_SUPPORT bool removeEntry(const QString &key)
+ { remove(key); return true; }
+
+ enum System { Unix, Windows, Mac };
+ inline QT3_SUPPORT void insertSearchPath(System, const QString &) {}
+ inline QT3_SUPPORT void removeSearchPath(System, const QString &) {}
+
+ inline QT3_SUPPORT void setPath(const QString &organization, const QString &application,
+ Scope scope = Global)
+ {
+ setPath_helper(scope == Global ? QSettings::SystemScope : QSettings::UserScope,
+ organization, application);
+ }
+ inline QT3_SUPPORT void resetGroup()
+ {
+ while (!group().isEmpty())
+ endGroup();
+ }
+ inline QT3_SUPPORT QStringList entryList(const QString &key) const
+ {
+ QSettings *that = const_cast<QSettings *>(this);
+ QStringList result;
+
+ that->beginGroup(key);
+ result = that->childKeys();
+ that->endGroup();
+ return result;
+ }
+ inline QT3_SUPPORT QStringList subkeyList(const QString &key) const
+ {
+ QSettings *that = const_cast<QSettings *>(this);
+ QStringList result;
+
+ that->beginGroup(key);
+ result = that->childGroups();
+ that->endGroup();
+ return result;
+ }
+#endif
+
+protected:
+#ifndef QT_NO_QOBJECT
+ bool event(QEvent *event);
+#endif
+
+private:
+#ifdef QT3_SUPPORT
+ void setPath_helper(Scope scope, const QString &organization, const QString &application);
+#endif
+
+ Q_DISABLE_COPY(QSettings)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SETTINGS
+
+QT_END_HEADER
+
+#endif // QSETTINGS_H
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
new file mode 100644
index 0000000000..6bc41a6afb
--- /dev/null
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -0,0 +1,654 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsettings.h"
+#include "qsettings_p.h"
+#include "qdatetime.h"
+#include "qdir.h"
+#include "qvarlengtharray.h"
+#include "private/qcore_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static const CFStringRef hostNames[2] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost };
+static const int numHostNames = 2;
+
+/*
+ On the Mac, it is more natural to use '.' as the key separator
+ than '/'. Therefore, it makes sense to replace '/' with '.' in
+ keys. Then we replace '.' with middle dots (which we can't show
+ here) and middle dots with '/'. A key like "4.0/BrowserCommand"
+ becomes "4<middot>0.BrowserCommand".
+*/
+
+enum RotateShift { Macify = 1, Qtify = 2 };
+
+static QString rotateSlashesDotsAndMiddots(const QString &key, int shift)
+{
+ static const int NumKnights = 3;
+ static const char knightsOfTheRoundTable[NumKnights] = { '/', '.', '\xb7' };
+ QString result = key;
+
+ for (int i = 0; i < result.size(); ++i) {
+ for (int j = 0; j < NumKnights; ++j) {
+ if (result.at(i) == QLatin1Char(knightsOfTheRoundTable[j])) {
+ result[i] = QLatin1Char(knightsOfTheRoundTable[(j + shift) % NumKnights]).unicode();
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+static QCFType<CFStringRef> macKey(const QString &key)
+{
+ return QCFString::toCFStringRef(rotateSlashesDotsAndMiddots(key, Macify));
+}
+
+static QString qtKey(CFStringRef cfkey)
+{
+ return rotateSlashesDotsAndMiddots(QCFString::toQString(cfkey), Qtify);
+}
+
+static QCFType<CFPropertyListRef> macValue(const QVariant &value);
+
+static CFArrayRef macList(const QList<QVariant> &list)
+{
+ int n = list.size();
+ 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()),
+ CFIndex(n), &kCFTypeArrayCallBacks);
+}
+
+static QCFType<CFPropertyListRef> macValue(const QVariant &value)
+{
+ CFPropertyListRef result = 0;
+
+ switch (value.type()) {
+ case QVariant::ByteArray:
+ {
+ QByteArray ba = value.toByteArray();
+ result = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(ba.data()),
+ CFIndex(ba.size()));
+ }
+ break;
+ // should be same as below (look for LIST)
+ case QVariant::List:
+ case QVariant::StringList:
+ case QVariant::Polygon:
+ result = macList(value.toList());
+ break;
+ case QVariant::Map:
+ {
+ /*
+ 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.first().type()) {
+ // should be same as above (look for LIST)
+ case QVariant::List:
+ case QVariant::StringList:
+ case QVariant::Polygon:
+ singleton = false;
+ default:
+ ;
+ }
+ }
+
+ cfkeys[numUniqueKeys] = QCFString::toCFStringRef(key);
+ cfvalues[numUniqueKeys] = singleton ? macValue(values.first()) : macList(values);
+ ++numUniqueKeys;
+ }
+
+ result = CFDictionaryCreate(kCFAllocatorDefault,
+ reinterpret_cast<const void **>(cfkeys.data()),
+ reinterpret_cast<const void **>(cfvalues.data()),
+ CFIndex(numUniqueKeys),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ /*
+ CFDate, unlike QDateTime, doesn't store timezone information.
+ */
+ QDateTime dt = value.toDateTime();
+ if (dt.timeSpec() == Qt::LocalTime) {
+ QDateTime reference;
+ reference.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970);
+ result = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTime(reference.secsTo(dt)));
+ } else {
+ goto string_case;
+ }
+ }
+ break;
+ case QVariant::Bool:
+ result = value.toBool() ? kCFBooleanTrue : kCFBooleanFalse;
+ break;
+ case QVariant::Int:
+ case QVariant::UInt:
+ {
+ int n = value.toInt();
+ result = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n);
+ }
+ break;
+ case QVariant::Double:
+ {
+ double n = value.toDouble();
+ result = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &n);
+ }
+ break;
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ {
+ qint64 n = value.toLongLong();
+ result = CFNumberCreate(0, kCFNumberLongLongType, &n);
+ }
+ break;
+ case QVariant::String:
+ string_case:
+ default:
+ result = QCFString::toCFStringRef(QSettingsPrivate::variantToString(value));
+ }
+ return result;
+}
+
+static QVariant qtValue(CFPropertyListRef cfvalue)
+{
+ if (!cfvalue)
+ return QVariant();
+
+ CFTypeID typeId = CFGetTypeID(cfvalue);
+
+ /*
+ Sorted grossly from most to least frequent type.
+ */
+ if (typeId == CFStringGetTypeID()) {
+ return QSettingsPrivate::stringToVariant(QCFString::toQString(static_cast<CFStringRef>(cfvalue)));
+ } else if (typeId == CFNumberGetTypeID()) {
+ CFNumberRef cfnumber = static_cast<CFNumberRef>(cfvalue);
+ if (CFNumberIsFloatType(cfnumber)) {
+ double d;
+ CFNumberGetValue(cfnumber, kCFNumberDoubleType, &d);
+ return d;
+ } else {
+ int i;
+ qint64 ll;
+
+ if (CFNumberGetValue(cfnumber, kCFNumberIntType, &i))
+ return i;
+ CFNumberGetValue(cfnumber, kCFNumberLongLongType, &ll);
+ return ll;
+ }
+ } else if (typeId == CFArrayGetTypeID()) {
+ CFArrayRef cfarray = static_cast<CFArrayRef>(cfvalue);
+ QList<QVariant> list;
+ CFIndex size = CFArrayGetCount(cfarray);
+ bool metNonString = false;
+ for (CFIndex i = 0; i < size; ++i) {
+ QVariant value = qtValue(CFArrayGetValueAtIndex(cfarray, i));
+ if (value.type() != QVariant::String)
+ metNonString = true;
+ list << value;
+ }
+ if (metNonString)
+ return list;
+ else
+ return QVariant(list).toStringList();
+ } else if (typeId == CFBooleanGetTypeID()) {
+ return (bool)CFBooleanGetValue(static_cast<CFBooleanRef>(cfvalue));
+ } else if (typeId == CFDataGetTypeID()) {
+ CFDataRef cfdata = static_cast<CFDataRef>(cfvalue);
+ return QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)),
+ CFDataGetLength(cfdata));
+ } else if (typeId == CFDictionaryGetTypeID()) {
+ CFDictionaryRef cfdict = static_cast<CFDictionaryRef>(cfvalue);
+ CFTypeID arrayTypeId = CFArrayGetTypeID();
+ int size = (int)CFDictionaryGetCount(cfdict);
+ QVarLengthArray<CFPropertyListRef> keys(size);
+ QVarLengthArray<CFPropertyListRef> values(size);
+ CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
+
+ QMultiMap<QString, QVariant> map;
+ for (int i = 0; i < size; ++i) {
+ QString key = QCFString::toQString(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)));
+ } else {
+ map.insert(key, qtValue(values[i]));
+ }
+ }
+ return map;
+ } else if (typeId == CFDateGetTypeID()) {
+ QDateTime dt;
+ dt.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970);
+ return dt.addSecs((int)CFDateGetAbsoluteTime(static_cast<CFDateRef>(cfvalue)));
+ }
+ return QVariant();
+}
+
+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)
+ || 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")) {
+ QString result = organization;
+ result.replace(QLatin1Char('/'), QLatin1Char(' '));
+ return result;
+ }
+ break;
+ }
+ int uc = ch.unicode();
+ if ((uc < 'a' || uc > 'z') && (uc < 'A' || uc > 'Z'))
+ break;
+ }
+
+ QString domain;
+ for (int i = 0; i < organization.size(); ++i) {
+ QChar ch = organization.at(i);
+ int uc = ch.unicode();
+ if ((uc >= 'a' && uc <= 'z') || (uc >= '0' && uc <= '9')) {
+ domain += ch;
+ } else if (uc >= 'A' && uc <= 'Z') {
+ domain += ch.toLower();
+ } else {
+ domain += QLatin1Char(' ');
+ }
+ }
+ domain = domain.simplified();
+ domain.replace(QLatin1Char(' '), QLatin1Char('-'));
+ if (!domain.isEmpty())
+ domain.append(QLatin1String(".com"));
+ return domain;
+}
+
+class QMacSettingsPrivate : public QSettingsPrivate
+{
+public:
+ QMacSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application);
+ ~QMacSettingsPrivate();
+
+ void remove(const QString &key);
+ void set(const QString &key, const QVariant &value);
+ bool get(const QString &key, QVariant *value) const;
+ QStringList children(const QString &prefix, ChildSpec spec) const;
+ void clear();
+ void sync();
+ void flush();
+ bool isWritable() const;
+ QString fileName() const;
+
+private:
+ struct SearchDomain
+ {
+ CFStringRef userName;
+ CFStringRef applicationOrSuiteId;
+ };
+
+ QCFString applicationId;
+ QCFString suiteId;
+ QCFString hostName;
+ SearchDomain domains[6];
+ int numDomains;
+};
+
+QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application)
+ : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
+{
+ QString javaPackageName;
+ int curPos = 0;
+ int nextDot;
+
+ QString domainName = comify(organization);
+ if (domainName.isEmpty()) {
+ setStatus(QSettings::AccessError);
+ domainName = QLatin1String("unknown-organization.trolltech.com");
+ }
+
+ while ((nextDot = domainName.indexOf(QLatin1Char('.'), curPos)) != -1) {
+ javaPackageName.prepend(domainName.mid(curPos, nextDot - curPos));
+ javaPackageName.prepend(QLatin1Char('.'));
+ curPos = nextDot + 1;
+ }
+ javaPackageName.prepend(domainName.mid(curPos));
+ javaPackageName = javaPackageName.toLower();
+ if (curPos == 0)
+ javaPackageName.prepend(QLatin1String("com."));
+ suiteId = javaPackageName;
+
+ if (scope == QSettings::SystemScope)
+ spec |= F_System;
+
+ if (application.isEmpty()) {
+ spec |= F_Organization;
+ } else {
+ javaPackageName += QLatin1Char('.');
+ javaPackageName += application;
+ applicationId = javaPackageName;
+ }
+
+ numDomains = 0;
+ for (int i = (spec & F_System) ? 1 : 0; i < 2; ++i) {
+ for (int j = (spec & F_Organization) ? 1 : 0; j < 3; ++j) {
+ SearchDomain &domain = domains[numDomains++];
+ domain.userName = (i == 0) ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ if (j == 0)
+ domain.applicationOrSuiteId = applicationId;
+ else if (j == 1)
+ domain.applicationOrSuiteId = suiteId;
+ else
+ domain.applicationOrSuiteId = kCFPreferencesAnyApplication;
+ }
+ }
+
+ hostName = (scope == QSettings::SystemScope) ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ sync();
+}
+
+QMacSettingsPrivate::~QMacSettingsPrivate()
+{
+}
+
+void QMacSettingsPrivate::remove(const QString &key)
+{
+ QStringList keys = children(key + QLatin1Char('/'), 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 += keys.at(i);
+ }
+ CFPreferencesSetValue(macKey(subKey), 0, domains[0].applicationOrSuiteId,
+ domains[0].userName, hostName);
+ }
+}
+
+void QMacSettingsPrivate::set(const QString &key, const QVariant &value)
+{
+ CFPreferencesSetValue(macKey(key), macValue(value), domains[0].applicationOrSuiteId,
+ domains[0].userName, hostName);
+}
+
+bool QMacSettingsPrivate::get(const QString &key, QVariant *value) const
+{
+ QCFString k = macKey(key);
+ for (int i = 0; i < numDomains; ++i) {
+ for (int j = 0; j < numHostNames; ++j) {
+ QCFType<CFPropertyListRef> ret =
+ CFPreferencesCopyValue(k, domains[i].applicationOrSuiteId, domains[i].userName,
+ hostNames[j]);
+ if (ret) {
+ if (value)
+ *value = qtValue(ret);
+ return true;
+ }
+ }
+
+ if (!fallbacks)
+ break;
+ }
+ return false;
+}
+
+QStringList QMacSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
+{
+ QMap<QString, QString> result;
+ int startPos = prefix.size();
+
+ for (int i = 0; i < numDomains; ++i) {
+ for (int j = 0; j < numHostNames; ++j) {
+ QCFType<CFArrayRef> cfarray = CFPreferencesCopyKeyList(domains[i].applicationOrSuiteId,
+ domains[i].userName,
+ hostNames[j]);
+ if (cfarray) {
+ CFIndex size = CFArrayGetCount(cfarray);
+ for (CFIndex k = 0; k < size; ++k) {
+ QString currentKey =
+ qtKey(static_cast<CFStringRef>(CFArrayGetValueAtIndex(cfarray, k)));
+ if (currentKey.startsWith(prefix))
+ processChild(currentKey.mid(startPos), spec, result);
+ }
+ }
+ }
+
+ if (!fallbacks)
+ break;
+ }
+ return result.keys();
+}
+
+void QMacSettingsPrivate::clear()
+{
+ QCFType<CFArrayRef> cfarray = CFPreferencesCopyKeyList(domains[0].applicationOrSuiteId,
+ domains[0].userName, hostName);
+ CFPreferencesSetMultiple(0, cfarray, domains[0].applicationOrSuiteId, domains[0].userName,
+ hostName);
+}
+
+void QMacSettingsPrivate::sync()
+{
+ for (int i = 0; i < numDomains; ++i) {
+ for (int j = 0; j < numHostNames; ++j) {
+ Boolean ok = CFPreferencesSynchronize(domains[i].applicationOrSuiteId,
+ domains[i].userName, hostNames[j]);
+ // only report failures for the primary file (the one we write to)
+ if (!ok && i == 0 && hostNames[j] == hostName && status == QSettings::NoError) {
+#if 1
+ // work around what seems to be a bug in CFPreferences:
+ // don't report an error if there are no preferences for the application
+ QCFType<CFArrayRef> appIds = CFPreferencesCopyApplicationList(domains[i].userName,
+ hostNames[j]);
+
+ // iterate through all the applications and see if we're there
+ CFIndex size = CFArrayGetCount(appIds);
+ for (CFIndex k = 0; k < size; ++k) {
+ const void *cfvalue = CFArrayGetValueAtIndex(appIds, k);
+ if (CFGetTypeID(cfvalue) == CFStringGetTypeID()) {
+ if (CFStringCompare(static_cast<CFStringRef>(cfvalue),
+ domains[i].applicationOrSuiteId,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ setStatus(QSettings::AccessError);
+ break;
+ }
+ }
+ }
+#else
+ setStatus(QSettings::AccessError);
+#endif
+ }
+ }
+ }
+}
+
+void QMacSettingsPrivate::flush()
+{
+ sync();
+}
+
+bool QMacSettingsPrivate::isWritable() const
+{
+ QMacSettingsPrivate *that = const_cast<QMacSettingsPrivate *>(this);
+ QString impossibleKey(QLatin1String("qt_internal/"));
+
+ QSettings::Status oldStatus = that->status;
+ that->status = QSettings::NoError;
+
+ that->set(impossibleKey, QVariant());
+ that->sync();
+ bool writable = (status == QSettings::NoError) && that->get(impossibleKey, 0);
+ that->remove(impossibleKey);
+ that->sync();
+
+ that->status = oldStatus;
+ return writable;
+}
+
+QString QMacSettingsPrivate::fileName() const
+{
+ QString result;
+ if ((spec & F_System) == 0)
+ result = QDir::homePath();
+ result += QLatin1String("/Library/Preferences/");
+ result += QCFString::toQString(domains[0].applicationOrSuiteId);
+ result += QLatin1String(".plist");
+ return result;
+}
+
+QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format,
+ QSettings::Scope scope,
+ const QString &organization,
+ const QString &application)
+{
+ if (format == QSettings::NativeFormat) {
+ return new QMacSettingsPrivate(scope, organization, application);
+ } else {
+ return new QConfFileSettingsPrivate(format, scope, organization, application);
+ }
+}
+
+static QCFType<CFURLRef> urlFromFileName(const QString &fileName)
+{
+ return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, QCFString(fileName),
+ kCFURLPOSIXPathStyle, false);
+}
+
+bool QConfFileSettingsPrivate::readPlistFile(const QString &fileName, ParsedSettingsMap *map) const
+{
+ QCFType<CFDataRef> resource;
+ SInt32 code;
+ if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, urlFromFileName(fileName),
+ &resource, 0, 0, &code))
+ return false;
+
+ QCFString errorStr;
+ QCFType<CFPropertyListRef> propertyList =
+ CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, kCFPropertyListImmutable,
+ &errorStr);
+
+ if (!propertyList)
+ return true;
+ if (CFGetTypeID(propertyList) != CFDictionaryGetTypeID())
+ return false;
+
+ CFDictionaryRef cfdict =
+ static_cast<CFDictionaryRef>(static_cast<CFPropertyListRef>(propertyList));
+ int size = (int)CFDictionaryGetCount(cfdict);
+ QVarLengthArray<CFPropertyListRef> keys(size);
+ QVarLengthArray<CFPropertyListRef> values(size);
+ CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
+
+ for (int i = 0; i < size; ++i) {
+ QString key = qtKey(static_cast<CFStringRef>(keys[i]));
+ map->insert(QSettingsKey(key, Qt::CaseSensitive), qtValue(values[i]));
+ }
+ return true;
+}
+
+bool QConfFileSettingsPrivate::writePlistFile(const QString &fileName,
+ const ParsedSettingsMap &map) const
+{
+ QVarLengthArray<QCFType<CFStringRef> > cfkeys(map.size());
+ QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(map.size());
+ int i = 0;
+ ParsedSettingsMap::const_iterator j;
+ for (j = map.constBegin(); j != map.constEnd(); ++j) {
+ cfkeys[i] = macKey(j.key());
+ cfvalues[i] = macValue(j.value());
+ ++i;
+ }
+
+ QCFType<CFDictionaryRef> propertyList =
+ CFDictionaryCreate(kCFAllocatorDefault,
+ reinterpret_cast<const void **>(cfkeys.data()),
+ reinterpret_cast<const void **>(cfvalues.data()),
+ CFIndex(map.size()),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ QCFType<CFDataRef> xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList);
+
+ SInt32 code;
+ return CFURLWriteDataAndPropertiesToResource(urlFromFileName(fileName), xmlData, 0, &code);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
new file mode 100644
index 0000000000..ec5b6bbe1b
--- /dev/null
+++ b/src/corelib/io/qsettings_p.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSETTINGS_P_H
+#define QSETTINGS_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/qdatetime.h"
+#include "QtCore/qmap.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qiodevice.h"
+#include "QtCore/qstack.h"
+#include "QtCore/qstringlist.h"
+#ifndef QT_NO_QOBJECT
+#include "private/qobject_p.h"
+#endif
+#include "private/qscopedpointer_p.h"
+
+#ifdef Q_OS_WIN
+#include "QtCore/qt_windows.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+#define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
+#endif
+
+// used in testing framework
+#define QSETTINGS_P_H_VERSION 3
+
+#ifdef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
+static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseSensitive;
+
+class QSettingsKey : public QString
+{
+public:
+ inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, int /* position */ = -1)
+ : QString(key) { Q_ASSERT(cs == Qt::CaseSensitive); Q_UNUSED(cs); }
+
+ inline QString originalCaseKey() const { return *this; }
+ inline int originalKeyPosition() const { return -1; }
+};
+#else
+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)
+ {
+ if (cs == Qt::CaseInsensitive)
+ QString::operator=(toLower());
+ }
+
+ inline QString originalCaseKey() const { return theOriginalKey; }
+ inline int originalKeyPosition() const { return theOriginalKeyPosition; }
+
+private:
+ QString theOriginalKey;
+ int theOriginalKeyPosition;
+};
+#endif
+
+typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
+typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
+
+class QSettingsGroup
+{
+public:
+ inline QSettingsGroup()
+ : num(-1), maxNum(-1) {}
+ inline QSettingsGroup(const QString &s)
+ : str(s), num(-1), maxNum(-1) {}
+ inline QSettingsGroup(const QString &s, bool guessArraySize)
+ : str(s), num(0), maxNum(guessArraySize ? 0 : -1) {}
+
+ 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)
+ { num = i + 1; if (maxNum != -1 && num > maxNum) maxNum = num; }
+
+ QString str;
+ int num;
+ int maxNum;
+};
+
+inline QString QSettingsGroup::toString() const
+{
+ QString result;
+ result = str;
+ if (num > 0) {
+ result += QLatin1Char('/');
+ result += QString::number(num);
+ }
+ return result;
+}
+
+class Q_AUTOTEST_EXPORT QConfFile
+{
+public:
+ ~QConfFile();
+
+ ParsedSettingsMap mergedKeyMap() const;
+ bool isWritable() const;
+
+ static QConfFile *fromName(const QString &name, bool _userPerms);
+ static void clearCache();
+
+ QString name;
+ QDateTime timeStamp;
+ qint64 size;
+ UnparsedSettingsMap unparsedIniSections;
+ ParsedSettingsMap originalKeys;
+ ParsedSettingsMap addedKeys;
+ ParsedSettingsMap removedKeys;
+ QAtomicInt ref;
+ QMutex mutex;
+ bool userPerms;
+
+private:
+#ifdef Q_DISABLE_COPY
+ QConfFile(const QConfFile &);
+ QConfFile &operator=(const QConfFile &);
+#endif
+ QConfFile(const QString &name, bool _userPerms);
+
+ friend class QConfFile_createsItself; // silences compiler warning
+};
+
+class Q_AUTOTEST_EXPORT QSettingsPrivate
+#ifndef QT_NO_QOBJECT
+ : public QObjectPrivate
+#endif
+{
+#ifdef QT_NO_QOBJECT
+ QSettings *q_ptr;
+#endif
+ Q_DECLARE_PUBLIC(QSettings)
+
+public:
+ QSettingsPrivate(QSettings::Format format);
+ QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application);
+ virtual ~QSettingsPrivate();
+
+ 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;
+
+ enum ChildSpec { AllKeys, ChildKeys, ChildGroups };
+ virtual QStringList children(const QString &prefix, ChildSpec spec) const = 0;
+
+ virtual void clear() = 0;
+ virtual void sync() = 0;
+ virtual void flush() = 0;
+ virtual bool isWritable() const = 0;
+ virtual QString fileName() const = 0;
+
+ QString actualKey(const QString &key) const;
+ void beginGroupOrArray(const QSettingsGroup &group);
+ void setStatus(QSettings::Status status) const;
+ void requestUpdate();
+ void update();
+
+ static QString normalizedKey(const QString &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);
+
+ static void processChild(QString key, ChildSpec spec, QMap<QString, QString> &result);
+
+ // Variant streaming functions
+ static QStringList variantListToStringList(const QVariantList &l);
+ static QVariant stringListToVariantList(const QStringList &l);
+
+ // parser functions
+ 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 void iniEscapedString(const QString &str, QByteArray &result, QTextCodec *codec);
+ static void iniEscapedStringList(const QStringList &strs, QByteArray &result, QTextCodec *codec);
+ static bool iniUnescapedStringList(const QByteArray &str, int from, int to,
+ QString &stringResult, QStringList &stringListResult,
+ QTextCodec *codec);
+ static QStringList splitArgs(const QString &s, int idx);
+
+ /*
+ The numeric values of these enums define their search order. For example,
+ F_User | F_Organization is searched before F_System | F_Application,
+ because their values are respectively 1 and 2.
+ */
+ enum {
+ F_Application = 0x0,
+ F_Organization = 0x1,
+ F_User = 0x0,
+ F_System = 0x2,
+ NumConfFiles = 4
+ };
+
+ QSettings::Format format;
+ QSettings::Scope scope;
+ QString organizationName;
+ QString applicationName;
+ QTextCodec *iniCodec;
+
+protected:
+ QStack<QSettingsGroup> groupStack;
+ QString groupPrefix;
+ int spec;
+ bool fallbacks;
+ bool pendingChanges;
+ mutable QSettings::Status status;
+};
+
+class QConfFileSettingsPrivate : public QSettingsPrivate
+{
+public:
+ QConfFileSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application);
+ QConfFileSettingsPrivate(const QString &fileName, QSettings::Format format);
+ ~QConfFileSettingsPrivate();
+
+ void remove(const QString &key);
+ void set(const QString &key, const QVariant &value);
+ bool get(const QString &key, QVariant *value) const;
+
+ QStringList children(const QString &prefix, ChildSpec spec) const;
+
+ void clear();
+ void sync();
+ void flush();
+ bool isWritable() const;
+ QString fileName() const;
+
+ static bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections);
+ static bool readIniSection(const QSettingsKey &section, const QByteArray &data,
+ ParsedSettingsMap *settingsMap, QTextCodec *codec);
+ static bool readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen,
+ int &equalsPos);
+
+private:
+ void initFormat();
+ void initAccess();
+ void syncConfFile(int confFileNo);
+ bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
+#ifdef Q_OS_MAC
+ bool readPlistFile(const QString &fileName, ParsedSettingsMap *map) const;
+ bool writePlistFile(const QString &fileName, const ParsedSettingsMap &map) const;
+#endif
+ void ensureAllSectionsParsed(QConfFile *confFile) const;
+ void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
+
+ QScopedSharedPointer<QConfFile> confFiles[NumConfFiles];
+ QSettings::ReadFunc readFunc;
+ QSettings::WriteFunc writeFunc;
+ QString extension;
+ Qt::CaseSensitivity caseSensitivity;
+ int nextPosition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSETTINGS_P_H
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
new file mode 100644
index 0000000000..3ef919a5ff
--- /dev/null
+++ b/src/corelib/io/qsettings_win.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsettings.h"
+
+#ifndef QT_NO_SETTINGS
+
+#include "qsettings_p.h"
+#include "qvector.h"
+#include "qmap.h"
+#include "qt_windows.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/* 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". */
+
+/*******************************************************************************
+** Some convenience functions
+*/
+
+/*
+ We don't use KEY_ALL_ACCESS because it gives more rights than what we
+ need. See task 199061.
+ */
+static const REGSAM registryPermissions = KEY_READ | KEY_WRITE;
+
+static QString keyPath(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return QString();
+ return rKey.left(idx + 1);
+}
+
+static QString keyName(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+
+ QString res;
+ if (idx == -1)
+ res = rKey;
+ else
+ res = rKey.mid(idx + 1);
+
+ if (res == QLatin1String("Default") || res == QLatin1String("."))
+ res = QLatin1String("");
+
+ return res;
+}
+
+static QString escapedKey(QString uKey)
+{
+ QChar *data = uKey.data();
+ int l = uKey.length();
+ for (int i = 0; i < l; ++i) {
+ ushort &ucs = data[i].unicode();
+ if (ucs == '\\')
+ ucs = '/';
+ else if (ucs == '/')
+ ucs = '\\';
+ }
+ return uKey;
+}
+
+static QString unescapedKey(QString rKey)
+{
+ return escapedKey(rKey);
+}
+
+typedef QMap<QString, QString> NameSet;
+
+static void mergeKeySets(NameSet *dest, const NameSet &src)
+{
+ NameSet::const_iterator it = src.constBegin();
+ for (; it != src.constEnd(); ++it)
+ dest->insert(unescapedKey(it.key()), QString());
+}
+
+static void mergeKeySets(NameSet *dest, const QStringList &src)
+{
+ QStringList::const_iterator it = src.constBegin();
+ for (; it != src.constEnd(); ++it)
+ dest->insert(unescapedKey(*it), QString());
+}
+
+/*******************************************************************************
+** Wrappers for the insane windows registry API
+*/
+
+static QString errorCodeToString(DWORD errorCode)
+{
+ wchar_t *data = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0);
+ QString result = QString::fromWCharArray(data);
+
+ if (data != 0)
+ LocalFree(data);
+
+ if (result.endsWith(QLatin1Char('\n')))
+ result.truncate(result.length() - 1);
+
+ return result;
+}
+
+// Open a key with the specified perms
+static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
+{
+ HKEY resultHandle = 0;
+ LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
+ 0, perms, &resultHandle);
+
+ if (res == ERROR_SUCCESS)
+ return resultHandle;
+
+ return 0;
+}
+
+// Open a key with the specified perms, create it if it does not exist
+static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
+{
+ // try to open it
+ HKEY resultHandle = openKey(parentHandle, perms, rSubKey);
+ if (resultHandle != 0)
+ return resultHandle;
+
+ // try to create it
+ LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
+ REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0);
+
+ if (res == ERROR_SUCCESS)
+ return resultHandle;
+
+ //qWarning("QSettings: Failed to create subkey \"%s\": %s",
+ // rSubKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+
+ return 0;
+}
+
+// Open or create a key in read-write mode if possible, otherwise read-only
+static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly)
+{
+ // try to open or create it read/write
+ HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey);
+ if (resultHandle != 0) {
+ if (readOnly != 0)
+ *readOnly = false;
+ return resultHandle;
+ }
+
+ // try to open or create it read/only
+ resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey);
+ if (resultHandle != 0) {
+ if (readOnly != 0)
+ *readOnly = true;
+ return resultHandle;
+ }
+ return 0;
+}
+
+static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec)
+{
+ QStringList result;
+ DWORD numKeys;
+ DWORD maxKeySize;
+ DWORD numSubgroups;
+ DWORD maxSubgroupSize;
+
+ // Find the number of keys and subgroups, as well as the max of their lengths.
+ LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
+ &numKeys, &maxKeySize, 0, 0, 0);
+
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data());
+ return result;
+ }
+
+ ++maxSubgroupSize;
+ ++maxKeySize;
+
+ int n;
+ int m;
+ if (spec == QSettingsPrivate::ChildKeys) {
+ n = numKeys;
+ m = maxKeySize;
+ } else {
+ n = numSubgroups;
+ m = maxSubgroupSize;
+ }
+
+ /* The size does not include the terminating null character. */
+ ++m;
+
+ // Get the list
+ QByteArray buff(m * sizeof(wchar_t), 0);
+ for (int i = 0; i < n; ++i) {
+ QString item;
+ DWORD l = buff.size() / sizeof(wchar_t);
+ if (spec == QSettingsPrivate::ChildKeys) {
+ res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
+ } else {
+ res = RegEnumKeyEx(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
+ }
+ if (res == ERROR_SUCCESS)
+ item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
+
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data());
+ continue;
+ }
+ if (item.isEmpty())
+ item = QLatin1String(".");
+ result.append(item);
+ }
+ return result;
+}
+
+static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
+{
+ HKEY handle = openKey(parentHandle, KEY_READ, rSubKey);
+ if (handle == 0)
+ return;
+
+ QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
+ QStringList childGroups = childKeysOrGroups(handle, QSettingsPrivate::ChildGroups);
+ RegCloseKey(handle);
+
+ for (int i = 0; i < childKeys.size(); ++i) {
+ QString s = rSubKey;
+ if (!s.isEmpty())
+ s += QLatin1Char('\\');
+ s += childKeys.at(i);
+ result->insert(s, QString());
+ }
+
+ for (int i = 0; i < childGroups.size(); ++i) {
+ QString s = rSubKey;
+ if (!s.isEmpty())
+ s += QLatin1Char('\\');
+ s += childGroups.at(i);
+ allKeys(parentHandle, s, result);
+ }
+}
+
+static void deleteChildGroups(HKEY parentHandle)
+{
+ QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups);
+
+ for (int i = 0; i < childGroups.size(); ++i) {
+ QString group = childGroups.at(i);
+
+ // delete subgroups in group
+ HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group);
+ if (childGroupHandle == 0)
+ continue;
+ deleteChildGroups(childGroupHandle);
+ RegCloseKey(childGroupHandle);
+
+ // delete group itself
+ LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s",
+ group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+** class RegistryKey
+*/
+
+class RegistryKey
+{
+public:
+ RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true);
+ QString key() const;
+ HKEY handle() const;
+ HKEY parentHandle() const;
+ bool readOnly() const;
+ void close();
+private:
+ HKEY m_parent_handle;
+ mutable HKEY m_handle;
+ QString m_key;
+ mutable bool m_read_only;
+};
+
+RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only)
+{
+ m_parent_handle = parent_handle;
+ m_handle = 0;
+ m_read_only = read_only;
+ m_key = key;
+}
+
+QString RegistryKey::key() const
+{
+ return m_key;
+}
+
+HKEY RegistryKey::handle() const
+{
+ if (m_handle != 0)
+ return m_handle;
+
+ if (m_read_only)
+ m_handle = openKey(m_parent_handle, KEY_READ, m_key);
+ else
+ m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only);
+
+ return m_handle;
+}
+
+HKEY RegistryKey::parentHandle() const
+{
+ return m_parent_handle;
+}
+
+bool RegistryKey::readOnly() const
+{
+ return m_read_only;
+}
+
+void RegistryKey::close()
+{
+ if (m_handle != 0)
+ RegCloseKey(m_handle);
+ m_handle = 0;
+}
+
+typedef QVector<RegistryKey> RegistryKeyList;
+
+/*******************************************************************************
+** class QWinSettingsPrivate
+*/
+
+class QWinSettingsPrivate : public QSettingsPrivate
+{
+public:
+ QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application);
+ QWinSettingsPrivate(QString rKey);
+ ~QWinSettingsPrivate();
+
+ void remove(const QString &uKey);
+ void set(const QString &uKey, const QVariant &value);
+ bool get(const QString &uKey, QVariant *value) const;
+ QStringList children(const QString &uKey, ChildSpec spec) const;
+ void clear();
+ void sync();
+ void flush();
+ bool isWritable() const;
+ HKEY writeHandle() const;
+ bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const;
+ QString fileName() const;
+
+private:
+ RegistryKeyList regList; // list of registry locations to search for keys
+ bool deleteWriteHandleOnExit;
+};
+
+QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application)
+ : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
+{
+ deleteWriteHandleOnExit = false;
+
+ if (!organization.isEmpty()) {
+ QString prefix = QLatin1String("Software\\") + organization;
+ QString orgPrefix = prefix + QLatin1String("\\OrganizationDefaults");
+ QString appPrefix = prefix + QLatin1Char('\\') + application;
+
+ if (scope == QSettings::UserScope) {
+ if (!application.isEmpty())
+ regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty()));
+
+ regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty()));
+ }
+
+ if (!application.isEmpty())
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty()));
+
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty()));
+ }
+
+ if (regList.isEmpty())
+ setStatus(QSettings::AccessError);
+}
+
+QWinSettingsPrivate::QWinSettingsPrivate(QString rPath)
+ : QSettingsPrivate(QSettings::NativeFormat)
+{
+ deleteWriteHandleOnExit = false;
+
+ if (rPath.startsWith(QLatin1String("\\")))
+ rPath = rPath.mid(1);
+
+ if (rPath.startsWith(QLatin1String("HKEY_CURRENT_USER\\")))
+ regList.append(RegistryKey(HKEY_CURRENT_USER, rPath.mid(18), false));
+ else if (rPath == QLatin1String("HKEY_CURRENT_USER"))
+ regList.append(RegistryKey(HKEY_CURRENT_USER, QString(), false));
+ else if (rPath.startsWith(QLatin1String("HKEY_LOCAL_MACHINE\\")))
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, rPath.mid(19), false));
+ else if (rPath == QLatin1String("HKEY_LOCAL_MACHINE"))
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, QString(), false));
+ else if (rPath.startsWith(QLatin1String("HKEY_CLASSES_ROOT\\")))
+ regList.append(RegistryKey(HKEY_CLASSES_ROOT, rPath.mid(18), false));
+ else if (rPath == QLatin1String("HKEY_CLASSES_ROOT"))
+ regList.append(RegistryKey(HKEY_CLASSES_ROOT, QString(), false));
+ else if (rPath.startsWith(QLatin1String("HKEY_USERS\\")))
+ regList.append(RegistryKey(HKEY_USERS, rPath.mid(11), false));
+ else if (rPath == QLatin1String(QLatin1String("HKEY_USERS")))
+ regList.append(RegistryKey(HKEY_USERS, QString(), false));
+ else
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, rPath, false));
+}
+
+bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
+{
+ QString rSubkeyName = keyName(rSubKey);
+ QString rSubkeyPath = keyPath(rSubKey);
+
+ // open a handle on the subkey
+ HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath);
+ if (handle == 0)
+ return false;
+
+ // 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;
+ }
+
+ // get the value
+ 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;
+ }
+
+ switch (dataType) {
+ case REG_EXPAND_SZ:
+ case REG_SZ: {
+ QString s;
+ if (dataSize) {
+ s = QString::fromWCharArray(((const wchar_t *)data.constData()));
+ }
+ if (value != 0)
+ *value = stringToVariant(s);
+ break;
+ }
+
+ case REG_MULTI_SZ: {
+ QStringList l;
+ if (dataSize) {
+ int i = 0;
+ for (;;) {
+ QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
+ i += s.length() + 1;
+
+ if (s.isEmpty())
+ break;
+ l.append(s);
+ }
+ }
+ if (value != 0)
+ *value = stringListToVariantList(l);
+ break;
+ }
+
+ case REG_NONE:
+ case REG_BINARY: {
+ QString s;
+ if (dataSize) {
+ s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
+ }
+ if (value != 0)
+ *value = stringToVariant(s);
+ break;
+ }
+
+ case REG_DWORD_BIG_ENDIAN:
+ case REG_DWORD: {
+ Q_ASSERT(data.size() == sizeof(int));
+ int i;
+ memcpy((char*)&i, data.constData(), sizeof(int));
+ if (value != 0)
+ *value = i;
+ break;
+ }
+
+ case REG_QWORD: {
+ Q_ASSERT(data.size() == sizeof(qint64));
+ qint64 i;
+ memcpy((char*)&i, data.constData(), sizeof(qint64));
+ if (value != 0)
+ *value = i;
+ break;
+ }
+
+ default:
+ qWarning("QSettings: Unknown data %d type in Windows registry", static_cast<int>(dataType));
+ if (value != 0)
+ *value = QVariant();
+ break;
+ }
+
+ RegCloseKey(handle);
+ return true;
+}
+
+HKEY QWinSettingsPrivate::writeHandle() const
+{
+ if (regList.isEmpty())
+ return 0;
+ const RegistryKey &key = regList.at(0);
+ if (key.handle() == 0 || key.readOnly())
+ return 0;
+ return key.handle();
+}
+
+QWinSettingsPrivate::~QWinSettingsPrivate()
+{
+ if (deleteWriteHandleOnExit && writeHandle() != 0) {
+#if defined(Q_OS_WINCE)
+ remove(regList.at(0).key());
+#else
+ QString emptyKey;
+ DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: Failed to delete key \"%s\": %s",
+ regList.at(0).key().toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ }
+#endif
+ }
+
+ for (int i = 0; i < regList.size(); ++i)
+ regList[i].close();
+}
+
+void QWinSettingsPrivate::remove(const QString &uKey)
+{
+ if (writeHandle() == 0) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
+ QString rKey = escapedKey(uKey);
+
+ // try to delete value bar in key foo
+ LONG res;
+ HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey));
+ if (handle != 0) {
+ res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
+ RegCloseKey(handle);
+ }
+
+ // try to delete key foo/bar and all subkeys
+ handle = openKey(writeHandle(), registryPermissions, rKey);
+ if (handle != 0) {
+ deleteChildGroups(handle);
+
+ if (rKey.isEmpty()) {
+ QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
+
+ for (int i = 0; i < childKeys.size(); ++i) {
+ QString group = childKeys.at(i);
+
+ LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
+ group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ }
+ }
+ } else {
+#if defined(Q_OS_WINCE)
+ // For WinCE always Close the handle first.
+ RegCloseKey(handle);
+#endif
+ res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
+
+ if (res != ERROR_SUCCESS) {
+ qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s",
+ rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ }
+ }
+ RegCloseKey(handle);
+ }
+}
+
+static bool stringContainsNullChar(const QString &s)
+{
+ for (int i = 0; i < s.length(); ++i) {
+ if (s.at(i).unicode() == 0)
+ return true;
+ }
+ return false;
+}
+
+void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
+{
+ if (writeHandle() == 0) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
+ QString rKey = escapedKey(uKey);
+
+ HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey));
+ if (handle == 0) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
+ DWORD type;
+ QByteArray regValueBuff;
+
+ // Determine the type
+ switch (value.type()) {
+ case QVariant::List:
+ case QVariant::StringList: {
+ // 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;
+ QStringList l = variantListToStringList(value.toList());
+ QStringList::const_iterator it = l.constBegin();
+ for (; it != l.constEnd(); ++it) {
+ if ((*it).length() == 0 || stringContainsNullChar(*it)) {
+ type = REG_BINARY;
+ break;
+ }
+ }
+
+ if (type == REG_BINARY) {
+ QString s = variantToString(value);
+ regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
+ } else {
+ QStringList::const_iterator it = l.constBegin();
+ for (; it != l.constEnd(); ++it) {
+ const QString &s = *it;
+ regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
+ }
+ regValueBuff.append((char)0);
+ regValueBuff.append((char)0);
+ }
+ break;
+ }
+
+ case QVariant::Int:
+ case QVariant::UInt: {
+ type = REG_DWORD;
+ qint32 i = value.toInt();
+ regValueBuff = QByteArray((const char*)&i, sizeof(qint32));
+ break;
+ }
+
+ case QVariant::LongLong:
+ case QVariant::ULongLong: {
+ type = REG_QWORD;
+ qint64 i = value.toLongLong();
+ regValueBuff = QByteArray((const char*)&i, sizeof(qint64));
+ break;
+ }
+
+ case QVariant::ByteArray:
+ // fallthrough intended
+
+ default: {
+ // If the string does not contain '\0', we can use REG_SZ, the native registry
+ // string type. Otherwise we use REG_BINARY.
+ QString s = variantToString(value);
+ type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ;
+ if (type == REG_BINARY) {
+ regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
+ } else {
+ regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
+ }
+ break;
+ }
+ }
+
+ // set the value
+ LONG res = RegSetValueEx(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type,
+ reinterpret_cast<const unsigned char*>(regValueBuff.constData()),
+ regValueBuff.size());
+
+ if (res == ERROR_SUCCESS) {
+ deleteWriteHandleOnExit = false;
+ } else {
+ qWarning("QSettings: failed to set subkey \"%s\": %s",
+ rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ setStatus(QSettings::AccessError);
+ }
+
+ RegCloseKey(handle);
+}
+
+bool QWinSettingsPrivate::get(const QString &uKey, QVariant *value) const
+{
+ QString rKey = escapedKey(uKey);
+
+ for (int i = 0; i < regList.size(); ++i) {
+ HKEY handle = regList.at(i).handle();
+ if (handle != 0 && readKey(handle, rKey, value))
+ return true;
+
+ if (!fallbacks)
+ return false;
+ }
+
+ return false;
+}
+
+QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) const
+{
+ NameSet result;
+ QString rKey = escapedKey(uKey);
+
+ for (int i = 0; i < regList.size(); ++i) {
+ HKEY parent_handle = regList.at(i).handle();
+ if (parent_handle == 0)
+ continue;
+ HKEY handle = openKey(parent_handle, KEY_READ, rKey);
+ if (handle == 0)
+ continue;
+
+ if (spec == AllKeys) {
+ NameSet keys;
+ allKeys(handle, QLatin1String(""), &keys);
+ mergeKeySets(&result, keys);
+ } else { // ChildGroups or ChildKeys
+ QStringList names = childKeysOrGroups(handle, spec);
+ mergeKeySets(&result, names);
+ }
+
+ RegCloseKey(handle);
+
+ if (!fallbacks)
+ return result.keys();
+ }
+
+ return result.keys();
+}
+
+void QWinSettingsPrivate::clear()
+{
+ remove(QString());
+ deleteWriteHandleOnExit = true;
+}
+
+void QWinSettingsPrivate::sync()
+{
+ RegFlushKey(writeHandle());
+}
+
+void QWinSettingsPrivate::flush()
+{
+ // Windows does this for us.
+}
+
+QString QWinSettingsPrivate::fileName() const
+{
+ if (regList.isEmpty())
+ return QString();
+
+ const RegistryKey &key = regList.at(0);
+ QString result;
+ if (key.parentHandle() == HKEY_CURRENT_USER)
+ result = QLatin1String("\\HKEY_CURRENT_USER\\");
+ else
+ result = QLatin1String("\\HKEY_LOCAL_MACHINE\\");
+
+ return result + regList.at(0).key();
+}
+
+bool QWinSettingsPrivate::isWritable() const
+{
+ return writeHandle() != 0;
+}
+
+QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application)
+{
+ if (format == QSettings::NativeFormat) {
+ return new QWinSettingsPrivate(scope, organization, application);
+ } else {
+ return new QConfFileSettingsPrivate(format, scope, organization, application);
+ }
+}
+
+QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
+{
+ if (format == QSettings::NativeFormat) {
+ return new QWinSettingsPrivate(fileName);
+ } else {
+ return new QConfFileSettingsPrivate(fileName, format);
+ }
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_SETTINGS
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
new file mode 100644
index 0000000000..b5e5808145
--- /dev/null
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -0,0 +1,713 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtemporaryfile.h"
+
+#ifndef QT_NO_TEMPORARYFILE
+
+#include "qplatformdefs.h"
+#include "qabstractfileengine.h"
+#include "private/qfile_p.h"
+#include "private/qabstractfileengine_p.h"
+#include "private/qfsfileengine_p.h"
+
+#if !defined(Q_OS_WINCE)
+# include <errno.h>
+#endif
+
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#if defined(Q_OS_UNIX)
+# include "private/qcore_unix_p.h" // overrides QT_OPEN
+#endif
+
+#if defined(QT_BUILD_CORE_LIB)
+#include "qcoreapplication.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*!
+ \internal
+
+ Generates a unique file path and returns a native handle to the open file.
+ \a path is used as a template when generating unique paths,
+ \a placeholderStart and \a placeholderEnd delimit the sub-string that will
+ be randomized.
+
+ Returns an open handle to the newly created file if successful, an invalid
+ handle otherwise. In both cases, the string in \a path will be changed and
+ contain the generated path name.
+*/
+static int createFileFromTemplate(char *const path,
+ char *const placeholderStart, char *const placeholderEnd)
+{
+ Q_ASSERT(placeholderEnd > placeholderStart);
+
+ // Initialize placeholder with random chars + PID.
+ {
+ char *rIter = placeholderEnd;
+
+#if defined(QT_BUILD_CORE_LIB)
+ qint64 pid = QCoreApplication::applicationPid();
+ do {
+ *--rIter = (pid % 10) + '0';
+ pid /= 10;
+ } while (rIter != placeholderStart && pid != 0);
+#endif
+
+ while (rIter != placeholderStart) {
+ char ch = char((qrand() & 0xffff) % (26 + 26));
+ if (ch < 26)
+ *--rIter = ch + 'A';
+ else
+ *--rIter = ch - 26 + 'a';
+ }
+ }
+
+ for (;;) {
+ // Atomically create file and obtain handle
+#ifndef Q_OS_WIN
+ {
+ int fd = QT_OPEN(path, QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE, 0600);
+ if (fd != -1)
+ return fd;
+ if (errno != EEXIST)
+ return -1;
+ }
+#else
+ if (!QFileInfo(QLatin1String(path)).exists())
+ return 1;
+#endif
+
+ /* tricky little algorwwithm for backward compatibility */
+ for (char *iter = placeholderStart;;) {
+ // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
+ // String progression: "ZZaiC" => "aabiC"
+ if (*iter == 'Z') {
+ *iter++ = 'a';
+ if (iter == placeholderEnd)
+ return -1;
+ } else {
+ if (isdigit(*iter))
+ *iter = 'a';
+ else if (*iter == 'z') /* inc from z to A */
+ *iter = 'A';
+ else {
+ ++*iter;
+ }
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
+
+//************* QTemporaryFileEngine
+class QTemporaryFileEngine : public QFSFileEngine
+{
+ Q_DECLARE_PRIVATE(QFSFileEngine)
+public:
+ QTemporaryFileEngine(const QString &file, bool fileIsTemplate = true)
+ : QFSFileEngine(), filePathIsTemplate(fileIsTemplate)
+ {
+ Q_D(QFSFileEngine);
+ d->fileEntry = QFileSystemEntry(file);
+
+ if (!filePathIsTemplate)
+ QFSFileEngine::setFileName(file);
+ }
+
+ ~QTemporaryFileEngine();
+
+ bool isReallyOpen();
+ void setFileName(const QString &file);
+ void setFileTemplate(const QString &fileTemplate);
+
+ bool open(QIODevice::OpenMode flags);
+ bool remove();
+ bool rename(const QString &newName);
+ bool close();
+
+ bool filePathIsTemplate;
+};
+
+QTemporaryFileEngine::~QTemporaryFileEngine()
+{
+ QFSFileEngine::close();
+}
+
+bool QTemporaryFileEngine::isReallyOpen()
+{
+ Q_D(QFSFileEngine);
+
+ if (!((0 == d->fh) && (-1 == d->fd)
+#if defined (Q_OS_SYMBIAN)
+ && (0 == d->symbianFile.SubSessionHandle())
+#endif
+#if defined Q_OS_WIN
+ && (INVALID_HANDLE_VALUE == d->fileHandle)
+#endif
+ ))
+ return true;
+
+ return false;
+
+}
+
+void QTemporaryFileEngine::setFileName(const QString &file)
+{
+ // Really close the file, so we don't leak
+ QFSFileEngine::close();
+ QFSFileEngine::setFileName(file);
+}
+
+void QTemporaryFileEngine::setFileTemplate(const QString &fileTemplate)
+{
+ Q_D(QFSFileEngine);
+ if (filePathIsTemplate)
+ d->fileEntry = QFileSystemEntry(fileTemplate);
+}
+
+bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
+{
+ Q_D(QFSFileEngine);
+ Q_ASSERT(!isReallyOpen());
+
+ openMode |= QIODevice::ReadWrite;
+
+ if (!filePathIsTemplate)
+ return QFSFileEngine::open(openMode);
+
+ QString qfilename = d->fileEntry.filePath();
+
+ // Find placeholder string.
+ uint phPos = qfilename.length();
+ uint phLength = 0;
+
+ while (phPos != 0) {
+ --phPos;
+
+ if (qfilename[phPos] == QLatin1Char('X')) {
+ ++phLength;
+ continue;
+ }
+
+ if (qfilename[phPos] == QLatin1Char('/')
+ || phLength >= 6) {
+ ++phPos;
+ break;
+ }
+
+ phLength = 0;
+ }
+
+ QStringRef prefix, suffix;
+ if (phLength < 6) {
+ qfilename += QLatin1Char('.');
+ prefix = QStringRef(&qfilename);
+ phLength = 6;
+ } else {
+ prefix = qfilename.leftRef(phPos);
+ suffix = qfilename.midRef(phPos + phLength);
+ }
+
+ QByteArray filename = prefix.toLocal8Bit();
+ phPos = filename.length();
+ if (suffix.isEmpty())
+ filename.resize(phPos + phLength);
+ else
+ filename.insert(phPos + phLength, suffix.toLocal8Bit());
+
+ char *path = filename.data();
+
+#ifndef Q_OS_WIN
+ int fd = createFileFromTemplate(path, path + phPos, path + phPos + phLength);
+ if (fd != -1) {
+ // First open the fd as an external file descriptor to
+ // initialize the engine properly.
+ if (QFSFileEngine::open(openMode, fd)) {
+
+ // Allow the engine to close the handle even if it's "external".
+ d->closeFileHandle = true;
+
+ // Restore the file names (open() resets them).
+ d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length())); //note that filename is NOT a native path
+ filePathIsTemplate = false;
+ return true;
+ }
+
+ QT_CLOSE(fd);
+ }
+ setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno));
+ return false;
+#else
+ if (createFileFromTemplate(path, path + phPos, path + phPos + phLength) == -1) {
+ return false;
+ }
+
+ QString template_ = d->fileEntry.filePath();
+ d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length()));
+
+ if (QFSFileEngine::open(openMode)) {
+ filePathIsTemplate = false;
+ return true;
+ }
+
+ d->fileEntry = QFileSystemEntry(template_);
+ return false;
+#endif
+}
+
+bool QTemporaryFileEngine::remove()
+{
+ Q_D(QFSFileEngine);
+ // Since the QTemporaryFileEngine::close() does not really close the file,
+ // we must explicitly call QFSFileEngine::close() before we remove it.
+ QFSFileEngine::close();
+ if (QFSFileEngine::remove()) {
+ d->fileEntry.clear();
+ return true;
+ }
+ return false;
+}
+
+bool QTemporaryFileEngine::rename(const QString &newName)
+{
+ QFSFileEngine::close();
+ return QFSFileEngine::rename(newName);
+}
+
+bool QTemporaryFileEngine::close()
+{
+ // Don't close the file, just seek to the front.
+ seek(0);
+ setError(QFile::UnspecifiedError, QString());
+ return true;
+}
+
+//************* QTemporaryFilePrivate
+class QTemporaryFilePrivate : public QFilePrivate
+{
+ Q_DECLARE_PUBLIC(QTemporaryFile)
+
+protected:
+ QTemporaryFilePrivate();
+ ~QTemporaryFilePrivate();
+
+ bool autoRemove;
+ QString templateName;
+};
+
+QTemporaryFilePrivate::QTemporaryFilePrivate() : autoRemove(true)
+{
+}
+
+QTemporaryFilePrivate::~QTemporaryFilePrivate()
+{
+}
+
+//************* QTemporaryFile
+
+/*!
+ \class QTemporaryFile
+ \reentrant
+ \brief The QTemporaryFile class is an I/O device that operates on temporary files.
+
+ \ingroup io
+
+
+ QTemporaryFile is used to create unique temporary files safely.
+ The file itself is created by calling open(). The name of the
+ temporary file is guaranteed to be unique (i.e., you are
+ guaranteed to not overwrite an existing file), and the file will
+ subsequently be removed upon destruction of the QTemporaryFile
+ object. This is an important technique that avoids data
+ corruption for applications that store data in temporary files.
+ The file name is either auto-generated, or created based on a
+ template, which is passed to QTemporaryFile's constructor.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtemporaryfile.cpp 0
+
+ Reopening a QTemporaryFile after calling close() is safe. For as long as
+ the QTemporaryFile object itself is not destroyed, the unique temporary
+ file will exist and be kept open internally by QTemporaryFile.
+
+ The file name of the temporary file can be found by calling fileName().
+ Note that this is only defined after the file is first opened; the function
+ returns an empty string before this.
+
+ A temporary file will have some static part of the name and some
+ part that is calculated to be unique. The default filename \c
+ qt_temp will 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.
+
+ Specified filenames can contain the following template \c XXXXXX
+ (six upper case "X" characters), which will be replaced by the
+ auto-generated portion of the filename. Note that the template is
+ case sensitive. If the template is not present in the filename,
+ QTemporaryFile appends the generated part to the filename given.
+
+ \sa QDir::tempPath(), QFile
+*/
+
+#ifdef QT_NO_QOBJECT
+QTemporaryFile::QTemporaryFile()
+ : QFile(*new QTemporaryFilePrivate)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = QDir::tempPath() + QLatin1String("/qt_temp.XXXXXX");
+}
+
+QTemporaryFile::QTemporaryFile(const QString &templateName)
+ : QFile(*new QTemporaryFilePrivate)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = templateName;
+}
+
+#else
+/*!
+ Constructs a QTemporaryFile in QDir::tempPath(), using the file template
+ "qt_temp.XXXXXX". The file is stored in the system's temporary directory.
+
+ \sa setFileTemplate(), QDir::tempPath()
+*/
+QTemporaryFile::QTemporaryFile()
+ : QFile(*new QTemporaryFilePrivate, 0)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = QDir::tempPath() + QLatin1String("/qt_temp.XXXXXX");
+}
+
+/*!
+ Constructs a QTemporaryFile with a template filename of \a
+ templateName. Upon opening the temporary file this will be used to create
+ a unique filename.
+
+ If the \a templateName does not contain XXXXXX it will automatically be
+ appended and used as the dynamic portion of the filename.
+
+ 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.
+
+ \sa open(), fileTemplate()
+*/
+QTemporaryFile::QTemporaryFile(const QString &templateName)
+ : QFile(*new QTemporaryFilePrivate, 0)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = templateName;
+}
+
+/*!
+ Constructs a QTemporaryFile (with the given \a parent) in
+ QDir::tempPath(), using the file template "qt_temp.XXXXXX".
+
+ \sa setFileTemplate()
+*/
+QTemporaryFile::QTemporaryFile(QObject *parent)
+ : QFile(*new QTemporaryFilePrivate, parent)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = QDir::tempPath() + QLatin1String("/qt_temp.XXXXXX");
+}
+
+/*!
+ Constructs a QTemporaryFile with a template filename of \a
+ templateName and the specified \a parent.
+ Upon opening the temporary file this will be used to
+ create a unique filename.
+
+ If the \a templateName does not contain XXXXXX it will automatically be
+ appended and used as the dynamic portion of the filename.
+
+ 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.
+
+ \sa open(), fileTemplate()
+*/
+QTemporaryFile::QTemporaryFile(const QString &templateName, QObject *parent)
+ : QFile(*new QTemporaryFilePrivate, parent)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = templateName;
+}
+#endif
+
+/*!
+ Destroys the temporary file object, the file is automatically
+ closed if necessary and if in auto remove mode it will
+ automatically delete the file.
+
+ \sa autoRemove()
+*/
+QTemporaryFile::~QTemporaryFile()
+{
+ Q_D(QTemporaryFile);
+ close();
+ if (!d->fileName.isEmpty() && d->autoRemove)
+ remove();
+}
+
+/*!
+ \fn bool QTemporaryFile::open()
+
+ A QTemporaryFile will always be opened in QIODevice::ReadWrite mode,
+ this allows easy access to the data in the file. This function will
+ return true upon success and will set the fileName() to the unique
+ filename used.
+
+ \sa fileName()
+*/
+
+/*!
+ Returns true if the QTemporaryFile is in auto remove
+ mode. Auto-remove mode will automatically delete the filename from
+ disk upon destruction. This makes it very easy to create your
+ QTemporaryFile object on the stack, fill it with data, read from
+ it, and finally on function return it will automatically clean up
+ after itself.
+
+ Auto-remove is on by default.
+
+ \sa setAutoRemove(), remove()
+*/
+bool QTemporaryFile::autoRemove() const
+{
+ Q_D(const QTemporaryFile);
+ return d->autoRemove;
+}
+
+/*!
+ Sets the QTemporaryFile into auto-remove mode if \a b is true.
+
+ Auto-remove is on by default.
+
+ \sa autoRemove(), remove()
+*/
+void QTemporaryFile::setAutoRemove(bool b)
+{
+ Q_D(QTemporaryFile);
+ d->autoRemove = b;
+}
+
+/*!
+ Returns the complete unique filename backing the QTemporaryFile
+ object. This string is null before the QTemporaryFile is opened,
+ afterwards it will contain the fileTemplate() plus
+ additional characters to make it unique.
+
+ \sa fileTemplate()
+*/
+
+QString QTemporaryFile::fileName() const
+{
+ Q_D(const QTemporaryFile);
+ if(d->fileName.isEmpty())
+ return QString();
+ return fileEngine()->fileName(QAbstractFileEngine::DefaultName);
+}
+
+/*!
+ Returns the set file template. The default file template will be
+ called qt_temp and be placed in QDir::tempPath().
+
+ \sa setFileTemplate()
+*/
+QString QTemporaryFile::fileTemplate() const
+{
+ Q_D(const QTemporaryFile);
+ return d->templateName;
+}
+
+/*!
+ Sets the static portion of the file name to \a name. If the file
+ template ends in XXXXXX that will automatically be replaced with
+ the unique part of the filename, otherwise a filename will be
+ determined automatically based on the static portion specified.
+
+ 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.
+
+ \sa fileTemplate()
+*/
+void QTemporaryFile::setFileTemplate(const QString &name)
+{
+ Q_D(QTemporaryFile);
+ d->templateName = name;
+ if (d->fileEngine)
+ static_cast<QTemporaryFileEngine*>(d->fileEngine)->setFileTemplate(name);
+}
+
+/*!
+ \fn QTemporaryFile *QTemporaryFile::createLocalFile(const QString &fileName)
+ \overload
+
+ Works on the given \a fileName rather than an existing QFile
+ object.
+*/
+
+
+/*!
+ If \a file is not on a local disk, a temporary file is created
+ on a local disk, \a file is copied into the temporary local file,
+ and a pointer to the temporary local file is returned. If \a file
+ is already on a local disk, a copy is not created and 0 is returned.
+*/
+QTemporaryFile *QTemporaryFile::createLocalFile(QFile &file)
+{
+ if (QAbstractFileEngine *engine = file.fileEngine()) {
+ if(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)
+ return 0; //local already
+ //cache
+ bool wasOpen = file.isOpen();
+ qint64 old_off = 0;
+ if(wasOpen)
+ old_off = file.pos();
+ else
+ file.open(QIODevice::ReadOnly);
+ //dump data
+ QTemporaryFile *ret = new QTemporaryFile;
+ ret->open();
+ file.seek(0);
+ char buffer[1024];
+ while(true) {
+ qint64 len = file.read(buffer, 1024);
+ if(len < 1)
+ break;
+ ret->write(buffer, len);
+ }
+ ret->seek(0);
+ //restore
+ if(wasOpen)
+ file.seek(old_off);
+ else
+ file.close();
+ //done
+ return ret;
+ }
+ return 0;
+}
+
+/*!
+ \internal
+*/
+
+QAbstractFileEngine *QTemporaryFile::fileEngine() const
+{
+ Q_D(const QTemporaryFile);
+ if(!d->fileEngine) {
+ if (d->fileName.isEmpty())
+ d->fileEngine = new QTemporaryFileEngine(d->templateName);
+ else
+ d->fileEngine = new QTemporaryFileEngine(d->fileName, false);
+ }
+ return d->fileEngine;
+}
+
+/*!
+ \reimp
+
+ Creates a unique file name for the temporary file, and opens it. You can
+ get the unique name later by calling fileName(). The file is guaranteed to
+ have been created by this function (i.e., it has never existed before).
+*/
+bool QTemporaryFile::open(OpenMode flags)
+{
+ Q_D(QTemporaryFile);
+ if (!d->fileName.isEmpty()) {
+ if (static_cast<QTemporaryFileEngine*>(fileEngine())->isReallyOpen()) {
+ setOpenMode(flags);
+ return true;
+ }
+ }
+
+ if (QFile::open(flags)) {
+ d->fileName = d->fileEngine->fileName(QAbstractFileEngine::DefaultName);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TEMPORARYFILE
+
+
diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h
new file mode 100644
index 0000000000..23b41dcdce
--- /dev/null
+++ b/src/corelib/io/qtemporaryfile.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEMPORARYFILE_H
+#define QTEMPORARYFILE_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qfile.h>
+
+#ifdef open
+#error qtemporaryfile.h must be included before any header file that defines open
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_TEMPORARYFILE
+
+class QTemporaryFilePrivate;
+
+class Q_CORE_EXPORT QTemporaryFile : public QFile
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#endif
+ Q_DECLARE_PRIVATE(QTemporaryFile)
+
+public:
+ QTemporaryFile();
+ explicit QTemporaryFile(const QString &templateName);
+#ifndef QT_NO_QOBJECT
+ explicit QTemporaryFile(QObject *parent);
+ QTemporaryFile(const QString &templateName, QObject *parent);
+#endif
+ ~QTemporaryFile();
+
+ bool autoRemove() const;
+ void setAutoRemove(bool b);
+
+ // ### Hides open(flags)
+ bool open() { return open(QIODevice::ReadWrite); }
+
+ QString fileName() const;
+ QString fileTemplate() const;
+ void setFileTemplate(const QString &name);
+
+ inline static QTemporaryFile *createLocalFile(const QString &fileName)
+ { QFile file(fileName); return createLocalFile(file); }
+ static QTemporaryFile *createLocalFile(QFile &file);
+
+ virtual QAbstractFileEngine *fileEngine() const;
+
+protected:
+ bool open(OpenMode flags);
+
+private:
+ friend class QFile;
+ Q_DISABLE_COPY(QTemporaryFile)
+};
+
+#endif // QT_NO_TEMPORARYFILE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTEMPORARYFILE_H
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
new file mode 100644
index 0000000000..a5837cbeb5
--- /dev/null
+++ b/src/corelib/io/qtextstream.cpp
@@ -0,0 +1,3413 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QTEXTSTREAM_DEBUG
+static const int QTEXTSTREAM_BUFFERSIZE = 16384;
+
+/*!
+ \class QTextStream
+
+ \brief The QTextStream class provides a convenient interface for
+ reading and writing text.
+
+ \ingroup io
+ \ingroup string-processing
+ \reentrant
+
+ QTextStream can operate on a QIODevice, a QByteArray or a
+ QString. Using QTextStream's streaming operators, you can
+ conveniently read and write words, lines and numbers. For
+ generating text, QTextStream supports formatting options for field
+ padding and alignment, and formatting of numbers. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 0
+
+ It's also common to use QTextStream to read console input and write
+ console output. QTextStream is locale aware, and will automatically decode
+ standard input using the correct codec. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 1
+
+ Note that you cannot use QTextStream::atEnd(), which returns true when you
+ have reached the end of the data stream, with stdin. The reason for this is
+ that as long as stdin doesn't give any input to the QTextStream, \c atEnd()
+ will return true even if the stdin is open and waiting for more characters.
+
+ Besides using QTextStream's constructors, you can also set the
+ device or string QTextStream operates on by calling setDevice() or
+ setString(). You can seek to a position by calling seek(), and
+ atEnd() will return true when there is no data left to be read. If
+ you call flush(), QTextStream will empty all data from its write
+ buffer into the device and call flush() on the device.
+
+ Internally, QTextStream uses a Unicode based buffer, and
+ QTextCodec is used by QTextStream to automatically support
+ different character sets. By default, QTextCodec::codecForLocale()
+ is used for reading and writing, but you can also set the codec by
+ calling setCodec(). Automatic Unicode detection is also
+ supported. When this feature is enabled (the default behavior),
+ QTextStream will detect the UTF-16 or the UTF-32 BOM (Byte Order Mark) and
+ switch to the appropriate UTF codec when reading. QTextStream
+ does not write a BOM by default, but you can enable this by calling
+ setGenerateByteOrderMark(true). When QTextStream operates on a QString
+ directly, the codec is disabled.
+
+ There are three general ways to use QTextStream when reading text
+ files:
+
+ \list
+
+ \o Chunk by chunk, by calling readLine() or readAll().
+
+ \o Word by word. QTextStream supports streaming into QStrings,
+ QByteArrays and char* buffers. Words are delimited by space, and
+ leading white space is automatically skipped.
+
+ \o Character by character, by streaming into QChar or char types.
+ This method is often used for convenient input handling when
+ parsing files, independent of character encoding and end-of-line
+ semantics. To skip white space, call skipWhiteSpace().
+
+ \endlist
+
+ Since the text stream uses a buffer, you should not read from
+ the stream using the implementation of a superclass. For instance,
+ if you have a QFile and read from it directly using
+ QFile::readLine() instead of using the stream, the text stream's
+ internal position will be out of sync with the file's position.
+
+ By default, when reading numbers from a stream of text,
+ QTextStream will automatically detect the number's base
+ representation. For example, if the number starts with "0x", it is
+ assumed to be in hexadecimal form. If it starts with the digits
+ 1-9, it is assumed to be in decimal form, and so on. You can set
+ the integer base, thereby disabling the automatic detection, by
+ calling setIntegerBase(). Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 2
+
+ QTextStream supports many formatting options for generating text.
+ You can set the field width and pad character by calling
+ setFieldWidth() and setPadChar(). Use setFieldAlignment() to set
+ the alignment within each field. For real numbers, call
+ setRealNumberNotation() and setRealNumberPrecision() to set the
+ notation (SmartNotation, ScientificNotation, FixedNotation) and precision in
+ digits of the generated number. Some extra number formatting
+ options are also available through setNumberFlags().
+
+ \keyword QTextStream manipulators
+
+ Like \c <iostream> in the standard C++ library, QTextStream also
+ defines several global manipulator functions:
+
+ \table
+ \header \o Manipulator \o Description
+ \row \o \c bin \o Same as setIntegerBase(2).
+ \row \o \c oct \o Same as setIntegerBase(8).
+ \row \o \c dec \o Same as setIntegerBase(10).
+ \row \o \c hex \o Same as setIntegerBase(16).
+ \row \o \c showbase \o Same as setNumberFlags(numberFlags() | ShowBase).
+ \row \o \c forcesign \o Same as setNumberFlags(numberFlags() | ForceSign).
+ \row \o \c forcepoint \o Same as setNumberFlags(numberFlags() | ForcePoint).
+ \row \o \c noshowbase \o Same as setNumberFlags(numberFlags() & ~ShowBase).
+ \row \o \c noforcesign \o Same as setNumberFlags(numberFlags() & ~ForceSign).
+ \row \o \c noforcepoint \o Same as setNumberFlags(numberFlags() & ~ForcePoint).
+ \row \o \c uppercasebase \o Same as setNumberFlags(numberFlags() | UppercaseBase).
+ \row \o \c uppercasedigits \o Same as setNumberFlags(numberFlags() | UppercaseDigits).
+ \row \o \c lowercasebase \o Same as setNumberFlags(numberFlags() & ~UppercaseBase).
+ \row \o \c lowercasedigits \o Same as setNumberFlags(numberFlags() & ~UppercaseDigits).
+ \row \o \c fixed \o Same as setRealNumberNotation(FixedNotation).
+ \row \o \c scientific \o Same as setRealNumberNotation(ScientificNotation).
+ \row \o \c left \o Same as setFieldAlignment(AlignLeft).
+ \row \o \c right \o Same as setFieldAlignment(AlignRight).
+ \row \o \c center \o Same as setFieldAlignment(AlignCenter).
+ \row \o \c endl \o Same as operator<<('\n') and flush().
+ \row \o \c flush \o Same as flush().
+ \row \o \c reset \o Same as reset().
+ \row \o \c ws \o Same as skipWhiteSpace().
+ \row \o \c bom \o Same as setGenerateByteOrderMark(true).
+ \endtable
+
+ In addition, Qt provides three global manipulators that take a
+ parameter: qSetFieldWidth(), qSetPadChar(), and
+ qSetRealNumberPrecision().
+
+ \sa QDataStream, QIODevice, QFile, QBuffer, QTcpSocket, {Codecs Example}
+*/
+
+/*! \enum QTextStream::RealNumberNotation
+
+ This enum specifies which notations to use for expressing \c
+ float and \c double as strings.
+
+ \value ScientificNotation Scientific notation (\c{printf()}'s \c %e flag).
+ \value FixedNotation Fixed-point notation (\c{printf()}'s \c %f flag).
+ \value SmartNotation Scientific or fixed-point notation, depending on which makes most sense (\c{printf()}'s \c %g flag).
+
+ \sa setRealNumberNotation()
+*/
+
+/*! \enum QTextStream::FieldAlignment
+
+ This enum specifies how to align text in fields when the field is
+ wider than the text that occupies it.
+
+ \value AlignLeft Pad on the right side of fields.
+ \value AlignRight Pad on the left side of fields.
+ \value AlignCenter Pad on both sides of field.
+ \value AlignAccountingStyle Same as AlignRight, except that the
+ sign of a number is flush left.
+
+ \sa setFieldAlignment()
+*/
+
+/*! \enum QTextStream::NumberFlag
+
+ This enum specifies various flags that can be set to affect the
+ output of integers, \c{float}s, and \c{double}s.
+
+ \value ShowBase Show the base as a prefix if the base
+ is 16 ("0x"), 8 ("0"), or 2 ("0b").
+ \value ForcePoint Always put the decimal separator in numbers, even if
+ there are no decimals.
+ \value ForceSign Always put the sign in numbers, even for positive numbers.
+ \value UppercaseBase Use uppercase versions of base prefixes ("0X", "0B").
+ \value UppercaseDigits Use uppercase letters for expressing
+ digits 10 to 35 instead of lowercase.
+
+ \sa setNumberFlags()
+*/
+
+/*! \enum QTextStream::Status
+
+ This enum describes the current status of the text stream.
+
+ \value Ok The text stream is operating normally.
+ \value ReadPastEnd The text stream has read past the end of the
+ data in the underlying device.
+ \value ReadCorruptData The text stream has read corrupt data.
+ \value WriteFailed The text stream cannot write to the underlying device.
+
+ \sa status()
+*/
+
+#include "qtextstream.h"
+#include "qbuffer.h"
+#include "qfile.h"
+#include "qnumeric.h"
+#ifndef QT_NO_TEXTCODEC
+#include "qtextcodec.h"
+#endif
+#ifndef Q_OS_WINCE
+#include <locale.h>
+#endif
+#include "private/qlocale_p.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <new>
+
+#if defined QTEXTSTREAM_DEBUG
+#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) {
+ 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:
+ QString tmp;
+ tmp.sprintf("\\x%x", (unsigned int)(unsigned char)c);
+ out += tmp.toLatin1();
+ }
+ }
+
+ if (len < maxSize)
+ out += "...";
+
+ return out;
+}
+QT_END_NAMESPACE
+
+#endif
+
+// A precondition macro
+#define Q_VOID
+#define CHECK_VALID_STREAM(x) do { \
+ if (!d->string && !d->device) { \
+ qWarning("QTextStream: No device"); \
+ return x; \
+ } } while (0)
+
+// Base implementations of operator>> for ints and reals
+#define IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(type) do { \
+ Q_D(QTextStream); \
+ CHECK_VALID_STREAM(*this); \
+ qulonglong tmp; \
+ switch (d->getNumber(&tmp)) { \
+ case QTextStreamPrivate::npsOk: \
+ i = (type)tmp; \
+ break; \
+ case QTextStreamPrivate::npsMissingDigit: \
+ case QTextStreamPrivate::npsInvalidPrefix: \
+ i = (type)0; \
+ setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData); \
+ break; \
+ } \
+ return *this; } while (0)
+
+#define IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(type) do { \
+ Q_D(QTextStream); \
+ CHECK_VALID_STREAM(*this); \
+ double tmp; \
+ if (d->getReal(&tmp)) { \
+ f = (type)tmp; \
+ } else { \
+ f = (type)0; \
+ setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData); \
+ } \
+ return *this; } while (0)
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QOBJECT
+class QDeviceClosedNotifier : public QObject
+{
+ Q_OBJECT
+public:
+ inline QDeviceClosedNotifier()
+ { }
+
+ inline void setupDevice(QTextStream *stream, QIODevice *device)
+ {
+ disconnect();
+ if (device)
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
+ this->stream = stream;
+ }
+
+public Q_SLOTS:
+ inline void flushStream() { stream->flush(); }
+
+private:
+ QTextStream *stream;
+};
+#endif
+
+//-------------------------------------------------------------------
+class QTextStreamPrivate
+{
+ Q_DECLARE_PUBLIC(QTextStream)
+public:
+ QTextStreamPrivate(QTextStream *q_ptr);
+ ~QTextStreamPrivate();
+ void reset();
+
+ // device
+ QIODevice *device;
+#ifndef QT_NO_QOBJECT
+ QDeviceClosedNotifier deviceClosedNotifier;
+#endif
+ bool deleteDevice;
+
+ // string
+ QString *string;
+ int stringOffset;
+ QIODevice::OpenMode stringOpenMode;
+
+#ifndef QT_NO_TEXTCODEC
+ // codec
+ QTextCodec *codec;
+ QTextCodec::ConverterState readConverterState;
+ QTextCodec::ConverterState writeConverterState;
+ QTextCodec::ConverterState *readConverterSavedState;
+ bool autoDetectUnicode;
+#endif
+
+ // i/o
+ enum TokenDelimiter {
+ Space,
+ NotSpace,
+ EndOfLine
+ };
+
+ QString read(int maxlen);
+ bool scan(const QChar **ptr, int *tokenLength,
+ int maxlen, TokenDelimiter delimiter);
+ inline const QChar *readPtr() const;
+ inline void consumeLastToken();
+ inline void consume(int nchars);
+ void saveConverterState(qint64 newPos);
+ void restoreToSavedConverterState();
+ int lastTokenSize;
+
+ // Return value type for getNumber()
+ enum NumberParsingStatus {
+ npsOk,
+ npsMissingDigit,
+ npsInvalidPrefix
+ };
+
+ inline bool getChar(QChar *ch);
+ inline void ungetChar(const QChar &ch);
+ NumberParsingStatus getNumber(qulonglong *l);
+ bool getReal(double *f);
+
+ inline void write(const QString &data);
+ inline void putString(const QString &ch, bool number = false);
+ void putNumber(qulonglong number, bool negative);
+
+ // buffers
+ bool fillReadBuffer(qint64 maxBytes = -1);
+ void resetReadBuffer();
+ void flushWriteBuffer();
+ QString writeBuffer;
+ QString readBuffer;
+ int readBufferOffset;
+ int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
+ qint64 readBufferStartDevicePos;
+
+ // streaming parameters
+ int realNumberPrecision;
+ int integerBase;
+ int fieldWidth;
+ QChar padChar;
+ QTextStream::FieldAlignment fieldAlignment;
+ QTextStream::RealNumberNotation realNumberNotation;
+ QTextStream::NumberFlags numberFlags;
+
+ // status
+ QTextStream::Status status;
+
+ QLocale locale;
+
+ QTextStream *q_ptr;
+};
+
+/*! \internal
+*/
+QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
+ :
+#ifndef QT_NO_TEXTCODEC
+ readConverterSavedState(0),
+#endif
+ readConverterSavedStateOffset(0),
+ locale(QLocale::c())
+{
+ this->q_ptr = q_ptr;
+ reset();
+}
+
+/*! \internal
+*/
+QTextStreamPrivate::~QTextStreamPrivate()
+{
+ if (deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ device->blockSignals(true);
+#endif
+ delete device;
+ }
+#ifndef QT_NO_TEXTCODEC
+ delete readConverterSavedState;
+#endif
+}
+
+#ifndef QT_NO_TEXTCODEC
+static void resetCodecConverterStateHelper(QTextCodec::ConverterState *state)
+{
+ state->~ConverterState();
+ new (state) QTextCodec::ConverterState;
+}
+
+static void copyConverterStateHelper(QTextCodec::ConverterState *dest,
+ const QTextCodec::ConverterState *src)
+{
+ // ### QTextCodec::ConverterState's copy constructors and assignments are
+ // private. This function copies the structure manually.
+ Q_ASSERT(!src->d);
+ dest->flags = src->flags;
+ dest->invalidChars = src->invalidChars;
+ dest->state_data[0] = src->state_data[0];
+ dest->state_data[1] = src->state_data[1];
+ dest->state_data[2] = src->state_data[2];
+}
+#endif
+
+/*! \internal
+*/
+void QTextStreamPrivate::reset()
+{
+ realNumberPrecision = 6;
+ integerBase = 0;
+ fieldWidth = 0;
+ padChar = QLatin1Char(' ');
+ fieldAlignment = QTextStream::AlignRight;
+ realNumberNotation = QTextStream::SmartNotation;
+ numberFlags = 0;
+
+ device = 0;
+ deleteDevice = false;
+ string = 0;
+ stringOffset = 0;
+ stringOpenMode = QIODevice::NotOpen;
+
+ readBufferOffset = 0;
+ readBufferStartDevicePos = 0;
+ lastTokenSize = 0;
+
+#ifndef QT_NO_TEXTCODEC
+ codec = QTextCodec::codecForLocale();
+ resetCodecConverterStateHelper(&readConverterState);
+ resetCodecConverterStateHelper(&writeConverterState);
+ delete readConverterSavedState;
+ readConverterSavedState = 0;
+ writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ autoDetectUnicode = true;
+#endif
+}
+
+/*! \internal
+*/
+bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
+{
+ // no buffer next to the QString itself; this function should only
+ // be called internally, for devices.
+ Q_ASSERT(!string);
+ Q_ASSERT(device);
+
+ // handle text translation and bypass the Text flag in the device.
+ bool textModeEnabled = device->isTextModeEnabled();
+ if (textModeEnabled)
+ device->setTextModeEnabled(false);
+
+ // read raw data into a temporary buffer
+ char buf[QTEXTSTREAM_BUFFERSIZE];
+ qint64 bytesRead = 0;
+#if defined(Q_OS_WIN)
+ // On Windows, there is no non-blocking stdin - so we fall back to reading
+ // lines instead. If there is no QOBJECT, we read lines for all sequential
+ // devices; otherwise, we read lines only for stdin.
+ QFile *file = 0;
+ Q_UNUSED(file);
+ if (device->isSequential()
+#if !defined(QT_NO_QOBJECT)
+ && (file = qobject_cast<QFile *>(device)) && file->handle() == 0
+#endif
+ ) {
+ if (maxBytes != -1)
+ bytesRead = device->readLine(buf, qMin<qint64>(sizeof(buf), maxBytes));
+ else
+ bytesRead = device->readLine(buf, sizeof(buf));
+ } else
+#endif
+ {
+ if (maxBytes != -1)
+ bytesRead = device->read(buf, qMin<qint64>(sizeof(buf), maxBytes));
+ else
+ bytesRead = device->read(buf, sizeof(buf));
+ }
+
+#ifndef QT_NO_TEXTCODEC
+ // codec auto detection, explicitly defaults to locale encoding if the
+ // codec has been set to 0.
+ if (!codec || autoDetectUnicode) {
+ autoDetectUnicode = false;
+
+ codec = QTextCodec::codecForUtfText(QByteArray::fromRawData(buf, bytesRead), codec);
+ if (!codec) {
+ codec = QTextCodec::codecForLocale();
+ writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ }
+ }
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec",
+ codec->name().constData());
+#endif
+#endif
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d",
+ qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), sizeof(buf), int(bytesRead));
+#endif
+
+ if (bytesRead <= 0)
+ return false;
+
+ int oldReadBufferSize = readBuffer.size();
+#ifndef QT_NO_TEXTCODEC
+ // convert to unicode
+ readBuffer += codec->toUnicode(buf, bytesRead, &readConverterState);
+#else
+ readBuffer += QString::fromLatin1(QByteArray(buf, bytesRead).constData());
+#endif
+
+ // reset the Text flag.
+ if (textModeEnabled)
+ device->setTextModeEnabled(true);
+
+ // remove all '\r\n' in the string.
+ if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
+ QChar CR = QLatin1Char('\r');
+ QChar *writePtr = readBuffer.data() + oldReadBufferSize;
+ QChar *readPtr = readBuffer.data() + oldReadBufferSize;
+ QChar *endPtr = readBuffer.data() + readBuffer.size();
+
+ int n = oldReadBufferSize;
+ if (readPtr < endPtr) {
+ // Cut-off to avoid unnecessary self-copying.
+ while (*readPtr++ != CR) {
+ ++n;
+ if (++writePtr == endPtr)
+ break;
+ }
+ }
+ while (readPtr < endPtr) {
+ QChar ch = *readPtr++;
+ if (ch != CR) {
+ *writePtr++ = ch;
+ } else {
+ if (n < readBufferOffset)
+ --readBufferOffset;
+ --bytesRead;
+ }
+ ++n;
+ }
+ readBuffer.resize(writePtr - readBuffer.data());
+ }
+
+#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());
+#endif
+ return true;
+}
+
+/*! \internal
+*/
+void QTextStreamPrivate::resetReadBuffer()
+{
+ readBuffer.clear();
+ readBufferOffset = 0;
+ readBufferStartDevicePos = (device ? device->pos() : 0);
+}
+
+/*! \internal
+*/
+void QTextStreamPrivate::flushWriteBuffer()
+{
+ // no buffer next to the QString itself; this function should only
+ // be called internally, for devices.
+ if (string || !device)
+ return;
+
+ // Stream went bye-bye already. Appending further data may succeed again,
+ // but would create a corrupted stream anyway.
+ if (status != QTextStream::Ok)
+ return;
+
+ if (writeBuffer.isEmpty())
+ return;
+
+#if defined (Q_OS_WIN)
+ // handle text translation and bypass the Text flag in the device.
+ bool textModeEnabled = device->isTextModeEnabled();
+ if (textModeEnabled) {
+ device->setTextModeEnabled(false);
+ writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ }
+#endif
+
+#ifndef QT_NO_TEXTCODEC
+ if (!codec)
+ codec = QTextCodec::codecForLocale();
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)",
+ codec->name().constData(), writeConverterState.flags & QTextCodec::IgnoreHeader ? "not" : "");
+#endif
+
+ // convert from unicode to raw data
+ QByteArray data = codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState);
+#else
+ QByteArray data = writeBuffer.toLocal8Bit();
+#endif
+ writeBuffer.clear();
+
+ // write raw data to the device
+ 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));
+#endif
+ if (bytesWritten <= 0) {
+ status = QTextStream::WriteFailed;
+ return;
+ }
+
+#if defined (Q_OS_WIN)
+ // replace the text flag
+ if (textModeEnabled)
+ device->setTextModeEnabled(true);
+#endif
+
+ // flush the file
+#ifndef QT_NO_QOBJECT
+ QFile *file = qobject_cast<QFile *>(device);
+ bool flushed = !file || file->flush();
+#else
+ bool flushed = true;
+#endif
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::flushWriteBuffer() wrote %d bytes",
+ int(bytesWritten));
+#endif
+ if (!flushed || bytesWritten != qint64(data.size()))
+ status = QTextStream::WriteFailed;
+}
+
+QString QTextStreamPrivate::read(int maxlen)
+{
+ QString ret;
+ if (string) {
+ lastTokenSize = qMin(maxlen, string->size() - stringOffset);
+ ret = string->mid(stringOffset, lastTokenSize);
+ } else {
+ while (readBuffer.size() - readBufferOffset < maxlen && fillReadBuffer()) ;
+ lastTokenSize = qMin(maxlen, readBuffer.size() - readBufferOffset);
+ ret = readBuffer.mid(readBufferOffset, lastTokenSize);
+ }
+ consumeLastToken();
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::read() maxlen = %d, token length = %d", maxlen, ret.length());
+#endif
+ return ret;
+}
+
+/*! \internal
+
+ Scans no more than \a maxlen QChars in the current buffer for the
+ first \a delimiter. Stores a pointer to the start offset of the
+ token in \a ptr, and the length in QChars in \a length.
+*/
+bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenDelimiter delimiter)
+{
+ int totalSize = 0;
+ int delimSize = 0;
+ bool consumeDelimiter = false;
+ bool foundToken = false;
+ int startOffset = device ? readBufferOffset : stringOffset;
+ QChar lastChar;
+
+ bool canStillReadFromDevice = true;
+ do {
+ int endOffset;
+ const QChar *chPtr;
+ if (device) {
+ chPtr = readBuffer.constData();
+ endOffset = readBuffer.size();
+ } else {
+ chPtr = string->constData();
+ endOffset = string->size();
+ }
+ chPtr += startOffset;
+
+ for (; !foundToken && startOffset < endOffset && (!maxlen || totalSize < maxlen); ++startOffset) {
+ const QChar ch = *chPtr++;
+ ++totalSize;
+
+ switch (delimiter) {
+ case Space:
+ if (ch.isSpace()) {
+ foundToken = true;
+ delimSize = 1;
+ }
+ break;
+ case NotSpace:
+ if (!ch.isSpace()) {
+ foundToken = true;
+ delimSize = 1;
+ }
+ break;
+ case EndOfLine:
+ if (ch == QLatin1Char('\n')) {
+ foundToken = true;
+ delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1;
+ consumeDelimiter = true;
+ }
+ lastChar = ch;
+ break;
+ }
+ }
+ } while (!foundToken
+ && (!maxlen || totalSize < maxlen)
+ && (device && (canStillReadFromDevice = fillReadBuffer())));
+
+ // if the token was not found, but we reached the end of input,
+ // then we accept what we got. if we are not at the end of input,
+ // we return false.
+ if (!foundToken && (!maxlen || totalSize < maxlen)
+ && (totalSize == 0
+ || (string && stringOffset + totalSize < string->size())
+ || (device && !device->atEnd() && canStillReadFromDevice))) {
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::scan() did not find the token.");
+#endif
+ return false;
+ }
+
+ // if we find a '\r' at the end of the data when reading lines,
+ // 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')) {
+ consumeDelimiter = true;
+ ++delimSize;
+ }
+ }
+
+ // set the read offset and length of the token
+ if (length)
+ *length = totalSize - delimSize;
+ if (ptr)
+ *ptr = readPtr();
+
+ // update last token size. the callee will call consumeLastToken() when
+ // done.
+ lastTokenSize = totalSize;
+ if (!consumeDelimiter)
+ lastTokenSize -= delimSize;
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::scan(%p, %p, %d, %x) token length = %d, delimiter = %d",
+ ptr, length, maxlen, (int)delimiter, totalSize - delimSize, delimSize);
+#endif
+ return true;
+}
+
+/*! \internal
+*/
+inline const QChar *QTextStreamPrivate::readPtr() const
+{
+ Q_ASSERT(readBufferOffset <= readBuffer.size());
+ if (string)
+ return string->constData() + stringOffset;
+ return readBuffer.constData() + readBufferOffset;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::consumeLastToken()
+{
+ if (lastTokenSize)
+ consume(lastTokenSize);
+ lastTokenSize = 0;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::consume(int size)
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::consume(%d)", size);
+#endif
+ if (string) {
+ stringOffset += size;
+ if (stringOffset > string->size())
+ stringOffset = string->size();
+ } else {
+ readBufferOffset += size;
+ if (readBufferOffset >= readBuffer.size()) {
+ readBufferOffset = 0;
+ readBuffer.clear();
+ saveConverterState(device->pos());
+ } else if (readBufferOffset > QTEXTSTREAM_BUFFERSIZE) {
+ readBuffer = readBuffer.remove(0,readBufferOffset);
+ readConverterSavedStateOffset += readBufferOffset;
+ readBufferOffset = 0;
+ }
+ }
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (readConverterState.d) {
+ // converter cannot be copied, so don't save anything
+ // don't update readBufferStartDevicePos either
+ return;
+ }
+
+ if (!readConverterSavedState)
+ readConverterSavedState = new QTextCodec::ConverterState;
+ copyConverterStateHelper(readConverterSavedState, &readConverterState);
+#endif
+
+ readBufferStartDevicePos = newPos;
+ readConverterSavedStateOffset = 0;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::restoreToSavedConverterState()
+{
+#ifndef QT_NO_TEXTCODEC
+ if (readConverterSavedState) {
+ // we have a saved state
+ // that means the converter can be copied
+ copyConverterStateHelper(&readConverterState, readConverterSavedState);
+ } else {
+ // the only state we could save was the initial
+ // so reset to that
+ resetCodecConverterStateHelper(&readConverterState);
+ }
+#endif
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::write(const QString &data)
+{
+ if (string) {
+ // ### What about seek()??
+ string->append(data);
+ } else {
+ writeBuffer += data;
+ if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE)
+ flushWriteBuffer();
+ }
+}
+
+/*! \internal
+*/
+inline bool QTextStreamPrivate::getChar(QChar *ch)
+{
+ if ((string && stringOffset == string->size())
+ || (device && readBuffer.isEmpty() && !fillReadBuffer())) {
+ if (ch)
+ *ch = 0;
+ return false;
+ }
+ if (ch)
+ *ch = *readPtr();
+ consume(1);
+ return true;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::ungetChar(const QChar &ch)
+{
+ if (string) {
+ if (stringOffset == 0)
+ string->prepend(ch);
+ else
+ (*string)[--stringOffset] = ch;
+ return;
+ }
+
+ if (readBufferOffset == 0) {
+ readBuffer.prepend(ch);
+ return;
+ }
+
+ readBuffer[--readBufferOffset] = ch;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::putString(const QString &s, bool number)
+{
+ QString tmp = s;
+
+ // handle padding
+ int padSize = fieldWidth - s.size();
+ if (padSize > 0) {
+ QString pad(padSize, padChar);
+ if (fieldAlignment == QTextStream::AlignLeft) {
+ tmp.append(QString(padSize, padChar));
+ } else if (fieldAlignment == QTextStream::AlignRight
+ || fieldAlignment == QTextStream::AlignAccountingStyle) {
+ tmp.prepend(QString(padSize, padChar));
+ if (fieldAlignment == QTextStream::AlignAccountingStyle && number) {
+ const QChar sign = s.size() > 0 ? s.at(0) : QChar();
+ if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
+ QChar *data = tmp.data();
+ data[padSize] = tmp.at(0);
+ data[0] = sign;
+ }
+ }
+ } else if (fieldAlignment == QTextStream::AlignCenter) {
+ tmp.prepend(QString(padSize/2, padChar));
+ tmp.append(QString(padSize - padSize/2, padChar));
+ }
+ }
+
+#if defined (QTEXTSTREAM_DEBUG)
+ QByteArray a = s.toUtf8();
+ QByteArray b = tmp.toUtf8();
+ qDebug("QTextStreamPrivate::putString(\"%s\") calls write(\"%s\")",
+ qt_prettyDebug(a.constData(), a.size(), qMax(16, a.size())).constData(),
+ qt_prettyDebug(b.constData(), b.size(), qMax(16, b.size())).constData());
+#endif
+ write(tmp);
+}
+
+/*!
+ Constructs a QTextStream. Before you can use it for reading or
+ writing, you must assign a device or a string.
+
+ \sa setDevice(), setString()
+*/
+QTextStream::QTextStream()
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream()");
+#endif
+ Q_D(QTextStream);
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a device.
+*/
+QTextStream::QTextStream(QIODevice *device)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QIODevice *device == *%p)",
+ device);
+#endif
+ Q_D(QTextStream);
+ d->device = device;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a string, using \a
+ openMode to define the open mode.
+*/
+QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QString *string == *%p, openMode = %d)",
+ string, int(openMode));
+#endif
+ Q_D(QTextStream);
+ d->string = string;
+ d->stringOpenMode = openMode;
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a array, using \a
+ openMode to define the open mode. Internally, the array is wrapped
+ by a QBuffer.
+*/
+QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QByteArray *array == *%p, openMode = %d)",
+ array, int(openMode));
+#endif
+ Q_D(QTextStream);
+ d->device = new QBuffer(array);
+ d->device->open(openMode);
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a array, using \a
+ openMode to define the open mode. The array is accessed as
+ read-only, regardless of the values in \a openMode.
+
+ This constructor is convenient for working on constant
+ strings. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 3
+*/
+QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(const QByteArray &array == *(%p), openMode = %d)",
+ &array, int(openMode));
+#endif
+ QBuffer *buffer = new QBuffer;
+ buffer->setData(array);
+ buffer->open(openMode);
+
+ Q_D(QTextStream);
+ d->device = buffer;
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a fileHandle, using \a
+ openMode to define the open mode. Internally, a QFile is created
+ to handle the FILE pointer.
+
+ This constructor is useful for working directly with the common
+ FILE based input and output streams: stdin, stdout and stderr. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 4
+*/
+
+QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(FILE *fileHandle = %p, openMode = %d)",
+ fileHandle, int(openMode));
+#endif
+ QFile *file = new QFile;
+ file->open(fileHandle, openMode);
+
+ Q_D(QTextStream);
+ d->device = file;
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Destroys the QTextStream.
+
+ If the stream operates on a device, flush() will be called
+ implicitly. Otherwise, the device is unaffected.
+*/
+QTextStream::~QTextStream()
+{
+ Q_D(QTextStream);
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::~QTextStream()");
+#endif
+ if (!d->writeBuffer.isEmpty())
+ d->flushWriteBuffer();
+}
+
+/*!
+ Resets QTextStream's formatting options, bringing it back to its
+ original constructed state. The device, string and any buffered
+ data is left untouched.
+*/
+void QTextStream::reset()
+{
+ Q_D(QTextStream);
+
+ d->realNumberPrecision = 6;
+ d->integerBase = 0;
+ d->fieldWidth = 0;
+ d->padChar = QLatin1Char(' ');
+ d->fieldAlignment = QTextStream::AlignRight;
+ d->realNumberNotation = QTextStream::SmartNotation;
+ d->numberFlags = 0;
+}
+
+/*!
+ Flushes any buffered data waiting to be written to the device.
+
+ If QTextStream operates on a string, this function does nothing.
+*/
+void QTextStream::flush()
+{
+ Q_D(QTextStream);
+ d->flushWriteBuffer();
+}
+
+/*!
+ Seeks to the position \a pos in the device. Returns true on
+ success; otherwise returns false.
+*/
+bool QTextStream::seek(qint64 pos)
+{
+ Q_D(QTextStream);
+ d->lastTokenSize = 0;
+
+ if (d->device) {
+ // Empty the write buffer
+ d->flushWriteBuffer();
+ if (!d->device->seek(pos))
+ return false;
+ d->resetReadBuffer();
+
+#ifndef QT_NO_TEXTCODEC
+ // Reset the codec converter states.
+ resetCodecConverterStateHelper(&d->readConverterState);
+ resetCodecConverterStateHelper(&d->writeConverterState);
+ delete d->readConverterSavedState;
+ d->readConverterSavedState = 0;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+#endif
+ return true;
+ }
+
+ // string
+ if (d->string && pos <= d->string->size()) {
+ d->stringOffset = int(pos);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \since 4.2
+
+ Returns the device position corresponding to the current position of the
+ stream, or -1 if an error occurs (e.g., if there is no device or string,
+ or if there's a device error).
+
+ Because QTextStream is buffered, this function may have to
+ seek the device to reconstruct a valid device position. This
+ operation can be expensive, so you may want to avoid calling this
+ function in a tight loop.
+
+ \sa seek()
+*/
+qint64 QTextStream::pos() const
+{
+ Q_D(const QTextStream);
+ if (d->device) {
+ // Cutoff
+ if (d->readBuffer.isEmpty())
+ return d->device->pos();
+ if (d->device->isSequential())
+ return 0;
+
+ // Seek the device
+ if (!d->device->seek(d->readBufferStartDevicePos))
+ return qint64(-1);
+
+ // Reset the read buffer
+ QTextStreamPrivate *thatd = const_cast<QTextStreamPrivate *>(d);
+ thatd->readBuffer.clear();
+
+#ifndef QT_NO_TEXTCODEC
+ thatd->restoreToSavedConverterState();
+ if (d->readBufferStartDevicePos == 0)
+ thatd->autoDetectUnicode = true;
+#endif
+
+ // Rewind the device to get to the current position Ensure that
+ // readBufferOffset is unaffected by fillReadBuffer()
+ int oldReadBufferOffset = d->readBufferOffset + d->readConverterSavedStateOffset;
+ while (d->readBuffer.size() < oldReadBufferOffset) {
+ if (!thatd->fillReadBuffer(1))
+ return qint64(-1);
+ }
+ thatd->readBufferOffset = oldReadBufferOffset;
+ thatd->readConverterSavedStateOffset = 0;
+
+ // Return the device position.
+ return d->device->pos();
+ }
+
+ if (d->string)
+ return d->stringOffset;
+
+ qWarning("QTextStream::pos: no device");
+ return qint64(-1);
+}
+
+/*!
+ Reads and discards whitespace from the stream until either a
+ non-space character is detected, or until atEnd() returns
+ true. This function is useful when reading a stream character by
+ character.
+
+ Whitespace characters are all characters for which
+ QChar::isSpace() returns true.
+
+ \sa operator>>()
+*/
+void QTextStream::skipWhiteSpace()
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(Q_VOID);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+}
+
+/*!
+ Sets the current device to \a device. If a device has already been
+ assigned, QTextStream will call flush() before the old device is
+ replaced.
+
+ \note This function resets locale to the default locale ('C')
+ and codec to the default codec, QTextCodec::codecForLocale().
+
+ \sa device(), setString()
+*/
+void QTextStream::setDevice(QIODevice *device)
+{
+ Q_D(QTextStream);
+ flush();
+ if (d->deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.disconnect();
+#endif
+ delete d->device;
+ d->deleteDevice = false;
+ }
+
+ d->reset();
+ d->status = Ok;
+ d->device = device;
+ d->resetReadBuffer();
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+}
+
+/*!
+ Returns the current device associated with the QTextStream,
+ or 0 if no device has been assigned.
+
+ \sa setDevice(), string()
+*/
+QIODevice *QTextStream::device() const
+{
+ Q_D(const QTextStream);
+ return d->device;
+}
+
+/*!
+ Sets the current string to \a string, using the given \a
+ openMode. If a device has already been assigned, QTextStream will
+ call flush() before replacing it.
+
+ \sa string(), setDevice()
+*/
+void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
+{
+ Q_D(QTextStream);
+ flush();
+ if (d->deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.disconnect();
+ d->device->blockSignals(true);
+#endif
+ delete d->device;
+ d->deleteDevice = false;
+ }
+
+ d->reset();
+ d->status = Ok;
+ d->string = string;
+ d->stringOpenMode = openMode;
+}
+
+/*!
+ Returns the current string assigned to the QTextStream, or 0 if no
+ string has been assigned.
+
+ \sa setString(), device()
+*/
+QString *QTextStream::string() const
+{
+ Q_D(const QTextStream);
+ return d->string;
+}
+
+/*!
+ Sets the field alignment to \a mode. When used together with
+ setFieldWidth(), this function allows you to generate formatted
+ output with text aligned to the left, to the right or center
+ aligned.
+
+ \sa fieldAlignment(), setFieldWidth()
+*/
+void QTextStream::setFieldAlignment(FieldAlignment mode)
+{
+ Q_D(QTextStream);
+ d->fieldAlignment = mode;
+}
+
+/*!
+ Returns the current field alignment.
+
+ \sa setFieldAlignment(), fieldWidth()
+*/
+QTextStream::FieldAlignment QTextStream::fieldAlignment() const
+{
+ Q_D(const QTextStream);
+ return d->fieldAlignment;
+}
+
+/*!
+ Sets the pad character to \a ch. The default value is the ASCII
+ space character (' '), or QChar(0x20). This character is used to
+ fill in the space in fields when generating text.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 5
+
+ The string \c s contains:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 6
+
+ \sa padChar(), setFieldWidth()
+*/
+void QTextStream::setPadChar(QChar ch)
+{
+ Q_D(QTextStream);
+ d->padChar = ch;
+}
+
+/*!
+ Returns the current pad character.
+
+ \sa setPadChar(), setFieldWidth()
+*/
+QChar QTextStream::padChar() const
+{
+ Q_D(const QTextStream);
+ return d->padChar;
+}
+
+/*!
+ Sets the current field width to \a width. If \a width is 0 (the
+ default), the field width is equal to the length of the generated
+ text.
+
+ \note The field width applies to every element appended to this
+ stream after this function has been called (e.g., it also pads
+ endl). This behavior is different from similar classes in the STL,
+ where the field width only applies to the next element.
+
+ \sa fieldWidth(), setPadChar()
+*/
+void QTextStream::setFieldWidth(int width)
+{
+ Q_D(QTextStream);
+ d->fieldWidth = width;
+}
+
+/*!
+ Returns the current field width.
+
+ \sa setFieldWidth()
+*/
+int QTextStream::fieldWidth() const
+{
+ Q_D(const QTextStream);
+ return d->fieldWidth;
+}
+
+/*!
+ Sets the current number flags to \a flags. \a flags is a set of
+ flags from the NumberFlag enum, and describes options for
+ formatting generated code (e.g., whether or not to always write
+ the base or sign of a number).
+
+ \sa numberFlags(), setIntegerBase(), setRealNumberNotation()
+*/
+void QTextStream::setNumberFlags(NumberFlags flags)
+{
+ Q_D(QTextStream);
+ d->numberFlags = flags;
+}
+
+/*!
+ Returns the current number flags.
+
+ \sa setNumberFlags(), integerBase(), realNumberNotation()
+*/
+QTextStream::NumberFlags QTextStream::numberFlags() const
+{
+ Q_D(const QTextStream);
+ return d->numberFlags;
+}
+
+/*!
+ Sets the base of integers to \a base, both for reading and for
+ generating numbers. \a base can be either 2 (binary), 8 (octal),
+ 10 (decimal) or 16 (hexadecimal). If \a base is 0, QTextStream
+ will attempt to detect the base by inspecting the data on the
+ stream. When generating numbers, QTextStream assumes base is 10
+ unless the base has been set explicitly.
+
+ \sa integerBase(), QString::number(), setNumberFlags()
+*/
+void QTextStream::setIntegerBase(int base)
+{
+ Q_D(QTextStream);
+ d->integerBase = base;
+}
+
+/*!
+ Returns the current base of integers. 0 means that the base is
+ detected when reading, or 10 (decimal) when generating numbers.
+
+ \sa setIntegerBase(), QString::number(), numberFlags()
+*/
+int QTextStream::integerBase() const
+{
+ Q_D(const QTextStream);
+ return d->integerBase;
+}
+
+/*!
+ Sets the real number notation to \a notation (SmartNotation,
+ FixedNotation, ScientificNotation). When reading and generating
+ numbers, QTextStream uses this value to detect the formatting of
+ real numbers.
+
+ \sa realNumberNotation(), setRealNumberPrecision(), setNumberFlags(), setIntegerBase()
+*/
+void QTextStream::setRealNumberNotation(RealNumberNotation notation)
+{
+ Q_D(QTextStream);
+ d->realNumberNotation = notation;
+}
+
+/*!
+ Returns the current real number notation.
+
+ \sa setRealNumberNotation(), realNumberPrecision(), numberFlags(), integerBase()
+*/
+QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
+{
+ Q_D(const QTextStream);
+ return d->realNumberNotation;
+}
+
+/*!
+ Sets the precision of real numbers to \a precision. This value
+ describes the number of fraction digits QTextStream should
+ write when generating real numbers.
+
+ The precision cannot be a negative value. The default value is 6.
+
+ \sa realNumberPrecision(), setRealNumberNotation()
+*/
+void QTextStream::setRealNumberPrecision(int precision)
+{
+ Q_D(QTextStream);
+ if (precision < 0) {
+ qWarning("QTextStream::setRealNumberPrecision: Invalid precision (%d)", precision);
+ d->realNumberPrecision = 6;
+ return;
+ }
+ d->realNumberPrecision = precision;
+}
+
+/*!
+ Returns the current real number precision, or the number of fraction
+ digits QTextStream will write when generating real numbers.
+
+ \sa setRealNumberNotation(), realNumberNotation(), numberFlags(), integerBase()
+*/
+int QTextStream::realNumberPrecision() const
+{
+ Q_D(const QTextStream);
+ return d->realNumberPrecision;
+}
+
+/*!
+ Returns the status of the text stream.
+
+ \sa QTextStream::Status, setStatus(), resetStatus()
+*/
+
+QTextStream::Status QTextStream::status() const
+{
+ Q_D(const QTextStream);
+ return d->status;
+}
+
+/*!
+ \since 4.1
+
+ Resets the status of the text stream.
+
+ \sa QTextStream::Status, status(), setStatus()
+*/
+void QTextStream::resetStatus()
+{
+ Q_D(QTextStream);
+ d->status = Ok;
+}
+
+/*!
+ \since 4.1
+
+ Sets the status of the text stream to the \a status given.
+
+ Subsequent calls to setStatus() are ignored until resetStatus()
+ is called.
+
+ \sa Status status() resetStatus()
+*/
+void QTextStream::setStatus(Status status)
+{
+ Q_D(QTextStream);
+ if (d->status == Ok)
+ d->status = status;
+}
+
+/*!
+ Returns true if there is no more data to be read from the
+ QTextStream; otherwise returns false. This is similar to, but not
+ the same as calling QIODevice::atEnd(), as QTextStream also takes
+ into account its internal Unicode buffer.
+*/
+bool QTextStream::atEnd() const
+{
+ Q_D(const QTextStream);
+ CHECK_VALID_STREAM(true);
+
+ if (d->string)
+ return d->string->size() == d->stringOffset;
+ return d->readBuffer.isEmpty() && d->device->atEnd();
+}
+
+/*!
+ Reads the entire content of the stream, and returns it as a
+ QString. Avoid this function when working on large files, as it
+ will consume a significant amount of memory.
+
+ Calling readLine() is better if you do not know how much data is
+ available.
+
+ \sa readLine()
+*/
+QString QTextStream::readAll()
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ return d->read(INT_MAX);
+}
+
+/*!
+ Reads one line of text from the stream, and returns it as a
+ QString. The maximum allowed line length is set to \a maxlen. If
+ the stream contains lines longer than this, then the lines will be
+ split after \a maxlen characters and returned in parts.
+
+ If \a maxlen is 0, the lines can be of any length. A common value
+ for \a maxlen is 75.
+
+ The returned line has no trailing end-of-line characters ("\\n"
+ or "\\r\\n"), so calling QString::trimmed() is unnecessary.
+
+ If the stream has read to the end of the file, readLine() will return a
+ null QString. For strings, or for devices that support it, you can
+ explicitly test for the end of the stream using atEnd().
+
+ \sa readAll(), QIODevice::readLine()
+*/
+QString QTextStream::readLine(qint64 maxlen)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ const QChar *readPtr;
+ int length;
+ if (!d->scan(&readPtr, &length, int(maxlen), QTextStreamPrivate::EndOfLine))
+ return QString();
+
+ QString tmp = QString(readPtr, length);
+ d->consumeLastToken();
+ return tmp;
+}
+
+/*!
+ \since 4.1
+
+ Reads at most \a maxlen characters from the stream, and returns the data
+ read as a QString.
+
+ \sa readAll(), readLine(), QIODevice::read()
+*/
+QString QTextStream::read(qint64 maxlen)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ if (maxlen <= 0)
+ return QString::fromLatin1(""); // empty, not null
+
+ return d->read(int(maxlen));
+}
+
+/*! \internal
+*/
+QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong *ret)
+{
+ scan(0, 0, 0, NotSpace);
+ consumeLastToken();
+
+ // detect int encoding
+ int base = integerBase;
+ if (base == 0) {
+ QChar ch;
+ if (!getChar(&ch))
+ return npsInvalidPrefix;
+ if (ch == QLatin1Char('0')) {
+ QChar ch2;
+ if (!getChar(&ch2)) {
+ // Result is the number 0
+ *ret = 0;
+ return npsOk;
+ }
+ ch2 = ch2.toLower();
+
+ if (ch2 == QLatin1Char('x')) {
+ base = 16;
+ } else if (ch2 == QLatin1Char('b')) {
+ base = 2;
+ } else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) {
+ base = 8;
+ } else {
+ base = 10;
+ }
+ ungetChar(ch2);
+ } else if (ch == locale.negativeSign() || ch == locale.positiveSign() || ch.isDigit()) {
+ base = 10;
+ } else {
+ ungetChar(ch);
+ return npsInvalidPrefix;
+ }
+ ungetChar(ch);
+ // State of the stream is now the same as on entry
+ // (cursor is at prefix),
+ // and local variable 'base' has been set appropriately.
+ }
+
+ qulonglong val=0;
+ switch (base) {
+ case 2: {
+ QChar pf1, pf2, dig;
+ // Parse prefix '0b'
+ if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('b'))
+ return npsInvalidPrefix;
+ // Parse digits
+ int ndigits = 0;
+ while (getChar(&dig)) {
+ int n = dig.toLower().unicode();
+ if (n == '0' || n == '1') {
+ val <<= 1;
+ val += n - '0';
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ // Unwind the prefix and abort
+ ungetChar(pf2);
+ ungetChar(pf1);
+ return npsMissingDigit;
+ }
+ break;
+ }
+ case 8: {
+ QChar pf, dig;
+ // Parse prefix '0'
+ if (!getChar(&pf) || pf != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ // Parse digits
+ int ndigits = 0;
+ while (getChar(&dig)) {
+ int n = dig.toLower().unicode();
+ if (n >= '0' && n <= '7') {
+ val *= 8;
+ val += n - '0';
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ // Unwind the prefix and abort
+ ungetChar(pf);
+ return npsMissingDigit;
+ }
+ break;
+ }
+ case 10: {
+ // Parse sign (or first digit)
+ QChar sign;
+ int ndigits = 0;
+ if (!getChar(&sign))
+ return npsMissingDigit;
+ if (sign != locale.negativeSign() && sign != locale.positiveSign()) {
+ if (!sign.isDigit()) {
+ ungetChar(sign);
+ return npsMissingDigit;
+ }
+ val += sign.digitValue();
+ ndigits++;
+ }
+ // Parse digits
+ QChar ch;
+ while (getChar(&ch)) {
+ if (ch.isDigit()) {
+ val *= 10;
+ val += ch.digitValue();
+ } else if (locale != QLocale::c() && ch == locale.groupSeparator()) {
+ continue;
+ } else {
+ ungetChar(ch);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0)
+ return npsMissingDigit;
+ if (sign == locale.negativeSign()) {
+ qlonglong ival = qlonglong(val);
+ if (ival > 0)
+ ival = -ival;
+ val = qulonglong(ival);
+ }
+ break;
+ }
+ case 16: {
+ QChar pf1, pf2, dig;
+ // Parse prefix ' 0x'
+ if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('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') {
+ val <<= 4;
+ val += 10 + (n - 'a');
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ return npsMissingDigit;
+ }
+ break;
+ }
+ default:
+ // Unsupported integerBase
+ return npsInvalidPrefix;
+ }
+
+ if (ret)
+ *ret = val;
+ return npsOk;
+}
+
+/*! \internal
+ (hihi)
+*/
+bool QTextStreamPrivate::getReal(double *f)
+{
+ // We use a table-driven FSM to parse floating point numbers
+ // strtod() cannot be used directly since we may be reading from a
+ // QIODevice.
+ enum ParserState {
+ Init = 0,
+ Sign = 1,
+ Mantissa = 2,
+ Dot = 3,
+ Abscissa = 4,
+ ExpMark = 5,
+ ExpSign = 6,
+ Exponent = 7,
+ Nan1 = 8,
+ Nan2 = 9,
+ Inf1 = 10,
+ Inf2 = 11,
+ NanInf = 12,
+ Done = 13
+ };
+ enum InputToken {
+ None = 0,
+ InputSign = 1,
+ InputDigit = 2,
+ InputDot = 3,
+ InputExp = 4,
+ InputI = 5,
+ InputN = 6,
+ InputF = 7,
+ InputA = 8,
+ InputT = 9
+ };
+
+ static const uchar table[13][10] = {
+ // None InputSign InputDigit InputDot InputExp InputI InputN InputF InputA InputT
+ { 0, Sign, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 }, // 0 Init
+ { 0, 0, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 }, // 1 Sign
+ { Done, Done, Mantissa, Dot, ExpMark, 0, 0, 0, 0, 0 }, // 2 Mantissa
+ { 0, 0, Abscissa, 0, 0, 0, 0, 0, 0, 0 }, // 3 Dot
+ { Done, Done, Abscissa, Done, ExpMark, 0, 0, 0, 0, 0 }, // 4 Abscissa
+ { 0, ExpSign, Exponent, 0, 0, 0, 0, 0, 0, 0 }, // 5 ExpMark
+ { 0, 0, Exponent, 0, 0, 0, 0, 0, 0, 0 }, // 6 ExpSign
+ { Done, Done, Exponent, Done, Done, 0, 0, 0, 0, 0 }, // 7 Exponent
+ { 0, 0, 0, 0, 0, 0, 0, 0, Nan2, 0 }, // 8 Nan1
+ { 0, 0, 0, 0, 0, 0, NanInf, 0, 0, 0 }, // 9 Nan2
+ { 0, 0, 0, 0, 0, 0, Inf2, 0, 0, 0 }, // 10 Inf1
+ { 0, 0, 0, 0, 0, 0, 0, NanInf, 0, 0 }, // 11 Inf2
+ { Done, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 11 NanInf
+ };
+
+ ParserState state = Init;
+ InputToken input = None;
+
+ scan(0, 0, 0, NotSpace);
+ consumeLastToken();
+
+ const int BufferSize = 128;
+ char buf[BufferSize];
+ int i = 0;
+
+ QChar c;
+ while (getChar(&c)) {
+ switch (c.unicode()) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ input = InputDigit;
+ break;
+ case 'i': case 'I':
+ input = InputI;
+ break;
+ case 'n': case 'N':
+ input = InputN;
+ break;
+ case 'f': case 'F':
+ input = InputF;
+ break;
+ case 'a': case 'A':
+ input = InputA;
+ break;
+ case 't': case 'T':
+ input = InputT;
+ break;
+ default: {
+ QChar lc = c.toLower();
+ if (lc == locale.decimalPoint().toLower())
+ input = InputDot;
+ else if (lc == locale.exponential().toLower())
+ input = InputExp;
+ else if (lc == locale.negativeSign().toLower()
+ || lc == locale.positiveSign().toLower())
+ input = InputSign;
+ else if (locale != QLocale::c() // backward-compatibility
+ && lc == locale.groupSeparator().toLower())
+ input = InputDigit; // well, it isn't a digit, but no one cares.
+ else
+ input = None;
+ }
+ break;
+ }
+
+ state = ParserState(table[state][input]);
+
+ if (state == Init || state == Done || i > (BufferSize - 5)) {
+ ungetChar(c);
+ if (i > (BufferSize - 5)) { // ignore rest of digits
+ while (getChar(&c)) {
+ if (!c.isDigit()) {
+ ungetChar(c);
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ buf[i++] = c.toLatin1();
+ }
+
+ if (i == 0)
+ return false;
+ if (!f)
+ return true;
+ buf[i] = '\0';
+
+ // backward-compatibility. Old implementation supported +nan/-nan
+ // for some reason. QLocale only checks for lower-case
+ // 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 = qSNaN();
+ return true;
+ } else if (!qstricmp(buf, "+inf") || !qstricmp(buf, "inf")) {
+ *f = qInf();
+ return true;
+ } else if (!qstricmp(buf, "-inf")) {
+ *f = -qInf();
+ return true;
+ }
+ bool ok;
+ *f = locale.toDouble(QString::fromLatin1(buf), &ok);
+ return ok;
+}
+
+/*!
+ Reads a character from the stream and stores it in \a c. Returns a
+ reference to the QTextStream, so several operators can be
+ nested. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 7
+
+ Whitespace is \e not skipped.
+*/
+
+QTextStream &QTextStream::operator>>(QChar &c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ if (!d->getChar(&c))
+ setStatus(ReadPastEnd);
+ return *this;
+}
+
+/*!
+ \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
+ stored.
+
+ \sa QChar::toLatin1()
+*/
+QTextStream &QTextStream::operator>>(char &c)
+{
+ QChar ch;
+ *this >> ch;
+ c = ch.toLatin1();
+ return *this;
+}
+
+/*!
+ 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
+ the stream, \a i is set to 0.
+
+ By default, QTextStream will attempt to detect the base of the
+ number using the following rules:
+
+ \table
+ \header \o Prefix \o Base
+ \row \o "0b" or "0B" \o 2 (binary)
+ \row \o "0" followed by "0-7" \o 8 (octal)
+ \row \o "0" otherwise \o 10 (decimal)
+ \row \o "0x" or "0X" \o 16 (hexadecimal)
+ \row \o "1" to "9" \o 10 (decimal)
+ \endtable
+
+ By calling setIntegerBase(), you can specify the integer base
+ explicitly. This will disable the auto-detection, and speed up
+ QTextStream slightly.
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(signed short &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed short);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned short \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned short &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned short);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the signed int \a i.
+*/
+QTextStream &QTextStream::operator>>(signed int &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed int);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned int \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned int &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned int);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the signed long \a i.
+*/
+QTextStream &QTextStream::operator>>(signed long &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed long);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned long \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned long &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned long);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the qlonglong \a i.
+*/
+QTextStream &QTextStream::operator>>(qlonglong &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(qlonglong);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the qulonglong \a i.
+*/
+QTextStream &QTextStream::operator>>(qulonglong &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(qulonglong);
+}
+
+/*!
+ Reads a real number from the stream and stores it in \a f, then
+ returns a reference to the QTextStream. The number is cast to
+ the correct type. If no real number is detect on the stream, \a f
+ is set to 0.0.
+
+ As a special exception, QTextStream allows the strings "nan" and "inf" to
+ represent NAN and INF floats or doubles.
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(float &f)
+{
+ IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(float);
+}
+
+/*!
+ \overload
+
+ Stores the real number in the double \a f.
+*/
+QTextStream &QTextStream::operator>>(double &f)
+{
+ IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(double);
+}
+
+/*!
+ Reads a word from the stream and stores it in \a str, then returns
+ a reference to the stream. Words are separated by whitespace
+ (i.e., all characters for which QChar::isSpace() returns true).
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(QString &str)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ str.clear();
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ str = QString(ptr, length);
+ d->consumeLastToken();
+ return *this;
+}
+
+/*!
+ \overload
+
+ Converts the word to ISO-8859-1, then stores it in \a array.
+
+ \sa QString::toLatin1()
+*/
+QTextStream &QTextStream::operator>>(QByteArray &array)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ array.clear();
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ for (int i = 0; i < length; ++i)
+ array += ptr[i].toLatin1();
+
+ d->consumeLastToken();
+ return *this;
+}
+
+/*!
+ \overload
+
+ Stores the word 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.
+
+ If possible, use the QByteArray operator instead.
+*/
+QTextStream &QTextStream::operator>>(char *c)
+{
+ Q_D(QTextStream);
+ *c = 0;
+ CHECK_VALID_STREAM(*this);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ for (int i = 0; i < length; ++i)
+ *c++ = ptr[i].toLatin1();
+ *c = '\0';
+ d->consumeLastToken();
+ return *this;
+}
+
+/*! \internal
+ */
+void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
+{
+ QString result;
+
+ unsigned flags = 0;
+ if (numberFlags & QTextStream::ShowBase)
+ flags |= QLocalePrivate::ShowBase;
+ if (numberFlags & QTextStream::ForceSign)
+ flags |= QLocalePrivate::AlwaysShowSign;
+ if (numberFlags & QTextStream::UppercaseBase)
+ flags |= QLocalePrivate::UppercaseBase;
+ if (numberFlags & QTextStream::UppercaseDigits)
+ flags |= QLocalePrivate::CapitalEorX;
+
+ // add thousands group separators. For backward compatibility we
+ // don't add a group separator for C locale.
+ if (locale != QLocale::c())
+ flags |= QLocalePrivate::ThousandsGroup;
+
+ const QLocalePrivate *dd = locale.d();
+ int base = integerBase ? integerBase : 10;
+ if (negative && base == 10) {
+ result = dd->longLongToString(-static_cast<qlonglong>(number), -1,
+ base, -1, flags);
+ } else if (negative) {
+ // Workaround for backward compatibility for writing negative
+ // numbers in octal and hex:
+ // QTextStream(result) << showbase << hex << -1 << oct << -1
+ // should output: -0x1 -0b1
+ result = dd->unsLongLongToString(number, -1, base, -1, flags);
+ result.prepend(locale.negativeSign());
+ } else {
+ result = dd->unsLongLongToString(number, -1, base, -1, flags);
+ // workaround for backward compatibility - in octal form with
+ // ShowBase flag set zero should be written as '00'
+ if (number == 0 && base == 8 && numberFlags & QTextStream::ShowBase
+ && result == QLatin1String("0")) {
+ result.prepend(QLatin1Char('0'));
+ }
+ }
+ putString(result, true);
+}
+
+/*!
+ \internal
+ \overload
+*/
+QTextStream &QTextStream::operator<<(QBool b)
+{
+ return *this << bool(b);
+}
+
+/*!
+ Writes the character \a c to the stream, then returns a reference
+ to the QTextStream.
+
+ \sa setFieldWidth()
+*/
+QTextStream &QTextStream::operator<<(QChar c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString(c));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Converts \a c from ASCII to a QChar, then writes it to the stream.
+*/
+QTextStream &QTextStream::operator<<(char c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString(QChar::fromAscii(c)));
+ return *this;
+}
+
+/*!
+ 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
+ setIntegerBase().
+
+ \sa setFieldWidth(), setNumberFlags()
+*/
+QTextStream &QTextStream::operator<<(signed short i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned short \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned short i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the signed int \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(signed int i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned int \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned int i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the signed long \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(signed long i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned long \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned long i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the qlonglong \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(qlonglong i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(i), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the qulonglong \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(qulonglong i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber(i, false);
+ return *this;
+}
+
+/*!
+ Writes the real number \a f to the stream, then returns a
+ reference to the QTextStream. By default, QTextStream stores it
+ using SmartNotation, with up to 6 digits of precision. You can
+ change the textual representation QTextStream will use for real
+ numbers by calling setRealNumberNotation(),
+ setRealNumberPrecision() and setNumberFlags().
+
+ \sa setFieldWidth(), setRealNumberNotation(),
+ setRealNumberPrecision(), setNumberFlags()
+*/
+QTextStream &QTextStream::operator<<(float f)
+{
+ return *this << double(f);
+}
+
+/*!
+ \overload
+
+ Writes the double \a f to the stream.
+*/
+QTextStream &QTextStream::operator<<(double f)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ switch (realNumberNotation()) {
+ case FixedNotation:
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case ScientificNotation:
+ form = QLocalePrivate::DFExponent;
+ break;
+ case SmartNotation:
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ }
+
+ uint flags = 0;
+ if (numberFlags() & ShowBase)
+ flags |= QLocalePrivate::ShowBase;
+ if (numberFlags() & ForceSign)
+ flags |= QLocalePrivate::AlwaysShowSign;
+ if (numberFlags() & UppercaseBase)
+ flags |= QLocalePrivate::UppercaseBase;
+ if (numberFlags() & UppercaseDigits)
+ flags |= QLocalePrivate::CapitalEorX;
+ if (numberFlags() & ForcePoint)
+ flags |= QLocalePrivate::Alternate;
+
+ const QLocalePrivate *dd = d->locale.d();
+ QString num = dd->doubleToString(f, d->realNumberPrecision, form, -1, flags);
+ d->putString(num, true);
+ return *this;
+}
+
+/*!
+ Writes the string \a string to the stream, and returns a reference
+ to the QTextStream. The string is first encoded using the assigned
+ codec (the default codec is QTextCodec::codecForLocale()) before
+ it is written to the stream.
+
+ \sa setFieldWidth(), setCodec()
+*/
+QTextStream &QTextStream::operator<<(const QString &string)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(string);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes \a array to the stream. The contents of \a array are
+ converted with QString::fromAscii().
+*/
+QTextStream &QTextStream::operator<<(const QByteArray &array)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString::fromAscii(array.constData(), array.length()));
+ return *this;
+}
+
+/*!
+ \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
+ is convenient when working with constant string data. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 8
+
+ Warning: QTextStream assumes that \a string points to a string of
+ text, terminated by a '\0' character. If there is no terminating
+ '\0' character, your application may crash.
+*/
+QTextStream &QTextStream::operator<<(const char *string)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QLatin1String(string));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes \a ptr to the stream as a hexadecimal number with a base.
+*/
+
+QTextStream &QTextStream::operator<<(const void *ptr)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ int oldBase = d->integerBase;
+ NumberFlags oldFlags = d->numberFlags;
+ d->integerBase = 16;
+ d->numberFlags |= ShowBase;
+ d->putNumber(reinterpret_cast<quintptr>(ptr), false);
+ d->integerBase = oldBase;
+ d->numberFlags = oldFlags;
+ return *this;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(2) on \a stream and returns \a
+ stream.
+
+ \sa oct(), dec(), hex(), {QTextStream manipulators}
+*/
+QTextStream &bin(QTextStream &stream)
+{
+ stream.setIntegerBase(2);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(8) on \a stream and returns \a
+ stream.
+
+ \sa bin(), dec(), hex(), {QTextStream manipulators}
+*/
+QTextStream &oct(QTextStream &stream)
+{
+ stream.setIntegerBase(8);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(10) on \a stream and returns \a
+ stream.
+
+ \sa bin(), oct(), hex(), {QTextStream manipulators}
+*/
+QTextStream &dec(QTextStream &stream)
+{
+ stream.setIntegerBase(10);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(16) on \a stream and returns \a
+ stream.
+
+ \note The hex modifier can only be used for writing to streams.
+ \sa bin(), oct(), dec(), {QTextStream manipulators}
+*/
+QTextStream &hex(QTextStream &stream)
+{
+ stream.setIntegerBase(16);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ShowBase) on \a stream and returns \a stream.
+
+ \sa noshowbase(), forcesign(), forcepoint(), {QTextStream manipulators}
+*/
+QTextStream &showbase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ShowBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ForceSign) on \a stream and returns \a stream.
+
+ \sa noforcesign(), forcepoint(), showbase(), {QTextStream manipulators}
+*/
+QTextStream &forcesign(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ForceSign);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ForcePoint) on \a stream and returns \a stream.
+
+ \sa noforcepoint(), forcesign(), showbase(), {QTextStream manipulators}
+*/
+QTextStream &forcepoint(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ForcePoint);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ShowBase) on \a stream and returns \a stream.
+
+ \sa showbase(), noforcesign(), noforcepoint(), {QTextStream manipulators}
+*/
+QTextStream &noshowbase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ShowBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ForceSign) on \a stream and returns \a stream.
+
+ \sa forcesign(), noforcepoint(), noshowbase(), {QTextStream manipulators}
+*/
+QTextStream &noforcesign(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ForceSign);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ForcePoint) on \a stream and returns \a stream.
+
+ \sa forcepoint(), noforcesign(), noshowbase(), {QTextStream manipulators}
+*/
+QTextStream &noforcepoint(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ForcePoint);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::UppercaseBase) on \a stream and returns \a stream.
+
+ \sa lowercasebase(), uppercasedigits(), {QTextStream manipulators}
+*/
+QTextStream &uppercasebase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::UppercaseBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::UppercaseDigits) on \a stream and returns \a stream.
+
+ \sa lowercasedigits(), uppercasebase(), {QTextStream manipulators}
+*/
+QTextStream &uppercasedigits(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::UppercaseDigits);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::UppercaseBase) on \a stream and returns \a stream.
+
+ \sa uppercasebase(), lowercasedigits(), {QTextStream manipulators}
+*/
+QTextStream &lowercasebase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() & ~QTextStream::UppercaseBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::UppercaseDigits) on \a stream and returns \a stream.
+
+ \sa uppercasedigits(), lowercasebase(), {QTextStream manipulators}
+*/
+QTextStream &lowercasedigits(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() & ~QTextStream::UppercaseDigits);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation)
+ on \a stream and returns \a stream.
+
+ \sa scientific(), {QTextStream manipulators}
+*/
+QTextStream &fixed(QTextStream &stream)
+{
+ stream.setRealNumberNotation(QTextStream::FixedNotation);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setRealNumberNotation(QTextStream::ScientificNotation)
+ on \a stream and returns \a stream.
+
+ \sa fixed(), {QTextStream manipulators}
+*/
+QTextStream &scientific(QTextStream &stream)
+{
+ stream.setRealNumberNotation(QTextStream::ScientificNotation);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft)
+ on \a stream and returns \a stream.
+
+ \sa right(), center(), {QTextStream manipulators}
+*/
+QTextStream &left(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignLeft);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignRight)
+ on \a stream and returns \a stream.
+
+ \sa left(), center(), {QTextStream manipulators}
+*/
+QTextStream &right(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignRight);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter)
+ on \a stream and returns \a stream.
+
+ \sa left(), right(), {QTextStream manipulators}
+*/
+QTextStream &center(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignCenter);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Writes '\n' to the \a stream and flushes the stream.
+
+ Equivalent to
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 9
+
+ Note: On Windows, all '\n' characters are written as '\r\n' if
+ QTextStream's device or string is opened using the QIODevice::Text flag.
+
+ \sa flush(), reset(), {QTextStream manipulators}
+*/
+QTextStream &endl(QTextStream &stream)
+{
+ return stream << QLatin1Char('\n') << flush;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::flush() on \a stream and returns \a stream.
+
+ \sa endl(), reset(), {QTextStream manipulators}
+*/
+QTextStream &flush(QTextStream &stream)
+{
+ stream.flush();
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::reset() on \a stream and returns \a stream.
+
+ \sa flush(), {QTextStream manipulators}
+*/
+QTextStream &reset(QTextStream &stream)
+{
+ stream.reset();
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls skipWhiteSpace() on \a stream and returns \a stream.
+
+ \sa {QTextStream manipulators}
+*/
+QTextStream &ws(QTextStream &stream)
+{
+ stream.skipWhiteSpace();
+ return stream;
+}
+
+/*!
+ \fn QTextStreamManipulator qSetFieldWidth(int width)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setFieldWidth(\a width).
+*/
+
+/*!
+ \fn QTextStreamManipulator qSetPadChar(QChar ch)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setPadChar(\a ch).
+*/
+
+/*!
+ \fn QTextStreamManipulator qSetRealNumberPrecision(int precision)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setRealNumberPrecision(\a precision).
+*/
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+ \relates QTextStream
+
+ Toggles insertion of the Byte Order Mark on \a stream when QTextStream is
+ used with a UTF codec.
+
+ \sa QTextStream::setGenerateByteOrderMark(), {QTextStream manipulators}
+*/
+QTextStream &bom(QTextStream &stream)
+{
+ stream.setGenerateByteOrderMark(true);
+ return stream;
+}
+
+/*!
+ Sets the codec for this stream to \a codec. The codec is used for
+ decoding any data that is read from the assigned device, and for
+ encoding any data that is written. By default,
+ QTextCodec::codecForLocale() is used, and automatic unicode
+ detection is enabled.
+
+ If QTextStream operates on a string, this function does nothing.
+
+ \warning If you call this function while the text stream is reading
+ from an open sequential socket, the internal buffer may still contain
+ text decoded using the old codec.
+
+ \sa codec(), setAutoDetectUnicode(), setLocale()
+*/
+void QTextStream::setCodec(QTextCodec *codec)
+{
+ Q_D(QTextStream);
+ qint64 seekPos = -1;
+ if (!d->readBuffer.isEmpty()) {
+ if (!d->device->isSequential()) {
+ seekPos = pos();
+ }
+ }
+ d->codec = codec;
+ if (seekPos >=0 && !d->readBuffer.isEmpty())
+ seek(seekPos);
+}
+
+/*!
+ Sets the codec for this stream to the QTextCodec for the encoding
+ specified by \a codecName. Common values for \c codecName include
+ "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
+ recognized, nothing happens.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 10
+
+ \sa QTextCodec::codecForName(), setLocale()
+*/
+void QTextStream::setCodec(const char *codecName)
+{
+ QTextCodec *codec = QTextCodec::codecForName(codecName);
+ if (codec)
+ setCodec(codec);
+}
+
+/*!
+ Returns the codec that is current assigned to the stream.
+
+ \sa setCodec(), setAutoDetectUnicode(), locale()
+*/
+QTextCodec *QTextStream::codec() const
+{
+ Q_D(const QTextStream);
+ return d->codec;
+}
+
+/*!
+ If \a enabled is true, QTextStream will attempt to detect Unicode
+ encoding by peeking into the stream data to see if it can find the
+ UTF-16 or UTF-32 BOM (Byte Order Mark). If this mark is found, QTextStream
+ will replace the current codec with the UTF codec.
+
+ This function can be used together with setCodec(). It is common
+ to set the codec to UTF-8, and then enable UTF-16 detection.
+
+ \sa autoDetectUnicode(), setCodec()
+*/
+void QTextStream::setAutoDetectUnicode(bool enabled)
+{
+ Q_D(QTextStream);
+ d->autoDetectUnicode = enabled;
+}
+
+/*!
+ Returns true if automatic Unicode detection is enabled, otherwise
+ returns false. Automatic Unicode detection is enabled by default.
+
+ \sa setAutoDetectUnicode(), setCodec()
+*/
+bool QTextStream::autoDetectUnicode() const
+{
+ Q_D(const QTextStream);
+ return d->autoDetectUnicode;
+}
+
+/*!
+ If \a generate is true and a UTF codec is used, QTextStream will insert
+ the BOM (Byte Order Mark) before any data has been written to the
+ 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()
+*/
+void QTextStream::setGenerateByteOrderMark(bool generate)
+{
+ Q_D(QTextStream);
+ if (d->writeBuffer.isEmpty()) {
+ if (generate)
+ d->writeConverterState.flags &= ~QTextCodec::IgnoreHeader;
+ else
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ }
+}
+
+/*!
+ Returns true if QTextStream is set to generate the UTF BOM (Byte Order
+ Mark) when using a UTF codec; otherwise returns false. UTF BOM generation is
+ set to false by default.
+
+ \sa setGenerateByteOrderMark()
+*/
+bool QTextStream::generateByteOrderMark() const
+{
+ Q_D(const QTextStream);
+ return (d->writeConverterState.flags & QTextCodec::IgnoreHeader) == 0;
+}
+
+#endif
+
+/*!
+ \since 4.5
+
+ Sets the locale for this stream to \a locale. The specified locale is
+ used for conversions between numbers and their string representations.
+
+ The default locale is C and it is a special case - the thousands
+ group separator is not used for backward compatibility reasons.
+
+ \sa locale()
+*/
+void QTextStream::setLocale(const QLocale &locale)
+{
+ Q_D(QTextStream);
+ d->locale = locale;
+}
+
+/*!
+ \since 4.5
+
+ Returns the locale for this stream. The default locale is C.
+
+ \sa setLocale()
+*/
+QLocale QTextStream::locale() const
+{
+ Q_D(const QTextStream);
+ return d->locale;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \class QTextIStream
+ \brief The QTextIStream class is a convenience class for input streams.
+
+ \compat
+ \reentrant
+
+ Use QTextStream instead.
+*/
+
+/*!
+ \fn QTextIStream::QTextIStream(const QString *string)
+
+ Use QTextStream(&\a{string}, QIODevice::ReadOnly) instead.
+*/
+/*!
+ \fn QTextIStream::QTextIStream(QByteArray *byteArray)
+
+ Use QTextStream(&\a{byteArray}, QIODevice::ReadOnly) instead.
+*/
+/*!
+ \fn QTextIStream::QTextIStream(FILE *file)
+
+ Use QTextStream(\a{file}, QIODevice::ReadOnly) instead.
+*/
+
+/*!
+ \class QTextOStream
+ \brief The QTextOStream class is a convenience class for output streams.
+
+ \compat
+ \reentrant
+
+ Use QTextStream instead.
+*/
+
+/*!
+ \fn QTextOStream::QTextOStream(QString *string)
+
+ Use QTextStream(&\a{string}, QIODevice::WriteOnly) instead.
+*/
+/*!
+ \fn QTextOStream::QTextOStream(QByteArray *byteArray)
+
+ Use QTextStream(&\a{byteArray}, QIODevice::WriteOnly) instead.
+*/
+/*!
+ \fn QTextOStream::QTextOStream(FILE *file)
+
+ Use QTextStream(\a{file}, QIODevice::WriteOnly) instead.
+*/
+
+/*! \internal
+*/
+int QTextStream::flagsInternal() const
+{
+ Q_D(const QTextStream);
+
+ int f = 0;
+ switch (d->fieldAlignment) {
+ case AlignLeft: f |= left; break;
+ case AlignRight: f |= right; break;
+ case AlignCenter: f |= internal; break;
+ default:
+ break;
+ }
+ switch (d->integerBase) {
+ case 2: f |= bin; break;
+ case 8: f |= oct; break;
+ case 10: f |= dec; break;
+ case 16: f |= hex; break;
+ default:
+ break;
+ }
+ switch (d->realNumberNotation) {
+ case FixedNotation: f |= fixed; break;
+ case ScientificNotation: f |= scientific; break;
+ default:
+ break;
+ }
+ if (d->numberFlags & ShowBase)
+ f |= showbase;
+ if (d->numberFlags & ForcePoint)
+ f |= showpoint;
+ if (d->numberFlags & ForceSign)
+ f |= showpos;
+ if (d->numberFlags & UppercaseBase)
+ f |= uppercase;
+ return f;
+}
+
+/*! \internal
+*/
+int QTextStream::flagsInternal(int newFlags)
+{
+ int oldFlags = flagsInternal();
+
+ if (newFlags & left)
+ setFieldAlignment(AlignLeft);
+ else if (newFlags & right)
+ setFieldAlignment(AlignRight);
+ else if (newFlags & internal)
+ setFieldAlignment(AlignCenter);
+
+ if (newFlags & bin)
+ setIntegerBase(2);
+ else if (newFlags & oct)
+ setIntegerBase(8);
+ else if (newFlags & dec)
+ setIntegerBase(10);
+ else if (newFlags & hex)
+ setIntegerBase(16);
+
+ if (newFlags & showbase)
+ setNumberFlags(numberFlags() | ShowBase);
+ if (newFlags & showpos)
+ setNumberFlags(numberFlags() | ForceSign);
+ if (newFlags & showpoint)
+ setNumberFlags(numberFlags() | ForcePoint);
+ if (newFlags & uppercase)
+ setNumberFlags(numberFlags() | UppercaseBase);
+
+ if (newFlags & fixed)
+ setRealNumberNotation(FixedNotation);
+ else if (newFlags & scientific)
+ setRealNumberNotation(ScientificNotation);
+
+ return oldFlags;
+}
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+ Use setCodec() and setAutoDetectUnicode() instead.
+*/
+void QTextStream::setEncoding(Encoding encoding)
+{
+ Q_D(QTextStream);
+ resetCodecConverterStateHelper(&d->readConverterState);
+ resetCodecConverterStateHelper(&d->writeConverterState);
+
+ switch (encoding) {
+ case Locale:
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForLocale());
+ d->autoDetectUnicode = true;
+ break;
+ case Latin1:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("ISO-8859-1"));
+ d->autoDetectUnicode = false;
+ break;
+ case Unicode:
+ setCodec(QTextCodec::codecForName("UTF-16"));
+ d->autoDetectUnicode = false;
+ break;
+ case RawUnicode:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeNetworkOrder:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16BE"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeReverse:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16LE"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeUTF8:
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-8"));
+ d->autoDetectUnicode = true;
+ break;
+ }
+}
+#endif
+
+/*!
+ \enum QTextStream::Encoding
+ \compat
+
+ \value Latin1 Use setCodec(QTextCodec::codecForName("ISO-8859-1")) instead.
+ \value Locale Use setCodec(QTextCodec::codecForLocale()) instead.
+ \value RawUnicode Use setCodec(QTextCodec::codecForName("UTF-16")) instead.
+ \value Unicode Use setCodec(QTextCodec::codecForName("UTF-16")) instead.
+ \value UnicodeNetworkOrder Use setCodec(QTextCodec::codecForName("UTF-16BE")) instead.
+ \value UnicodeReverse Use setCodec(QTextCodec::codecForName("UTF-16LE")) instead.
+ \value UnicodeUTF8 Use setCodec(QTextCodec::codecForName("UTF-8")) instead.
+
+ Also, for all encodings except QTextStream::Latin1 and
+ QTextStream::UTF8, you need to call setAutoDetectUnicode(false)
+ to obtain the Qt 3 behavior in addition to the setCodec() call.
+
+ \sa setCodec(), setAutoDetectUnicode()
+*/
+
+/*!
+ \fn int QTextStream::flags() const
+
+ Use fieldAlignment(), padChar(), fieldWidth(), numberFlags(),
+ integerBase(), realNumberNotation(), and realNumberNotation
+ instead.
+*/
+
+/*!
+ \fn int QTextStream::flags(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::setf(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::setf(int, int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::unsetf(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::width(int)
+
+ Use setFieldWidth() instead.
+*/
+
+/*!
+ \fn int QTextStream::fill(int)
+
+ Use setPadChar() instead.
+*/
+
+/*!
+ \fn int QTextStream::precision(int)
+
+ Use setRealNumberPrecision() instead.
+*/
+
+/*!
+ \fn int QTextStream::read()
+
+ Use readAll() or readLine() instead.
+*/
+
+/*!
+ \fn int QTextStream::unsetDevice()
+
+ Use setDevice(0) instead.
+*/
+
+/*!
+ \variable QTextStream::skipws
+ \variable QTextStream::left
+ \variable QTextStream::right
+ \variable QTextStream::internal
+ \variable QTextStream::bin
+ \variable QTextStream::oct
+ \variable QTextStream::dec
+ \variable QTextStream::hex
+ \variable QTextStream::showbase
+ \variable QTextStream::showpoint
+ \variable QTextStream::uppercase
+ \variable QTextStream::showpos
+ \variable QTextStream::scientific
+ \variable QTextStream::fixed
+ \variable QTextStream::basefield
+ \variable QTextStream::adjustfield
+ \variable QTextStream::floatfield
+ \compat
+
+ Use the new \l{QTextStream manipulators} instead.
+*/
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_QOBJECT
+#include "qtextstream.moc"
+#endif
+
diff --git a/src/corelib/io/qtextstream.h b/src/corelib/io/qtextstream.h
new file mode 100644
index 0000000000..fc2fee6ec9
--- /dev/null
+++ b/src/corelib/io/qtextstream.h
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTSTREAM_H
+#define QTEXTSTREAM_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qchar.h>
+#include <QtCore/qlocale.h>
+#include <QtCore/qscopedpointer.h>
+
+#ifndef QT_NO_TEXTCODEC
+# ifdef QT3_SUPPORT
+# include <QtCore/qtextcodec.h>
+# endif
+#endif
+
+#include <stdio.h>
+
+#ifdef Status
+#error qtextstream.h must be included before any header file that defines Status
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QTextCodec;
+class QTextDecoder;
+
+class QTextStreamPrivate;
+class Q_CORE_EXPORT QTextStream // text stream class
+{
+ Q_DECLARE_PRIVATE(QTextStream)
+
+public:
+ enum RealNumberNotation {
+ SmartNotation,
+ FixedNotation,
+ ScientificNotation
+ };
+ enum FieldAlignment {
+ AlignLeft,
+ AlignRight,
+ AlignCenter,
+ AlignAccountingStyle
+ };
+ enum Status {
+ Ok,
+ ReadPastEnd,
+ ReadCorruptData,
+ WriteFailed
+ };
+ enum NumberFlag {
+ ShowBase = 0x1,
+ ForcePoint = 0x2,
+ ForceSign = 0x4,
+ UppercaseBase = 0x8,
+ UppercaseDigits = 0x10
+ };
+ Q_DECLARE_FLAGS(NumberFlags, NumberFlag)
+
+ 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();
+
+#ifndef QT_NO_TEXTCODEC
+ void setCodec(QTextCodec *codec);
+ void setCodec(const char *codecName);
+ QTextCodec *codec() const;
+ void setAutoDetectUnicode(bool enabled);
+ bool autoDetectUnicode() const;
+ void setGenerateByteOrderMark(bool generate);
+ bool generateByteOrderMark() const;
+#endif
+
+ void setLocale(const QLocale &locale);
+ QLocale locale() const;
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+
+ void setString(QString *string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
+ QString *string() const;
+
+ Status status() const;
+ void setStatus(Status status);
+ void resetStatus();
+
+ bool atEnd() const;
+ void reset();
+ void flush();
+ bool seek(qint64 pos);
+ qint64 pos() const;
+
+ void skipWhiteSpace();
+
+ QString readLine(qint64 maxlen = 0);
+ QString readAll();
+ QString read(qint64 maxlen);
+
+ void setFieldAlignment(FieldAlignment alignment);
+ FieldAlignment fieldAlignment() const;
+
+ void setPadChar(QChar ch);
+ QChar padChar() const;
+
+ void setFieldWidth(int width);
+ int fieldWidth() const;
+
+ void setNumberFlags(NumberFlags flags);
+ NumberFlags numberFlags() const;
+
+ void setIntegerBase(int base);
+ int integerBase() const;
+
+ void setRealNumberNotation(RealNumberNotation notation);
+ RealNumberNotation realNumberNotation() const;
+
+ void setRealNumberPrecision(int precision);
+ int realNumberPrecision() const;
+
+ QTextStream &operator>>(QChar &ch);
+ QTextStream &operator>>(char &ch);
+ QTextStream &operator>>(signed short &i);
+ QTextStream &operator>>(unsigned short &i);
+ QTextStream &operator>>(signed int &i);
+ QTextStream &operator>>(unsigned int &i);
+ QTextStream &operator>>(signed long &i);
+ QTextStream &operator>>(unsigned long &i);
+ QTextStream &operator>>(qlonglong &i);
+ QTextStream &operator>>(qulonglong &i);
+ QTextStream &operator>>(float &f);
+ QTextStream &operator>>(double &f);
+ QTextStream &operator>>(QString &s);
+ QTextStream &operator>>(QByteArray &array);
+ QTextStream &operator>>(char *c);
+
+ QTextStream &operator<<(QBool b);
+ QTextStream &operator<<(QChar ch);
+ QTextStream &operator<<(char ch);
+ QTextStream &operator<<(signed short i);
+ QTextStream &operator<<(unsigned short i);
+ QTextStream &operator<<(signed int i);
+ QTextStream &operator<<(unsigned int i);
+ QTextStream &operator<<(signed long i);
+ QTextStream &operator<<(unsigned long i);
+ QTextStream &operator<<(qlonglong i);
+ QTextStream &operator<<(qulonglong i);
+ QTextStream &operator<<(float f);
+ QTextStream &operator<<(double f);
+ QTextStream &operator<<(const QString &s);
+ QTextStream &operator<<(const QByteArray &array);
+ QTextStream &operator<<(const char *c);
+ QTextStream &operator<<(const void *ptr);
+
+#ifdef QT3_SUPPORT
+ // not marked as QT3_SUPPORT to avoid double compiler warnings, as
+ // they are used in the QT3_SUPPORT functions below.
+ inline QT3_SUPPORT int flags() const { return flagsInternal(); }
+ inline QT3_SUPPORT int flags(int f) { return flagsInternal(f); }
+
+ inline QT3_SUPPORT int setf(int bits)
+ { int old = flagsInternal(); flagsInternal(flagsInternal() | bits); return old; }
+ inline QT3_SUPPORT int setf(int bits, int mask)
+ { int old = flagsInternal(); flagsInternal(flagsInternal() | (bits & mask)); return old; }
+ inline QT3_SUPPORT int unsetf(int bits)
+ { int old = flagsInternal(); flagsInternal(flagsInternal() & ~bits); return old; }
+
+ inline QT3_SUPPORT int width(int w)
+ { int old = fieldWidth(); setFieldWidth(w); return old; }
+ inline QT3_SUPPORT int fill(int f)
+ { QChar ch = padChar(); setPadChar(QChar(f)); return ch.unicode(); }
+ inline QT3_SUPPORT int precision(int p)
+ { int old = realNumberPrecision(); setRealNumberPrecision(p); return old; }
+
+ enum {
+ skipws = 0x0001, // skip whitespace on input
+ left = 0x0002, // left-adjust output
+ right = 0x0004, // right-adjust output
+ internal = 0x0008, // pad after sign
+ bin = 0x0010, // binary format integer
+ oct = 0x0020, // octal format integer
+ dec = 0x0040, // decimal format integer
+ hex = 0x0080, // hex format integer
+ showbase = 0x0100, // show base indicator
+ showpoint = 0x0200, // force decimal point (float)
+ uppercase = 0x0400, // upper-case hex output
+ showpos = 0x0800, // add '+' to positive integers
+ scientific = 0x1000, // scientific float output
+ fixed = 0x2000 // fixed float output
+ };
+ enum {
+ basefield = bin | oct | dec | hex,
+ adjustfield = left | right | internal,
+ floatfield = scientific | fixed
+ };
+
+#ifndef QT_NO_TEXTCODEC
+ enum Encoding { Locale, Latin1, Unicode, UnicodeNetworkOrder,
+ UnicodeReverse, RawUnicode, UnicodeUTF8 };
+ QT3_SUPPORT void setEncoding(Encoding encoding);
+#endif
+ inline QT3_SUPPORT QString read() { return readAll(); }
+ inline QT3_SUPPORT void unsetDevice() { setDevice(0); }
+#endif
+
+private:
+#ifdef QT3_SUPPORT
+ int flagsInternal() const;
+ int flagsInternal(int flags);
+#endif
+
+ Q_DISABLE_COPY(QTextStream)
+
+ QScopedPointer<QTextStreamPrivate> d_ptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QTextStream::NumberFlags)
+
+/*****************************************************************************
+ QTextStream manipulators
+ *****************************************************************************/
+
+typedef QTextStream & (*QTextStreamFunction)(QTextStream &);// manipulator function
+typedef void (QTextStream::*QTSMFI)(int); // manipulator w/int argument
+typedef void (QTextStream::*QTSMFC)(QChar); // manipulator w/QChar argument
+
+class Q_CORE_EXPORT QTextStreamManipulator
+{
+public:
+ QTextStreamManipulator(QTSMFI m, int a) { mf = m; mc = 0; arg = a; }
+ QTextStreamManipulator(QTSMFC m, QChar c) { mf = 0; mc = m; ch = c; arg = -1; }
+ void exec(QTextStream &s) { if (mf) { (s.*mf)(arg); } else { (s.*mc)(ch); } }
+
+private:
+ QTSMFI mf; // QTextStream member function
+ QTSMFC mc; // QTextStream member function
+ int arg; // member function argument
+ QChar ch;
+};
+
+inline QTextStream &operator>>(QTextStream &s, QTextStreamFunction f)
+{ return (*f)(s); }
+
+inline QTextStream &operator<<(QTextStream &s, QTextStreamFunction f)
+{ return (*f)(s); }
+
+inline QTextStream &operator<<(QTextStream &s, QTextStreamManipulator m)
+{ m.exec(s); return s; }
+
+Q_CORE_EXPORT QTextStream &bin(QTextStream &s);
+Q_CORE_EXPORT QTextStream &oct(QTextStream &s);
+Q_CORE_EXPORT QTextStream &dec(QTextStream &s);
+Q_CORE_EXPORT QTextStream &hex(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &showbase(QTextStream &s);
+Q_CORE_EXPORT QTextStream &forcesign(QTextStream &s);
+Q_CORE_EXPORT QTextStream &forcepoint(QTextStream &s);
+Q_CORE_EXPORT QTextStream &noshowbase(QTextStream &s);
+Q_CORE_EXPORT QTextStream &noforcesign(QTextStream &s);
+Q_CORE_EXPORT QTextStream &noforcepoint(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &uppercasebase(QTextStream &s);
+Q_CORE_EXPORT QTextStream &uppercasedigits(QTextStream &s);
+Q_CORE_EXPORT QTextStream &lowercasebase(QTextStream &s);
+Q_CORE_EXPORT QTextStream &lowercasedigits(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &fixed(QTextStream &s);
+Q_CORE_EXPORT QTextStream &scientific(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &left(QTextStream &s);
+Q_CORE_EXPORT QTextStream &right(QTextStream &s);
+Q_CORE_EXPORT QTextStream &center(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &endl(QTextStream &s);
+Q_CORE_EXPORT QTextStream &flush(QTextStream &s);
+Q_CORE_EXPORT QTextStream &reset(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &bom(QTextStream &s);
+
+Q_CORE_EXPORT QTextStream &ws(QTextStream &s);
+
+inline QTextStreamManipulator qSetFieldWidth(int width)
+{
+ QTSMFI func = &QTextStream::setFieldWidth;
+ return QTextStreamManipulator(func,width);
+}
+
+inline QTextStreamManipulator qSetPadChar(QChar ch)
+{
+ QTSMFC func = &QTextStream::setPadChar;
+ return QTextStreamManipulator(func, ch);
+}
+
+inline QTextStreamManipulator qSetRealNumberPrecision(int precision)
+{
+ QTSMFI func = &QTextStream::setRealNumberPrecision;
+ return QTextStreamManipulator(func, precision);
+}
+
+#ifdef QT3_SUPPORT
+typedef QTextStream QTS;
+
+class Q_CORE_EXPORT QTextIStream : public QTextStream
+{
+public:
+ inline explicit QTextIStream(const QString *s) : QTextStream(const_cast<QString *>(s), QIODevice::ReadOnly) {}
+ inline explicit QTextIStream(QByteArray *a) : QTextStream(a, QIODevice::ReadOnly) {}
+ inline QTextIStream(FILE *f) : QTextStream(f, QIODevice::ReadOnly) {}
+
+private:
+ Q_DISABLE_COPY(QTextIStream)
+};
+
+class Q_CORE_EXPORT QTextOStream : public QTextStream
+{
+public:
+ inline explicit QTextOStream(QString *s) : QTextStream(s, QIODevice::WriteOnly) {}
+ inline explicit QTextOStream(QByteArray *a) : QTextStream(a, QIODevice::WriteOnly) {}
+ inline QTextOStream(FILE *f) : QTextStream(f, QIODevice::WriteOnly) {}
+
+private:
+ Q_DISABLE_COPY(QTextOStream)
+};
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTEXTSTREAM_H
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
new file mode 100644
index 0000000000..efd3f45ef0
--- /dev/null
+++ b/src/corelib/io/qurl.cpp
@@ -0,0 +1,6544 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QUrl
+
+ \brief The QUrl class provides a convenient interface for working
+ with URLs.
+
+ \reentrant
+ \ingroup io
+ \ingroup network
+ \ingroup shared
+
+
+ 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() and
+ setEncodedUrl() can also be used.
+
+ URLs can be represented in two forms: encoded or unencoded. The
+ unencoded representation is suitable for showing to users, but
+ the encoded representation is typically what you would send to
+ a web server. For example, the unencoded URL
+ "http://b\uuml\c{}hler.example.com" would be sent to the server as
+ "http://xn--bhler-kva.example.com/List%20of%20applicants.xml".
+
+ A URL can also be constructed piece by piece by calling
+ setScheme(), setUserName(), setPassword(), setHost(), setPort(),
+ setPath(), setEncodedQuery() and setFragment(). Some convenience
+ functions are also available: setAuthority() sets the user name,
+ password, host and port. setUserInfo() sets the user name and
+ password at once.
+
+ Call isValid() to check if the URL is valid. This can be done at
+ any point during the constructing of a URL.
+
+ Constructing a query is particularly convenient through the use
+ of setQueryItems(), addQueryItem() and removeQueryItem(). Use
+ setQueryDelimiters() to customize the delimiters used for
+ generating the query string.
+
+ For the convenience of generating encoded URL strings or query
+ strings, there are two static functions called
+ fromPercentEncoding() and toPercentEncoding() which deal with
+ percent encoding and decoding of QStrings.
+
+ Calling isRelative() will tell whether or not the URL is
+ relative. A relative URL can be resolved by passing it as argument
+ to resolved(), which returns an absolute URL. isParentOf() is used
+ for determining whether one URL is a parent of another.
+
+ fromLocalFile() constructs a QUrl by parsing a local
+ file path. toLocalFile() converts a URL to a local file path.
+
+ The human readable representation of the URL is fetched with
+ toString(). This representation is appropriate for displaying a
+ URL to a user in unencoded form. The encoded form however, as
+ returned by toEncoded(), is for internal use, passing to web
+ servers, mail clients and so on.
+
+ QUrl conforms to the URI specification from
+ \l{RFC 3986} (Uniform Resource Identifier: Generic Syntax), and includes
+ scheme extensions from \l{RFC 1738} (Uniform Resource Locators). Case
+ folding rules in QUrl conform to \l{RFC 3491} (Nameprep: A Stringprep
+ Profile for Internationalized Domain Names (IDN)).
+
+ \sa QUrlInfo
+*/
+
+/*!
+ \enum QUrl::ParsingMode
+
+ The parsing mode controls the way QUrl parses strings.
+
+ \value TolerantMode QUrl will try to correct some common errors in URLs.
+ This mode is useful when processing URLs entered by
+ users.
+
+ \value StrictMode Only valid URLs are accepted. This mode is useful for
+ general URL validation.
+
+ In TolerantMode, the parser corrects the following invalid input:
+
+ \list
+
+ \o Spaces and "%20": If an encoded URL contains a space, this will be
+ replaced with "%20". If a decoded URL contains "%20", this will be
+ replaced with a single space before the URL is parsed.
+
+ \o Single "%" characters: Any occurrences of a percent character "%" not
+ followed by exactly two hexadecimal characters (e.g., "13% coverage.html")
+ will be replaced by "%25".
+
+ \o Reserved and unreserved characters: An encoded URL should only
+ contain a few characters as literals; all other characters should
+ be percent-encoded. In TolerantMode, these characters will be
+ automatically percent-encoded where they are not allowed:
+ space / double-quote / "<" / ">" / "[" / "\" /
+ "]" / "^" / "`" / "{" / "|" / "}"
+
+ \endlist
+*/
+
+/*!
+ \enum QUrl::FormattingOption
+
+ The formatting options define how the URL is formatted when written out
+ as text.
+
+ \value None The format of the URL is unchanged.
+ \value RemoveScheme The scheme is removed from the URL.
+ \value RemovePassword Any password in the URL is removed.
+ \value RemoveUserInfo Any user information in the URL is removed.
+ \value RemovePort Any specified port is removed from the URL.
+ \value RemoveAuthority
+ \value RemovePath The URL's path is removed, leaving only the scheme,
+ host address, and port (if present).
+ \value RemoveQuery The query part of the URL (following a '?' character)
+ is removed.
+ \value RemoveFragment
+ \value StripTrailingSlash The trailing slash is removed if one is present.
+
+ Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
+ conforms to, require host names to always be converted to lower case,
+ regardless of the Qt::FormattingOptions used.
+*/
+
+/*!
+ \fn uint qHash(const QUrl &url)
+ \since 4.7
+ \relates QUrl
+
+ Computes a hash key from the normalized version of \a url.
+ */
+#include "qplatformdefs.h"
+#include "qurl.h"
+#include "qatomic.h"
+#include "qbytearray.h"
+#include "qdir.h"
+#include "qfile.h"
+#include "qlist.h"
+#ifndef QT_NO_REGEXP
+#include "qregexp.h"
+#endif
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qstack.h"
+#include "qvarlengtharray.h"
+#include "qdebug.h"
+#if defined QT3_SUPPORT
+#include "qfileinfo.h"
+#endif
+
+#if defined(Q_OS_WINCE_WM)
+#pragma optimize("g", off)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern void q_normalizePercentEncoding(QByteArray *ba, const char *exclude);
+extern void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include = 0);
+extern void q_fromPercentEncoding(QByteArray *ba);
+
+static QByteArray toPercentEncodingHelper(const QString &s, const char *exclude, const char *include = 0)
+{
+ if (s.isNull())
+ return QByteArray(); // null
+ QByteArray ba = s.toUtf8();
+ q_toPercentEncoding(&ba, exclude, include);
+ return ba;
+}
+
+static QString fromPercentEncodingHelper(const QByteArray &ba)
+{
+ if (ba.isNull())
+ return QString(); // null
+ QByteArray copy = ba;
+ q_fromPercentEncoding(&copy);
+ return QString::fromUtf8(copy.constData(), copy.length());
+}
+
+static QString fromPercentEncodingMutable(QByteArray *ba)
+{
+ if (ba->isNull())
+ return QString(); // null
+ q_fromPercentEncoding(ba);
+ return QString::fromUtf8(ba->constData(), ba->length());
+}
+
+// ### Qt 5: Consider accepting empty strings as valid. See task 144227.
+
+//#define QURL_DEBUG
+
+// implemented in qvsnprintf.cpp
+Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
+
+// 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;
+static const uint skew = 38;
+static const uint damp = 700;
+static const uint initial_bias = 72;
+static const uint initial_n = 128;
+
+#define QURL_SETFLAG(a, b) { (a) |= (b); }
+#define QURL_UNSETFLAG(a, b) { (a) &= ~(b); }
+#define QURL_HASFLAG(a, b) (((a) & (b)) == (b))
+
+struct QUrlErrorInfo {
+ inline QUrlErrorInfo() : _source(0), _message(0), _expected(0), _found(0)
+ { }
+
+ const char *_source;
+ const char *_message;
+ char _expected;
+ char _found;
+
+ inline void setParams(const char *source, const char *message, char expected, char found)
+ {
+ _source = source;
+ _message = message;
+ _expected = expected;
+ _found = found;
+ }
+};
+
+struct QUrlParseData
+{
+ const char *scheme;
+ int schemeLength;
+
+ const char *userInfo;
+ int userInfoDelimIndex;
+ int userInfoLength;
+
+ const char *host;
+ int hostLength;
+ int port;
+
+ const char *path;
+ int pathLength;
+ const char *query;
+ int queryLength;
+ const char *fragment;
+ int fragmentLength;
+};
+
+
+class QUrlPrivate
+{
+public:
+ QUrlPrivate();
+ QUrlPrivate(const QUrlPrivate &other);
+
+ bool setUrl(const QString &url);
+
+ QString canonicalHost() const;
+ void ensureEncodedParts() const;
+ QString authority(QUrl::FormattingOptions options = QUrl::None) const;
+ void setAuthority(const QString &auth);
+ void setUserInfo(const QString &userInfo);
+ QString userInfo(QUrl::FormattingOptions options = QUrl::None) const;
+ void setEncodedAuthority(const QByteArray &authority);
+ void setEncodedUserInfo(const QUrlParseData *parseData);
+
+ QByteArray mergePaths(const QByteArray &relativePath) const;
+
+ void queryItem(int pos, int *value, int *end);
+
+ enum ParseOptions {
+ ParseAndSet,
+ ParseOnly
+ };
+
+ void validate() const;
+ void parse(ParseOptions parseOptions = ParseAndSet) const;
+ void clear();
+
+ QByteArray toEncoded(QUrl::FormattingOptions options = QUrl::None) const;
+
+ QAtomicInt ref;
+
+ QString scheme;
+ QString userName;
+ QString password;
+ QString host;
+ QString path;
+ QByteArray query;
+ QString fragment;
+
+ QByteArray encodedOriginal;
+ QByteArray encodedUserName;
+ QByteArray encodedPassword;
+ QByteArray encodedPath;
+ QByteArray encodedFragment;
+
+ int port;
+ QUrl::ParsingMode parsingMode;
+
+ bool hasQuery;
+ bool hasFragment;
+ bool isValid;
+ bool isHostValid;
+
+ char valueDelimiter;
+ char pairDelimiter;
+
+ enum State {
+ Parsed = 0x1,
+ Validated = 0x2,
+ Normalized = 0x4,
+ HostCanonicalized = 0x8
+ };
+ int stateFlags;
+
+ mutable QByteArray encodedNormalized;
+ const QByteArray & normalized() const;
+
+ mutable QUrlErrorInfo errorInfo;
+ QString createErrorString();
+};
+
+
+static bool QT_FASTCALL _HEXDIG(const char **ptr)
+{
+ char ch = **ptr;
+ if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
+ ++(*ptr);
+ return true;
+ }
+
+ return false;
+}
+
+// pct-encoded = "%" HEXDIG HEXDIG
+static bool QT_FASTCALL _pctEncoded(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+
+ if (**ptr != '%')
+ return false;
+ ++(*ptr);
+
+ if (!_HEXDIG(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+ if (!_HEXDIG(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ return true;
+}
+
+#if 0
+// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+static bool QT_FASTCALL _genDelims(const char **ptr, char *c)
+{
+ char ch = **ptr;
+ switch (ch) {
+ case ':': case '/': case '?': case '#':
+ case '[': case ']': case '@':
+ *c = ch;
+ ++(*ptr);
+ return true;
+ default:
+ return false;
+ }
+}
+#endif
+
+// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+// / "*" / "+" / "," / ";" / "="
+static bool QT_FASTCALL _subDelims(const char **ptr)
+{
+ char ch = **ptr;
+ switch (ch) {
+ case '!': case '$': case '&': case '\'':
+ case '(': case ')': case '*': case '+':
+ case ',': case ';': case '=':
+ ++(*ptr);
+ return true;
+ default:
+ return false;
+ }
+}
+
+// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+static bool QT_FASTCALL _unreserved(const char **ptr)
+{
+ char ch = **ptr;
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
+ || (ch >= '0' && ch <= '9')
+ || ch == '-' || ch == '.' || ch == '_' || ch == '~') {
+ ++(*ptr);
+ return true;
+ }
+ return false;
+}
+
+// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+static bool QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData)
+{
+ bool first = true;
+ bool isSchemeValid = true;
+
+ parseData->scheme = *ptr;
+ for (;;) {
+ char ch = **ptr;
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
+ ;
+ } else if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.') {
+ if (first)
+ isSchemeValid = false;
+ } else {
+ break;
+ }
+
+ ++(*ptr);
+ first = false;
+ }
+
+ if (**ptr != ':') {
+ isSchemeValid = true;
+ *ptr = parseData->scheme;
+ } else {
+ parseData->schemeLength = *ptr - parseData->scheme;
+ ++(*ptr); // skip ':'
+ }
+
+ return isSchemeValid;
+}
+
+// IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+static bool QT_FASTCALL _IPvFuture(const char **ptr)
+{
+ if (**ptr != 'v')
+ return false;
+
+ const char *ptrBackup = *ptr;
+ ++(*ptr);
+
+ if (!_HEXDIG(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ while (_HEXDIG(ptr))
+ ;
+
+ if (**ptr != '.') {
+ *ptr = ptrBackup;
+ return false;
+ }
+ ++(*ptr);
+
+ if (!_unreserved(ptr) && !_subDelims(ptr) && *((*ptr)++) != ':') {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+
+ while (_unreserved(ptr) || _subDelims(ptr) || *((*ptr)++) == ':')
+ ;
+
+ return true;
+}
+
+// h16 = 1*4HEXDIG
+// ; 16 bits of address represented in hexadecimal
+static bool QT_FASTCALL _h16(const char **ptr)
+{
+ int i = 0;
+ for (; i < 4; ++i) {
+ if (!_HEXDIG(ptr))
+ break;
+ }
+ return (i != 0);
+}
+
+// dec-octet = DIGIT ; 0-9
+// / %x31-39 DIGIT ; 10-99
+// / "1" 2DIGIT ; 100-199
+// / "2" %x30-34 DIGIT ; 200-249
+// / "25" %x30-35 ; 250-255
+static bool QT_FASTCALL _decOctet(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+ char c1 = **ptr;
+
+ if (c1 < '0' || c1 > '9')
+ return false;
+
+ ++(*ptr);
+
+ if (c1 == '0')
+ return true;
+
+ char c2 = **ptr;
+
+ if (c2 < '0' || c2 > '9')
+ return true;
+
+ ++(*ptr);
+
+ char c3 = **ptr;
+ if (c3 < '0' || c3 > '9')
+ return true;
+
+ // If there is a three digit number larger than 255, reject the
+ // whole token.
+ if (c1 >= '2' && c2 >= '5' && c3 > '5') {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ ++(*ptr);
+
+ return true;
+}
+
+// IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+static bool QT_FASTCALL _IPv4Address(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+
+ if (!_decOctet(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ char ch = *((*ptr)++);
+ if (ch != '.') {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ if (!_decOctet(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// ls32 = ( h16 ":" h16 ) / IPv4address
+// ; least-significant 32 bits of address
+static bool QT_FASTCALL _ls32(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+ if (_h16(ptr) && *((*ptr)++) == ':' && _h16(ptr))
+ return true;
+
+ *ptr = ptrBackup;
+ return _IPv4Address(ptr);
+}
+
+// IPv6address = 6( h16 ":" ) ls32 // case 1
+// / "::" 5( h16 ":" ) ls32 // case 2
+// / [ h16 ] "::" 4( h16 ":" ) ls32 // case 3
+// / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 // case 4
+// / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 // case 5
+// / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 // case 6
+// / [ *4( h16 ":" ) h16 ] "::" ls32 // case 7
+// / [ *5( h16 ":" ) h16 ] "::" h16 // case 8
+// / [ *6( h16 ":" ) h16 ] "::" // case 9
+static bool QT_FASTCALL _IPv6Address(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+
+ // count of (h16 ":") to the left of and including ::
+ int leftHexColons = 0;
+ // count of (h16 ":") to the right of ::
+ int rightHexColons = 0;
+
+ // first count the number of (h16 ":") on the left of ::
+ while (_h16(ptr)) {
+
+ // an h16 not followed by a colon is considered an
+ // error.
+ if (**ptr != ':') {
+ *ptr = ptrBackup;
+ return false;
+ }
+ ++(*ptr);
+ ++leftHexColons;
+
+ // check for case 1, the only time when there can be no ::
+ if (leftHexColons == 6 && _ls32(ptr)) {
+ return true;
+ }
+ }
+
+ // check for case 2 where the address starts with a :
+ if (leftHexColons == 0 && *((*ptr)++) != ':') {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ // check for the second colon in ::
+ if (*((*ptr)++) != ':') {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ int canBeCase = -1;
+ bool ls32WasRead = false;
+
+ const char *tmpBackup = *ptr;
+
+ // count the number of (h16 ":") on the right of ::
+ for (;;) {
+ tmpBackup = *ptr;
+ if (!_h16(ptr)) {
+ if (!_ls32(ptr)) {
+ if (rightHexColons != 0) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ // the address ended with :: (case 9)
+ // only valid if 1 <= leftHexColons <= 7
+ canBeCase = 9;
+ } else {
+ ls32WasRead = true;
+ }
+ break;
+ }
+ ++rightHexColons;
+ if (**ptr != ':') {
+ // no colon could mean that what was read as an h16
+ // was in fact the first part of an ls32. we backtrack
+ // and retry.
+ const char *pb = *ptr;
+ *ptr = tmpBackup;
+ if (_ls32(ptr)) {
+ ls32WasRead = true;
+ --rightHexColons;
+ } else {
+ *ptr = pb;
+ // address ends with only 1 h16 after :: (case 8)
+ if (rightHexColons == 1)
+ canBeCase = 8;
+ }
+ break;
+ }
+ ++(*ptr);
+ }
+
+ // determine which case it is based on the number of rightHexColons
+ if (canBeCase == -1) {
+
+ // check if a ls32 was read. If it wasn't and rightHexColons >= 2 then the
+ // last 2 HexColons are in fact a ls32
+ if (!ls32WasRead && rightHexColons >= 2)
+ rightHexColons -= 2;
+
+ canBeCase = 7 - rightHexColons;
+ }
+
+ // based on the case we need to check that the number of leftHexColons is valid
+ if (leftHexColons > (canBeCase - 2)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ return true;
+}
+
+// IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+static bool QT_FASTCALL _IPLiteral(const char **ptr)
+{
+ const char *ptrBackup = *ptr;
+ if (**ptr != '[')
+ return false;
+ ++(*ptr);
+
+ if (!_IPv6Address(ptr) && !_IPvFuture(ptr)) {
+ *ptr = ptrBackup;
+ return false;
+ }
+
+ if (**ptr != ']') {
+ *ptr = ptrBackup;
+ return false;
+ }
+ ++(*ptr);
+
+ return true;
+}
+
+// reg-name = *( unreserved / pct-encoded / sub-delims )
+static void QT_FASTCALL _regName(const char **ptr)
+{
+ for (;;) {
+ if (!_unreserved(ptr) && !_subDelims(ptr)) {
+ if (!_pctEncoded(ptr))
+ break;
+ }
+ }
+}
+
+// host = IP-literal / IPv4address / reg-name
+static void QT_FASTCALL _host(const char **ptr, QUrlParseData *parseData)
+{
+ parseData->host = *ptr;
+ if (!_IPLiteral(ptr)) {
+ if (_IPv4Address(ptr)) {
+ char ch = **ptr;
+ if (ch && ch != ':' && ch != '/') {
+ // reset
+ *ptr = parseData->host;
+ _regName(ptr);
+ }
+ } else {
+ _regName(ptr);
+ }
+ }
+ parseData->hostLength = *ptr - parseData->host;
+}
+
+// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+static void QT_FASTCALL _userInfo(const char **ptr, QUrlParseData *parseData)
+{
+ parseData->userInfo = *ptr;
+ for (;;) {
+ if (_unreserved(ptr) || _subDelims(ptr)) {
+ ;
+ } else {
+ if (_pctEncoded(ptr)) {
+ ;
+ } else if (**ptr == ':') {
+ parseData->userInfoDelimIndex = *ptr - parseData->userInfo;
+ ++(*ptr);
+ } else {
+ break;
+ }
+ }
+ }
+ if (**ptr != '@') {
+ *ptr = parseData->userInfo;
+ parseData->userInfoDelimIndex = -1;
+ return;
+ }
+ parseData->userInfoLength = *ptr - parseData->userInfo;
+ ++(*ptr);
+}
+
+// port = *DIGIT
+static void QT_FASTCALL _port(const char **ptr, int *port)
+{
+ bool first = true;
+
+ for (;;) {
+ const char *ptrBackup = *ptr;
+ char ch = *((*ptr)++);
+ if (ch < '0' || ch > '9') {
+ *ptr = ptrBackup;
+ break;
+ }
+
+ if (first) {
+ first = false;
+ *port = 0;
+ }
+
+ *port *= 10;
+ *port += ch - '0';
+ }
+}
+
+// authority = [ userinfo "@" ] host [ ":" port ]
+static void QT_FASTCALL _authority(const char **ptr, QUrlParseData *parseData)
+{
+ _userInfo(ptr, parseData);
+ _host(ptr, parseData);
+
+ if (**ptr != ':')
+ return;
+
+ ++(*ptr);
+ _port(ptr, &parseData->port);
+}
+
+// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+static bool QT_FASTCALL _pchar(const char **ptr)
+{
+ char c = *(*ptr);
+
+ switch (c) {
+ case '!': case '$': case '&': case '\'': case '(': case ')': case '*':
+ case '+': case ',': case ';': case '=': case ':': case '@':
+ case '-': case '.': case '_': case '~':
+ ++(*ptr);
+ return true;
+ default:
+ break;
+ };
+
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
+ ++(*ptr);
+ return true;
+ }
+
+ if (_pctEncoded(ptr))
+ return true;
+
+ return false;
+}
+
+// segment = *pchar
+static bool QT_FASTCALL _segmentNZ(const char **ptr)
+{
+ if (!_pchar(ptr))
+ return false;
+
+ while(_pchar(ptr))
+ ;
+
+ return true;
+}
+
+// path-abempty = *( "/" segment )
+static void QT_FASTCALL _pathAbEmpty(const char **ptr)
+{
+ for (;;) {
+ if (**ptr != '/')
+ break;
+ ++(*ptr);
+
+ while (_pchar(ptr))
+ ;
+ }
+}
+
+// path-abs = "/" [ segment-nz *( "/" segment ) ]
+static bool QT_FASTCALL _pathAbs(const char **ptr)
+{
+ // **ptr == '/' already checked in caller
+ ++(*ptr);
+
+ // we might be able to unnest this to gain some performance.
+ if (!_segmentNZ(ptr))
+ return true;
+
+ _pathAbEmpty(ptr);
+
+ return true;
+}
+
+// path-rootless = segment-nz *( "/" segment )
+static bool QT_FASTCALL _pathRootless(const char **ptr)
+{
+ // we might be able to unnest this to gain some performance.
+ if (!_segmentNZ(ptr))
+ return false;
+
+ _pathAbEmpty(ptr);
+
+ return true;
+}
+
+
+// hier-part = "//" authority path-abempty
+// / path-abs
+// / path-rootless
+// / path-empty
+static void QT_FASTCALL _hierPart(const char **ptr, QUrlParseData *parseData)
+{
+ const char *ptrBackup = *ptr;
+ const char *pathStart = 0;
+ if (*((*ptr)++) == '/' && *((*ptr)++) == '/') {
+ _authority(ptr, parseData);
+ pathStart = *ptr;
+ _pathAbEmpty(ptr);
+ } else {
+ *ptr = ptrBackup;
+ pathStart = *ptr;
+ if (**ptr == '/')
+ _pathAbs(ptr);
+ else
+ _pathRootless(ptr);
+ }
+ parseData->path = pathStart;
+ parseData->pathLength = *ptr - pathStart;
+}
+
+// query = *( pchar / "/" / "?" )
+static void QT_FASTCALL _query(const char **ptr, QUrlParseData *parseData)
+{
+ parseData->query = *ptr;
+ for (;;) {
+ if (_pchar(ptr)) {
+ ;
+ } else if (**ptr == '/' || **ptr == '?') {
+ ++(*ptr);
+ } else {
+ break;
+ }
+ }
+ parseData->queryLength = *ptr - parseData->query;
+}
+
+// fragment = *( pchar / "/" / "?" )
+static void QT_FASTCALL _fragment(const char **ptr, QUrlParseData *parseData)
+{
+ parseData->fragment = *ptr;
+ for (;;) {
+ if (_pchar(ptr)) {
+ ;
+ } else if (**ptr == '/' || **ptr == '?' || **ptr == '#') {
+ ++(*ptr);
+ } else {
+ break;
+ }
+ }
+ parseData->fragmentLength = *ptr - parseData->fragment;
+}
+
+struct NameprepCaseFoldingEntry {
+ uint uc;
+ ushort mapping[4];
+};
+
+inline bool operator<(uint one, const NameprepCaseFoldingEntry &other)
+{ return one < other.uc; }
+
+inline bool operator<(const NameprepCaseFoldingEntry &one, uint 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)
+{
+ int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]);
+
+ ushort *d = 0;
+ 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 NameprepCaseFoldingEntry *entry = qBinaryFind(NameprepCaseFolding,
+ NameprepCaseFolding + N,
+ uc);
+ if ((entry - NameprepCaseFolding) != N) {
+ int l = 1;
+ while (l < 4 && entry->mapping[l])
+ ++l;
+ if (l > 1) {
+ if (uc <= 0xffff)
+ str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l);
+ else
+ str->replace(i-1, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l);
+ d = 0;
+ } 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;
+ }
+}
+
+
+static void stripProhibitedOutput(QString *str, int from)
+{
+ ushort *out = (ushort *)str->data() + from;
+ const ushort *in = out;
+ const ushort *end = (ushort *)str->data() + str->size();
+ while (in < end) {
+ uint uc = *in;
+ if (QChar(uc).isHighSurrogate() && in < end - 1) {
+ ushort low = *(in + 1);
+ if (QChar(low).isLowSurrogate()) {
+ ++in;
+ uc = QChar::surrogateToUcs4(uc, low);
+ }
+ }
+ 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 && uc <= 0xFFFF))) {
+ *out++ = *in;
+ }
+ } 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))) {
+ *out++ = QChar::highSurrogate(uc);
+ *out++ = QChar::lowSurrogate(uc);
+ }
+ }
+ ++in;
+ }
+ if (in != out)
+ str->truncate(out - str->utf16());
+}
+
+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;
+}
+
+#ifdef QT_BUILD_INTERNAL
+// export for tst_qurl.cpp
+Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from);
+Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len);
+#else
+// non-test build, keep the symbols for ourselves
+static void qt_nameprep(QString *source, int from);
+static bool qt_check_std3rules(const QChar *uc, int len);
+#endif
+
+void 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) {
+ register ushort uc = out->unicode();
+ if (uc > 0x80) {
+ break;
+ } else if (uc >= 'A' && uc <= 'Z') {
+ *out = QChar(uc | 0x20);
+ }
+ }
+ if (out == e)
+ return; // 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;
+ }
+ }
+ if (!isMappedToNothing(uc)) {
+ if (uc <= 0xFFFF) {
+ *out++ = *in;
+ } else {
+ *out++ = QChar::highSurrogate(uc);
+ *out++ = QChar::lowSurrogate(uc);
+ }
+ }
+ }
+ 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);
+
+ // Strip prohibited output
+ stripProhibitedOutput(source, firstNonAscii);
+
+ // 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
+ }
+}
+
+bool qt_check_std3rules(const QChar *uc, int len)
+{
+ if (len > 63)
+ return false;
+
+ for (int i = 0; i < len; ++i) {
+ register ushort c = uc[i].unicode();
+ if (c == '-' && (i == 0 || i == len - 1))
+ return false;
+
+ // verifying the absence of LDH is the same as verifying that
+ // only LDH is present
+ if (c == '-' || (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z')
+ //underscore is not supposed to be allowed, but other browser accept it (QTBUG-7434)
+ || c == '_')
+ continue;
+
+ return false;
+ }
+
+ return true;
+}
+
+
+static inline uint encodeDigit(uint digit)
+{
+ return digit + 22 + 75 * (digit < 26);
+}
+
+static inline uint adapt(uint delta, uint numpoints, bool firsttime)
+{
+ delta /= (firsttime ? damp : 2);
+ delta += (delta / numpoints);
+
+ uint k = 0;
+ for (; delta > ((base - tmin) * tmax) / 2; k += base)
+ delta /= (base - tmin);
+
+ return k + (((base - tmin + 1) * delta) / (delta + skew));
+}
+
+static inline void appendEncode(QString* output, uint& delta, uint& bias, uint& b, uint& h)
+{
+ uint qq;
+ uint k;
+ uint t;
+
+ // insert the variable length delta integer; fail on
+ // overflow.
+ for (qq = delta, k = base;; k += base) {
+ // stop generating digits when the threshold is
+ // detected.
+ t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias;
+ if (qq < t) break;
+
+ *output += QChar(encodeDigit(t + (qq - t) % (base - t)));
+ qq = (qq - t) / (base - t);
+ }
+
+ *output += QChar(encodeDigit(qq));
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
+}
+
+static void toPunycodeHelper(const QChar *s, int ucLength, QString *output)
+{
+ uint n = initial_n;
+ uint delta = 0;
+ uint bias = initial_bias;
+
+ int outLen = output->length();
+ output->resize(outLen + ucLength);
+
+ QChar *d = output->data() + outLen;
+ bool skipped = false;
+ // copy all basic code points verbatim to output.
+ for (uint j = 0; j < (uint) ucLength; ++j) {
+ ushort js = s[j].unicode();
+ if (js < 0x80)
+ *d++ = js;
+ else
+ skipped = true;
+ }
+
+ // if there were only basic code points, just return them
+ // directly; don't do any encoding.
+ if (!skipped)
+ return;
+
+ output->truncate(d - output->constData());
+ int copied = output->size() - outLen;
+
+ // h and b now contain the number of basic code points in input.
+ uint b = copied;
+ uint h = copied;
+
+ // if basic code points were copied, add the delimiter character.
+ if (h > 0)
+ *output += QChar(0x2d);
+
+ // while there are still unprocessed non-basic code points left in
+ // the input string...
+ while (h < (uint) ucLength) {
+ // find the character in the input string with the lowest
+ // unicode value.
+ uint m = Q_MAXINT;
+ uint j;
+ for (j = 0; j < (uint) ucLength; ++j) {
+ if (s[j].unicode() >= n && s[j].unicode() < m)
+ m = (uint) s[j].unicode();
+ }
+
+ // reject out-of-bounds unicode characters
+ if (m - n > (Q_MAXINT - delta) / (h + 1)) {
+ output->truncate(outLen);
+ return; // punycode_overflow
+ }
+
+ delta += (m - n) * (h + 1);
+ n = m;
+
+ // for each code point in the input string
+ for (j = 0; j < (uint) ucLength; ++j) {
+
+ // increase delta until we reach the character with the
+ // lowest unicode code. fail if delta overflows.
+ if (s[j].unicode() < n) {
+ ++delta;
+ if (!delta) {
+ output->truncate(outLen);
+ return; // punycode_overflow
+ }
+ }
+
+ // if j is the index of the character with the lowest
+ // unicode code...
+ if (s[j].unicode() == n) {
+ appendEncode(output, delta, bias, b, h);
+ }
+ }
+
+ ++delta;
+ ++n;
+ }
+
+ // prepend ACE prefix
+ output->insert(outLen, QLatin1String("xn--"));
+ return;
+}
+
+
+static const char * const idn_whitelist[] = {
+ "ac", "ar", "at",
+ "biz", "br",
+ "cat", "ch", "cl", "cn",
+ "de", "dk",
+ "es",
+ "fi",
+ "gr",
+ "hu",
+ "info", "io", "is",
+ "jp",
+ "kr",
+ "li", "lt",
+ "museum",
+ "no",
+ "org",
+ "se", "sh",
+ "th", "tm", "tw",
+ "vn",
+ "xn--mgbaam7a8h", // UAE
+ "xn--mgberp4a5d4ar", // Saudi Arabia
+ "xn--wgbh1c" // Egypt
+};
+
+static QStringList *user_idn_whitelist = 0;
+
+static bool lessThan(const QChar *a, int l, const char *c)
+{
+ const ushort *uc = (const ushort *)a;
+ const ushort *e = uc + l;
+
+ if (!c || *c == 0)
+ return false;
+
+ while (*c) {
+ if (uc == e || *uc != *c)
+ break;
+ ++uc;
+ ++c;
+ }
+ return (uc == e ? *c : *uc < *c);
+}
+
+static bool equal(const QChar *a, int l, const char *b)
+{
+ while (l && a->unicode() && *b) {
+ if (*a != QLatin1Char(*b))
+ return false;
+ ++a;
+ ++b;
+ --l;
+ }
+ return l == 0;
+}
+
+static bool qt_is_idn_enabled(const QString &domain)
+{
+ int idx = domain.lastIndexOf(QLatin1Char('.'));
+ if (idx == -1)
+ return false;
+
+ int len = domain.size() - idx - 1;
+ QString tldString(domain.constData() + idx + 1, len);
+ qt_nameprep(&tldString, 0);
+
+ const QChar *tld = tldString.constData();
+
+ if (user_idn_whitelist)
+ return user_idn_whitelist->contains(tldString);
+
+ int l = 0;
+ int r = sizeof(idn_whitelist)/sizeof(const char *) - 1;
+ int i = (l + r + 1) / 2;
+
+ while (r != l) {
+ if (lessThan(tld, len, idn_whitelist[i]))
+ r = i - 1;
+ else
+ l = i;
+ i = (l + r + 1) / 2;
+ }
+ return equal(tld, len, idn_whitelist[i]);
+}
+
+static inline bool isDotDelimiter(ushort uc)
+{
+ // IDNA / rfc3490 describes these four delimiters used for
+ // separating labels in unicode international domain
+ // names.
+ return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61;
+}
+
+static int nextDotDelimiter(const QString &domain, int from = 0)
+{
+ const QChar *b = domain.unicode();
+ const QChar *ch = b + from;
+ const QChar *e = b + domain.length();
+ while (ch < e) {
+ if (isDotDelimiter(ch->unicode()))
+ break;
+ else
+ ++ch;
+ }
+ return ch - b;
+}
+
+enum AceOperation { ToAceOnly, NormalizeAce };
+static QString qt_ACE_do(const QString &domain, AceOperation op)
+{
+ if (domain.isEmpty())
+ return domain;
+
+ QString result;
+ result.reserve(domain.length());
+
+ const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false;
+ int lastIdx = 0;
+ QString aceForm; // this variable is here for caching
+
+ while (1) {
+ int idx = nextDotDelimiter(domain, lastIdx);
+ int labelLength = idx - lastIdx;
+ if (labelLength == 0) {
+ if (idx == domain.length())
+ break;
+ return QString(); // two delimiters in a row -- empty label not allowed
+ }
+
+ // 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;
+ const QChar *in = domain.constData() + lastIdx;
+ const QChar *e = in + labelLength;
+ for (; in < e; ++in, ++out) {
+ register ushort uc = in->unicode();
+ if (uc > 0x7f)
+ simple = false;
+ if (uc >= 'A' && uc <= 'Z')
+ *out = QChar(uc | 0x20);
+ else
+ *out = *in;
+ }
+ }
+
+ 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;
+ }
+
+ if (simple) {
+ // fastest case: this is the common case (non IDN-domains)
+ // so we're done
+ if (!qt_check_std3rules(result.constData() + prevLen, labelLength))
+ return QString();
+ } else {
+ // Punycode encoding and decoding cannot be done in-place
+ // That means we need one or two temporaries
+ qt_nameprep(&result, prevLen);
+ labelLength = result.length() - prevLen;
+ register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes
+ aceForm.resize(0);
+ if (toReserve > aceForm.capacity())
+ aceForm.reserve(toReserve);
+ toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm);
+
+ // We use resize()+memcpy() here because we're overwriting the data we've copied
+ if (isIdnEnabled) {
+ QString tmp = QUrl::fromPunycode(aceForm.toLatin1());
+ if (tmp.isEmpty())
+ return QString(); // shouldn't happen, since we've just punycode-encoded it
+ result.resize(prevLen + tmp.size());
+ memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar));
+ } else {
+ result.resize(prevLen + aceForm.size());
+ memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar));
+ }
+
+ if (!qt_check_std3rules(aceForm.constData(), aceForm.size()))
+ return QString();
+ }
+
+
+ lastIdx = idx + 1;
+ if (lastIdx < domain.size() + 1)
+ result += QLatin1Char('.');
+ else
+ break;
+ }
+ return result;
+}
+
+
+QUrlPrivate::QUrlPrivate()
+{
+ ref = 1;
+ port = -1;
+ isValid = false;
+ isHostValid = true;
+ parsingMode = QUrl::TolerantMode;
+ valueDelimiter = '=';
+ pairDelimiter = '&';
+ stateFlags = 0;
+ hasFragment = false;
+ hasQuery = false;
+}
+
+QUrlPrivate::QUrlPrivate(const QUrlPrivate &copy)
+ : scheme(copy.scheme),
+ userName(copy.userName),
+ password(copy.password),
+ host(copy.host),
+ path(copy.path),
+ query(copy.query),
+ fragment(copy.fragment),
+ encodedOriginal(copy.encodedOriginal),
+ encodedUserName(copy.encodedUserName),
+ encodedPassword(copy.encodedPassword),
+ encodedPath(copy.encodedPath),
+ encodedFragment(copy.encodedFragment),
+ port(copy.port),
+ parsingMode(copy.parsingMode),
+ hasQuery(copy.hasQuery),
+ hasFragment(copy.hasFragment),
+ isValid(copy.isValid),
+ isHostValid(copy.isHostValid),
+ valueDelimiter(copy.valueDelimiter),
+ pairDelimiter(copy.pairDelimiter),
+ stateFlags(copy.stateFlags),
+ encodedNormalized(copy.encodedNormalized)
+{ ref = 1; }
+
+QString QUrlPrivate::canonicalHost() const
+{
+ if (QURL_HASFLAG(stateFlags, HostCanonicalized) || host.isEmpty())
+ return host;
+
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
+ QURL_SETFLAG(that->stateFlags, HostCanonicalized);
+ if (host.contains(QLatin1Char(':'))) {
+ // This is an IP Literal, use _IPLiteral to validate
+ QByteArray ba = host.toLatin1();
+ bool needsBraces = false;
+ if (!ba.startsWith('[')) {
+ // surround the IP Literal with [ ] if it's not already done so
+ ba.reserve(ba.length() + 2);
+ ba.prepend('[');
+ ba.append(']');
+ needsBraces = true;
+ }
+
+ const char *ptr = ba.constData();
+ if (!_IPLiteral(&ptr))
+ that->host.clear();
+ else if (needsBraces)
+ that->host = QString::fromLatin1(ba.toLower());
+ else
+ that->host = host.toLower();
+ } else {
+ that->host = qt_ACE_do(host, NormalizeAce);
+ }
+ that->isHostValid = !that->host.isNull();
+ return that->host;
+}
+
+// From RFC 3896, Appendix A Collected ABNF for URI
+// authority = [ userinfo "@" ] host [ ":" port ]
+// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+// host = IP-literal / IPv4address / reg-name
+// port = *DIGIT
+//[...]
+// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+//
+// query = *( pchar / "/" / "?" )
+//
+// fragment = *( pchar / "/" / "?" )
+//
+// pct-encoded = "%" HEXDIG HEXDIG
+//
+// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+// reserved = gen-delims / sub-delims
+// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+// / "*" / "+" / "," / ";" / "="
+
+// use defines for concatenation:
+#define ABNF_sub_delims "!$&'()*+,;="
+#define ABNF_gen_delims ":/?#[]@"
+#define ABNF_pchar ABNF_sub_delims ":@"
+#define ABNF_reserved ABNF_sub_delims ABNF_gen_delims
+
+// list the characters that don't have to be converted according to the list above.
+// "unreserved" is already automatically not encoded, so we don't have to list it.
+// the path component has a complex ABNF that basically boils down to
+// slash-separated segments of "pchar"
+
+static const char userNameExcludeChars[] = ABNF_sub_delims;
+static const char passwordExcludeChars[] = ABNF_sub_delims ":";
+static const char pathExcludeChars[] = ABNF_pchar "/";
+static const char queryExcludeChars[] = ABNF_pchar "/?";
+static const char fragmentExcludeChars[] = ABNF_pchar "/?";
+
+void QUrlPrivate::ensureEncodedParts() const
+{
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
+
+ if (encodedUserName.isNull())
+ // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ that->encodedUserName = toPercentEncodingHelper(userName, userNameExcludeChars);
+ if (encodedPassword.isNull())
+ // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ that->encodedPassword = toPercentEncodingHelper(password, passwordExcludeChars);
+ if (encodedPath.isNull())
+ // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" ... also "/"
+ that->encodedPath = toPercentEncodingHelper(path, pathExcludeChars);
+ if (encodedFragment.isNull())
+ // fragment = *( pchar / "/" / "?" )
+ that->encodedFragment = toPercentEncodingHelper(fragment, fragmentExcludeChars);
+}
+
+QString QUrlPrivate::authority(QUrl::FormattingOptions options) const
+{
+ if ((options & QUrl::RemoveAuthority) == QUrl::RemoveAuthority)
+ return QString();
+
+ QString tmp = userInfo(options);
+ if (!tmp.isEmpty())
+ tmp += QLatin1Char('@');
+ tmp += canonicalHost();
+ if (!(options & QUrl::RemovePort) && port != -1)
+ tmp += QLatin1Char(':') + QString::number(port);
+
+ return tmp;
+}
+
+void QUrlPrivate::setAuthority(const QString &auth)
+{
+ isHostValid = true;
+ if (auth.isEmpty()) {
+ setUserInfo(QString());
+ host.clear();
+ port = -1;
+ return;
+ }
+
+ // find the port section of the authority by searching from the
+ // end towards the beginning for numbers until a ':' is reached.
+ int portIndex = auth.length() - 1;
+ if (portIndex == 0) {
+ portIndex = -1;
+ } else {
+ short c = auth.at(portIndex--).unicode();
+ if (c < '0' || c > '9') {
+ portIndex = -1;
+ } else while (portIndex >= 0) {
+ c = auth.at(portIndex).unicode();
+ if (c == ':') {
+ break;
+ } else if (c == '.') {
+ portIndex = -1;
+ break;
+ }
+ --portIndex;
+ }
+ }
+
+ if (portIndex != -1) {
+ port = 0;
+ for (int i = portIndex + 1; i < auth.length(); ++i)
+ port = (port * 10) + (auth.at(i).unicode() - '0');
+ } else {
+ port = -1;
+ }
+
+ int userInfoIndex = auth.indexOf(QLatin1Char('@'));
+ if (userInfoIndex != -1 && (portIndex == -1 || userInfoIndex < portIndex))
+ setUserInfo(auth.left(userInfoIndex));
+
+ int hostIndex = 0;
+ if (userInfoIndex != -1)
+ hostIndex = userInfoIndex + 1;
+ int hostLength = auth.length() - hostIndex;
+ if (portIndex != -1)
+ hostLength -= (auth.length() - portIndex);
+
+ host = auth.mid(hostIndex, hostLength).trimmed();
+}
+
+void QUrlPrivate::setUserInfo(const QString &userInfo)
+{
+ encodedUserName.clear();
+ encodedPassword.clear();
+
+ int delimIndex = userInfo.indexOf(QLatin1Char(':'));
+ if (delimIndex == -1) {
+ userName = userInfo;
+ password.clear();
+ return;
+ }
+ userName = userInfo.left(delimIndex);
+ password = userInfo.right(userInfo.length() - delimIndex - 1);
+}
+
+void QUrlPrivate::setEncodedUserInfo(const QUrlParseData *parseData)
+{
+ userName.clear();
+ password.clear();
+ if (!parseData->userInfoLength) {
+ encodedUserName.clear();
+ encodedPassword.clear();
+ } else if (parseData->userInfoDelimIndex == -1) {
+ encodedUserName = QByteArray(parseData->userInfo, parseData->userInfoLength);
+ encodedPassword.clear();
+ } else {
+ encodedUserName = QByteArray(parseData->userInfo, parseData->userInfoDelimIndex);
+ encodedPassword = QByteArray(parseData->userInfo + parseData->userInfoDelimIndex + 1,
+ parseData->userInfoLength - parseData->userInfoDelimIndex - 1);
+ }
+}
+
+QString QUrlPrivate::userInfo(QUrl::FormattingOptions options) const
+{
+ if ((options & QUrl::RemoveUserInfo) == QUrl::RemoveUserInfo)
+ return QString();
+
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
+ if (userName.isNull())
+ that->userName = fromPercentEncodingHelper(encodedUserName);
+ if (password.isNull())
+ that->password = fromPercentEncodingHelper(encodedPassword);
+
+ QString tmp = userName;
+
+ if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
+ tmp += QLatin1Char(':');
+ tmp += password;
+ }
+
+ return tmp;
+}
+
+/*
+ From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths
+
+ Returns a merge of the current path with the relative path passed
+ as argument.
+*/
+QByteArray QUrlPrivate::mergePaths(const QByteArray &relativePath) const
+{
+ if (encodedPath.isNull())
+ ensureEncodedParts();
+
+ // If the base URI has a defined authority component and an empty
+ // path, then return a string consisting of "/" concatenated with
+ // the reference's path; otherwise,
+ if (!authority().isEmpty() && encodedPath.isEmpty())
+ return '/' + relativePath;
+
+ // Return a string consisting of the reference's path component
+ // appended to all but the last segment of the base URI's path
+ // (i.e., excluding any characters after the right-most "/" in the
+ // base URI path, or excluding the entire base URI path if it does
+ // not contain any "/" characters).
+ QByteArray newPath;
+ if (!encodedPath.contains('/'))
+ newPath = relativePath;
+ else
+ newPath = encodedPath.left(encodedPath.lastIndexOf('/') + 1) + relativePath;
+
+ return newPath;
+}
+
+void QUrlPrivate::queryItem(int pos, int *value, int *end)
+{
+ *end = query.indexOf(pairDelimiter, pos);
+ if (*end == -1)
+ *end = query.size();
+ *value = pos;
+ while (*value < *end) {
+ if (query[*value] == valueDelimiter)
+ break;
+ ++*value;
+ }
+}
+
+/*
+ From http://www.ietf.org/rfc/rfc3986.txt, 5.2.4: Remove dot segments
+
+ Removes unnecessary ../ and ./ from the path. Used for normalizing
+ the URL.
+*/
+static void removeDotsFromPath(QByteArray *path)
+{
+ // The input buffer is initialized with the now-appended path
+ // components and the output buffer is initialized to the empty
+ // string.
+ char *out = path->data();
+ const char *in = out;
+ const char *end = out + path->size();
+
+ // If the input buffer consists only of
+ // "." or "..", then remove that from the input
+ // buffer;
+ if (path->size() == 1 && in[0] == '.')
+ ++in;
+ else if (path->size() == 2 && in[0] == '.' && in[1] == '.')
+ in += 2;
+ // While the input buffer is not empty, loop:
+ while (in < end) {
+
+ // otherwise, if the input buffer begins with a prefix of "../" or "./",
+ // then remove that prefix from the input buffer;
+ if (path->size() >= 2 && in[0] == '.' && in[1] == '/')
+ in += 2;
+ else if (path->size() >= 3 && in[0] == '.' && in[1] == '.' && in[2] == '/')
+ in += 3;
+
+ // otherwise, if the input buffer begins with a prefix of
+ // "/./" or "/.", where "." is a complete path segment,
+ // then replace that prefix with "/" in the input buffer;
+ if (in <= end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '/') {
+ in += 2;
+ continue;
+ } else if (in == end - 2 && in[0] == '/' && in[1] == '.') {
+ *out++ = '/';
+ in += 2;
+ break;
+ }
+
+ // otherwise, if the input buffer begins with a prefix
+ // of "/../" or "/..", where ".." is a complete path
+ // segment, then replace that prefix with "/" in the
+ // input buffer and remove the last //segment and its
+ // preceding "/" (if any) from the output buffer;
+ if (in <= end - 4 && in[0] == '/' && in[1] == '.' && in[2] == '.' && in[3] == '/') {
+ while (out > path->constData() && *(--out) != '/')
+ ;
+ if (out == path->constData() && *out != '/')
+ ++in;
+ in += 3;
+ continue;
+ } else if (in == end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '.') {
+ while (out > path->constData() && *(--out) != '/')
+ ;
+ if (*out == '/')
+ ++out;
+ in += 3;
+ break;
+ }
+
+ // otherwise move the first path segment in
+ // the input buffer to the end of the output
+ // buffer, including the initial "/" character
+ // (if any) and any subsequent characters up
+ // to, but not including, the next "/"
+ // character or the end of the input buffer.
+ *out++ = *in++;
+ while (in < end && *in != '/')
+ *out++ = *in++;
+ }
+ path->truncate(out - path->constData());
+}
+
+void QUrlPrivate::validate() const
+{
+ QUrlPrivate *that = (QUrlPrivate *)this;
+ that->encodedOriginal = that->toEncoded(); // may detach
+ parse(ParseOnly);
+
+ QURL_SETFLAG(that->stateFlags, Validated);
+
+ if (!isValid)
+ return;
+
+ QString auth = authority(); // causes the non-encoded forms to be valid
+
+ // authority() calls canonicalHost() which sets this
+ if (!isHostValid)
+ return;
+
+ if (scheme == QLatin1String("mailto")) {
+ if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) {
+ that->isValid = false;
+ that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "expected empty host, username,"
+ "port and password"),
+ 0, 0);
+ }
+ } else if (scheme == QLatin1String("ftp") || scheme == QLatin1String("http")) {
+ if (host.isEmpty() && !(path.isEmpty() && encodedPath.isEmpty())) {
+ that->isValid = false;
+ that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "the host is empty, but not the path"),
+ 0, 0);
+ }
+ }
+}
+
+void QUrlPrivate::parse(ParseOptions parseOptions) const
+{
+ QUrlPrivate *that = (QUrlPrivate *)this;
+ that->errorInfo.setParams(0, 0, 0, 0);
+ if (encodedOriginal.isEmpty()) {
+ that->isValid = false;
+ that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "empty"),
+ 0, 0);
+ QURL_SETFLAG(that->stateFlags, Validated | Parsed);
+ return;
+ }
+
+
+ QUrlParseData parseData;
+ memset(&parseData, 0, sizeof(parseData));
+ parseData.userInfoDelimIndex = -1;
+ parseData.port = -1;
+
+ const char *pptr = (char *) encodedOriginal.constData();
+ const char **ptr = &pptr;
+
+#if defined (QURL_DEBUG)
+ qDebug("QUrlPrivate::parse(), parsing \"%s\"", pptr);
+#endif
+
+ // optional scheme
+ bool isSchemeValid = _scheme(ptr, &parseData);
+
+ if (isSchemeValid == false) {
+ that->isValid = false;
+ char ch = *((*ptr)++);
+ that->errorInfo.setParams(*ptr, QT_TRANSLATE_NOOP(QUrl, "unexpected URL scheme"),
+ 0, ch);
+ QURL_SETFLAG(that->stateFlags, Validated | Parsed);
+#if defined (QURL_DEBUG)
+ qDebug("QUrlPrivate::parse(), unrecognized: %c%s", ch, *ptr);
+#endif
+ return;
+ }
+
+ // hierpart
+ _hierPart(ptr, &parseData);
+
+ // optional query
+ char ch = *((*ptr)++);
+ if (ch == '?') {
+ that->hasQuery = true;
+ _query(ptr, &parseData);
+ ch = *((*ptr)++);
+ }
+
+ // optional fragment
+ if (ch == '#') {
+ that->hasFragment = true;
+ _fragment(ptr, &parseData);
+ } else if (ch != '\0') {
+ that->isValid = false;
+ that->errorInfo.setParams(*ptr, QT_TRANSLATE_NOOP(QUrl, "expected end of URL"),
+ 0, ch);
+ QURL_SETFLAG(that->stateFlags, Validated | Parsed);
+#if defined (QURL_DEBUG)
+ qDebug("QUrlPrivate::parse(), unrecognized: %c%s", ch, *ptr);
+#endif
+ return;
+ }
+
+ // when doing lazy validation, this function is called after
+ // encodedOriginal has been constructed from the individual parts,
+ // only to see if the constructed URL can be parsed. in that case,
+ // parse() is called in ParseOnly mode; we don't want to set all
+ // the members over again.
+ if (parseOptions == ParseAndSet) {
+ QURL_UNSETFLAG(that->stateFlags, HostCanonicalized);
+
+ if (parseData.scheme) {
+ QByteArray s(parseData.scheme, parseData.schemeLength);
+ that->scheme = fromPercentEncodingMutable(&s);
+ }
+
+ that->setEncodedUserInfo(&parseData);
+
+ QByteArray h(parseData.host, parseData.hostLength);
+ that->host = fromPercentEncodingMutable(&h);
+ that->port = parseData.port;
+
+ that->path.clear();
+ that->encodedPath = QByteArray(parseData.path, parseData.pathLength);
+
+ if (that->hasQuery)
+ that->query = QByteArray(parseData.query, parseData.queryLength);
+ else
+ that->query.clear();
+
+ that->fragment.clear();
+ if (that->hasFragment) {
+ that->encodedFragment = QByteArray(parseData.fragment, parseData.fragmentLength);
+ } else {
+ that->encodedFragment.clear();
+ }
+ }
+
+ that->isValid = true;
+ QURL_SETFLAG(that->stateFlags, Parsed);
+
+#if defined (QURL_DEBUG)
+ qDebug("QUrl::setUrl(), scheme = %s", that->scheme.toLatin1().constData());
+ qDebug("QUrl::setUrl(), userInfo = %s", that->userInfo.toLatin1().constData());
+ qDebug("QUrl::setUrl(), host = %s", that->host.toLatin1().constData());
+ qDebug("QUrl::setUrl(), port = %i", that->port);
+ qDebug("QUrl::setUrl(), path = %s", fromPercentEncodingHelper(__path).toLatin1().constData());
+ qDebug("QUrl::setUrl(), query = %s", __query.constData());
+ qDebug("QUrl::setUrl(), fragment = %s", fromPercentEncodingHelper(__fragment).toLatin1().constData());
+#endif
+}
+
+void QUrlPrivate::clear()
+{
+ scheme.clear();
+ userName.clear();
+ password.clear();
+ host.clear();
+ port = -1;
+ path.clear();
+ query.clear();
+ fragment.clear();
+
+ encodedOriginal.clear();
+ encodedUserName.clear();
+ encodedPassword.clear();
+ encodedPath.clear();
+ encodedFragment.clear();
+ encodedNormalized.clear();
+
+ isValid = false;
+ hasQuery = false;
+ hasFragment = false;
+
+ valueDelimiter = '=';
+ pairDelimiter = '&';
+
+ QURL_UNSETFLAG(stateFlags, Parsed | Validated | Normalized | HostCanonicalized);
+}
+
+QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const
+{
+ if (!QURL_HASFLAG(stateFlags, Parsed)) parse();
+ else ensureEncodedParts();
+
+ if (options==0x100) // private - see qHash(QUrl)
+ return normalized();
+
+ QByteArray url;
+
+ if (!(options & QUrl::RemoveScheme) && !scheme.isEmpty()) {
+ url += scheme.toLatin1();
+ url += ':';
+ }
+ QString savedHost = host; // pre-validation, may be invalid!
+ QString auth = authority();
+ bool doFileScheme = scheme == QLatin1String("file") && encodedPath.startsWith('/');
+ if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority && (!auth.isEmpty() || doFileScheme || !savedHost.isEmpty())) {
+ if (doFileScheme && !encodedPath.startsWith('/'))
+ url += '/';
+ url += "//";
+
+ if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) {
+ bool hasUserOrPass = false;
+ if (!userName.isEmpty()) {
+ url += encodedUserName;
+ hasUserOrPass = true;
+ }
+ if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
+ url += ':';
+ url += encodedPassword;
+ hasUserOrPass = true;
+ }
+ if (hasUserOrPass)
+ url += '@';
+ }
+
+ if (host.startsWith(QLatin1Char('['))) {
+ url += host.toLatin1();
+ } else if (host.contains(QLatin1Char(':'))) {
+ url += '[';
+ url += host.toLatin1();
+ url += ']';
+ } else if (host.isEmpty() && !savedHost.isEmpty()) {
+ // this case is only possible with an invalid URL
+ // it's here only so that we can keep the original, invalid hostname
+ // in encodedOriginal.
+ // QUrl::isValid() will return false, so toEncoded() can be anything (it's not valid)
+ url += savedHost.toUtf8();
+ } else {
+ url += QUrl::toAce(host);
+ }
+ if (!(options & QUrl::RemovePort) && port != -1) {
+ url += ':';
+ url += QString::number(port).toAscii();
+ }
+ }
+
+ if (!(options & QUrl::RemovePath)) {
+ // check if we need to insert a slash
+ if (!encodedPath.isEmpty() && !auth.isEmpty()) {
+ if (!encodedPath.startsWith('/'))
+ url += '/';
+ }
+ url += encodedPath;
+
+ // check if we need to remove trailing slashes
+ while ((options & QUrl::StripTrailingSlash) && url.endsWith('/'))
+ url.chop(1);
+ }
+
+ if (!(options & QUrl::RemoveQuery) && hasQuery) {
+ url += '?';
+ url += query;
+ }
+ if (!(options & QUrl::RemoveFragment) && hasFragment) {
+ url += '#';
+ url += encodedFragment;
+ }
+
+ return url;
+}
+
+#define qToLower(ch) (((ch|32) >= 'a' && (ch|32) <= 'z') ? (ch|32) : ch)
+
+const QByteArray &QUrlPrivate::normalized() const
+{
+ if (QURL_HASFLAG(stateFlags, QUrlPrivate::Normalized))
+ return encodedNormalized;
+
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
+ QURL_SETFLAG(that->stateFlags, QUrlPrivate::Normalized);
+
+ QUrlPrivate tmp = *this;
+ tmp.scheme = tmp.scheme.toLower();
+ tmp.host = tmp.canonicalHost();
+
+ // ensure the encoded and normalized parts of the URL
+ tmp.ensureEncodedParts();
+ if (tmp.encodedUserName.contains('%'))
+ q_normalizePercentEncoding(&tmp.encodedUserName, userNameExcludeChars);
+ if (tmp.encodedPassword.contains('%'))
+ q_normalizePercentEncoding(&tmp.encodedPassword, passwordExcludeChars);
+ if (tmp.encodedFragment.contains('%'))
+ q_normalizePercentEncoding(&tmp.encodedFragment, fragmentExcludeChars);
+
+ if (tmp.encodedPath.contains('%')) {
+ // the path is a bit special:
+ // the slashes shouldn't be encoded or decoded.
+ // They should remain exactly like they are right now
+ //
+ // treat the path as a slash-separated sequence of pchar
+ QByteArray result;
+ result.reserve(tmp.encodedPath.length());
+ if (tmp.encodedPath.startsWith('/'))
+ result.append('/');
+
+ const char *data = tmp.encodedPath.constData();
+ int lastSlash = 0;
+ int nextSlash;
+ do {
+ ++lastSlash;
+ nextSlash = tmp.encodedPath.indexOf('/', lastSlash);
+ int len;
+ if (nextSlash == -1)
+ len = tmp.encodedPath.length() - lastSlash;
+ else
+ len = nextSlash - lastSlash;
+
+ if (memchr(data + lastSlash, '%', len)) {
+ // there's at least one percent before the next slash
+ QByteArray block = QByteArray(data + lastSlash, len);
+ q_normalizePercentEncoding(&block, pathExcludeChars);
+ result.append(block);
+ } else {
+ // no percents in this path segment, append wholesale
+ result.append(data + lastSlash, len);
+ }
+
+ // append the slash too, if it's there
+ if (nextSlash != -1)
+ result.append('/');
+
+ lastSlash = nextSlash;
+ } while (lastSlash != -1);
+
+ tmp.encodedPath = result;
+ }
+
+ if (!tmp.scheme.isEmpty()) // relative test
+ removeDotsFromPath(&tmp.encodedPath);
+
+ int qLen = tmp.query.length();
+ for (int i = 0; i < qLen; i++) {
+ if (qLen - i > 2 && tmp.query.at(i) == '%') {
+ ++i;
+ tmp.query[i] = qToLower(tmp.query.at(i));
+ ++i;
+ tmp.query[i] = qToLower(tmp.query.at(i));
+ }
+ }
+ encodedNormalized = tmp.toEncoded();
+
+ return encodedNormalized;
+}
+
+QString QUrlPrivate::createErrorString()
+{
+ if (isValid && isHostValid)
+ return QString();
+
+ QString errorString(QLatin1String(QT_TRANSLATE_NOOP(QUrl, "Invalid URL \"")));
+ errorString += QLatin1String(encodedOriginal.constData());
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\""));
+
+ if (errorInfo._source) {
+ int position = encodedOriginal.indexOf(errorInfo._source) - 1;
+ if (position > 0) {
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": error at position "));
+ errorString += QString::number(position);
+ } else {
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": "));
+ errorString += QLatin1String(errorInfo._source);
+ }
+ }
+
+ if (errorInfo._expected) {
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": expected \'"));
+ errorString += QLatin1Char(errorInfo._expected);
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\'"));
+ } else {
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": "));
+ if (isHostValid)
+ errorString += QLatin1String(errorInfo._message);
+ else
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "invalid hostname"));
+ }
+ if (errorInfo._found) {
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ", but found \'"));
+ errorString += QLatin1Char(errorInfo._found);
+ errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\'"));
+ }
+ return errorString;
+}
+
+/*!
+ \macro QT_NO_URL_CAST_FROM_STRING
+ \relates QUrl
+
+ Disables automatic conversions from QString (or char *) to QUrl.
+
+ Compiling your code with this define is useful when you have a lot of
+ code that uses QString for file names and you wish to convert it to
+ use QUrl for network transparency. In any code that uses QUrl, it can
+ help avoid missing QUrl::resolved() calls, and other misuses of
+ QString to QUrl conversions.
+
+ \oldcode
+ url = filename; // probably not what you want
+ \newcode
+ url = QUrl::fromLocalFile(filename);
+ url = baseurl.resolved(QUrl(filename));
+ \endcode
+
+ \sa QT_NO_CAST_FROM_ASCII
+*/
+
+
+/*!
+ Constructs a URL by parsing \a url. \a url is assumed to be in human
+ readable representation, with no percent encoding. QUrl will automatically
+ percent encode all characters that are not allowed in a URL.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 0
+
+ To construct a URL from an encoded string, call fromEncoded():
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 1
+
+ \sa setUrl(), setEncodedUrl(), fromEncoded(), TolerantMode
+*/
+QUrl::QUrl(const QString &url) : d(0)
+{
+ if (!url.isEmpty())
+ setUrl(url);
+}
+
+/*!
+ \overload
+
+ Parses the \a url using the parser mode \a parsingMode.
+
+ \sa setUrl()
+*/
+QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d(0)
+{
+ if (!url.isEmpty())
+ setUrl(url, parsingMode);
+ else {
+ d = new QUrlPrivate;
+ d->parsingMode = parsingMode;
+ }
+}
+
+/*!
+ Constructs an empty QUrl object.
+*/
+QUrl::QUrl() : d(0)
+{
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+QUrl::QUrl(const QUrl &other) : d(other.d)
+{
+ if (d)
+ d->ref.ref();
+}
+
+/*!
+ Destructor; called immediately before the object is deleted.
+*/
+QUrl::~QUrl()
+{
+ if (d && !d->ref.deref())
+ delete d;
+}
+
+/*!
+ Returns true if the URL is valid; otherwise returns false.
+
+ The URL is run through a conformance test. Every part of the URL
+ must conform to the standard encoding rules of the URI standard
+ for the URL to be reported as valid.
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 2
+*/
+bool QUrl::isValid() const
+{
+ if (!d) return false;
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate();
+
+ return d->isValid && d->isHostValid;
+}
+
+/*!
+ Returns true if the URL has no data; otherwise returns false.
+*/
+bool QUrl::isEmpty() const
+{
+ if (!d) return true;
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed))
+ return d->encodedOriginal.isEmpty();
+ else
+ return d->scheme.isEmpty() // no encodedScheme
+ && d->userName.isEmpty() && d->encodedUserName.isEmpty()
+ && d->password.isEmpty() && d->encodedPassword.isEmpty()
+ && d->host.isEmpty() // no encodedHost
+ && d->port == -1
+ && d->path.isEmpty() && d->encodedPath.isEmpty()
+ && d->query.isEmpty()
+ && d->fragment.isEmpty() && d->encodedFragment.isEmpty();
+}
+
+/*!
+ Resets the content of the QUrl. After calling this function, the
+ QUrl is equal to one that has been constructed with the default
+ empty constructor.
+*/
+void QUrl::clear()
+{
+ if (d && !d->ref.deref())
+ delete d;
+ d = 0;
+}
+
+/*!
+ Constructs a URL by parsing the contents of \a url.
+
+ \a url is assumed to be in unicode format, with no percent
+ encoding.
+
+ Calling isValid() will tell whether or not a valid URL was
+ constructed.
+
+ \sa setEncodedUrl()
+*/
+void QUrl::setUrl(const QString &url)
+{
+ setUrl(url, TolerantMode);
+}
+
+/*!
+ \overload
+
+ Parses \a url using the parsing mode \a parsingMode.
+
+ \sa setEncodedUrl()
+*/
+void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
+{
+ detach();
+ // escape all reserved characters and delimiters
+ // reserved = gen-delims / sub-delims
+ if (parsingMode != TolerantMode) {
+ setEncodedUrl(toPercentEncodingHelper(url, ABNF_reserved), parsingMode);
+ return;
+ }
+
+ // Tolerant preprocessing
+ QString tmp = url;
+
+ // Allow %20 in the QString variant
+ tmp.replace(QLatin1String("%20"), QLatin1String(" "));
+
+ // Percent-encode unsafe ASCII characters after host part
+ int start = tmp.indexOf(QLatin1String("//"));
+ if (start != -1) {
+ // Has host part, find delimiter
+ start += 2; // skip "//"
+ const char delims[] = "/#?";
+ const char *d = delims;
+ int hostEnd = -1;
+ while (*d && (hostEnd = tmp.indexOf(QLatin1Char(*d), start)) == -1)
+ ++d;
+ start = (hostEnd == -1) ? -1 : hostEnd + 1;
+ } else {
+ start = 0; // Has no host part
+ }
+ QByteArray encodedUrl;
+ if (start != -1) {
+ QString hostPart = tmp.left(start);
+ QString otherPart = tmp.mid(start);
+ encodedUrl = toPercentEncodingHelper(hostPart, ":/?#[]@!$&'()*+,;=")
+ + toPercentEncodingHelper(otherPart, ":/?#@!$&'()*+,;=");
+ } else {
+ encodedUrl = toPercentEncodingHelper(tmp, ABNF_reserved);
+ }
+ setEncodedUrl(encodedUrl, StrictMode);
+}
+
+/*!
+ 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.
+
+ Use isValid() to determine if a valid URL was constructed.
+
+ \sa setUrl()
+*/
+void QUrl::setEncodedUrl(const QByteArray &encodedUrl)
+{
+ setEncodedUrl(encodedUrl, TolerantMode);
+}
+
+inline static bool isHex(char c)
+{
+ c |= 0x20;
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
+}
+
+static inline char toHex(quint8 c)
+{
+ return c > 9 ? c - 10 + 'A' : c + '0';
+}
+
+/*!
+ Constructs a URL by parsing the contents of \a encodedUrl using
+ the given \a parsingMode.
+*/
+void QUrl::setEncodedUrl(const QByteArray &encodedUrl, ParsingMode parsingMode)
+{
+ QByteArray tmp = encodedUrl;
+ if (!d) d = new QUrlPrivate;
+ else d->clear();
+ if ((d->parsingMode = parsingMode) == TolerantMode) {
+ // Replace stray % with %25
+ QByteArray copy = tmp;
+ for (int i = 0, j = 0; i < copy.size(); ++i, ++j) {
+ if (copy.at(i) == '%') {
+ if (i + 2 >= copy.size() || !isHex(copy.at(i + 1)) || !isHex(copy.at(i + 2))) {
+ tmp.replace(j, 1, "%25");
+ j += 2;
+ }
+ }
+ }
+
+ // Find the host part
+ int hostStart = tmp.indexOf("//");
+ int hostEnd = -1;
+ if (hostStart != -1) {
+ // Has host part, find delimiter
+ hostStart += 2; // skip "//"
+ hostEnd = tmp.indexOf('/', hostStart);
+ if (hostEnd == -1)
+ hostEnd = tmp.indexOf('#', hostStart);
+ if (hostEnd == -1)
+ hostEnd = tmp.indexOf('?');
+ if (hostEnd == -1)
+ hostEnd = tmp.length() - 1;
+ }
+
+ // Reserved and unreserved characters are fine
+// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+// reserved = gen-delims / sub-delims
+// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+// / "*" / "+" / "," / ";" / "="
+ // Replace everything else with percent encoding
+ static const char doEncode[] = " \"<>[\\]^`{|}";
+ static const char doEncodeHost[] = " \"<>\\^`{|}";
+ for (int i = 0; i < tmp.size(); ++i) {
+ quint8 c = quint8(tmp.at(i));
+ if (c < 32 || c > 127 ||
+ strchr(hostStart <= i && i <= hostEnd ? doEncodeHost : doEncode, c)) {
+ char buf[4];
+ buf[0] = '%';
+ buf[1] = toHex(c >> 4);
+ buf[2] = toHex(c & 0xf);
+ buf[3] = '\0';
+ tmp.replace(i, 1, buf);
+ i += 2;
+ }
+ }
+ }
+
+ d->encodedOriginal = tmp;
+}
+
+/*!
+ Sets the scheme of the URL to \a scheme. As a scheme can only
+ contain ASCII characters, no conversion or encoding is done on the
+ input.
+
+ The scheme describes the type (or protocol) of the URL. It's
+ represented by one or more ASCII characters at the start the URL,
+ and is followed by a ':'. The following example shows a URL where
+ the scheme is "ftp":
+
+ \img qurl-authority2.png
+
+ The scheme can also be empty, in which case the URL is interpreted
+ as relative.
+
+ \sa scheme(), isRelative()
+*/
+void QUrl::setScheme(const QString &scheme)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->scheme = scheme;
+}
+
+/*!
+ Returns the scheme of the URL. If an empty string is returned,
+ this means the scheme is undefined and the URL is then relative.
+
+ \sa setScheme(), isRelative()
+*/
+QString QUrl::scheme() const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->scheme;
+}
+
+/*!
+ Sets the authority of the URL to \a authority.
+
+ The authority of a URL is the combination of user info, a host
+ name and a port. All of these elements are optional; an empty
+ authority is therefore valid.
+
+ The user info and host are separated by a '@', and the host and
+ port are separated by a ':'. If the user info is empty, the '@'
+ must be omitted; although a stray ':' is permitted if the port is
+ empty.
+
+ The following example shows a valid authority string:
+
+ \img qurl-authority.png
+*/
+void QUrl::setAuthority(const QString &authority)
+{
+ if (!d) d = new QUrlPrivate;
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized);
+ d->setAuthority(authority);
+}
+
+/*!
+ Returns the authority of the URL if it is defined; otherwise
+ an empty string is returned.
+
+ \sa setAuthority()
+*/
+QString QUrl::authority() const
+{
+ if (!d) return QString();
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->authority();
+}
+
+/*!
+ Sets the user info of the URL to \a userInfo. The user info is an
+ optional part of the authority of the URL, as described in
+ setAuthority().
+
+ The user info consists of a user name and optionally a password,
+ separated by a ':'. If the password is empty, the colon must be
+ omitted. The following example shows a valid user info string:
+
+ \img qurl-authority3.png
+
+ \sa userInfo(), setUserName(), setPassword(), setAuthority()
+*/
+void QUrl::setUserInfo(const QString &userInfo)
+{
+ if (!d) d = new QUrlPrivate;
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->setUserInfo(userInfo.trimmed());
+}
+
+/*!
+ Returns the user info of the URL, or an empty string if the user
+ info is undefined.
+*/
+QString QUrl::userInfo() const
+{
+ if (!d) return QString();
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->userInfo();
+}
+
+/*!
+ Sets the URL's user name to \a userName. The \a userName is part
+ of the user info element in the authority of the URL, as described
+ in setUserInfo().
+
+ \sa setEncodedUserName(), userName(), setUserInfo()
+*/
+void QUrl::setUserName(const QString &userName)
+{
+ if (!d) d = new QUrlPrivate;
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->userName = userName;
+ d->encodedUserName.clear();
+}
+
+/*!
+ Returns the user name of the URL if it is defined; otherwise
+ an empty string is returned.
+
+ \sa setUserName(), encodedUserName()
+*/
+QString QUrl::userName() const
+{
+ if (!d) return QString();
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->userInfo(); // causes the unencoded form to be set
+ return d->userName;
+}
+
+/*!
+ \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().
+
+ Note: this function does not verify that \a userName is properly
+ encoded. It is the caller's responsibility to ensure that the any
+ delimiters (such as colons or slashes) are properly encoded.
+
+ \sa setUserName(), encodedUserName(), setUserInfo()
+*/
+void QUrl::setEncodedUserName(const QByteArray &userName)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->encodedUserName = userName;
+ d->userName.clear();
+}
+
+/*!
+ \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().
+
+ \sa setEncodedUserName()
+*/
+QByteArray QUrl::encodedUserName() const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->ensureEncodedParts();
+ return d->encodedUserName;
+}
+
+/*!
+ 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().
+
+ \sa password(), setUserInfo()
+*/
+void QUrl::setPassword(const QString &password)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->password = password;
+ d->encodedPassword.clear();
+}
+
+/*!
+ Returns the password of the URL if it is defined; otherwise
+ an empty string is returned.
+
+ \sa setPassword()
+*/
+QString QUrl::password() const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->userInfo(); // causes the unencoded form to be set
+ return d->password;
+}
+
+/*!
+ \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().
+
+ Note: this function does not verify that \a password is properly
+ encoded. It is the caller's responsibility to ensure that the any
+ delimiters (such as colons or slashes) are properly encoded.
+
+ \sa setPassword(), encodedPassword(), setUserInfo()
+*/
+void QUrl::setEncodedPassword(const QByteArray &password)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->encodedPassword = password;
+ d->password.clear();
+}
+
+/*!
+ \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().
+
+ \sa setEncodedPassword(), toEncoded()
+*/
+QByteArray QUrl::encodedPassword() const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->ensureEncodedParts();
+ return d->encodedPassword;
+}
+
+/*!
+ Sets the host of the URL to \a host. The host is part of the
+ authority.
+
+ \sa host(), setAuthority()
+*/
+void QUrl::setHost(const QString &host)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ d->isHostValid = true;
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized);
+
+ d->host = host;
+}
+
+/*!
+ Returns the host of the URL if it is defined; otherwise
+ an empty string is returned.
+*/
+QString QUrl::host() const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ if (d->host.isEmpty() || d->host.at(0) != QLatin1Char('['))
+ return d->canonicalHost();
+ QString tmp = d->host.mid(1);
+ tmp.truncate(tmp.length() - 1);
+ return tmp;
+}
+
+/*!
+ \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().
+
+ \sa setHost(), encodedHost(), setAuthority(), fromAce()
+*/
+void QUrl::setEncodedHost(const QByteArray &host)
+{
+ setHost(fromPercentEncodingHelper(host));
+}
+
+/*!
+ \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().
+
+ \sa setEncodedHost()
+*/
+QByteArray QUrl::encodedHost() const
+{
+ // should we cache this in d->encodedHost?
+ return QUrl::toAce(host());
+}
+
+/*!
+ Sets the port of the URL to \a port. The port is part of the
+ authority of the URL, as described in setAuthority().
+
+ \a port must be between 0 and 65535 inclusive. Setting the
+ port to -1 indicates that the port is unspecified.
+*/
+void QUrl::setPort(int port)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ if (port < -1 || port > 65535) {
+ qWarning("QUrl::setPort: Out of range");
+ port = -1;
+ }
+
+ d->port = port;
+}
+
+/*!
+ Returns the port of the URL, or -1 if the port is unspecified.
+*/
+int QUrl::port() const
+{
+ if (!d) return -1;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate();
+ return d->port;
+}
+
+/*!
+ \overload
+ \since 4.1
+
+ Returns the port of the URL, or \a defaultPort if the port is
+ unspecified.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 3
+*/
+int QUrl::port(int defaultPort) const
+{
+ if (!d) return defaultPort;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ return d->port == -1 ? defaultPort : d->port;
+}
+
+/*!
+ Sets the path of the URL to \a path. The path is the part of the
+ URL that comes after the authority but before the query string.
+
+ \img qurl-ftppath.png
+
+ For non-hierarchical schemes, the path will be everything
+ following the scheme declaration, as in the following example:
+
+ \img qurl-mailtopath.png
+
+ \sa path()
+*/
+void QUrl::setPath(const QString &path)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->path = path;
+ d->encodedPath.clear();
+}
+
+/*!
+ Returns the path of the URL.
+
+ \sa setPath()
+*/
+QString QUrl::path() const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ if (d->path.isNull()) {
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(d);
+ that->path = fromPercentEncodingHelper(d->encodedPath);
+ }
+ return d->path;
+}
+
+/*!
+ \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.
+
+ \img qurl-ftppath.png
+
+ For non-hierarchical schemes, the path will be everything
+ following the scheme declaration, as in the following example:
+
+ \img qurl-mailtopath.png
+
+ Note: this function does not verify that \a path is properly
+ encoded. It is the caller's responsibility to ensure that the any
+ delimiters (such as '?' and '#') are properly encoded.
+
+ \sa setPath(), encodedPath(), setUserInfo()
+*/
+void QUrl::setEncodedPath(const QByteArray &path)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->encodedPath = path;
+ d->path.clear();
+}
+
+/*!
+ \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().
+
+ \sa setEncodedPath(), toEncoded()
+*/
+QByteArray QUrl::encodedPath() const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->ensureEncodedParts();
+ return d->encodedPath;
+}
+
+/*!
+ \since 4.2
+
+ Returns true if this URL contains a Query (i.e., if ? was seen on it).
+
+ \sa hasQueryItem(), encodedQuery()
+*/
+bool QUrl::hasQuery() const
+{
+ if (!d) return false;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->hasQuery;
+}
+
+/*!
+ Sets the characters used for delimiting between keys and values,
+ and between key-value pairs in the URL's query string. The default
+ value delimiter is '=' and the default pair delimiter is '&'.
+
+ \img qurl-querystring.png
+
+ \a valueDelimiter will be used for separating keys from values,
+ and \a pairDelimiter will be used to separate key-value pairs.
+ Any occurrences of these delimiting characters in the encoded
+ representation of the keys and values of the query string are
+ percent encoded.
+
+ If \a valueDelimiter is set to '-' and \a pairDelimiter is '/',
+ the above query string would instead be represented like this:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 4
+
+ Calling this function does not change the delimiters of the
+ current query string. It only affects queryItems(),
+ setQueryItems() and addQueryItems().
+*/
+void QUrl::setQueryDelimiters(char valueDelimiter, char pairDelimiter)
+{
+ if (!d) d = new QUrlPrivate;
+ detach();
+
+ d->valueDelimiter = valueDelimiter;
+ d->pairDelimiter = pairDelimiter;
+}
+
+/*!
+ Returns the character used to delimit between key-value pairs in
+ the query string of the URL.
+*/
+char QUrl::queryPairDelimiter() const
+{
+ if (!d) return '&';
+ return d->pairDelimiter;
+}
+
+/*!
+ Returns the character used to delimit between keys and values in
+ the query string of the URL.
+*/
+char QUrl::queryValueDelimiter() const
+{
+ if (!d) return '=';
+ return d->valueDelimiter;
+}
+
+/*!
+ 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 "?".
+
+ \sa encodedQuery(), hasQuery()
+*/
+void QUrl::setEncodedQuery(const QByteArray &query)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->query = query;
+ d->hasQuery = !query.isNull();
+}
+
+/*!
+ 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
+ pairDelimiter(), and the key and value are delimited by
+ valueDelimiter().
+
+ \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.
+
+ \sa setQueryDelimiters(), queryItems(), setEncodedQueryItems()
+*/
+void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ char alsoEncode[3];
+ alsoEncode[0] = d->valueDelimiter;
+ alsoEncode[1] = d->pairDelimiter;
+ alsoEncode[2] = 0;
+
+ QByteArray queryTmp;
+ for (int i = 0; i < query.size(); i++) {
+ if (i) queryTmp += d->pairDelimiter;
+ // query = *( pchar / "/" / "?" )
+ queryTmp += toPercentEncodingHelper(query.at(i).first, queryExcludeChars, alsoEncode);
+ queryTmp += d->valueDelimiter;
+ // query = *( pchar / "/" / "?" )
+ queryTmp += toPercentEncodingHelper(query.at(i).second, queryExcludeChars, alsoEncode);
+ }
+
+ d->query = queryTmp;
+ d->hasQuery = !query.isEmpty();
+}
+
+/*!
+ \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
+ pairDelimiter(), and the key and value are delimited by
+ valueDelimiter().
+
+ Note: this function does not verify that the key-value pairs
+ are properly encoded. It is the caller's responsibility to ensure
+ that the query delimiters are properly encoded, if any.
+
+ \sa setQueryDelimiters(), encodedQueryItems(), setQueryItems()
+*/
+void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ QByteArray queryTmp;
+ for (int i = 0; i < query.size(); i++) {
+ if (i) queryTmp += d->pairDelimiter;
+ queryTmp += query.at(i).first;
+ queryTmp += d->valueDelimiter;
+ queryTmp += query.at(i).second;
+ }
+
+ d->query = queryTmp;
+ d->hasQuery = !query.isEmpty();
+}
+
+/*!
+ 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 valueDelimiter(). Each key/value pair is
+ delimited by the character returned by pairDelimiter().
+
+ \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.
+
+ \sa addEncodedQueryItem()
+*/
+void QUrl::addQueryItem(const QString &key, const QString &value)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ char alsoEncode[3];
+ alsoEncode[0] = d->valueDelimiter;
+ alsoEncode[1] = d->pairDelimiter;
+ alsoEncode[2] = 0;
+
+ if (!d->query.isEmpty())
+ d->query += d->pairDelimiter;
+
+ // query = *( pchar / "/" / "?" )
+ d->query += toPercentEncodingHelper(key, queryExcludeChars, alsoEncode);
+ d->query += d->valueDelimiter;
+ // query = *( pchar / "/" / "?" )
+ d->query += toPercentEncodingHelper(value, queryExcludeChars, alsoEncode);
+
+ d->hasQuery = !d->query.isEmpty();
+}
+
+/*!
+ \since 4.4
+
+ Inserts the pair \a key = \a value into the query string of the
+ URL.
+
+ Note: this function does not verify that either \a key or \a value
+ are properly encoded. It is the caller's responsibility to ensure
+ that the query delimiters are properly encoded, if any.
+
+ \sa addQueryItem(), setQueryDelimiters()
+*/
+void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ if (!d->query.isEmpty())
+ d->query += d->pairDelimiter;
+
+ d->query += key;
+ d->query += d->valueDelimiter;
+ d->query += value;
+
+ d->hasQuery = !d->query.isEmpty();
+}
+
+/*!
+ 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.
+
+ \sa setQueryItems(), setEncodedQuery()
+*/
+QList<QPair<QString, QString> > QUrl::queryItems() const
+{
+ if (!d) return QList<QPair<QString, QString> >();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QList<QPair<QString, QString> > itemMap;
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ QByteArray q(query + pos, valuedelim - pos);
+ if (valuedelim < end) {
+ QByteArray v(query + valuedelim + 1, end - valuedelim - 1);
+ itemMap += qMakePair(fromPercentEncodingMutable(&q),
+ fromPercentEncodingMutable(&v));
+ } else {
+ itemMap += qMakePair(fromPercentEncodingMutable(&q), QString());
+ }
+ pos = end + 1;
+ }
+
+ return itemMap;
+}
+
+/*!
+ \since 4.4
+
+ Returns the query string of the URL, as a map of encoded keys and values.
+
+ \sa setEncodedQueryItems(), setQueryItems(), setEncodedQuery()
+*/
+QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
+{
+ if (!d) return QList<QPair<QByteArray, QByteArray> >();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QList<QPair<QByteArray, QByteArray> > itemMap;
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (valuedelim < end)
+ itemMap += qMakePair(QByteArray(query + pos, valuedelim - pos),
+ QByteArray(query + valuedelim + 1, end - valuedelim - 1));
+ else
+ itemMap += qMakePair(QByteArray(query + pos, valuedelim - pos), QByteArray());
+ pos = end + 1;
+ }
+
+ return itemMap;
+}
+
+/*!
+ Returns true if there is a query string pair whose key is equal
+ to \a key from the URL.
+
+ \sa hasEncodedQueryItem()
+*/
+bool QUrl::hasQueryItem(const QString &key) const
+{
+ if (!d) return false;
+ return hasEncodedQueryItem(toPercentEncoding(key, queryExcludeChars));
+}
+
+/*!
+ \since 4.4
+
+ Returns true if there is a query string pair whose key is equal
+ to \a key from the URL.
+
+ Note: if the encoded \a key does not match the encoded version of
+ the query, this function will return false. That is, if the
+ encoded query of this URL is "search=Qt%20Rules", calling this
+ function with \a key = "%73earch" will return false.
+
+ \sa hasQueryItem()
+*/
+bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
+{
+ if (!d) return false;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
+ return true;
+ pos = end + 1;
+ }
+ return false;
+}
+
+/*!
+ 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.
+
+ \sa allQueryItemValues()
+*/
+QString QUrl::queryItemValue(const QString &key) const
+{
+ if (!d) return QString();
+ QByteArray tmp = encodedQueryItemValue(toPercentEncoding(key, queryExcludeChars));
+ return fromPercentEncodingMutable(&tmp);
+}
+
+/*!
+ \since 4.4
+
+ Returns the first query string value whose key is equal to \a key
+ from the URL.
+
+ Note: if the encoded \a key does not match the encoded version of
+ the query, this function will not work. That is, if the
+ encoded query of this URL is "search=Qt%20Rules", calling this
+ function with \a key = "%73earch" will return an empty string.
+
+ \sa queryItemValue(), allQueryItemValues()
+*/
+QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
+ return valuedelim < end ?
+ QByteArray(query + valuedelim + 1, end - valuedelim - 1) : QByteArray();
+ pos = end + 1;
+ }
+ return QByteArray();
+}
+
+/*!
+ 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.
+
+ \sa queryItemValue()
+*/
+QStringList QUrl::allQueryItemValues(const QString &key) const
+{
+ if (!d) return QStringList();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QByteArray encodedKey = toPercentEncoding(key, queryExcludeChars);
+ QStringList values;
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (encodedKey == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
+ QByteArray v(query + valuedelim + 1, end - valuedelim - 1);
+ values += valuedelim < end ?
+ fromPercentEncodingMutable(&v)
+ : QString();
+ }
+ pos = end + 1;
+ }
+
+ return values;
+}
+
+/*!
+ \since 4.4
+
+ Returns the a list of query string values whose key is equal to
+ \a key from the URL.
+
+ Note: if the encoded \a key does not match the encoded version of
+ the query, this function will not work. That is, if the
+ encoded query of this URL is "search=Qt%20Rules", calling this
+ function with \a key = "%73earch" will return an empty list.
+
+ \sa allQueryItemValues(), queryItemValue(), encodedQueryItemValue()
+*/
+QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
+{
+ if (!d) return QList<QByteArray>();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QList<QByteArray> values;
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
+ values += valuedelim < end ?
+ QByteArray(query + valuedelim + 1, end - valuedelim - 1)
+ : QByteArray();
+ pos = end + 1;
+ }
+
+ return values;
+}
+
+/*!
+ Removes the first query string pair whose key is equal to \a key
+ from the URL.
+
+ \sa removeAllQueryItems()
+*/
+void QUrl::removeQueryItem(const QString &key)
+{
+ if (!d) return;
+ removeEncodedQueryItem(toPercentEncoding(key, queryExcludeChars));
+}
+
+/*!
+ \since 4.4
+
+ Removes the first query string pair whose key is equal to \a key
+ from the URL.
+
+ Note: if the encoded \a key does not match the encoded version of
+ the query, this function will not work. That is, if the
+ encoded query of this URL is "search=Qt%20Rules", calling this
+ function with \a key = "%73earch" will do nothing.
+
+ \sa removeQueryItem(), removeAllQueryItems()
+*/
+void QUrl::removeEncodedQueryItem(const QByteArray &key)
+{
+ if (!d) return;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (key == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
+ if (end < d->query.size())
+ ++end; // remove additional '%'
+ d->query.remove(pos, end - pos);
+ return;
+ }
+ pos = end + 1;
+ }
+}
+
+/*!
+ Removes all the query string pairs whose key is equal to \a key
+ from the URL.
+
+ \sa removeQueryItem()
+*/
+void QUrl::removeAllQueryItems(const QString &key)
+{
+ if (!d) return;
+ removeAllEncodedQueryItems(toPercentEncoding(key, queryExcludeChars));
+}
+
+/*!
+ \since 4.4
+
+ Removes all the query string pairs whose key is equal to \a key
+ from the URL.
+
+ Note: if the encoded \a key does not match the encoded version of
+ the query, this function will not work. That is, if the
+ encoded query of this URL is "search=Qt%20Rules", calling this
+ function with \a key = "%73earch" will do nothing.
+
+ \sa removeQueryItem()
+*/
+void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
+{
+ if (!d) return;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+
+ int pos = 0;
+ const char *query = d->query.constData();
+ while (pos < d->query.size()) {
+ int valuedelim, end;
+ d->queryItem(pos, &valuedelim, &end);
+ if (key == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
+ if (end < d->query.size())
+ ++end; // remove additional '%'
+ d->query.remove(pos, end - pos);
+ } else {
+ pos = end + 1;
+ }
+ }
+}
+
+/*!
+ Returns the query string of the URL in percent encoded form.
+*/
+QByteArray QUrl::encodedQuery() const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->query;
+}
+
+/*!
+ Sets the fragment of the URL to \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:
+
+ \img qurl-fragment.png
+
+ The fragment is sometimes also referred to as the URL "reference".
+
+ Passing an argument of QString() (a null QString) will unset the fragment.
+ Passing an argument of QString("") (an empty but not null QString)
+ will set the fragment to an empty string (as if the original URL
+ had a lone "#").
+
+ \sa fragment(), hasFragment()
+*/
+void QUrl::setFragment(const QString &fragment)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->fragment = fragment;
+ d->hasFragment = !fragment.isNull();
+ d->encodedFragment.clear();
+}
+
+/*!
+ Returns the fragment of the URL.
+
+ \sa setFragment()
+*/
+QString QUrl::fragment() const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ if (d->fragment.isNull() && !d->encodedFragment.isNull()) {
+ QUrlPrivate *that = const_cast<QUrlPrivate *>(d);
+ that->fragment = fromPercentEncodingHelper(d->encodedFragment);
+ }
+ return d->fragment;
+}
+
+/*!
+ \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:
+
+ \img 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 "#").
+
+ \sa setFragment(), encodedFragment()
+*/
+void QUrl::setEncodedFragment(const QByteArray &fragment)
+{
+ if (!d) d = new QUrlPrivate;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ detach();
+ QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
+
+ d->encodedFragment = fragment;
+ d->hasFragment = !fragment.isNull();
+ d->fragment.clear();
+}
+
+/*!
+ \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().
+
+ \sa setEncodedFragment(), toEncoded()
+*/
+QByteArray QUrl::encodedFragment() const
+{
+ if (!d) return QByteArray();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ d->ensureEncodedParts();
+ return d->encodedFragment;
+}
+
+/*!
+ \since 4.2
+
+ Returns true if this URL contains a fragment (i.e., if # was seen on it).
+
+ \sa fragment(), setFragment()
+*/
+bool QUrl::hasFragment() const
+{
+ if (!d) return false;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->hasFragment;
+}
+
+/*!
+ Returns the result of the merge of this URL with \a relative. This
+ URL is used as a base to convert \a relative to an absolute URL.
+
+ If \a relative is not a relative URL, this function will return \a
+ relative directly. Otherwise, the paths of the two URLs are
+ merged, and the new URL returned has the scheme and authority of
+ the base URL, but with the merged path, as in the following
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 5
+
+ Calling resolved() with ".." returns a QUrl whose directory is
+ one level higher than the original. Similarly, calling resolved()
+ with "../.." removes two levels from the path. If \a relative is
+ "/", the path becomes "/".
+
+ \sa isRelative()
+*/
+QUrl QUrl::resolved(const QUrl &relative) const
+{
+ if (!d) return relative;
+ if (!relative.d) return *this;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ if (!QURL_HASFLAG(relative.d->stateFlags, QUrlPrivate::Parsed))
+ relative.d->parse();
+
+ d->ensureEncodedParts();
+ relative.d->ensureEncodedParts();
+
+ QUrl t;
+ // be non strict and allow scheme in relative url
+ if (!relative.d->scheme.isEmpty() && relative.d->scheme != d->scheme) {
+ t = relative;
+ } else {
+ if (!relative.authority().isEmpty()) {
+ t = relative;
+ } else {
+ t.d = new QUrlPrivate;
+ if (relative.d->encodedPath.isEmpty()) {
+ t.d->encodedPath = d->encodedPath;
+ t.setEncodedQuery(relative.d->hasQuery ? relative.d->query : d->query);
+ } else {
+ t.d->encodedPath = relative.d->encodedPath.at(0) == '/'
+ ? relative.d->encodedPath
+ : d->mergePaths(relative.d->encodedPath);
+ t.setEncodedQuery(relative.d->query);
+ }
+ t.d->encodedUserName = d->encodedUserName;
+ t.d->encodedPassword = d->encodedPassword;
+ t.d->host = d->host;
+ t.d->port = d->port;
+ }
+ t.setScheme(d->scheme);
+ }
+ t.setFragment(relative.fragment());
+ removeDotsFromPath(&t.d->encodedPath);
+ t.d->path.clear();
+
+#if defined(QURL_DEBUG)
+ qDebug("QUrl(\"%s\").resolved(\"%s\") = \"%s\"",
+ toEncoded().constData(),
+ relative.toEncoded().constData(),
+ t.toEncoded().constData());
+#endif
+ return t;
+}
+
+/*!
+ Returns true if the URL is relative; otherwise returns false. A
+ URL is relative if its scheme is undefined; this function is
+ therefore equivalent to calling scheme().isEmpty().
+*/
+bool QUrl::isRelative() const
+{
+ if (!d) return true;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ return d->scheme.isEmpty();
+}
+
+/*!
+ Returns the human-displayable string representation of the
+ URL. The output can be customized by passing flags with \a
+ options.
+
+ \sa FormattingOptions, toEncoded()
+*/
+QString QUrl::toString(FormattingOptions options) const
+{
+ if (!d) return QString();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QString url;
+
+ if (!(options & QUrl::RemoveScheme) && !d->scheme.isEmpty())
+ url += d->scheme + QLatin1Char(':');
+ QString ourPath = path();
+ if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority) {
+ bool doFileScheme = d->scheme == QLatin1String("file") && ourPath.startsWith(QLatin1Char('/'));
+ QString tmp = d->authority(options);
+ if (!tmp.isNull() || doFileScheme) {
+ if (doFileScheme && !ourPath.startsWith(QLatin1Char('/')))
+ url += QLatin1Char('/');
+ url += QLatin1String("//");
+ url += tmp;
+ }
+ }
+ if (!(options & QUrl::RemovePath)) {
+ // check if we need to insert a slash
+ if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority
+ && !d->authority(options).isEmpty() && !ourPath.isEmpty() && ourPath.at(0) != QLatin1Char('/'))
+ url += QLatin1Char('/');
+ url += ourPath;
+ // check if we need to remove trailing slashes
+ while ((options & StripTrailingSlash) && url.endsWith(QLatin1Char('/')))
+ url.chop(1);
+ }
+
+ if (!(options & QUrl::RemoveQuery) && d->hasQuery) {
+ url += QLatin1Char('?');
+ url += fromPercentEncoding(d->query);
+ }
+ if (!(options & QUrl::RemoveFragment) && d->hasFragment) {
+ url += QLatin1Char('#');
+ url += fragment();
+ }
+
+ return url;
+}
+
+/*!
+ Returns the encoded representation of the URL if it's valid;
+ otherwise an empty QByteArray is returned. The output can be
+ customized by passing flags with \a options.
+
+ The user info, path and fragment are all converted to UTF-8, and
+ all non-ASCII characters are then percent encoded. The host name
+ is encoded using Punycode.
+*/
+QByteArray QUrl::toEncoded(FormattingOptions options) const
+{
+ if (!d) return QByteArray();
+ return d->toEncoded(options);
+}
+
+/*!
+ Parses \a input and returns the corresponding QUrl. \a input is
+ assumed to be in encoded form, containing only ASCII characters.
+
+ The URL is parsed using TolerantMode.
+
+ \sa toEncoded(), setUrl()
+*/
+QUrl QUrl::fromEncoded(const QByteArray &input)
+{
+ QUrl tmp;
+ tmp.setEncodedUrl(input, TolerantMode);
+ return tmp;
+}
+
+/*!
+ \overload
+
+ Parses the URL using \a parsingMode.
+
+ \sa toEncoded(), setUrl()
+*/
+QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode)
+{
+ QUrl tmp;
+ tmp.setEncodedUrl(input, parsingMode);
+ return tmp;
+}
+
+/*!
+ Returns a decoded copy of \a input. \a input is first decoded from
+ percent encoding, then converted from UTF-8 to unicode.
+*/
+QString QUrl::fromPercentEncoding(const QByteArray &input)
+{
+ return fromPercentEncodingHelper(input);
+}
+
+/*!
+ Returns an encoded copy of \a input. \a input is first converted
+ to UTF-8, and all ASCII-characters that are not in the unreserved group
+ are percent encoded. To prevent characters from being percent encoded
+ pass them to \a exclude. To force characters to be percent encoded pass
+ them to \a include.
+
+ Unreserved is defined as:
+ ALPHA / DIGIT / "-" / "." / "_" / "~"
+
+ \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 6
+*/
+QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
+{
+ return toPercentEncodingHelper(input, exclude.constData(), include.constData());
+}
+
+/*!
+ \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().
+*/
+QByteArray QUrl::toPunycode(const QString &uc)
+{
+ QString output;
+ toPunycodeHelper(uc.constData(), uc.size(), &output);
+ return output.toLatin1();
+}
+
+/*!
+ \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().
+*/
+QString QUrl::fromPunycode(const QByteArray &pc)
+{
+ uint n = initial_n;
+ uint i = 0;
+ uint bias = initial_bias;
+
+ // strip any ACE prefix
+ int start = pc.startsWith("xn--") ? 4 : 0;
+ if (!start)
+ return QString::fromLatin1(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(0x2d);
+ QString output = delimiterPos < 4 ?
+ QString() : QString::fromLatin1(pc.constData() + start, delimiterPos - start);
+
+ // if a delimiter was found, skip to the position after it;
+ // otherwise start at the front of the input string. everything
+ // before the delimiter is assumed to be basic code points.
+ uint cnt = delimiterPos + 1;
+
+ // loop through the rest of the input string, inserting non-basic
+ // characters into output as we go.
+ while (cnt < (uint) pc.size()) {
+ uint oldi = i;
+ uint w = 1;
+
+ // find the next index for inserting a non-basic character.
+ for (uint k = base; cnt < (uint) pc.size(); k += base) {
+ // grab a character from the punycode input and find its
+ // delta digit (each digit code is part of the
+ // variable-length integer delta)
+ uint digit = pc.at(cnt++);
+ if (digit - 48 < 10) digit -= 22;
+ else if (digit - 65 < 26) digit -= 65;
+ else if (digit - 97 < 26) digit -= 97;
+ else digit = base;
+
+ // reject out of range digits
+ if (digit >= base || digit > (Q_MAXINT - i) / w)
+ return QLatin1String("");
+
+ i += (digit * w);
+
+ // 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);
+ }
+
+ // 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);
+
+ // allow the deltas to wrap around
+ i %= (output.length() + 1);
+
+ // insert the character n at position i
+ output.insert((uint) i, QChar((ushort) n));
+ ++i;
+ }
+
+ return output;
+}
+
+/*!
+ \since 4.2
+
+ Returns the Unicode form of the given domain name
+ \a domain, which is encoded in the ASCII Compatible Encoding (ACE).
+ 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.
+*/
+QString QUrl::fromAce(const QByteArray &domain)
+{
+ return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce);
+}
+
+/*!
+ \since 4.2
+
+ Returns the ASCII Compatible Encoding of the given domain name \a domain.
+ 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.
+
+ This function return an empty QByteArra 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)
+{
+ QString result = qt_ACE_do(domain, ToAceOnly);
+ return result.toLatin1();
+}
+
+/*!
+ \since 4.2
+
+ Returns the current whitelist of top-level domains that are allowed
+ to have non-ASCII characters in their compositions.
+
+ See setIdnWhitelist() for the rationale of this list.
+*/
+QStringList QUrl::idnWhitelist()
+{
+ if (user_idn_whitelist)
+ return *user_idn_whitelist;
+ QStringList list;
+ unsigned int i = 0;
+ while (i < sizeof(idn_whitelist)/sizeof(const char *)) {
+ list << QLatin1String(idn_whitelist[i]);
+ ++i;
+ }
+ return list;
+}
+
+/*!
+ \since 4.2
+
+ Sets the whitelist of Top-Level Domains (TLDs) that are allowed to have
+ non-ASCII characters in domains to the value of \a list.
+
+ Qt has comes a default list that contains the Internet top-level domains
+ that have published support for Internationalized Domain Names (IDNs)
+ and rules to guarantee that no deception can happen between similarly-looking
+ characters (such as the Latin lowercase letter \c 'a' and the Cyrillic
+ equivalent, which in most fonts are visually identical).
+
+ This list is periodically maintained, as registrars publish new rules.
+
+ This function is provided for those who need to manipulate the list, in
+ order to add or remove a TLD. It is not recommended to change its value
+ for purposes other than testing, as it may expose users to security risks.
+*/
+void QUrl::setIdnWhitelist(const QStringList &list)
+{
+ if (!user_idn_whitelist)
+ user_idn_whitelist = new QStringList;
+ *user_idn_whitelist = list;
+}
+
+/*!
+ \internal
+
+ Returns true if this URL is "less than" the given \a url. This
+ provides a means of ordering URLs.
+*/
+bool QUrl::operator <(const QUrl &url) const
+{
+ if (!d) return url.d ? QByteArray() < url.d->normalized() : false;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ if (!url.d) return d->normalized() < QByteArray();
+ if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse();
+ return d->normalized() < url.d->normalized();
+}
+
+/*!
+ Returns true if this URL and the given \a url are equal;
+ otherwise returns false.
+*/
+bool QUrl::operator ==(const QUrl &url) const
+{
+ if (!d) return url.isEmpty();
+ if (!url.d) return isEmpty();
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+ if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse();
+ return d->normalized() == url.d->normalized();
+}
+
+/*!
+ Returns true if this URL and the given \a url are not equal;
+ otherwise returns false.
+*/
+bool QUrl::operator !=(const QUrl &url) const
+{
+ return !(*this == url);
+}
+
+/*!
+ Assigns the specified \a url to this object.
+*/
+QUrl &QUrl::operator =(const QUrl &url)
+{
+ if (!d) {
+ if (url.d) {
+ url.d->ref.ref();
+ d = url.d;
+ }
+ } else {
+ if (url.d)
+ qAtomicAssign(d, url.d);
+ else
+ clear();
+ }
+ return *this;
+}
+
+/*!
+ Assigns the specified \a url to this object.
+*/
+QUrl &QUrl::operator =(const QString &url)
+{
+ if (url.isEmpty()) {
+ clear();
+ } else {
+ QUrl tmp(url);
+ if (!d) d = new QUrlPrivate;
+ qAtomicAssign(d, tmp.d);
+ }
+ return *this;
+}
+
+/*!
+ \fn void QUrl::swap(QUrl &other)
+ \since 4.8
+
+ Swaps URL \a other with this URL. This operation is very
+ fast and never fails.
+*/
+
+/*! \internal
+
+ Forces a detach.
+*/
+void QUrl::detach()
+{
+ if (!d)
+ d = new QUrlPrivate;
+ else
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+*/
+bool QUrl::isDetached() const
+{
+ return !d || d->ref == 1;
+}
+
+
+/*!
+ Returns a QUrl representation of \a localFile, interpreted as a local
+ file. This function accepts paths separated by slashes as well as the
+ native separator for this platform.
+
+ This function also accepts paths with a doubled leading slash (or
+ backslash) to indicate a remote file, as in
+ "//servername/path/to/file.txt". Note that only certain platforms can
+ actually open this file using QFile::open().
+
+ \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators
+*/
+QUrl QUrl::fromLocalFile(const QString &localFile)
+{
+ QUrl url;
+ url.setScheme(QLatin1String("file"));
+ QString deslashified = QDir::fromNativeSeparators(localFile);
+
+ // magic for drives on windows
+ if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
+ url.setPath(QLatin1Char('/') + deslashified);
+ // magic for shared drive on windows
+ } else if (deslashified.startsWith(QLatin1String("//"))) {
+ int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
+ url.setHost(deslashified.mid(2, indexOfPath - 2));
+ if (indexOfPath > 2)
+ url.setPath(deslashified.right(deslashified.length() - indexOfPath));
+ } else {
+ url.setPath(deslashified);
+ }
+
+ return url;
+}
+
+/*!
+ Returns the path of this URL formatted as a local file path. The path
+ returned will use forward slashes, even if it was originally created
+ from one with backslashes.
+
+ If this URL contains a non-empty hostname, it will be encoded in the
+ returned value in the form found on SMB networks (for example,
+ "//servername/path/to/file.txt").
+
+ \sa fromLocalFile(), isLocalFile()
+*/
+QString QUrl::toLocalFile() const
+{
+ // the call to isLocalFile() also ensures that we're parsed
+ if (!isLocalFile())
+ return QString();
+
+ QString tmp;
+ QString ourPath = path();
+
+ // magic for shared drive on windows
+ if (!d->host.isEmpty()) {
+ tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/')
+ ? QLatin1Char('/') + ourPath : ourPath);
+ } else {
+ tmp = ourPath;
+ // magic for drives on windows
+ if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
+ tmp.remove(0, 1);
+ }
+
+ return tmp;
+}
+
+/*!
+ \since 4.7
+ Returns true if this URL is pointing to a local file path. A URL is a
+ local file path if the scheme is "file".
+
+ Note that this function considers URLs with hostnames to be local file
+ paths, even if the eventual file path cannot be opened with
+ QFile::open().
+
+ \sa fromLocalFile(), toLocalFile()
+*/
+bool QUrl::isLocalFile() const
+{
+ if (!d) return false;
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0)
+ return false; // not file
+ return true;
+}
+
+/*!
+ Returns true if this URL is a parent of \a childUrl. \a childUrl is a child
+ of this URL if the two URLs share the same scheme and authority,
+ and this URL's path is a parent of the path of \a childUrl.
+*/
+bool QUrl::isParentOf(const QUrl &childUrl) const
+{
+ QString childPath = childUrl.path();
+
+ if (!d)
+ return ((childUrl.scheme().isEmpty())
+ && (childUrl.authority().isEmpty())
+ && childPath.length() > 0 && childPath.at(0) == QLatin1Char('/'));
+
+ if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
+
+ QString ourPath = path();
+
+ return ((childUrl.scheme().isEmpty() || d->scheme == childUrl.scheme())
+ && (childUrl.authority().isEmpty() || d->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('/'))));
+}
+
+/*!
+ \fn void QUrl::setProtocol(const QString &s)
+
+ Use setScheme() instead.
+*/
+
+/*!
+ \fn void QUrl::setUser(const QString &s)
+
+ Use setUserName() instead.
+*/
+
+/*!
+ \fn bool QUrl::hasUser() const
+
+ Use !userName().isEmpty() instead.
+*/
+
+/*!
+ \fn bool QUrl::hasPassword() const
+
+ Use !password().isEmpty() instead.
+*/
+
+/*!
+ \fn bool QUrl::hasHost() const
+
+ Use !host().isEmpty() instead.
+*/
+
+/*!
+ \fn bool QUrl::hasPort() const
+
+ Use port() != -1 instead.
+*/
+
+/*!
+ \fn bool QUrl::hasPath() const
+
+ Use !path().isEmpty() instead.
+*/
+
+/*!
+ \fn void QUrl::setQuery(const QString &txt)
+
+ Use setEncodedQuery() instead.
+*/
+
+/*!
+ \fn void QUrl::setRef(const QString &txt)
+
+ Use setFragment() instead.
+*/
+
+/*!
+ \fn bool QUrl::hasRef() const
+
+ Use !fragment().isEmpty() instead.
+*/
+
+/*!
+ \fn void QUrl::addPath(const QString &p)
+
+ Use setPath() instead.
+*/
+
+/*!
+ \fn void QUrl::setFileName(const QString &txt)
+
+ Use setPath() instead.
+*/
+
+/*!
+ \fn void QUrl::decode(QString &url)
+
+ Use fromPercentEncoding() instead.
+*/
+
+/*!
+ \fn void QUrl::encode(QString &url)
+
+ Use toPercentEncoding() instead.
+*/
+
+/*!
+ \fn bool QUrl::cdUp()
+
+ Use resolved("..") instead.
+
+ \oldcode
+ QUrl url("http://example.com/Developer/");
+ url.cdUp();
+ \newcode
+ QUrl url("http://example.com/Developer/");
+ url = url.resolved("..");
+ \endcode
+*/
+
+/*!
+ \fn bool QUrl::isRelativeUrl(const QString &url)
+
+ Use isRelative() instead.
+*/
+
+/*!
+ \fn void QUrl::reset()
+
+ Use clear() instead.
+*/
+
+/*!
+ \fn QUrl::operator QString() const
+
+ Use toString() instead.
+*/
+
+/*!
+ \fn QString QUrl::protocol() const
+
+ Use scheme() instead.
+*/
+
+/*!
+ \fn QString QUrl::user() const
+
+ Use userName() instead.
+*/
+
+/*!
+ \fn QString QUrl::query() const
+
+ Use encodedQuery() instead.
+*/
+
+/*!
+ \fn QString QUrl::ref() const
+
+ Use fragment() instead.
+*/
+
+/*!
+ \fn QString QUrl::fileName() const
+
+ Use QFileInfo(path()).fileName() instead.
+*/
+
+/*!
+ \fn QString QUrl::dirPath() const
+
+ Use QFileInfo(path()).absolutePath() or QFileInfo(path()) instead.
+*/
+
+#ifdef QT3_SUPPORT
+void QUrl::setFileName(const QString &txt)
+{
+ QFileInfo fileInfo(path());
+ fileInfo.setFile(txt);
+ setPath(fileInfo.filePath());
+}
+
+QString QUrl::fileName() const
+{
+ QFileInfo fileInfo(path());
+ return fileInfo.fileName();
+}
+
+QString QUrl::dirPath() const
+{
+ QFileInfo fileInfo(path());
+ if (fileInfo.isAbsolute()) {
+ QString absPath = fileInfo.absolutePath();
+#ifdef Q_OS_WIN
+ if (absPath.size() > 1 && absPath.at(1) == QLatin1Char(':'))
+ absPath = absPath.mid(2);
+#endif
+ return absPath;
+ }
+ return fileInfo.path();
+}
+#endif
+
+
+#ifndef QT_NO_DATASTREAM
+/*! \relates QUrl
+
+ Writes url \a url to the stream \a out and returns a reference
+ to the stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator<<(QDataStream &out, const QUrl &url)
+{
+ QByteArray u = url.toEncoded();
+ out << u;
+ return out;
+}
+
+/*! \relates QUrl
+
+ Reads a url into \a url from the stream \a in and returns a
+ reference to the stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator>>(QDataStream &in, QUrl &url)
+{
+ QByteArray u;
+ in >> u;
+ url = QUrl::fromEncoded(u);
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QUrl &url)
+{
+ d.maybeSpace() << "QUrl(" << url.toString() << ')';
+ return d.space();
+}
+#endif
+
+/*!
+ \since 4.2
+
+ Returns a text string that explains why an URL is invalid in the case being;
+ otherwise returns an empty string.
+*/
+QString QUrl::errorString() const
+{
+ if (!d)
+ return QLatin1String(QT_TRANSLATE_NOOP(QUrl, "Invalid URL \"\": ")); // XXX not a good message, but the one an empty URL produces
+ return d->createErrorString();
+}
+
+/*!
+ \typedef QUrl::DataPtr
+ \internal
+*/
+
+/*!
+ \fn DataPtr &QUrl::data_ptr()
+ \internal
+*/
+
+// The following code has the following copyright:
+/*
+ Copyright (C) Research In Motion Limited 2009. 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 Research In Motion Limited 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 Research In Motion Limited ''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 Research In Motion Limited 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.
+
+*/
+
+
+/*!
+ 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.
+
+ When the string is not already a valid URL, a best guess is performed,
+ making various web related assumptions.
+
+ In the case the string corresponds to a valid file path on the system,
+ a file:// URL is constructed, using QUrl::fromLocalFile().
+
+ If that is not the case, an attempt is made to turn the string into a
+ http:// or ftp:// URL. The latter in the case the string starts with
+ 'ftp'. The result is then passed through QUrl's tolerant parser, and
+ in the case or success, a valid QUrl is returned, or else a QUrl().
+
+ \section1 Examples:
+
+ \list
+ \o qt.nokia.com becomes http://qt.nokia.com
+ \o ftp.qt.nokia.com becomes ftp://ftp.qt.nokia.com
+ \o hostname becomes http://hostname
+ \o /home/user/test.html becomes file:///home/user/test.html
+ \endlist
+
+ \section2 Tips to avoid erroneous character conversion when dealing with
+ URLs and strings:
+
+ \list
+ \o When creating an URL QString from a QByteArray or a char*, always use
+ QString::fromUtf8().
+ \o Favor the use of QUrl::fromEncoded() and QUrl::toEncoded() instead of
+ QUrl(string) and QUrl::toString() when converting QUrl to/from string.
+ \endlist
+*/
+QUrl QUrl::fromUserInput(const QString &userInput)
+{
+ QString trimmedString = userInput.trimmed();
+
+ // Check first for files, since on Windows drive letters can be interpretted as schemes
+ if (QDir::isAbsolutePath(trimmedString))
+ return QUrl::fromLocalFile(trimmedString);
+
+ QUrl url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode);
+ QUrl urlPrepended = QUrl::fromEncoded("http://" + trimmedString.toUtf8(), QUrl::TolerantMode);
+
+ // Check the most common case of a valid url with scheme and host
+ // 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
+ if (url.isValid()
+ && !url.scheme().isEmpty()
+ && (!url.host().isEmpty() || !url.path().isEmpty())
+ && urlPrepended.port() == -1)
+ return 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('.'));
+ const QString hostscheme = trimmedString.left(dotIndex).toLower();
+ if (hostscheme == QLatin1String("ftp"))
+ urlPrepended.setScheme(QLatin1String("ftp"));
+ return urlPrepended;
+ }
+
+ return QUrl();
+}
+// end of BSD code
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
new file mode 100644
index 0000000000..7534b8d474
--- /dev/null
+++ b/src/corelib/io/qurl.h
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QURL_H
+#define QURL_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QUrlPrivate;
+class QDataStream;
+
+class Q_CORE_EXPORT QUrl
+{
+public:
+ enum ParsingMode {
+ TolerantMode,
+ StrictMode
+ };
+
+ // encoding / toString values
+ enum FormattingOption {
+ None = 0x0,
+ RemoveScheme = 0x1,
+ RemovePassword = 0x2,
+ RemoveUserInfo = RemovePassword | 0x4,
+ RemovePort = 0x8,
+ RemoveAuthority = RemoveUserInfo | RemovePort | 0x10,
+ RemovePath = 0x20,
+ RemoveQuery = 0x40,
+ RemoveFragment = 0x80,
+ // 0x100: private: normalized
+
+ StripTrailingSlash = 0x10000
+ };
+ Q_DECLARE_FLAGS(FormattingOptions, FormattingOption)
+
+ QUrl();
+#ifdef QT_NO_URL_CAST_FROM_STRING
+ explicit
+#endif
+ QUrl(const QString &url);
+ QUrl(const QString &url, ParsingMode mode);
+ // ### Qt 5: merge the two constructors, with mode = TolerantMode
+ QUrl(const QUrl &copy);
+ QUrl &operator =(const QUrl &copy);
+#ifndef QT_NO_URL_CAST_FROM_STRING
+ QUrl &operator =(const QString &url);
+#endif
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QUrl &operator=(QUrl &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ ~QUrl();
+
+ inline void swap(QUrl &other) { qSwap(d, other.d); }
+
+ void setUrl(const QString &url);
+ void setUrl(const QString &url, ParsingMode mode);
+ // ### Qt 5: merge the two setUrl() functions, with mode = TolerantMode
+ void setEncodedUrl(const QByteArray &url);
+ void setEncodedUrl(const QByteArray &url, ParsingMode mode);
+ // ### Qt 5: merge the two setEncodedUrl() functions, with mode = TolerantMode
+
+ bool isValid() const;
+
+ bool isEmpty() const;
+
+ void clear();
+
+ void setScheme(const QString &scheme);
+ QString scheme() const;
+
+ void setAuthority(const QString &authority);
+ QString authority() const;
+
+ void setUserInfo(const QString &userInfo);
+ QString userInfo() const;
+
+ void setUserName(const QString &userName);
+ QString userName() const;
+ void setEncodedUserName(const QByteArray &userName);
+ QByteArray encodedUserName() const;
+
+ void setPassword(const QString &password);
+ QString password() const;
+ void setEncodedPassword(const QByteArray &password);
+ QByteArray encodedPassword() const;
+
+ void setHost(const QString &host);
+ QString host() const;
+ void setEncodedHost(const QByteArray &host);
+ QByteArray encodedHost() const;
+
+ void setPort(int port);
+ int port() const;
+ int port(int defaultPort) const;
+ // ### Qt 5: merge the two port() functions, with defaultPort = -1
+
+ void setPath(const QString &path);
+ QString path() const;
+ void setEncodedPath(const QByteArray &path);
+ QByteArray encodedPath() const;
+
+ bool hasQuery() const;
+
+ void setEncodedQuery(const QByteArray &query);
+ QByteArray encodedQuery() const;
+
+ void setQueryDelimiters(char valueDelimiter, char pairDelimiter);
+ char queryValueDelimiter() const;
+ char queryPairDelimiter() const;
+
+ void setQueryItems(const QList<QPair<QString, QString> > &query);
+ void addQueryItem(const QString &key, const QString &value);
+ QList<QPair<QString, QString> > queryItems() const;
+ bool hasQueryItem(const QString &key) const;
+ QString queryItemValue(const QString &key) const;
+ QStringList allQueryItemValues(const QString &key) const;
+ void removeQueryItem(const QString &key);
+ void removeAllQueryItems(const QString &key);
+
+ void setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query);
+ void addEncodedQueryItem(const QByteArray &key, const QByteArray &value);
+ QList<QPair<QByteArray, QByteArray> > encodedQueryItems() const;
+ bool hasEncodedQueryItem(const QByteArray &key) const;
+ QByteArray encodedQueryItemValue(const QByteArray &key) const;
+ QList<QByteArray> allEncodedQueryItemValues(const QByteArray &key) const;
+ void removeEncodedQueryItem(const QByteArray &key);
+ void removeAllEncodedQueryItems(const QByteArray &key);
+
+ void setFragment(const QString &fragment);
+ QString fragment() const;
+ void setEncodedFragment(const QByteArray &fragment);
+ QByteArray encodedFragment() const;
+ bool hasFragment() const;
+
+ QUrl resolved(const QUrl &relative) const;
+
+ bool isRelative() const;
+ bool isParentOf(const QUrl &url) const;
+
+ static QUrl fromLocalFile(const QString &localfile);
+ QString toLocalFile() const;
+ bool isLocalFile() const;
+
+ QString toString(FormattingOptions options = None) const;
+
+ QByteArray toEncoded(FormattingOptions options = None) const;
+ static QUrl fromEncoded(const QByteArray &url);
+ static QUrl fromEncoded(const QByteArray &url, ParsingMode mode);
+ // ### Qt 5: merge the two fromEncoded() functions, with mode = TolerantMode
+
+ static QUrl fromUserInput(const QString &userInput);
+
+ void detach();
+ bool isDetached() const;
+
+ bool operator <(const QUrl &url) const;
+ bool operator ==(const QUrl &url) const;
+ bool operator !=(const QUrl &url) const;
+
+ static QString fromPercentEncoding(const QByteArray &);
+ static QByteArray toPercentEncoding(const QString &,
+ const QByteArray &exclude = QByteArray(),
+ const QByteArray &include = QByteArray());
+ static QString fromPunycode(const QByteArray &);
+ static QByteArray toPunycode(const QString &);
+ static QString fromAce(const QByteArray &);
+ static QByteArray toAce(const QString &);
+ static QStringList idnWhitelist();
+ static void setIdnWhitelist(const QStringList &);
+
+#if defined QT3_SUPPORT
+ inline QT3_SUPPORT QString protocol() const { return scheme(); }
+ inline QT3_SUPPORT void setProtocol(const QString &s) { setScheme(s); }
+ inline QT3_SUPPORT void setUser(const QString &s) { setUserName(s); }
+ inline QT3_SUPPORT QString user() const { return userName(); }
+ inline QT3_SUPPORT bool hasUser() const { return !userName().isEmpty(); }
+ inline QT3_SUPPORT bool hasPassword() const { return !password().isEmpty(); }
+ inline QT3_SUPPORT bool hasHost() const { return !host().isEmpty(); }
+ inline QT3_SUPPORT bool hasPort() const { return port() != -1; }
+ inline QT3_SUPPORT bool hasPath() const { return !path().isEmpty(); }
+ inline QT3_SUPPORT void setQuery(const QString &txt)
+ {
+ setEncodedQuery(txt.toLatin1());
+ }
+ inline QT3_SUPPORT QString query() const
+ {
+ return QString::fromLatin1(encodedQuery().constData());
+ }
+ inline QT3_SUPPORT QString ref() const { return fragment(); }
+ inline QT3_SUPPORT void setRef(const QString &txt) { setFragment(txt); }
+ inline QT3_SUPPORT bool hasRef() const { return !fragment().isEmpty(); }
+ inline QT3_SUPPORT void addPath(const QString &p) { setPath(path() + QLatin1Char('/') + p); }
+ QT3_SUPPORT void setFileName(const QString &txt);
+ QT3_SUPPORT QString fileName() const;
+ QT3_SUPPORT QString dirPath() const;
+ static inline QT3_SUPPORT void decode(QString &url)
+ {
+ url = QUrl::fromPercentEncoding(url.toLatin1());
+ }
+ static inline QT3_SUPPORT void encode(QString &url)
+ {
+ url = QString::fromLatin1(QUrl::toPercentEncoding(url).constData());
+ }
+ inline QT3_SUPPORT operator QString() const { return toString(); }
+ inline QT3_SUPPORT bool cdUp()
+ {
+ *this = resolved(QUrl(QLatin1String("..")));
+ return true;
+ }
+ static inline QT3_SUPPORT bool isRelativeUrl(const QString &url)
+ {
+ return QUrl(url).isRelative();
+ }
+#endif
+
+ QString errorString() const;
+
+protected:
+#if defined (QT3_SUPPORT)
+ inline QT3_SUPPORT void reset() { clear(); }
+#endif
+
+private:
+ QUrlPrivate *d;
+public:
+ typedef QUrlPrivate * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+inline uint qHash(const QUrl &url)
+{
+ return qHash(url.toEncoded(QUrl::FormattingOption(0x100)));
+}
+
+Q_DECLARE_TYPEINFO(QUrl, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QUrl)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::FormattingOptions)
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUrl &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUrl &);
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QUrl &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QURL_H
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
new file mode 100644
index 0000000000..5c6728aad5
--- /dev/null
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowspipewriter_p.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_THREAD
+
+QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent)
+ : QThread(parent),
+ writePipe(INVALID_HANDLE_VALUE),
+ quitNow(false),
+ hasWritten(false)
+{
+#if !defined(Q_OS_WINCE) || (_WIN32_WCE >= 0x600)
+ DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(),
+ &writePipe, 0, FALSE, DUPLICATE_SAME_ACCESS);
+#else
+ Q_UNUSED(pipe);
+ writePipe = GetCurrentProcess();
+#endif
+}
+
+QWindowsPipeWriter::~QWindowsPipeWriter()
+{
+ lock.lock();
+ quitNow = true;
+ waitCondition.wakeOne();
+ lock.unlock();
+ if (!wait(100))
+ terminate();
+#if !defined(Q_OS_WINCE) || (_WIN32_WCE >= 0x600)
+ CloseHandle(writePipe);
+#endif
+}
+
+bool QWindowsPipeWriter::waitForWrite(int msecs)
+{
+ QMutexLocker locker(&lock);
+ bool hadWritten = hasWritten;
+ hasWritten = false;
+ if (hadWritten)
+ return true;
+ if (!waitCondition.wait(&lock, msecs))
+ return false;
+ hadWritten = hasWritten;
+ hasWritten = false;
+ return hadWritten;
+}
+
+qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
+{
+ if (!isRunning())
+ return -1;
+
+ QMutexLocker locker(&lock);
+ data.append(QByteArray(ptr, maxlen));
+ waitCondition.wakeOne();
+ return maxlen;
+}
+
+void QWindowsPipeWriter::run()
+{
+ OVERLAPPED overl;
+ memset(&overl, 0, sizeof overl);
+ overl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ forever {
+ lock.lock();
+ while(data.isEmpty() && (!quitNow)) {
+ waitCondition.wakeOne();
+ waitCondition.wait(&lock);
+ }
+
+ if (quitNow) {
+ lock.unlock();
+ quitNow = false;
+ break;
+ }
+
+ QByteArray copy = data;
+
+ lock.unlock();
+
+ const char *ptrData = copy.data();
+ qint64 maxlen = copy.size();
+ qint64 totalWritten = 0;
+ overl.Offset = 0;
+ overl.OffsetHigh = 0;
+ while ((!quitNow) && totalWritten < maxlen) {
+ DWORD written = 0;
+ if (!WriteFile(writePipe, ptrData + totalWritten,
+ maxlen - totalWritten, &written, &overl)) {
+
+ if (GetLastError() == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
+ // give the os a rest
+ msleep(100);
+ continue;
+ }
+#ifndef Q_OS_WINCE
+ if (GetLastError() == ERROR_IO_PENDING) {
+ if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
+ CloseHandle(overl.hEvent);
+ return;
+ }
+ } else {
+ CloseHandle(overl.hEvent);
+ return;
+ }
+#else
+ return;
+#endif
+ }
+ totalWritten += written;
+#if defined QPIPEWRITER_DEBUG
+ qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes",
+ written, int(totalWritten), int(maxlen));
+#endif
+ lock.lock();
+ data.remove(0, written);
+ hasWritten = true;
+ lock.unlock();
+ }
+ emit bytesWritten(totalWritten);
+ emit canWrite();
+ }
+ CloseHandle(overl.hEvent);
+}
+
+#endif //QT_NO_THREAD
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
new file mode 100644
index 0000000000..9ca0e82c35
--- /dev/null
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSPIPEWRITER_P_H
+#define QWINDOWSPIPEWRITER_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 <qdatetime.h>
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <qt_windows.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_THREAD
+
+#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(totalTimeOut - timer.elapsed(), 0);
+ }
+
+ bool hasTimedOut() const
+ {
+ if (totalTimeOut == -1)
+ return false;
+ return timer.elapsed() >= totalTimeOut;
+ }
+
+ void resetIncrements()
+ {
+ nextSleep = qMin(SLEEPMIN, timeLeft());
+ }
+
+private:
+ QTime timer;
+ int totalTimeOut;
+ int nextSleep;
+};
+
+class Q_CORE_EXPORT QWindowsPipeWriter : public QThread
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void canWrite();
+ void bytesWritten(qint64 bytes);
+
+public:
+ QWindowsPipeWriter(HANDLE writePipe, QObject * parent = 0);
+ ~QWindowsPipeWriter();
+
+ bool waitForWrite(int msecs);
+ qint64 write(const char *data, qint64 maxlen);
+
+ qint64 bytesToWrite() const
+ {
+ QMutexLocker locker(&lock);
+ return data.size();
+ }
+
+ bool hadWritten() const
+ {
+ return hasWritten;
+ }
+
+protected:
+ void run();
+
+private:
+ QByteArray data;
+ QWaitCondition waitCondition;
+ mutable QMutex lock;
+ HANDLE writePipe;
+ volatile bool quitNow;
+ bool hasWritten;
+};
+
+#endif //QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_PROCESS
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
new file mode 100644
index 0000000000..a3628b1be5
--- /dev/null
+++ b/src/corelib/kernel/kernel.pri
@@ -0,0 +1,164 @@
+# Qt core object module
+
+HEADERS += \
+ kernel/qabstracteventdispatcher.h \
+ kernel/qabstractitemmodel.h \
+ kernel/qabstractitemmodel_p.h \
+ kernel/qbasictimer.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/qobjectdefs.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/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
+
+SOURCES += \
+ kernel/qabstracteventdispatcher.cpp \
+ kernel/qabstractitemmodel.cpp \
+ kernel/qbasictimer.cpp \
+ kernel/qeventloop.cpp \
+ kernel/qcoreapplication.cpp \
+ kernel/qcoreevent.cpp \
+ kernel/qmetaobject.cpp \
+ kernel/qmetatype.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
+
+win32 {
+ SOURCES += \
+ kernel/qeventdispatcher_win.cpp \
+ kernel/qcoreapplication_win.cpp \
+ kernel/qwineventnotifier_p.cpp \
+ kernel/qsharedmemory_win.cpp \
+ kernel/qsystemsemaphore_win.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_win_p.h \
+ kernel/qwineventnotifier_p.h
+}
+
+
+wince*: {
+ SOURCES += \
+ kernel/qfunctions_wince.cpp
+ HEADERS += \
+ kernel/qfunctions_wince.h
+}
+
+mac:!embedded:!qpa{
+ SOURCES += \
+ kernel/qcoreapplication_mac.cpp
+}
+
+mac:!nacl {
+ SOURCES += \
+ kernel/qcore_mac.cpp
+}
+
+nacl {
+ SOURCES += \
+ kernel/qfunctions_nacl.cpp
+ HEADERS += \
+ kernel/qfunctions_nacl.h
+}
+
+unix:!symbian {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qeventdispatcher_glib.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_glib_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
+ }
+ SOURCES += \
+ kernel/qeventdispatcher_unix.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_unix_p.h
+
+ contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
+}
+
+symbian {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qeventdispatcher_symbian.cpp \
+ kernel/qcore_symbian_p.cpp \
+ kernel/qsharedmemory_symbian.cpp \
+ kernel/qsystemsemaphore_symbian.cpp
+
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h \
+ kernel/qeventdispatcher_symbian_p.h \
+ kernel/qcore_symbian_p.h
+}
+
+vxworks {
+ SOURCES += \
+ kernel/qfunctions_vxworks.cpp
+ HEADERS += \
+ kernel/qfunctions_vxworks.h
+}
+
+
+integrity {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp \
+ kernel/qeventdispatcher_unix.cpp
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h \
+ kernel/qeventdispatcher_unix_p.h
+
+ contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
+}
+
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
new file mode 100644
index 0000000000..2949cd0d3a
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstracteventdispatcher.h"
+#include "qabstracteventdispatcher_p.h"
+
+#include "qthread.h"
+#include <private/qthread_p.h>
+#include <private/qcoreapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
+static const int TimerIdMask = 0x00ffffff;
+static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
+static const int TimerSerialCounter = TimerIdMask + 1;
+static const int MaxTimerId = TimerIdMask;
+
+static int FirstBucket[] = {
+ 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, 28, 29, 30, 31, 32
+};
+
+enum {
+ FirstBucketOffset = 0,
+ SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]),
+ ThirdBucketOffset = 0x100,
+ FourthBucketOffset = 0x1000,
+ FifthBucketOffset = 0x10000,
+ SixthBucketOffset = 0x100000
+};
+
+enum {
+ FirstBucketSize = SecondBucketOffset,
+ SecondBucketSize = ThirdBucketOffset - SecondBucketOffset,
+ ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset,
+ FourthBucketSize = FifthBucketOffset - FourthBucketOffset,
+ FifthBucketSize = SixthBucketOffset - FifthBucketOffset,
+ SixthBucketSize = MaxTimerId - SixthBucketOffset
+};
+
+static const int BucketSize[] = {
+ FirstBucketSize, SecondBucketSize, ThirdBucketSize,
+ FourthBucketSize, FifthBucketSize, SixthBucketSize
+};
+enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) };
+
+static const int BucketOffset[] = {
+ FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset,
+ FourthBucketOffset, FifthBucketOffset, SixthBucketOffset
+};
+
+static QBasicAtomicPointer<int> timerIds[] =
+ { Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0) };
+
+static void timerIdsDestructorFunction()
+{
+ // start at one, the first bucket is pre-allocated
+ for (int i = 1; i < NumberOfBuckets; ++i)
+ delete [] static_cast<int *>(timerIds[i]);
+}
+Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
+
+static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
+
+// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
+static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
+{
+ return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
+}
+
+namespace {
+ template<bool> struct QStaticAssertType;
+ template<> struct QStaticAssertType<true> { enum { Value = 1 }; };
+}
+#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value
+
+static inline int bucketOffset(int timerId)
+{
+ q_static_assert(sizeof BucketSize == sizeof BucketOffset);
+ q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets);
+
+ for (int i = 0; i < NumberOfBuckets; ++i) {
+ if (timerId < BucketSize[i])
+ return i;
+ timerId -= BucketSize[i];
+ }
+ qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
+ return -1;
+}
+
+static inline int bucketIndex(int bucket, int timerId)
+{
+ return timerId - BucketOffset[bucket];
+}
+
+static inline int *allocateBucket(int bucket)
+{
+ // allocate a new bucket
+ const int size = BucketSize[bucket];
+ const int offset = BucketOffset[bucket];
+ int *b = new int[size];
+ for (int i = 0; i != size; ++i)
+ b[i] = offset + i + 1;
+ return b;
+}
+
+void QAbstractEventDispatcherPrivate::init()
+{
+ Q_Q(QAbstractEventDispatcher);
+ if (threadData->eventDispatcher != 0) {
+ qWarning("QAbstractEventDispatcher: An event dispatcher has already been created for this thread");
+ } else {
+ threadData->eventDispatcher = q;
+ }
+}
+
+// Timer IDs are implemented using a free-list;
+// there's a vector initialized with:
+// X[i] = i + 1
+// and nextFreeTimerId starts with 1.
+//
+// Allocating a timer ID involves taking the ID from
+// X[nextFreeTimerId]
+// updating nextFreeTimerId to this value and returning the old value
+//
+// When the timer ID is allocated, its cell in the vector is unused (it's a
+// free list). As an added protection, we use the cell to store an invalid
+// (negative) value that we can later check for integrity.
+//
+// (continues below).
+int QAbstractEventDispatcherPrivate::allocateTimerId()
+{
+ int timerId, newTimerId;
+ int at, *b;
+ do {
+ timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics
+
+ // which bucket are we looking in?
+ int which = timerId & TimerIdMask;
+ int bucket = bucketOffset(which);
+ at = bucketIndex(bucket, which);
+ b = timerIds[bucket];
+
+ if (!b) {
+ // allocate a new bucket
+ b = allocateBucket(bucket);
+ if (!timerIds[bucket].testAndSetRelease(0, b)) {
+ // another thread won the race to allocate the bucket
+ delete [] b;
+ b = timerIds[bucket];
+ }
+ }
+
+ newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]);
+ } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
+
+ b[at] = -timerId;
+
+ return timerId;
+}
+
+// Releasing a timer ID requires putting the current ID back in the vector;
+// we do it by setting:
+// X[timerId] = nextFreeTimerId;
+// then we update nextFreeTimerId to the timer we've just released
+//
+// The extra code in allocateTimerId and releaseTimerId are ABA prevention
+// and bucket memory. The buckets are simply to make sure we allocate only
+// the necessary number of timers. See above.
+//
+// ABA prevention simply adds a value to 7 of the top 8 bits when resetting
+// nextFreeTimerId.
+void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
+{
+ int which = timerId & TimerIdMask;
+ int bucket = bucketOffset(which);
+ int at = bucketIndex(bucket, which);
+ int *b = timerIds[bucket];
+
+ Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
+ "Internal error: timer ID not found");
+
+ int freeId, newTimerId;
+ do {
+ freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics
+ b[at] = freeId & TimerIdMask;
+
+ newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
+ } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
+}
+
+/*!
+ \class QAbstractEventDispatcher
+ \brief The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
+
+ \ingroup events
+
+ An event dispatcher receives events from the window system and other
+ sources. It then sends them to the QCoreApplication or QApplication
+ instance for processing and delivery. QAbstractEventDispatcher provides
+ fine-grained control over event delivery.
+
+ For simple control of event processing use
+ QCoreApplication::processEvents().
+
+ For finer control of the application's event loop, call
+ instance() and call functions on the QAbstractEventDispatcher
+ object that is returned. If you want to use your own instance of
+ QAbstractEventDispatcher or of a QAbstractEventDispatcher
+ subclass, you must create your instance \e before you create the
+ QApplication object.
+
+ The main event loop is started by calling
+ QCoreApplication::exec(), and stopped by calling
+ QCoreApplication::exit(). Local event loops can be created using
+ QEventLoop.
+
+ Programs that perform long operations can call processEvents()
+ with a bitwise OR combination of various QEventLoop::ProcessEventsFlag
+ values to control which events should be delivered.
+
+ QAbstractEventDispatcher also allows the integration of an
+ external event loop with the Qt event loop. For example, the
+ \l{Qt Solutions}{Motif Extension Qt Solution} includes a
+ reimplementation of QAbstractEventDispatcher that merges Qt and
+ Motif events together.
+
+ \sa QEventLoop, QCoreApplication
+*/
+
+/*!
+ Constructs a new event dispatcher with the given \a parent.
+*/
+QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
+ : QObject(*new QAbstractEventDispatcherPrivate, parent)
+{
+ Q_D(QAbstractEventDispatcher);
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,
+ QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QAbstractEventDispatcher);
+ d->init();
+}
+
+/*!
+ Destroys the event dispatcher.
+*/
+QAbstractEventDispatcher::~QAbstractEventDispatcher()
+{ }
+
+/*!
+ Returns a pointer to the event dispatcher object for the specified
+ \a thread. If \a thread is zero, the current thread is used. If no
+ event dispatcher exists for the specified thread, this function
+ returns 0.
+
+ \bold{Note:} If Qt is built without thread support, the \a thread
+ argument is ignored.
+ */
+QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
+{
+ QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
+ return data->eventDispatcher;
+}
+
+/*!
+ \fn bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+
+ Processes pending events that match \a flags until there are no
+ more events to process. Returns true if an event was processed;
+ otherwise returns false.
+
+ 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 QEventLoop::ExcludeUserInputEvents flag.
+
+ If the QEventLoop::WaitForMoreEvents flag is set in \a flags, the
+ behavior of this function is as follows:
+
+ \list
+
+ \i If events are available, this function returns after processing
+ them.
+
+ \i If no events are available, this function will wait until more
+ are available and return after processing newly available events.
+
+ \endlist
+
+ If the QEventLoop::WaitForMoreEvents flag is not set in \a flags,
+ and no events are available, this function will return
+ immediately.
+
+ \bold{Note:} This function does not process events continuously; it
+ returns after all available events are processed.
+
+ \sa hasPendingEvents()
+*/
+
+/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
+
+ Returns true if there is an event waiting; otherwise returns
+ false.
+*/
+
+/*!
+ \fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
+
+ Registers \a notifier with the event loop. Subclasses must
+ implement this method to tie a socket notifier into another
+ event loop.
+*/
+
+/*! \fn void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
+
+ Unregisters \a notifier from the event dispatcher. Subclasses must
+ reimplement this method to tie a socket notifier into another
+ event loop. Reimplementations must call the base
+ implementation.
+*/
+
+/*!
+ \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+
+ Registers a timer with the specified \a interval for the given \a object.
+*/
+int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+{
+ int id = QAbstractEventDispatcherPrivate::allocateTimerId();
+ registerTimer(id, interval, object);
+ return id;
+}
+
+/*!
+ \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
+
+ Register a timer with the specified \a timerId and \a interval for
+ the given \a object.
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimer(int timerId)
+
+ Unregisters the timer with the given \a timerId.
+ Returns true if successful; otherwise returns false.
+
+ \sa registerTimer(), unregisterTimers()
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
+
+ Unregisters all the timers associated with the given \a object.
+ Returns true if all timers were successful removed; otherwise returns false.
+
+ \sa unregisterTimer(), registeredTimers()
+*/
+
+/*!
+ \fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
+
+ Returns a list of registered timers for \a object. The timer ID
+ is the first member in each pair; the interval is the second.
+*/
+
+/*! \fn void QAbstractEventDispatcher::wakeUp()
+ \threadsafe
+
+ Wakes up the event loop.
+
+ \sa awake()
+*/
+
+/*!
+ \fn void QAbstractEventDispatcher::interrupt()
+
+ Interrupts event dispatching; i.e. the event dispatcher will
+ return from processEvents() as soon as possible.
+*/
+
+/*! \fn void QAbstractEventDispatcher::flush()
+
+ Flushes the event queue. This normally returns almost
+ immediately. Does nothing on platforms other than X11.
+*/
+
+// ### DOC: Are these called when the _application_ starts/stops or just
+// when the current _event loop_ starts/stops?
+/*! \internal */
+void QAbstractEventDispatcher::startingUp()
+{ }
+
+/*! \internal */
+void QAbstractEventDispatcher::closingDown()
+{ }
+
+/*!
+ \typedef QAbstractEventDispatcher::TimerInfo
+
+ Typedef for QPair<int, int>. The first component of
+ the pair is the timer ID; the second component is
+ the interval.
+
+ \sa registeredTimers()
+*/
+
+/*!
+ \typedef QAbstractEventDispatcher::EventFilter
+
+ Typedef for a function with the signature
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstracteventdispatcher.cpp 0
+
+ Note that the type of the \a message is platform dependent. The
+ following table shows the \a {message}'s type on Windows, Mac, and
+ X11. You can do a static cast to these types.
+
+ \table
+ \header
+ \o Platform
+ \o type
+ \row
+ \o Windows
+ \o MSG
+ \row
+ \o X11
+ \o XEvent
+ \row
+ \o Mac
+ \o NSEvent
+ \endtable
+
+
+
+ \sa setEventFilter(), filterEvent()
+*/
+
+/*!
+ Replaces the event filter function for this
+ QAbstractEventDispatcher with \a filter and returns the replaced
+ event filter function. Only the current event filter function is
+ called. If you want to use both filter functions, save the
+ replaced EventFilter in a place where yours can call it.
+
+ The event filter function set here is called for all messages
+ taken from the system event loop before the event is dispatched to
+ the respective target, including the messages not meant for Qt
+ objects.
+
+ The event filter function should return true if the message should
+ be filtered, (i.e. stopped). It should return false to allow
+ processing the message to continue.
+
+ By default, no event filter function is set (i.e., this function
+ returns a null EventFilter the first time it is called).
+*/
+QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
+{
+ Q_D(QAbstractEventDispatcher);
+ EventFilter oldFilter = d->event_filter;
+ d->event_filter = filter;
+ return oldFilter;
+}
+
+/*!
+ Sends \a message through the event filter that was set by
+ setEventFilter(). If no event filter has been set, this function
+ returns false; otherwise, this function returns the result of the
+ event filter function.
+
+ Subclasses of QAbstractEventDispatcher \e must call this function
+ for \e all messages received from the system to ensure
+ compatibility with any extensions that may be used in the
+ application.
+
+ Note that the type of \a message is platform dependent. See
+ QAbstractEventDispatcher::EventFilter for details.
+
+ \sa setEventFilter()
+*/
+bool QAbstractEventDispatcher::filterEvent(void *message)
+{
+ Q_D(QAbstractEventDispatcher);
+ if (d->event_filter)
+ return d->event_filter(message);
+ return false;
+}
+
+/*! \fn void QAbstractEventDispatcher::awake()
+
+ This signal is emitted after the event loop returns from a
+ function that could block.
+
+ \sa wakeUp() aboutToBlock()
+*/
+
+/*! \fn void QAbstractEventDispatcher::aboutToBlock()
+
+ This signal is emitted before the event loop calls a function that
+ could block.
+
+ \sa awake()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
new file mode 100644
index 0000000000..212b832ae2
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTEVENTDISPATCHER_H
+#define QABSTRACTEVENTDISPATCHER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qeventloop.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractEventDispatcherPrivate;
+class QSocketNotifier;
+template <typename T1, typename T2> struct QPair;
+
+class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractEventDispatcher)
+
+public:
+ typedef QPair<int, int> TimerInfo;
+
+ explicit QAbstractEventDispatcher(QObject *parent = 0);
+ ~QAbstractEventDispatcher();
+
+ static QAbstractEventDispatcher *instance(QThread *thread = 0);
+
+ virtual bool processEvents(QEventLoop::ProcessEventsFlags flags) = 0;
+ virtual bool hasPendingEvents() = 0;
+
+ virtual void registerSocketNotifier(QSocketNotifier *notifier) = 0;
+ virtual void unregisterSocketNotifier(QSocketNotifier *notifier) = 0;
+
+ int registerTimer(int interval, QObject *object);
+ virtual void registerTimer(int timerId, int interval, QObject *object) = 0;
+ virtual bool unregisterTimer(int timerId) = 0;
+ virtual bool unregisterTimers(QObject *object) = 0;
+ virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0;
+
+ virtual void wakeUp() = 0;
+ virtual void interrupt() = 0;
+ virtual void flush() = 0;
+
+ virtual void startingUp();
+ virtual void closingDown();
+
+ typedef bool(*EventFilter)(void *message);
+ EventFilter setEventFilter(EventFilter filter);
+ bool filterEvent(void *message);
+
+Q_SIGNALS:
+ void aboutToBlock();
+ void awake();
+
+protected:
+ QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &,
+ QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTEVENTDISPATCHER_H
diff --git a/src/corelib/kernel/qabstracteventdispatcher_p.h b/src/corelib/kernel/qabstracteventdispatcher_p.h
new file mode 100644
index 0000000000..4a55dfba09
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTEVENTDISPATCHER_P_H
+#define QABSTRACTEVENTDISPATCHER_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/qabstracteventdispatcher.h"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT uint qGlobalPostedEventsCount();
+
+class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
+public:
+ inline QAbstractEventDispatcherPrivate()
+ : event_filter(0)
+ { }
+ void init();
+ QAbstractEventDispatcher::EventFilter event_filter;
+
+ static int allocateTimerId();
+ static void releaseTimerId(int id);
+};
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTEVENTDISPATCHER_P_H
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
new file mode 100644
index 0000000000..9dd22dc39b
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -0,0 +1,3454 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractitemmodel.h"
+#include <private/qabstractitemmodel_p.h>
+#include <qdatastream.h>
+#include <qstringlist.h>
+#include <qsize.h>
+#include <qmimedata.h>
+#include <qdebug.h>
+#include <qvector.h>
+#include <qstack.h>
+#include <qbitarray.h>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index)
+{
+ Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
+ QPersistentModelIndexData *d = 0;
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
+ QHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = indexes.find(index);
+ if (it != indexes.end()) {
+ d = (*it);
+ } else {
+ d = new QPersistentModelIndexData(index);
+ indexes.insert(index, d);
+ }
+ Q_ASSERT(d);
+ return d;
+}
+
+void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
+{
+ Q_ASSERT(data);
+ Q_ASSERT(data->ref == 0);
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->model);
+ // a valid persistent model index with a null model pointer can only happen if the model was destroyed
+ if (model) {
+ QAbstractItemModelPrivate *p = model->d_func();
+ Q_ASSERT(p);
+ p->removePersistentIndexData(data);
+ }
+ delete data;
+}
+
+/*!
+ \class QPersistentModelIndex
+
+ \brief The QPersistentModelIndex class is used to locate data in a data model.
+
+ \ingroup model-view
+
+ A QPersistentModelIndex is a model index that can be stored by an
+ application, and later used to access information in a model.
+ Unlike the QModelIndex class, it is safe to store a
+ QPersistentModelIndex since the model will ensure that references
+ to items will continue to be valid as long as they can be accessed
+ by the model.
+
+ It is good practice to check that persistent model indexes are valid
+ before using them.
+
+ \sa {Model/View Programming}, QModelIndex, QAbstractItemModel
+*/
+
+
+/*!
+ \fn QPersistentModelIndex::QPersistentModelIndex()
+
+ \internal
+*/
+
+QPersistentModelIndex::QPersistentModelIndex()
+ : d(0)
+{
+}
+
+/*!
+ \fn QPersistentModelIndex::QPersistentModelIndex(const QPersistentModelIndex &other)
+
+ Creates a new QPersistentModelIndex that is a copy of the \a other persistent
+ model index.
+*/
+
+QPersistentModelIndex::QPersistentModelIndex(const QPersistentModelIndex &other)
+ : d(other.d)
+{
+ if (d) d->ref.ref();
+}
+
+/*!
+ Creates a new QPersistentModelIndex that is a copy of the model \a index.
+*/
+
+QPersistentModelIndex::QPersistentModelIndex(const QModelIndex &index)
+ : d(0)
+{
+ if (index.isValid()) {
+ d = QPersistentModelIndexData::create(index);
+ d->ref.ref();
+ }
+}
+
+/*!
+ \fn QPersistentModelIndex::~QPersistentModelIndex()
+
+ \internal
+*/
+
+QPersistentModelIndex::~QPersistentModelIndex()
+{
+ if (d && !d->ref.deref()) {
+ QPersistentModelIndexData::destroy(d);
+ d = 0;
+ }
+}
+
+/*!
+ Returns true if this persistent model index is equal to the \a other
+ persistent model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing
+ with another persistent model index.
+*/
+
+bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
+{
+ if (d && other.d)
+ return d->index == other.d->index;
+ return d == other.d;
+}
+
+/*!
+ \since 4.1
+
+ Returns true if this persistent model index is smaller than the \a other
+ persistent model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing
+ with another persistent model index.
+*/
+
+bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const
+{
+ if (d && other.d)
+ return d->index < other.d->index;
+
+ return d < other.d;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator!=(const QPersistentModelIndex &other) const
+ \since 4.2
+
+ Returns true if this persistent model index is not equal to the \a
+ other persistent model index; otherwise returns false.
+*/
+
+/*!
+ Sets the persistent model index to refer to the same item in a model
+ as the \a other persistent model index.
+*/
+
+QPersistentModelIndex &QPersistentModelIndex::operator=(const QPersistentModelIndex &other)
+{
+ if (d == other.d)
+ return *this;
+ if (d && !d->ref.deref())
+ QPersistentModelIndexData::destroy(d);
+ d = other.d;
+ if (d) d->ref.ref();
+ return *this;
+}
+
+/*!
+ Sets the persistent model index to refer to the same item in a model
+ as the \a other model index.
+*/
+
+QPersistentModelIndex &QPersistentModelIndex::operator=(const QModelIndex &other)
+{
+ if (d && !d->ref.deref())
+ QPersistentModelIndexData::destroy(d);
+ if (other.isValid()) {
+ d = QPersistentModelIndexData::create(other);
+ if (d) d->ref.ref();
+ } else {
+ d = 0;
+ }
+ return *this;
+}
+
+/*!
+ \fn QPersistentModelIndex::operator const QModelIndex&() const
+
+ Cast operator that returns a const QModelIndex&.
+*/
+
+QPersistentModelIndex::operator const QModelIndex&() const
+{
+ static const QModelIndex invalid;
+ if (d)
+ return d->index;
+ return invalid;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+
+ Returns true if this persistent model index refers to the same location as
+ the \a other model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing with
+ another model index.
+*/
+
+bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+{
+ if (d)
+ return d->index == other;
+ return !other.isValid();
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+
+ Returns true if this persistent model index does not refer to the same
+ location as the \a other model index; otherwise returns false.
+*/
+
+bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+{
+ if (d)
+ return d->index != other;
+ return other.isValid();
+}
+
+/*!
+ \fn int QPersistentModelIndex::row() const
+
+ Returns the row this persistent model index refers to.
+*/
+
+int QPersistentModelIndex::row() const
+{
+ if (d)
+ return d->index.row();
+ return -1;
+}
+
+/*!
+ \fn int QPersistentModelIndex::column() const
+
+ Returns the column this persistent model index refers to.
+*/
+
+int QPersistentModelIndex::column() const
+{
+ if (d)
+ return d->index.column();
+ return -1;
+}
+
+/*!
+ \fn void *QPersistentModelIndex::internalPointer() const
+
+ \internal
+
+ Returns a \c{void} \c{*} pointer used by the model to associate the index with
+ the internal data structure.
+*/
+
+void *QPersistentModelIndex::internalPointer() const
+{
+ if (d)
+ return d->index.internalPointer();
+ return 0;
+}
+
+/*!
+ \fn void *QPersistentModelIndex::internalId() const
+
+ \internal
+
+ Returns a \c{qint64} used by the model to associate the index with
+ the internal data structure.
+*/
+
+qint64 QPersistentModelIndex::internalId() const
+{
+ if (d)
+ return d->index.internalId();
+ return 0;
+}
+
+/*!
+ Returns the parent QModelIndex for this persistent index, or an invalid
+ QModelIndex if it has no parent.
+
+ \sa child() sibling() model()
+*/
+QModelIndex QPersistentModelIndex::parent() const
+{
+ if (d)
+ return d->index.parent();
+ return QModelIndex();
+}
+
+/*!
+ Returns the sibling at \a row and \a column or an invalid QModelIndex if
+ there is no sibling at this position.
+
+ \sa parent() child()
+*/
+
+QModelIndex QPersistentModelIndex::sibling(int row, int column) const
+{
+ if (d)
+ return d->index.sibling(row, column);
+ return QModelIndex();
+}
+
+/*!
+ Returns the child of the model index that is stored in the given \a row
+ and \a column.
+
+ \sa parent() sibling()
+*/
+
+QModelIndex QPersistentModelIndex::child(int row, int column) const
+{
+ if (d)
+ return d->index.child(row, column);
+ return QModelIndex();
+}
+
+/*!
+ Returns the data for the given \a role for the item referred to by the
+ index.
+
+ \sa Qt::ItemDataRole, QAbstractItemModel::setData()
+*/
+QVariant QPersistentModelIndex::data(int role) const
+{
+ if (d)
+ return d->index.data(role);
+ return QVariant();
+}
+
+/*!
+ \since 4.2
+
+ Returns the flags for the item referred to by the index.
+*/
+Qt::ItemFlags QPersistentModelIndex::flags() const
+{
+ if (d)
+ return d->index.flags();
+ return 0;
+}
+
+/*!
+ Returns the model that the index belongs to.
+*/
+const QAbstractItemModel *QPersistentModelIndex::model() const
+{
+ if (d)
+ return d->index.model();
+ return 0;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::isValid() const
+
+ Returns true if this persistent model index is valid; otherwise returns
+ false.
+
+ A valid index belongs to a model, and has non-negative row and column
+ numbers.
+
+ \sa model(), row(), column()
+*/
+
+bool QPersistentModelIndex::isValid() const
+{
+ return d && d->index.isValid();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QModelIndex &idx)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QModelIndex(" << idx.row() << ',' << idx.column()
+ << ',' << idx.internalPointer() << ',' << idx.model() << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QModelIndex to QDebug");
+ return dbg;
+ Q_UNUSED(idx);
+#endif
+}
+
+QDebug operator<<(QDebug dbg, const QPersistentModelIndex &idx)
+{
+ if (idx.d)
+ dbg << idx.d->index;
+ else
+ dbg << QModelIndex();
+ return dbg;
+}
+#endif
+
+class QEmptyItemModel : public QAbstractItemModel
+{
+public:
+ explicit QEmptyItemModel(QObject *parent = 0) : QAbstractItemModel(parent) {}
+ QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); }
+ QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+ int rowCount(const QModelIndex &) const { return 0; }
+ int columnCount(const QModelIndex &) const { return 0; }
+ bool hasChildren(const QModelIndex &) const { return false; }
+ QVariant data(const QModelIndex &, int) const { return QVariant(); }
+};
+
+Q_GLOBAL_STATIC(QEmptyItemModel, qEmptyModel)
+
+QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
+{
+ return qEmptyModel();
+}
+
+namespace {
+ struct DefaultRoleNames : public QHash<int, QByteArray>
+ {
+ DefaultRoleNames() {
+ (*this)[Qt::DisplayRole] = "display";
+ (*this)[Qt::DecorationRole] = "decoration";
+ (*this)[Qt::EditRole] = "edit";
+ (*this)[Qt::ToolTipRole] = "toolTip";
+ (*this)[Qt::StatusTipRole] = "statusTip";
+ (*this)[Qt::WhatsThisRole] = "whatsThis";
+ }
+ };
+}
+
+Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames)
+
+const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
+{
+ return *qDefaultRoleNames();
+}
+
+
+static uint typeOfVariant(const QVariant &value)
+{
+ //return 0 for integer, 1 for floating point and 2 for other
+ switch (value.userType()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Char:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ return 0;
+ case QVariant::Double:
+ case QMetaType::Float:
+ return 1;
+ default:
+ return 2;
+ }
+}
+
+/*!
+ \internal
+ return true if \a value contains a numerical type
+
+ This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort.
+*/
+bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVariant &v2)
+{
+ switch(qMax(typeOfVariant(v1), typeOfVariant(v2)))
+ {
+ case 0: //integer type
+ return v1.toLongLong() < v2.toLongLong();
+ case 1: //floating point
+ return v1.toReal() < v2.toReal();
+ default:
+ return v1.toString().localeAwareCompare(v2.toString()) < 0;
+ }
+}
+
+void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
+{
+ if (data->index.isValid()) {
+ int removed = persistent.indexes.remove(data->index);
+ Q_ASSERT_X(removed == 1, "QPersistentModelIndex::~QPersistentModelIndex",
+ "persistent model indexes corrupted"); //maybe the index was somewhat invalid?
+ // This assert may happen if the model use changePersistentIndex in a way that could result on two
+ // QPersistentModelIndex pointing to the same index.
+ Q_UNUSED(removed);
+ }
+ // make sure our optimization still works
+ for (int i = persistent.moved.count() - 1; i >= 0; --i) {
+ int idx = persistent.moved[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) {
+ int idx = persistent.invalidated[i].indexOf(data);
+ if (idx >= 0)
+ persistent.invalidated[i].remove(idx);
+ }
+
+}
+
+void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ Q_Q(QAbstractItemModel);
+ Q_UNUSED(last);
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ if (first < q->rowCount(parent)) {
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ if (index.row() >= first && index.isValid() && index.parent() == parent) {
+ persistent_moved.append(data);
+ }
+ }
+ }
+ persistent.moved.push(persistent_moved);
+}
+
+void QAbstractItemModelPrivate::rowsInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row() + count, old.column(), parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << ',' << old.column() << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved_explicitly;
+ QVector<QPersistentModelIndexData *> persistent_moved_in_source;
+ QVector<QPersistentModelIndexData *> persistent_moved_in_destination;
+
+ QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator begin = persistent.indexes.constBegin();
+ const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator end = persistent.indexes.constEnd();
+
+ const bool sameParent = (srcParent == destinationParent);
+ const bool movingUp = (srcFirst > destinationChild);
+
+ for ( it = begin; it != end; ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ const QModelIndex &parent = index.parent();
+ const bool isSourceIndex = (parent == srcParent);
+ const bool isDestinationIndex = (parent == destinationParent);
+
+ int childPosition;
+ if (orientation == Qt::Vertical)
+ childPosition = index.row();
+ else
+ childPosition = index.column();
+
+ if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
+ continue;
+
+ if (!sameParent && isDestinationIndex) {
+ if (childPosition >= destinationChild)
+ persistent_moved_in_destination.append(data);
+ continue;
+ }
+
+ if (sameParent && movingUp && childPosition < destinationChild)
+ continue;
+
+ if (sameParent && !movingUp && childPosition < srcFirst )
+ continue;
+
+ if (!sameParent && childPosition < srcFirst)
+ continue;
+
+ if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
+ continue;
+
+ if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
+ persistent_moved_explicitly.append(data);
+ } else {
+ persistent_moved_in_source.append(data);
+ }
+ }
+ persistent.moved.push(persistent_moved_explicitly);
+ persistent.moved.push(persistent_moved_in_source);
+ persistent.moved.push(persistent_moved_in_destination);
+}
+
+/*!
+ \internal
+
+ Moves persistent indexes \a indexes by amount \a change. The change will be either a change in row value or a change in
+ column value depending on the value of \a orientation. The indexes may also be moved to a different parent if \a parent
+ differs from the existing parent for the index.
+*/
+void QAbstractItemModelPrivate::movePersistentIndexes(QVector<QPersistentModelIndexData *> indexes, int change, const QModelIndex &parent, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *>::const_iterator it;
+ const QVector<QPersistentModelIndexData *>::const_iterator begin = indexes.constBegin();
+ const QVector<QPersistentModelIndexData *>::const_iterator end = indexes.constEnd();
+
+ for (it = begin; it != end; ++it)
+ {
+ QPersistentModelIndexData *data = *it;
+
+ int row = data->index.row();
+ int column = data->index.column();
+
+ if (Qt::Vertical == orientation)
+ row += change;
+ else
+ column += change;
+
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = q_func()->index(row, column, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endMoveRows: Invalid index (" << row << "," << column << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::itemsMoved(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
+ QVector<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
+ QVector<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
+
+ const bool sameParent = (sourceParent == destinationParent);
+ const bool movingUp = (sourceFirst > destinationChild);
+
+ const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
+ const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
+ const int destination_change = sourceLast - sourceFirst + 1;
+
+ movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
+ movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
+ movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
+}
+
+void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ QVector<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 (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ bool level_changed = false;
+ QModelIndex current = data->index;
+ while (current.isValid()) {
+ QModelIndex current_parent = current.parent();
+ if (current_parent == parent) { // on the same level as the change
+ if (!level_changed && current.row() > last) // below the removed rows
+ persistent_moved.append(data);
+ else if (current.row() <= last && current.row() >= first) // in the removed subtree
+ persistent_invalidated.append(data);
+ break;
+ }
+ current = current_parent;
+ level_changed = true;
+ }
+ }
+
+ persistent.moved.push(persistent_moved);
+ persistent.invalidated.push(persistent_invalidated);
+}
+
+void QAbstractItemModelPrivate::rowsRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row() - count, old.column(), parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << ',' << old.column() << ") in model" << q_func();
+ }
+ }
+ QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin();
+ it != persistent_invalidated.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+}
+
+void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ Q_Q(QAbstractItemModel);
+ Q_UNUSED(last);
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ if (first < q->columnCount(parent)) {
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ if (index.column() >= first && index.isValid() && index.parent() == parent)
+ persistent_moved.append(data);
+ }
+ }
+ persistent.moved.push(persistent_moved);
+}
+
+void QAbstractItemModelPrivate::columnsInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row(), old.column() + count, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << ',' << old.column() + count << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ QVector<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 (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ bool level_changed = false;
+ QModelIndex current = data->index;
+ while (current.isValid()) {
+ QModelIndex current_parent = current.parent();
+ if (current_parent == parent) { // on the same level as the change
+ if (!level_changed && current.column() > last) // right of the removed columns
+ persistent_moved.append(data);
+ else if (current.column() <= last && current.column() >= first) // in the removed subtree
+ persistent_invalidated.append(data);
+ break;
+ }
+ current = current_parent;
+ level_changed = true;
+ }
+ }
+
+ persistent.moved.push(persistent_moved);
+ persistent.invalidated.push(persistent_invalidated);
+
+}
+
+void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row(), old.column() - count, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << ',' << old.column() - count << ") in model" << q_func();
+ }
+ }
+ QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin();
+ it != persistent_invalidated.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+}
+
+/*!
+ \class QModelIndex
+
+ \brief The QModelIndex class is used to locate data in a data model.
+
+ \ingroup model-view
+
+
+ This class is used as an index into item models derived from
+ QAbstractItemModel. The index is used by item views, delegates, and
+ selection models to locate an item in the model.
+
+ New QModelIndex objects are created by the model using the
+ QAbstractItemModel::createIndex() function. An \e invalid model index can
+ be constructed with the QModelIndex constructor. Invalid indexes are often
+ used as parent indexes when referring to top-level items in a model.
+
+ Model indexes refer to items in models, and contain all the information
+ required to specify their locations in those models. Each index is located
+ in a given row and column, and may have a parent index; use row(),
+ column(), and parent() to obtain this information. Each top-level item in a
+ model is represented by a model index that does not have a parent index -
+ in this case, parent() will return an invalid model index, equivalent to an
+ index constructed with the zero argument form of the QModelIndex()
+ constructor.
+
+ To obtain a model index that refers to an existing item in a model, call
+ QAbstractItemModel::index() with the required row and column values, and
+ the model index of the parent. When referring to top-level items in a
+ model, supply QModelIndex() as the parent index.
+
+ The model() function returns the model that the index references as a
+ QAbstractItemModel. The child() function is used to examine items held
+ under the index in the model. The sibling() function allows you to traverse
+ items in the model on the same level as the index.
+
+ \note Model indexes should be used immediately and then discarded. You
+ should not rely on indexes to remain valid after calling model functions
+ that change the structure of the model or delete items. If you need to
+ keep a model index over time use a QPersistentModelIndex.
+
+ \sa {Model/View Programming}, QPersistentModelIndex, QAbstractItemModel
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex()
+
+ Creates a new empty model index. This type of model index is used to
+ indicate that the position in the model is invalid.
+
+ \sa isValid() QAbstractItemModel
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex(int row, int column, void *data, const QAbstractItemModel *model)
+
+ \internal
+
+ Creates a new model index at the given \a row and \a column,
+ pointing to some \a data.
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex(const QModelIndex &other)
+
+ Creates a new model index that is a copy of the \a other model
+ index.
+*/
+
+/*!
+ \fn QModelIndex::~QModelIndex()
+
+ Destroys the model index.
+*/
+
+/*!
+ \fn int QModelIndex::row() const
+
+ Returns the row this model index refers to.
+*/
+
+
+/*!
+ \fn int QModelIndex::column() const
+
+ Returns the column this model index refers to.
+*/
+
+
+/*!
+ \fn void *QModelIndex::internalPointer() const
+
+ Returns a \c{void} \c{*} pointer used by the model to associate
+ the index with the internal data structure.
+
+ \sa QAbstractItemModel::createIndex()
+*/
+
+/*!
+ \fn void *QModelIndex::internalId() const
+
+ Returns a \c{qint64} used by the model to associate
+ the index with the internal data structure.
+
+ \sa QAbstractItemModel::createIndex()
+*/
+
+/*!
+ \fn bool QModelIndex::isValid() const
+
+ Returns true if this model index is valid; otherwise returns false.
+
+ A valid index belongs to a model, and has non-negative row and column
+ numbers.
+
+ \sa model(), row(), column()
+*/
+
+/*!
+ \fn const QAbstractItemModel *QModelIndex::model() const
+
+ Returns a pointer to the model containing the item that this index
+ refers to.
+
+ A const pointer to the model is returned because calls to non-const
+ functions of the model might invalidate the model index and possibly
+ crash your application.
+*/
+
+/*!
+ \fn QModelIndex QModelIndex::sibling(int row, int column) const
+
+ Returns the sibling at \a row and \a column. If there is no sibling at this
+ position, an invalid QModelIndex is returned.
+
+ \sa parent(), child()
+*/
+
+/*!
+ \fn QModelIndex QModelIndex::child(int row, int column) const
+
+ Returns the child of the model index that is stored in the given \a row and
+ \a column.
+
+ \note This function does not work for an invalid model index which is often
+ used as the root index.
+
+ \sa parent(), sibling()
+*/
+
+/*!
+ \fn QVariant QModelIndex::data(int role) const
+
+ Returns the data for the given \a role for the item referred to by the
+ index.
+*/
+
+/*!
+ \fn Qt::ItemFlags QModelIndex::flags() const
+ \since 4.2
+
+ Returns the flags for the item referred to by the index.
+*/
+
+/*!
+ \fn bool QModelIndex::operator==(const QModelIndex &other) const
+
+ Returns true if this model index refers to the same location as the
+ \a other model index; otherwise returns false.
+
+ All values in the model index are used when comparing with another model
+ index.
+*/
+
+
+/*!
+ \fn bool QModelIndex::operator!=(const QModelIndex &other) const
+
+ Returns true if this model index does not refer to the same location as
+ the \a other model index; otherwise returns false.
+*/
+
+
+/*!
+ \fn QModelIndex QModelIndex::parent() const
+
+ Returns the parent of the model index, or QModelIndex() if it has no
+ parent.
+
+ \sa child(), sibling(), model()
+*/
+
+/*!
+ \class QAbstractItemModel
+
+ \brief The QAbstractItemModel class provides the abstract interface for
+ item model classes.
+
+ \ingroup model-view
+
+
+ The QAbstractItemModel class defines the standard interface that item
+ models must use to be able to interoperate with other components in the
+ model/view architecture. It is not supposed to be instantiated directly.
+ Instead, you should subclass it to create new models.
+
+ The QAbstractItemModel class is one of the \l{Model/View Classes}
+ and is part of Qt's \l{Model/View Programming}{model/view framework}.
+
+ If you need a model to use with a QListView or a QTableView, you should
+ consider subclassing QAbstractListModel or QAbstractTableModel instead of
+ this class.
+
+ The underlying data model is exposed to views and delegates as a hierarchy
+ of tables. If you do not make use of the hierarchy, then the model is a
+ simple table of rows and columns. Each item has a unique index specified by
+ a QModelIndex.
+
+ \image modelindex-no-parent.png
+
+ Every item of data that can be accessed via a model has an associated model
+ index. You can obtain this model index using the index() function. Each
+ index may have a sibling() index; child items have a parent() index.
+
+ Each item has a number of data elements associated with it and they can be
+ retrieved by specifying a role (see \l Qt::ItemDataRole) to the model's
+ data() function. Data for all available roles can be obtained at the same
+ time using the itemData() function.
+
+ Data for each role is set using a particular \l Qt::ItemDataRole. Data for
+ individual roles are set individually with setData(), or they can be set
+ for all roles with setItemData().
+
+ Items can be queried with flags() (see \l Qt::ItemFlag) to see if they can
+ be selected, dragged, or manipulated in other ways.
+
+ If an item has child objects, hasChildren() returns true for the
+ corresponding index.
+
+ The model has a rowCount() and a columnCount() for each level of the
+ hierarchy. Rows and columns can be inserted and removed with insertRows(),
+ insertColumns(), removeRows(), and removeColumns().
+
+ The model emits signals to indicate changes. For example, dataChanged() is
+ emitted whenever items of data made available by the model are changed.
+ Changes to the headers supplied by the model cause headerDataChanged() to
+ be emitted. If the structure of the underlying data changes, the model can
+ emit layoutChanged() to indicate to any attached views that they should
+ redisplay any items shown, taking the new structure into account.
+
+ The items available through the model can be searched for particular data
+ using the match() function.
+
+ To sort the model, you can use sort().
+
+
+ \section1 Subclassing
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ When subclassing QAbstractItemModel, at the very least you must implement
+ index(), parent(), rowCount(), columnCount(), and data(). These functions
+ are used in all read-only models, and form the basis of editable models.
+
+ You can also reimplement hasChildren() to provide special behavior for
+ models where the implementation of rowCount() is expensive. This makes it
+ possible for models to restrict the amount of data requested by views, and
+ can be used as a way to implement lazy population of model data.
+
+ To enable editing in your model, you must also implement setData(), and
+ reimplement flags() to ensure that \c ItemIsEditable is returned. You can
+ also reimplement headerData() and setHeaderData() to control the way the
+ headers for your model are presented.
+
+ The dataChanged() and headerDataChanged() signals must be emitted
+ explicitly when reimplementing the setData() and setHeaderData() functions,
+ respectively.
+
+ Custom models need to create model indexes for other components to use. To
+ do this, call createIndex() with suitable row and column numbers for the
+ item, and an identifier for it, either as a pointer or as an integer value.
+ The combination of these values must be unique for each item. Custom models
+ typically use these unique identifiers in other reimplemented functions to
+ retrieve item data and access information about the item's parents and
+ children. See the \l{Simple Tree Model Example} for more information about
+ unique identifiers.
+
+ It is not necessary to support every role defined in Qt::ItemDataRole.
+ Depending on the type of data contained within a model, it may only be
+ useful to implement the data() function to return valid information for
+ some of the more common roles. Most models provide at least a textual
+ representation of item data for the Qt::DisplayRole, and well-behaved
+ models should also provide valid information for the Qt::ToolTipRole and
+ Qt::WhatsThisRole. Supporting these roles enables models to be used with
+ standard Qt views. However, for some models that handle highly-specialized
+ data, it may be appropriate to provide data only for user-defined roles.
+
+ Models that provide interfaces to resizable data structures can provide
+ implementations of insertRows(), removeRows(), insertColumns(),and
+ removeColumns(). When implementing these functions, it is important to
+ notify any connected views about changes to the model's dimensions both
+ \e before and \e after they occur:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows() \e before
+ inserting new rows into the data structure, and endInsertRows()
+ \e{immediately afterwards}.
+ \o An insertColumns() implementation must call beginInsertColumns()
+ \e before inserting new columns into the data structure, and
+ endInsertColumns() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows() \e before
+ the rows are removed from the data structure, and endRemoveRows()
+ \e{immediately afterwards}.
+ \o A removeColumns() implementation must call beginRemoveColumns()
+ \e before the columns are removed from the data structure, and
+ endRemoveColumns() \e{immediately afterwards}.
+ \endlist
+
+ The \e private signals that these functions emit give attached components
+ the chance to take action before any data becomes unavailable. The
+ encapsulation of the insert and remove operations with these begin and end
+ functions also enables the model to manage \l{QPersistentModelIndex}
+ {persistent model indexes} correctly. \bold{If you want selections to be
+ handled properly, you must ensure that you call these functions.} If you
+ insert or remove an item with children, you do not need to call these
+ functions for the child items. In other words, the parent item will take
+ care of its child items.
+
+ To create models that populate incrementally, you can reimplement
+ fetchMore() and canFetchMore(). If the reimplementation of fetchMore() adds
+ rows to the model, \l{QAbstractItemModel::}{beginInsertRows()} and
+ \l{QAbstractItemModel::}{endInsertRows()} must be called.
+
+ \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}
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent) const = 0
+
+ Returns the index of the item in the model specified by the given \a row,
+ \a column and \a parent index.
+
+ When reimplementing this function in a subclass, call createIndex() to
+ generate model indexes that other components can use to refer to items in
+ your model.
+
+ \sa createIndex()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::insertColumn(int column, const QModelIndex &parent)
+
+ Inserts a single column before the given \a column in the child items of
+ the \a parent specified.
+
+ Returns true if the column is inserted; otherwise returns false.
+
+ \sa insertColumns() insertRow() removeColumn()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::insertRow(int row, const QModelIndex &parent)
+
+ \note The base class implementation of this function does nothing and
+ returns false.
+
+ Inserts a single row before the given \a row in the child items of the
+ \a parent specified.
+
+ Returns true if the row is inserted; otherwise returns false.
+
+ \sa insertRows() insertColumn() removeRow()
+*/
+
+/*!
+ \fn QObject *QAbstractItemModel::parent() const
+ \internal
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const = 0
+
+ Returns the parent of the model item with the given \a index. If the item
+ has no parent, an invalid QModelIndex is returned.
+
+ A common convention used in models that expose tree data structures is that
+ only items in the first column have children. For that case, when
+ reimplementing this function in a subclass the column of the returned
+ QModelIndex would be 0.
+
+ When reimplementing this function in a subclass, be careful to avoid
+ calling QModelIndex member functions, such as QModelIndex::parent(), since
+ indexes belonging to your model will simply call your implementation,
+ leading to infinite recursion.
+
+ \sa createIndex()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::removeColumn(int column, const QModelIndex &parent)
+
+ Removes the given \a column from the child items of the \a parent
+ specified.
+
+ Returns true if the column is removed; otherwise returns false.
+
+ \sa removeColumns(), removeRow(), insertColumn()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::removeRow(int row, const QModelIndex &parent)
+
+ Removes the given \a row from the child items of the \a parent specified.
+
+ Returns true if the row is removed; otherwise returns false.
+
+ This is a convenience function that calls removeRows(). The
+ QAbstractItemModel implementation of removeRows() does nothing.
+
+ \sa removeRows(), removeColumn(), insertRow()
+*/
+
+/*!
+ \fn void QAbstractItemModel::headerDataChanged(Qt::Orientation orientation, int first, int last)
+
+ This signal is emitted whenever a header is changed. The \a orientation
+ indicates whether the horizontal or vertical header has changed. The
+ sections in the header from the \a first to the \a last need to be updated.
+
+ When reimplementing the setHeaderData() function, this signal must be
+ emitted explicitly.
+
+ If you are changing the number of columns or rows you do not need to emit
+ this signal, but use the begin/end functions (refer to the section on
+ subclassing in the QAbstractItemModel class description for details).
+
+ \sa headerData(), setHeaderData(), dataChanged()
+*/
+
+/*!
+ \fn void QAbstractItemModel::layoutAboutToBeChanged()
+ \since 4.2
+
+ This signal is emitted just before the layout of a model is changed.
+ Components connected to this signal use it to adapt to changes in the
+ model's layout.
+
+ Subclasses should update any persistent model indexes after emitting
+ layoutAboutToBeChanged().
+
+ \sa layoutChanged(), changePersistentIndex()
+*/
+
+/*!
+ \fn void QAbstractItemModel::layoutChanged()
+
+ This signal is emitted whenever the layout of items exposed by the model
+ has changed; for example, when the model has been sorted. When this signal
+ is received by a view, it should update the layout of items to reflect this
+ change.
+
+ When subclassing QAbstractItemModel or QAbstractProxyModel, ensure that you
+ emit layoutAboutToBeChanged() before changing the order of items or
+ altering the structure of the data you expose to views, and emit
+ layoutChanged() after changing the layout.
+
+ Subclasses should update any persistent model indexes before emitting
+ layoutChanged(). In other words, when the structure changes:
+
+ \list
+ \o emit layoutAboutToBeChanged
+ \o Remember the QModelIndex that will change
+ \o Update your internal data
+ \o Call changePersistentIndex()
+ \o emit layoutChanged
+ \endlist
+
+ \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), modelReset(),
+ changePersistentIndex()
+*/
+
+/*!
+ Constructs an abstract item model with the given \a parent.
+*/
+QAbstractItemModel::QAbstractItemModel(QObject *parent)
+ : QObject(*new QAbstractItemModelPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAbstractItemModel::QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Destroys the abstract item model.
+*/
+QAbstractItemModel::~QAbstractItemModel()
+{
+ d_func()->invalidatePersistentIndexes();
+}
+
+/*!
+ \fn QModelIndex QAbstractItemModel::sibling(int row, int column, const QModelIndex &index) const
+
+ Returns the sibling at \a row and \a column for the item at \a index, or an
+ invalid QModelIndex if there is no sibling at that location.
+
+ sibling() is just a convenience function that finds the item's parent, and
+ uses it to retrieve the index of the child item in the specified \a row and
+ \a column.
+
+ \sa index(), QModelIndex::row(), QModelIndex::column()
+*/
+
+
+/*!
+ \fn int QAbstractItemModel::rowCount(const QModelIndex &parent) const
+
+ Returns the number of rows under the given \a parent. When the parent is
+ valid it means that rowCount is returning the number of children of parent.
+
+ \note When implementing a table based model, rowCount() should return 0
+ when the parent is valid.
+
+ \sa columnCount()
+*/
+
+/*!
+ \fn int QAbstractItemModel::columnCount(const QModelIndex &parent) const
+
+ Returns the number of columns for the children of the given \a parent.
+
+ In most subclasses, the number of columns is independent of the \a parent.
+
+ For example:
+
+ \snippet examples/itemviews/simpledommodel/dommodel.cpp 2
+
+ \note When implementing a table based model, columnCount() should return 0
+ when the parent is valid.
+
+ \sa rowCount()
+*/
+
+/*!
+ \fn void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+
+ This signal is emitted whenever the data in an existing item changes.
+
+ If the items are of the same parent, the affected ones are those between
+ \a topLeft and \a bottomRight inclusive. If the items do not have the same
+ parent, the behavior is undefined.
+
+ When reimplementing the setData() function, this signal must be emitted
+ explicitly.
+
+ \sa headerDataChanged(), setData(), layoutChanged()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after rows have been inserted into the
+ model. The new items are those between \a start and \a end
+ inclusive, under the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertRows(), beginInsertRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before rows are inserted into the model. The
+ new items will be positioned between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertRows(), beginInsertRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after rows have been removed from the model. The
+ removed items are those between \a start and \a end inclusive, under the
+ given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeRows(), beginRemoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before rows are removed from the model. The
+ items that will be removed are those between \a start and \a end inclusive,
+ under the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeRows(), beginRemoveRows()
+*/
+
+/*!
+ \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 sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the row \a destinationRow.
+
+ \bold{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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+ \since 4.6
+
+ This signal is emitted just before rows are moved within the
+ model. The items that will be moved are those between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent
+ starting at the row \a destinationRow.
+
+ \bold{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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \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 sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the column \a destinationColumn.
+
+ \bold{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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
+ \since 4.6
+
+ This signal is emitted just before columns are moved within the
+ model. The items that will be moved are those between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent
+ starting at the column \a destinationColumn.
+
+ \bold{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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after columns have been inserted into the model. The
+ new items are those between \a start and \a end inclusive, under the given
+ \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertColumns(), beginInsertColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before columns are inserted into the model. The
+ new items will be positioned between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertColumns(), beginInsertColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after columns have been removed from the model.
+ The removed items are those between \a start and \a end inclusive,
+ under the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeColumns(), beginRemoveColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before columns are removed from the model. The
+ items to be removed are those between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \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
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeColumns(), beginRemoveColumns()
+*/
+
+/*!
+ Returns true if the model returns a valid QModelIndex for \a row and
+ \a column with \a parent, otherwise returns false.
+*/
+bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0 || column < 0)
+ return false;
+ return row < rowCount(parent) && column < columnCount(parent);
+}
+
+
+/*!
+ Returns true if \a parent has any children; otherwise returns false.
+
+ Use rowCount() on the parent to find out the number of children.
+
+ \sa parent() index()
+*/
+bool QAbstractItemModel::hasChildren(const QModelIndex &parent) const
+{
+ return (rowCount(parent) > 0) && (columnCount(parent) > 0);
+}
+
+
+/*!
+ Returns a map with values for all predefined roles in the model for the
+ item at the given \a index.
+
+ Reimplement this function if you want to extend the default behavior of
+ this function to include custom roles in the map.
+
+ \sa Qt::ItemDataRole, data()
+*/
+QMap<int, QVariant> QAbstractItemModel::itemData(const QModelIndex &index) const
+{
+ QMap<int, QVariant> roles;
+ for (int i = 0; i < Qt::UserRole; ++i) {
+ QVariant variantData = data(index, i);
+ if (variantData.isValid())
+ roles.insert(i, variantData);
+ }
+ return roles;
+}
+
+/*!
+ Sets the \a role data for the item at \a index to \a value.
+
+ Returns true if successful; otherwise returns false.
+
+ The dataChanged() signal should be emitted if the data was successfully
+ set.
+
+ The base class implementation returns false. This function and data() must
+ be reimplemented for editable models.
+
+ \sa Qt::ItemDataRole, data(), itemData()
+*/
+bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+/*!
+ \fn QVariant QAbstractItemModel::data(const QModelIndex &index, int role) const = 0
+
+ Returns the data stored under the given \a role for the item referred to
+ by the \a index.
+
+ \note If you do not have a value to return, return an \bold invalid
+ QVariant instead of returning 0.
+
+ \sa Qt::ItemDataRole, setData(), headerData()
+*/
+
+/*!
+ Sets the role data for the item at \a index to the associated value in
+ \a roles, for every Qt::ItemDataRole.
+
+ Returns true if successful; otherwise returns false.
+
+ Roles that are not in \a roles will not be modified.
+
+ \sa setData() data() itemData()
+*/
+bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
+{
+ bool b = true;
+ for (QMap<int, QVariant>::ConstIterator it = roles.begin(); it != roles.end(); ++it)
+ b = b && setData(index, it.value(), it.key());
+ return b;
+}
+
+/*!
+ Returns a list of MIME types that can be used to describe a list of model
+ indexes.
+
+ \sa mimeData()
+*/
+QStringList QAbstractItemModel::mimeTypes() const
+{
+ QStringList types;
+ types << QLatin1String("application/x-qabstractitemmodeldatalist");
+ return types;
+}
+
+/*!
+ Returns an object that contains serialized items of data corresponding to
+ the list of \a indexes specified. The formats used to describe the encoded
+ data is obtained from the mimeTypes() function.
+
+ If the list of indexes is empty, or there are no supported MIME types, 0 is
+ returned rather than a serialized empty list.
+
+ \sa mimeTypes(), dropMimeData()
+*/
+QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
+{
+ if (indexes.count() <= 0)
+ return 0;
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return 0;
+ QMimeData *data = new QMimeData();
+ QString format = types.at(0);
+ QByteArray encoded;
+ QDataStream stream(&encoded, QIODevice::WriteOnly);
+ encodeData(indexes, stream);
+ data->setData(format, encoded);
+ return data;
+}
+
+/*!
+ Handles the \a data supplied by a drag and drop operation that ended with
+ the given \a action.
+
+ Returns true if the data and action can be handled by the model; otherwise
+ returns false.
+
+ Although the specified \a row, \a column and \a parent indicate the
+ location of an item in the model where the operation ended, it is the
+ responsibility of the view to provide a suitable location for where the
+ data should be inserted.
+
+ For instance, a drop action on an item in a QTreeView can result in new
+ items either being inserted as children of the item specified by \a row,
+ \a column, and \a parent, or as siblings of the item.
+
+ When row and column are -1 it means that it is up to the model to decide
+ where to place the data. This can occur in a tree when data is dropped on
+ a parent. Models will usually append the data to the parent in this case.
+
+ \sa supportedDropActions(), {Using drag and drop with item views}
+*/
+bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ // check if the action is supported
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+ // check if the format is supported
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+ if (row > rowCount(parent))
+ row = rowCount(parent);
+ if (row == -1)
+ row = rowCount(parent);
+ if (column == -1)
+ column = 0;
+ // decode and insert
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \since 4.2
+
+ Returns the drop actions supported by this model.
+
+ The default implementation returns Qt::CopyAction. Reimplement this
+ function if you wish to support additional actions. You must also
+ reimplement the dropMimeData() function to handle the additional
+ operations.
+
+ \sa dropMimeData(), Qt::DropActions, {Using drag and drop with item
+ views}
+*/
+Qt::DropActions QAbstractItemModel::supportedDropActions() const
+{
+ return Qt::CopyAction;
+}
+
+/*!
+ Returns the actions supported by the data in this model.
+
+ The default implementation returns supportedDropActions() unless specific
+ values have been set with setSupportedDragActions().
+
+ supportedDragActions() is used by QAbstractItemView::startDrag() as the
+ default values when a drag occurs.
+
+ \sa Qt::DropActions, {Using drag and drop with item views}
+*/
+Qt::DropActions QAbstractItemModel::supportedDragActions() const
+{
+ // ### Qt 5: make this virtual or these properties
+ Q_D(const QAbstractItemModel);
+ if (d->supportedDragActions != -1)
+ return d->supportedDragActions;
+ return supportedDropActions();
+}
+
+/*!
+ \since 4.2
+
+ Sets the supported drag \a actions for the items in the model.
+
+ \sa supportedDragActions(), {Using drag and drop with item views}
+*/
+void QAbstractItemModel::setSupportedDragActions(Qt::DropActions actions)
+{
+ Q_D(QAbstractItemModel);
+ d->supportedDragActions = actions;
+}
+
+/*!
+ \note The base class implementation of this function does nothing and
+ returns false.
+
+ On models that support this, inserts \a count rows into the model before
+ the given \a row. Items in the new row will be children of the item
+ represented by the \a parent model index.
+
+ If \a row is 0, the rows are prepended to any existing rows in the parent.
+
+ If \a row is rowCount(), the rows are appended to any existing rows in the
+ parent.
+
+ If \a parent has no children, a single column with \a count rows is
+ inserted.
+
+ Returns true if the rows were successfully inserted; otherwise returns
+ false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support insertions. Alternatively, you can provide your own API for
+ altering the data. In either case, you will need to call
+ beginInsertRows() and endInsertRows() to notify other components that the
+ model has changed.
+
+ \sa insertColumns(), removeRows(), beginInsertRows(), endInsertRows()
+*/
+bool QAbstractItemModel::insertRows(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, inserts \a count new columns into the model
+ before the given \a column. The items in each new column will be children
+ of the item represented by the \a parent model index.
+
+ If \a column is 0, the columns are prepended to any existing columns.
+
+ If \a column is columnCount(), the columns are appended to any existing
+ columns.
+
+ If \a parent has no children, a single row with \a count columns is
+ inserted.
+
+ Returns true if the columns were successfully inserted; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support insertions. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa insertRows(), removeColumns(), beginInsertColumns(), endInsertColumns()
+*/
+bool QAbstractItemModel::insertColumns(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, removes \a count rows starting with the given
+ \a row under parent \a parent from the model.
+
+ Returns true if the rows were successfully removed; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support removing. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa removeRow(), removeColumns(), insertColumns(), beginRemoveRows(),
+ endRemoveRows()
+*/
+bool QAbstractItemModel::removeRows(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, removes \a count columns starting with the
+ given \a column under parent \a parent from the model.
+
+ Returns true if the columns were successfully removed; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support removing. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa removeColumn(), removeRows(), insertColumns(), beginRemoveColumns(),
+ endRemoveColumns()
+*/
+bool QAbstractItemModel::removeColumns(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ Fetches any available data for the items with the parent specified by the
+ \a parent index.
+
+ Reimplement this if you are populating your model incrementally.
+
+ The default implementation does nothing.
+
+ \sa canFetchMore()
+*/
+void QAbstractItemModel::fetchMore(const QModelIndex &)
+{
+ // do nothing
+}
+
+/*!
+ Returns true if there is more data available for \a parent; otherwise
+ returns false.
+
+ The default implementation always returns false.
+
+ If canFetchMore() returns true, QAbstractItemView will call fetchMore().
+ However, the fetchMore() function is only called when the model is being
+ populated incrementally.
+
+ \sa fetchMore()
+*/
+bool QAbstractItemModel::canFetchMore(const QModelIndex &) const
+{
+ return false;
+}
+
+/*!
+ Returns the item flags for the given \a index.
+
+ The base class implementation returns a combination of flags that enables
+ the item (\c ItemIsEnabled) and allows it to be selected
+ (\c ItemIsSelectable).
+
+ \sa Qt::ItemFlags
+*/
+Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const
+{
+ Q_D(const QAbstractItemModel);
+ if (!d->indexValid(index))
+ return 0;
+
+ return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
+}
+
+/*!
+ Sorts the model by \a column in the given \a order.
+
+ The base class implementation does nothing.
+*/
+void QAbstractItemModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column);
+ Q_UNUSED(order);
+ // do nothing
+}
+
+/*!
+ Returns a model index for the buddy of the item represented by \a index.
+ When the user wants to edit an item, the view will call this function to
+ check whether another item in the model should be edited instead. Then, the
+ view will construct a delegate using the model index returned by the buddy
+ item.
+
+ The default implementation of this function has each item as its own buddy.
+*/
+QModelIndex QAbstractItemModel::buddy(const QModelIndex &index) const
+{
+ return index;
+}
+
+/*!
+ Returns a list of indexes for the items in the column of the \a start index
+ where data stored under the given \a role matches the specified \a value.
+ The way the search is performed is defined by the \a flags given. The list
+ that is returned may be empty.
+
+ The search begins from the \a start index, and continues until the number
+ of matching data items equals \a hits, the search reaches the last row, or
+ the search reaches \a start again - depending on whether \c MatchWrap is
+ specified in \a flags. If you want to search for all matching items, use
+ \a hits = -1.
+
+ By default, this function will perform a wrapping, string-based comparison
+ on all items, searching for items that begin with the search term specified
+ by \a value.
+
+ \note The default implementation of this function only searches columns.
+ Reimplement this function to include a different search behavior.
+*/
+QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
+ const QVariant &value, int hits,
+ Qt::MatchFlags flags) const
+{
+ QModelIndexList result;
+ uint matchType = flags & 0x0F;
+ Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ bool recurse = flags & Qt::MatchRecursive;
+ bool wrap = flags & Qt::MatchWrap;
+ bool allHits = (hits == -1);
+ QString text; // only convert to a string if it is needed
+ QModelIndex p = parent(start);
+ int from = start.row();
+ int to = rowCount(p);
+
+ // 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) {
+ QModelIndex idx = index(r, start.column(), p);
+ if (!idx.isValid())
+ continue;
+ QVariant v = data(idx, role);
+ // QVariant based matching
+ if (matchType == Qt::MatchExactly) {
+ if (value == v)
+ result.append(idx);
+ } else { // QString based matching
+ if (text.isEmpty()) // lazy conversion
+ text = value.toString();
+ QString t = v.toString();
+ switch (matchType) {
+ case Qt::MatchRegExp:
+ if (QRegExp(text, cs).exactMatch(t))
+ result.append(idx);
+ break;
+ case Qt::MatchWildcard:
+ if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
+ result.append(idx);
+ break;
+ case Qt::MatchStartsWith:
+ if (t.startsWith(text, cs))
+ result.append(idx);
+ break;
+ case Qt::MatchEndsWith:
+ if (t.endsWith(text, cs))
+ result.append(idx);
+ break;
+ case Qt::MatchFixedString:
+ if (t.compare(text, cs) == 0)
+ result.append(idx);
+ break;
+ case Qt::MatchContains:
+ default:
+ if (t.contains(text, cs))
+ result.append(idx);
+ }
+ }
+ if (recurse && hasChildren(idx)) { // search the hierarchy
+ result += match(index(0, idx.column(), idx), role,
+ (text.isEmpty() ? value : text),
+ (allHits ? -1 : hits - result.count()), flags);
+ }
+ }
+ // prepare for the next iteration
+ from = 0;
+ to = start.row();
+ }
+ return result;
+}
+
+/*!
+ Returns the row and column span of the item represented by \a index.
+
+ \note Currently, span is not used.
+*/
+
+QSize QAbstractItemModel::span(const QModelIndex &) const
+{
+ return QSize(1, 1);
+}
+
+/*!
+ \since 4.6
+
+ Sets the model's role names to \a roleNames.
+
+ This function allows mapping of role identifiers to role property names in
+ Declarative UI. This function must be called before the model is used.
+ Modifying the role names after the model has been set may result in
+ undefined behaviour.
+
+ \sa roleNames()
+*/
+void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames)
+{
+ Q_D(QAbstractItemModel);
+ d->roleNames = roleNames;
+}
+
+/*!
+ \since 4.6
+
+ Returns the model's role names.
+
+ \sa setRoleNames()
+*/
+const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const
+{
+ Q_D(const QAbstractItemModel);
+ return d->roleNames;
+}
+
+/*!
+ Lets the model know that it should submit cached information to permanent
+ storage. This function is typically used for row editing.
+
+ Returns true if there is no error; otherwise returns false.
+
+ \sa revert()
+*/
+
+bool QAbstractItemModel::submit()
+{
+ return true;
+}
+
+/*!
+ Lets the model know that it should discard cached information. This
+ function is typically used for row editing.
+
+ \sa submit()
+*/
+
+void QAbstractItemModel::revert()
+{
+ // do nothing
+}
+
+/*!
+ Returns the data for the given \a role and \a section in the header with
+ the specified \a orientation.
+
+ For horizontal headers, the section number corresponds to the column
+ number. Similarly, for vertical headers, the section number corresponds to
+ the row number.
+
+ \sa Qt::ItemDataRole, setHeaderData(), QHeaderView
+*/
+
+QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_UNUSED(orientation);
+ if (role == Qt::DisplayRole)
+ return section + 1;
+ return QVariant();
+}
+
+/*!
+ Sets the data for the given \a role and \a section in the header with the
+ specified \a orientation to the \a value supplied.
+
+ Returns true if the header's data was updated; otherwise returns false.
+
+ When reimplementing this function, the headerDataChanged() signal must be
+ emitted explicitly.
+
+ \sa Qt::ItemDataRole, headerData()
+*/
+
+bool QAbstractItemModel::setHeaderData(int section, Qt::Orientation orientation,
+ const QVariant &value, int role)
+{
+ Q_UNUSED(section);
+ Q_UNUSED(orientation);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, void *ptr) const
+
+ Creates a model index for the given \a row and \a column with the internal
+ pointer \a ptr.
+
+ When using a QSortFilterProxyModel, its indexes have their own internal
+ pointer. It is not advisable to access this internal pointer outside of the
+ model. Use the data() function instead.
+
+ This function provides a consistent interface that model subclasses must
+ use to create model indexes.
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, int id) const
+ \obsolete
+
+ Use QModelIndex
+ QAbstractItemModel::createIndex(int row, int column, quint32 id) instead.
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, quint32 id) const
+
+ Creates a model index for the given \a row and \a column with the internal
+ identifier, \a id.
+
+ This function provides a consistent interface that model subclasses must
+ use to create model indexes.
+
+ \sa QModelIndex::internalId()
+*/
+
+/*!
+ \internal
+*/
+void QAbstractItemModel::encodeData(const QModelIndexList &indexes, QDataStream &stream) const
+{
+ QModelIndexList::ConstIterator it = indexes.begin();
+ for (; it != indexes.end(); ++it)
+ stream << (*it).row() << (*it).column() << itemData(*it);
+}
+
+/*!
+ \internal
+ */
+bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &parent,
+ QDataStream &stream)
+{
+ int top = INT_MAX;
+ int left = INT_MAX;
+ int bottom = 0;
+ int right = 0;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ bottom = qMax(r, bottom);
+ right = qMax(c, right);
+ }
+
+ // insert the dragged items into the table, use a bit array to avoid overwriting items,
+ // since items from different tables can have the same row and column
+ int dragRowCount = 0;
+ int dragColumnCount = right - left + 1;
+
+ // Compute the number of continuous rows upon insertion and modify the rows to match
+ QVector<int> rowsToInsert(bottom + 1);
+ for (int i = 0; i < rows.count(); ++i)
+ rowsToInsert[rows.at(i)] = 1;
+ for (int i = 0; i < rowsToInsert.count(); ++i) {
+ if (rowsToInsert[i] == 1){
+ rowsToInsert[i] = dragRowCount;
+ ++dragRowCount;
+ }
+ }
+ for (int i = 0; i < rows.count(); ++i)
+ rows[i] = top + rowsToInsert[rows[i]];
+
+ QBitArray isWrittenTo(dragRowCount * dragColumnCount);
+
+ // make space in the table for the dropped data
+ int colCount = columnCount(parent);
+ if (colCount == 0) {
+ insertColumns(colCount, dragColumnCount - colCount, parent);
+ colCount = columnCount(parent);
+ }
+ insertRows(row, dragRowCount, parent);
+
+ row = qMax(0, row);
+ column = qMax(0, column);
+
+ QVector<QPersistentModelIndex> newIndexes(data.size());
+ // set the data in the table
+ for (int j = 0; j < data.size(); ++j) {
+ int relativeRow = rows.at(j) - top;
+ int relativeColumn = columns.at(j) - left;
+ int destinationRow = relativeRow + row;
+ int destinationColumn = relativeColumn + column;
+ int flat = (relativeRow * dragColumnCount) + relativeColumn;
+ // if the item was already written to, or we just can't fit it in the table, create a new row
+ if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
+ destinationColumn = qBound(column, destinationColumn, colCount - 1);
+ destinationRow = row + dragRowCount;
+ insertRows(row + dragRowCount, 1, parent);
+ flat = (dragRowCount * dragColumnCount) + relativeColumn;
+ isWrittenTo.resize(++dragRowCount * dragColumnCount);
+ }
+ if (!isWrittenTo.testBit(flat)) {
+ newIndexes[j] = index(destinationRow, destinationColumn, parent);
+ isWrittenTo.setBit(flat);
+ }
+ }
+
+ for(int k = 0; k < newIndexes.size(); k++) {
+ if (newIndexes.at(k).isValid())
+ setItemData(newIndexes.at(k), data.at(k));
+ }
+
+ return true;
+}
+
+/*!
+ Begins a row insertion operation.
+
+ When reimplementing insertRows() in a subclass, you must call this function
+ \e before inserting data into the model's underlying data store.
+
+ The \a parent index corresponds to the parent into which the new rows are
+ inserted; \a first and \a last are the row numbers that the new rows will
+ have after they have been inserted.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-insert-rows.png Inserting rows
+ \o Specify the first and last row numbers for the span of rows you
+ want to insert into an item in a model.
+
+ For example, as shown in the diagram, we insert three rows before
+ row 2, so \a first is 2 and \a last is 4:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 0
+
+ This inserts the three new rows as rows 2, 3, and 4.
+ \row
+ \o \inlineimage modelview-begin-append-rows.png Appending rows
+ \o To append rows, insert them after the last row.
+
+ For example, as shown in the diagram, we append two rows to a
+ collection of 4 existing rows (ending in row 3), so \a first is 4
+ and \a last is 5:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 1
+
+ This appends the two new rows as rows 4 and 5.
+ \endtable
+
+ \note This function emits the rowsAboutToBeInserted() signal which
+ connected views (or proxies) must handle before the data is inserted.
+ Otherwise, the views may end up in an invalid state.
+ \sa endInsertRows()
+*/
+void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit rowsAboutToBeInserted(parent, first, last);
+ d->rowsAboutToBeInserted(parent, first, last);
+}
+
+/*!
+ Ends a row insertion operation.
+
+ When reimplementing insertRows() in a subclass, you must call this function
+ \e after inserting data into the model's underlying data store.
+
+ \sa beginInsertRows()
+*/
+void QAbstractItemModel::endInsertRows()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->rowsInserted(change.parent, change.first, change.last);
+ emit rowsInserted(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a row removal operation.
+
+ When reimplementing removeRows() in a subclass, you must call this
+ function \e before removing data from the model's underlying data store.
+
+ The \a parent index corresponds to the parent from which the new rows are
+ removed; \a first and \a last are the row numbers of the rows to be
+ removed.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-remove-rows.png Removing rows
+ \o Specify the first and last row numbers for the span of rows you
+ want to remove from an item in a model.
+
+ For example, as shown in the diagram, we remove the two rows from
+ row 2 to row 3, so \a first is 2 and \a last is 3:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 2
+ \endtable
+
+ \note This function emits the rowsAboutToBeRemoved() signal which connected
+ views (or proxies) must handle before the data is removed. Otherwise, the
+ views may end up in an invalid state.
+
+ \sa endRemoveRows()
+*/
+void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit rowsAboutToBeRemoved(parent, first, last);
+ d->rowsAboutToBeRemoved(parent, first, last);
+}
+
+/*!
+ Ends a row removal operation.
+
+ When reimplementing removeRows() in a subclass, you must call this function
+ \e after removing data from the model's underlying data store.
+
+ \sa beginRemoveRows()
+*/
+void QAbstractItemModel::endRemoveRows()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->rowsRemoved(change.parent, change.first, change.last);
+ emit rowsRemoved(change.parent, change.first, change.last);
+}
+
+/*!
+ Returns whether a move operation is valid.
+
+ A move operation is not allowed if it moves a continuous range of rows to a destination within
+ itself, or if it attempts to move a row to one of its own descendants.
+
+ \internal
+*/
+bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation)
+{
+ // Don't move the range within itself.
+ if (destinationParent == srcParent)
+ return !(destinationStart >= start && destinationStart <= end + 1);
+
+ QModelIndex destinationAncestor = destinationParent;
+ int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
+ forever {
+ if (destinationAncestor == srcParent) {
+ if (pos >= start && pos <= end)
+ return false;
+ break;
+ }
+
+ if (!destinationAncestor.isValid())
+ break;
+
+ pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
+ destinationAncestor = destinationAncestor.parent();
+ }
+
+ return true;
+}
+
+/*!
+ \since 4.6
+
+ Begins a row move operation.
+
+ When reimplementing a subclass, this method simplifies moving
+ entities in your model. This method is responsible for moving
+ persistent indexes in the model, which you would otherwise be
+ required to do yourself. Using beginMoveRows and endMoveRows
+ is an alternative to emitting layoutAboutToBeChanged and
+ layoutChanged directly along with changePersistentIndexes.
+ layoutAboutToBeChanged is emitted by this method for compatibility
+ reasons.
+
+ The \a sourceParent index corresponds to the parent from which the
+ rows are moved; \a sourceFirst and \a sourceLast are the first and last
+ row numbers of the rows to be moved. The \a destinationParent index
+ corresponds to the parent into which those rows are moved. The \a
+ destinationChild is the row to which the rows will be moved. That
+ is, the index at row \a sourceFirst in \a sourceParent will become
+ row \a destinationChild in \a destinationParent, followed by all other
+ rows up to \a sourceLast.
+
+ However, when moving rows down in the same parent (\a sourceParent
+ and \a destinationParent are equal), the rows will be placed before the
+ \a destinationChild index. That is, if you wish to move rows 0 and 1 so
+ they will become rows 1 and 2, \a destinationChild should be 3. In this
+ case, the new index for the source row \c i (which is between
+ \a sourceFirst and \a sourceLast) is equal to
+ \c {(destinationChild-sourceLast-1+i)}.
+
+ Note that if \a sourceParent and \a destinationParent are the same,
+ you must ensure that the \a destinationChild is not within the range
+ of \a sourceFirst and \a sourceLast + 1. You must also ensure that you
+ do not attempt to move a row to one of its own children or ancestors.
+ This method returns false if either condition is true, in which case you
+ should abort your move operation.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-move-rows-1.png Moving rows to another parent
+ \o Specify the first and last row numbers for the span of rows in
+ the source parent you want to move in the model. Also specify
+ the row in the destination parent to move the span to.
+
+ For example, as shown in the diagram, we move three rows from
+ row 2 to 4 in the source, so \a sourceFirst is 2 and \a sourceLast is 4.
+ We move those items to above row 2 in the destination, so \a destinationChild is 2.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 6
+
+ This moves the three rows rows 2, 3, and 4 in the source to become 2, 3 and 4 in
+ the destination. Other affected siblings are displaced accordingly.
+ \row
+ \o \inlineimage modelview-move-rows-2.png Moving rows to append to another parent
+ \o To append rows to another parent, move them to after the last row.
+
+ For example, as shown in the diagram, we move three rows to a
+ collection of 6 existing rows (ending in row 5), so \a destinationChild is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 7
+
+ This moves the target rows to the end of the target parent as 6, 7 and 8.
+ \row
+ \o \inlineimage modelview-move-rows-3.png Moving rows in the same parent up
+ \o To move rows within the same parent, specify the row to move them to.
+
+ For example, as shown in the diagram, we move one item from row 2 to row 0,
+ so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 0.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 8
+
+ Note that other rows may be displaced accordingly. Note also that when moving
+ items within the same parent you should not attempt invalid or no-op moves. In
+ the above example, item 2 is at row 2 before the move, so it can not be moved
+ to row 2 (where it is already) or row 3 (no-op as row 3 means above row 3, where
+ it is already)
+
+ \row
+ \o \inlineimage modelview-move-rows-4.png Moving rows in the same parent down
+ \o To move rows within the same parent, specify the row to move them to.
+
+ For example, as shown in the diagram, we move one item from row 2 to row 4,
+ so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 4.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 9
+
+ Note that other rows may be displaced accordingly.
+ \endtable
+
+ \sa endMoveRows()
+*/
+bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceFirst >= 0);
+ Q_ASSERT(sourceLast >= sourceFirst);
+ Q_ASSERT(destinationChild >= 0);
+ Q_D(QAbstractItemModel);
+
+ if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
+ return false;
+ }
+
+ QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
+ sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
+ d->changes.push(sourceChange);
+ int destinationLast = destinationChild + (sourceLast - sourceFirst);
+ QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
+ destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
+ d->changes.push(destinationChange);
+
+ emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild);
+ emit layoutAboutToBeChanged();
+ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
+ return true;
+}
+
+/*!
+ Ends a row move operation.
+
+ When implementing a subclass, you must call this
+ function \e after moving data within the model's underlying data
+ store.
+
+ layoutChanged is emitted by this method for compatibility reasons.
+
+ \sa beginMoveRows()
+
+ \since 4.6
+*/
+void QAbstractItemModel::endMoveRows()
+{
+ Q_D(QAbstractItemModel);
+
+ QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
+ QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
+
+ QModelIndex adjustedSource = removeChange.parent;
+ QModelIndex adjustedDestination = insertChange.parent;
+
+ const int numMoved = removeChange.last - removeChange.first + 1;
+ if (insertChange.needsAdjust)
+ adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
+
+ if (removeChange.needsAdjust)
+ adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
+
+ d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
+
+ emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first);
+ emit layoutChanged();
+}
+
+/*!
+ Begins a column insertion operation.
+
+ When reimplementing insertColumns() in a subclass, you must call this
+ function \e before inserting data into the model's underlying data store.
+
+ The \a parent index corresponds to the parent into which the new columns
+ are inserted; \a first and \a last are the column numbers of the new
+ columns will have after they have been inserted.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-insert-columns.png Inserting columns
+ \o Specify the first and last column numbers for the span of columns
+ you want to insert into an item in a model.
+
+ For example, as shown in the diagram, we insert three columns
+ before column 4, so \a first is 4 and \a last is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 3
+
+ This inserts the three new columns as columns 4, 5, and 6.
+ \row
+ \o \inlineimage modelview-begin-append-columns.png Appending columns
+ \o To append columns, insert them after the last column.
+
+ For example, as shown in the diagram, we append three columns to a
+ collection of six existing columns (ending in column 5), so
+ \a first is 6 and \a last is 8:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 4
+
+ This appends the two new columns as columns 6, 7, and 8.
+ \endtable
+
+ \note This function emits the columnsAboutToBeInserted() signal which
+ connected views (or proxies) must handle before the data is inserted.
+ Otherwise, the views may end up in an invalid state.
+
+ \sa endInsertColumns()
+*/
+void QAbstractItemModel::beginInsertColumns(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit columnsAboutToBeInserted(parent, first, last);
+ d->columnsAboutToBeInserted(parent, first, last);
+}
+
+/*!
+ Ends a column insertion operation.
+
+ When reimplementing insertColumns() in a subclass, you must call this
+ function \e after inserting data into the model's underlying data
+ store.
+
+ \sa beginInsertColumns()
+*/
+void QAbstractItemModel::endInsertColumns()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->columnsInserted(change.parent, change.first, change.last);
+ emit columnsInserted(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a column removal operation.
+
+ When reimplementing removeColumns() in a subclass, you must call this
+ function \e before removing data from the model's underlying data store.
+
+ The \a parent index corresponds to the parent from which the new columns
+ are removed; \a first and \a last are the column numbers of the first and
+ last columns to be removed.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-remove-columns.png Removing columns
+ \o Specify the first and last column numbers for the span of columns
+ you want to remove from an item in a model.
+
+ For example, as shown in the diagram, we remove the three columns
+ from column 4 to column 6, so \a first is 4 and \a last is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 5
+ \endtable
+
+ \note This function emits the columnsAboutToBeRemoved() signal which
+ connected views (or proxies) must handle before the data is removed.
+ Otherwise, the views may end up in an invalid state.
+
+ \sa endRemoveColumns()
+*/
+void QAbstractItemModel::beginRemoveColumns(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit columnsAboutToBeRemoved(parent, first, last);
+ d->columnsAboutToBeRemoved(parent, first, last);
+}
+
+/*!
+ Ends a column removal operation.
+
+ When reimplementing removeColumns() in a subclass, you must call this
+ function \e after removing data from the model's underlying data store.
+
+ \sa beginRemoveColumns()
+*/
+void QAbstractItemModel::endRemoveColumns()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->columnsRemoved(change.parent, change.first, change.last);
+ emit columnsRemoved(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a column move operation.
+
+ When reimplementing a subclass, this method simplifies moving
+ entities in your model. This method is responsible for moving
+ persistent indexes in the model, which you would otherwise be
+ required to do yourself. Using beginMoveRows and endMoveRows
+ is an alternative to emitting layoutAboutToBeChanged and
+ layoutChanged directly along with changePersistentIndexes.
+ layoutAboutToBeChanged is emitted by this method for compatibility
+ reasons.
+
+ The \a sourceParent index corresponds to the parent from which the
+ columns are moved; \a sourceFirst and \a sourceLast are the first and last
+ column numbers of the columns to be moved. The \a destinationParent index
+ corresponds to the parent into which those columns are moved. The \a
+ destinationChild is the column to which the columns will be moved. That
+ is, the index at column \a sourceFirst in \a sourceParent will become
+ column \a destinationChild in \a destinationParent, followed by all other
+ columns up to \a sourceLast.
+
+ However, when moving columns down in the same parent (\a sourceParent
+ and \a destinationParent are equal), the columnss will be placed before the
+ \a destinationChild index. That is, if you wish to move columns 0 and 1 so
+ they will become columns 1 and 2, \a destinationChild should be 3. In this
+ case, the new index for the source column \c i (which is between
+ \a sourceFirst and \a sourceLast) is equal to
+ \c {(destinationChild-sourceLast-1+i)}.
+
+ Note that if \a sourceParent and \a destinationParent are the same,
+ you must ensure that the \a destinationChild is not within the range
+ of \a sourceFirst and \a sourceLast + 1. You must also ensure that you
+ do not attempt to move a column to one of its own children or ancestors.
+ This method returns false if either condition is true, in which case you
+ should abort your move operation.
+
+ \sa endMoveColumns()
+
+ \since 4.6
+*/
+bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceFirst >= 0);
+ Q_ASSERT(sourceLast >= sourceFirst);
+ Q_ASSERT(destinationChild >= 0);
+ Q_D(QAbstractItemModel);
+
+ if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
+ return false;
+ }
+
+ QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
+ sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
+ d->changes.push(sourceChange);
+ int destinationLast = destinationChild + (sourceLast - sourceFirst);
+ QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
+ 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);
+ emit layoutAboutToBeChanged();
+ return true;
+}
+
+/*!
+ Ends a column move operation.
+
+ When implementing a subclass, you must call this
+ function \e after moving data within the model's underlying data
+ store.
+
+ layoutChanged is emitted by this method for compatibility reasons.
+
+ \sa beginMoveColumns()
+
+ \since 4.6
+*/
+void QAbstractItemModel::endMoveColumns()
+{
+ Q_D(QAbstractItemModel);
+
+ QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
+ QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
+
+ QModelIndex adjustedSource = removeChange.parent;
+ QModelIndex adjustedDestination = insertChange.parent;
+
+ const int numMoved = removeChange.last - removeChange.first + 1;
+ if (insertChange.needsAdjust)
+ adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
+
+ if (removeChange.needsAdjust)
+ 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);
+ emit layoutChanged();
+}
+
+/*!
+ Resets the model to its original state in any attached views.
+
+ \note Use beginResetModel() and endResetModel() instead whenever possible.
+ Use this method only if there is no way to call beginResetModel() before invalidating the model.
+ Otherwise it could lead to unexpected behaviour, especially when used with proxy models.
+*/
+void QAbstractItemModel::reset()
+{
+ Q_D(QAbstractItemModel);
+ emit modelAboutToBeReset();
+ d->invalidatePersistentIndexes();
+ emit modelReset();
+}
+
+/*!
+ Begins a model reset operation.
+
+ A reset operation resets the model to its current state in any attached views.
+
+ \note Any views attached to this model will be reset as well.
+
+ When a model is reset it means that any previous data reported from the
+ model is now invalid and has to be queried for again. This also means that
+ the current item and any selected items will become invalid.
+
+ When a model radically changes its data it can sometimes be easier to just
+ call this function rather than emit dataChanged() to inform other
+ components when the underlying data source, or its structure, has changed.
+
+ You must call this function before resetting any internal data structures in your model
+ or proxy model.
+
+ \sa modelAboutToBeReset(), modelReset(), endResetModel()
+ \since 4.6
+*/
+void QAbstractItemModel::beginResetModel()
+{
+ emit modelAboutToBeReset();
+}
+
+/*!
+ Completes a model reset operation.
+
+ You must call this function after resetting any internal data structure in your model
+ or proxy model.
+
+ \sa beginResetModel()
+ \since 4.6
+*/
+void QAbstractItemModel::endResetModel()
+{
+ Q_D(QAbstractItemModel);
+ d->invalidatePersistentIndexes();
+ emit modelReset();
+}
+
+/*!
+ Changes the QPersistentModelIndex that is equal to the given \a from model
+ index to the given \a to model index.
+
+ If no persistent model index equal to the given \a from model index was
+ found, nothing is changed.
+
+ \sa persistentIndexList(), changePersistentIndexList()
+*/
+void QAbstractItemModel::changePersistentIndex(const QModelIndex &from, const QModelIndex &to)
+{
+ Q_D(QAbstractItemModel);
+ if (d->persistent.indexes.isEmpty())
+ return;
+ // find the data and reinsert it sorted
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = d->persistent.indexes.find(from);
+ if (it != d->persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.indexes.erase(it);
+ data->index = to;
+ if (to.isValid())
+ d->persistent.insertMultiAtEnd(to, data);
+ else
+ data->model = 0;
+ }
+}
+
+/*!
+ \since 4.1
+
+ Changes the QPersistentModelIndexes that is equal to the indexes in the
+ given \a from model index list to the given \a to model index list.
+
+ If no persistent model indexes equal to the indexes in the given \a from
+ model index list was found, nothing is changed.
+
+ \sa persistentIndexList(), changePersistentIndex()
+*/
+void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
+ const QModelIndexList &to)
+{
+ Q_D(QAbstractItemModel);
+ if (d->persistent.indexes.isEmpty())
+ return;
+ QVector<QPersistentModelIndexData *> toBeReinserted;
+ toBeReinserted.reserve(to.count());
+ for (int i = 0; i < from.count(); ++i) {
+ if (from.at(i) == to.at(i))
+ continue;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = d->persistent.indexes.find(from.at(i));
+ if (it != d->persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.indexes.erase(it);
+ data->index = to.at(i);
+ if (data->index.isValid())
+ toBeReinserted << data;
+ else
+ data->model = 0;
+ }
+ }
+
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = toBeReinserted.constBegin();
+ it != toBeReinserted.constEnd() ; ++it) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.insertMultiAtEnd(data->index, data);
+ }
+}
+
+/*!
+ \since 4.2
+
+ Returns the list of indexes stored as persistent indexes in the model.
+*/
+QModelIndexList QAbstractItemModel::persistentIndexList() const
+{
+ Q_D(const QAbstractItemModel);
+ QModelIndexList result;
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = d->persistent.indexes.constBegin();
+ it != d->persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ result.append(data->index);
+ }
+ return result;
+}
+
+
+/*!
+ \class QAbstractTableModel
+ \brief The QAbstractTableModel class provides an abstract model that can be
+ subclassed to create table models.
+
+ \ingroup model-view
+
+ QAbstractTableModel provides a standard interface for models that represent
+ their data as a two-dimensional array of items. It is not used directly,
+ but must be subclassed.
+
+ Since the model provides a more specialized interface than
+ QAbstractItemModel, it is not suitable for use with tree views, although it
+ can be used to provide data to a QListView. If you need to represent a
+ simple list of items, and only need a model to contain a single column of
+ data, subclassing the QAbstractListModel may be more appropriate.
+
+ The rowCount() and columnCount() functions return the dimensions of the
+ table. To retrieve a model index corresponding to an item in the model, use
+ index() and provide only the row and column numbers.
+
+ \section1 Subclassing
+
+ When subclassing QAbstractTableModel, you must implement rowCount(),
+ columnCount(), and data(). Default implementations of the index() and
+ parent() functions are provided by QAbstractTableModel.
+ Well behaved models will also implement headerData().
+
+ Editable models need to implement setData(), and implement flags() to
+ return a value containing
+ \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
+
+ Models that provide interfaces to resizable data structures can
+ provide implementations of insertRows(), removeRows(), insertColumns(),
+ and removeColumns(). When implementing these functions, it is
+ important to call the appropriate functions so that all connected views
+ are aware of any changes:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows()
+ \e before inserting new rows into the data structure, and it must
+ call endInsertRows() \e{immediately afterwards}.
+ \o An insertColumns() implementation must call beginInsertColumns()
+ \e before inserting new columns into the data structure, and it must
+ call endInsertColumns() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows()
+ \e before the rows are removed from the data structure, and it must
+ call endRemoveRows() \e{immediately afterwards}.
+ \o A removeColumns() implementation must call beginRemoveColumns()
+ \e before the columns are removed from the data structure, and it must
+ call endRemoveColumns() \e{immediately afterwards}.
+ \endlist
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ \note
+
+ \sa {Model Classes}, QAbstractItemModel, QAbstractListModel,
+ {Pixelator Example}
+*/
+
+/*!
+ Constructs an abstract table model for the given \a parent.
+*/
+
+QAbstractTableModel::QAbstractTableModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+
+}
+
+/*!
+ \internal
+
+ Constructs an abstract table model with \a dd and the given \a parent.
+*/
+
+QAbstractTableModel::QAbstractTableModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QAbstractItemModel(dd, parent)
+{
+
+}
+
+/*!
+ Destroys the abstract table model.
+*/
+
+QAbstractTableModel::~QAbstractTableModel()
+{
+
+}
+
+/*!
+ \fn QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+
+ Returns the index of the data in \a row and \a column with \a parent.
+
+ \sa parent()
+*/
+
+QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
+}
+
+/*!
+ \fn QModelIndex QAbstractTableModel::parent(const QModelIndex &index) const
+
+ Returns the parent of the model item with the given \a index.
+
+ \sa index() hasChildren()
+*/
+
+QModelIndex QAbstractTableModel::parent(const QModelIndex &) const
+{
+ return QModelIndex();
+}
+
+bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
+{
+ if (parent.model() == this || !parent.isValid())
+ return rowCount(parent) > 0 && columnCount(parent) > 0;
+ return false;
+}
+
+/*!
+ \class QAbstractListModel
+ \brief The QAbstractListModel class provides an abstract model that can be
+ subclassed to create one-dimensional list models.
+
+ \ingroup model-view
+
+ QAbstractListModel provides a standard interface for models that represent
+ their data as a simple non-hierarchical sequence of items. It is not used
+ directly, but must be subclassed.
+
+ Since the model provides a more specialized interface than
+ QAbstractItemModel, it is not suitable for use with tree views; you will
+ need to subclass QAbstractItemModel if you want to provide a model for
+ that purpose. If you need to use a number of list models to manage data,
+ it may be more appropriate to subclass QAbstractTableModel class instead.
+
+ Simple models can be created by subclassing this class and implementing
+ the minimum number of required functions. For example, we could implement
+ a simple read-only QStringList-based model that provides a list of strings
+ to a QListView widget. In such a case, we only need to implement the
+ rowCount() function to return the number of items in the list, and the
+ data() function to retrieve items from the list.
+
+ Since the model represents a one-dimensional structure, the rowCount()
+ function returns the total number of items in the model. The columnCount()
+ function is implemented for interoperability with all kinds of views, but
+ by default informs views that the model contains only one column.
+
+ \section1 Subclassing
+
+ When subclassing QAbstractListModel, you must provide implementations
+ of the rowCount() and data() functions. Well behaved models also provide
+ a headerData() implementation.
+
+ For editable list models, you must also provide an implementation of
+ setData(), implement the flags() function so that it returns a value
+ containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
+
+ Note that QAbstractListModel provides a default implementation of
+ columnCount() that informs views that there is only a single column
+ of items in this model.
+
+ Models that provide interfaces to resizable list-like data structures
+ can provide implementations of insertRows() and removeRows(). When
+ implementing these functions, it is important to call the appropriate
+ functions so that all connected views are aware of any changes:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows()
+ \e before inserting new rows into the data structure, and it must
+ call endInsertRows() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows()
+ \e before the rows are removed from the data structure, and it must
+ call endRemoveRows() \e{immediately afterwards}.
+ \endlist
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ \sa {Model Classes}, {Model Subclassing Reference}, QAbstractItemView,
+ QAbstractTableModel, {Item Views Puzzle Example}
+*/
+
+/*!
+ Constructs an abstract list model with the given \a parent.
+*/
+
+QAbstractListModel::QAbstractListModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+
+}
+
+/*!
+ \internal
+
+ Constructs an abstract list model with \a dd and the given \a parent.
+*/
+
+QAbstractListModel::QAbstractListModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QAbstractItemModel(dd, parent)
+{
+
+}
+
+/*!
+ Destroys the abstract list model.
+*/
+
+QAbstractListModel::~QAbstractListModel()
+{
+
+}
+
+/*!
+ \fn QModelIndex QAbstractListModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+
+ Returns the index of the data in \a row and \a column with \a parent.
+
+ \sa parent()
+*/
+
+QModelIndex QAbstractListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
+}
+
+/*!
+ Returns the parent of the model item with the given \a index.
+
+ \sa index() hasChildren()
+*/
+
+QModelIndex QAbstractListModel::parent(const QModelIndex & /* index */) const
+{
+ return QModelIndex();
+}
+
+/*!
+ \internal
+
+ Returns the number of columns in the list with the given \a parent.
+
+ \sa rowCount()
+*/
+
+int QAbstractListModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 1;
+}
+
+bool QAbstractListModel::hasChildren(const QModelIndex &parent) const
+{
+ return parent.isValid() ? false : (rowCount() > 0);
+}
+
+/*!
+ \typedef QModelIndexList
+ \relates QModelIndex
+
+ Synonym for QList<QModelIndex>.
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+
+ // if the drop is on an item, replace the data in the items
+ if (parent.isValid() && row == -1 && column == -1) {
+ int top = INT_MAX;
+ int left = INT_MAX;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ }
+
+ for (int i = 0; i < data.size(); ++i) {
+ int r = (rows.at(i) - top) + parent.row();
+ int c = (columns.at(i) - left) + parent.column();
+ if (hasIndex(r, c))
+ setItemData(index(r, c), data.at(i));
+ }
+
+ return true;
+ }
+
+ // otherwise insert new rows for the data
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \reimp
+*/
+bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+
+ // if the drop is on an item, replace the data in the items
+ if (parent.isValid() && row == -1 && column == -1) {
+ int top = INT_MAX;
+ int left = INT_MAX;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ }
+
+ for (int i = 0; i < data.size(); ++i) {
+ int r = (rows.at(i) - top) + parent.row();
+ if (columns.at(i) == left && hasIndex(r, 0))
+ setItemData(index(r), data.at(i));
+ }
+
+ return true;
+ }
+
+ if (row == -1)
+ row = rowCount(parent);
+
+ // otherwise insert new rows for the data
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \fn QAbstractItemModel::modelAboutToBeReset()
+ \since 4.2
+
+ This signal is emitted when reset() is called, before the model's internal
+ state (e.g. persistent model indexes) has been invalidated.
+
+ \sa beginResetModel(), modelReset()
+*/
+
+/*!
+ \fn QAbstractItemModel::modelReset()
+ \since 4.1
+
+ This signal is emitted when reset() is called, after the model's internal
+ state (e.g. persistent model indexes) has been invalidated.
+
+ \sa endResetModel(), modelAboutToBeReset()
+*/
+
+/*!
+ \fn bool QModelIndex::operator<(const QModelIndex &other) const
+ \since 4.1
+
+ Returns true if this model index is smaller than the \a other
+ model index; otherwise returns false.
+*/
+
+/*!
+ \fn uint qHash(const QPersistentModelIndex &index)
+ \since 4.5
+
+ Returns a hash of the QPersistentModelIndex
+ */
+
+
+/*!
+ \internal
+ QHash::insertMulti insert the value before the old value. and find() return the new value.
+ We need insertMultiAtEnd because we don't want to overwrite the old one, which should be removed later
+
+ There should be only one instance QPersistentModelIndexData per index, but in some intermediate state there may be
+ severals of PersistantModelIndex pointing to the same index, but one is already updated, and the other one is not.
+ This make sure than when updating the first one we don't overwrite the second one in the hash, and the second one
+ will be updated right later.
+ */
+void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data)
+{
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt =
+ indexes.insertMulti(key, data);
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt + 1;
+ while (it != indexes.end() && it.key() == key) {
+ qSwap(*newIt,*it);
+ newIt = it;
+ ++it;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
new file mode 100644
index 0000000000..6de3bf5e4f
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTITEMMODEL_H
+#define QABSTRACTITEMMODEL_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractItemModel;
+class QPersistentModelIndex;
+
+class Q_CORE_EXPORT QModelIndex
+{
+ friend class QAbstractItemModel;
+ friend class QProxyModel;
+public:
+ inline QModelIndex() : r(-1), c(-1), p(0), m(0) {}
+ inline QModelIndex(const QModelIndex &other)
+ : r(other.r), c(other.c), p(other.p), m(other.m) {}
+ inline ~QModelIndex() { p = 0; m = 0; }
+ inline int row() const { return r; }
+ inline int column() const { return c; }
+ inline void *internalPointer() const { return p; }
+ inline qint64 internalId() const { return reinterpret_cast<qint64>(p); }
+ inline QModelIndex parent() const;
+ inline QModelIndex sibling(int row, int column) const;
+ inline QModelIndex child(int row, int column) const;
+ inline QVariant data(int role = Qt::DisplayRole) const;
+ inline Qt::ItemFlags flags() const;
+ inline const QAbstractItemModel *model() const { return m; }
+ inline bool isValid() const { return (r >= 0) && (c >= 0) && (m != 0); }
+ inline bool operator==(const QModelIndex &other) const
+ { return (other.r == r) && (other.p == p) && (other.c == c) && (other.m == m); }
+ inline bool operator!=(const QModelIndex &other) const
+ { return !(*this == other); }
+ inline bool operator<(const QModelIndex &other) const
+ {
+ if (r < other.r) return true;
+ if (r == other.r) {
+ if (c < other.c) return true;
+ if (c == other.c) {
+ if (p < other.p) return true;
+ if (p == other.p) return m < other.m;
+ }
+ }
+ return false; }
+private:
+ inline QModelIndex(int row, int column, void *ptr, const QAbstractItemModel *model);
+ int r, c;
+ void *p;
+ const QAbstractItemModel *m;
+};
+Q_DECLARE_TYPEINFO(QModelIndex, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &);
+#endif
+
+class QPersistentModelIndexData;
+
+class Q_CORE_EXPORT QPersistentModelIndex
+{
+public:
+ QPersistentModelIndex();
+ 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
+ { return !operator==(other); }
+ QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
+ bool operator==(const QModelIndex &other) const;
+ bool operator!=(const QModelIndex &other) const;
+ QPersistentModelIndex &operator=(const QModelIndex &other);
+ operator const QModelIndex&() const;
+ int row() const;
+ int column() const;
+ void *internalPointer() const;
+ qint64 internalId() const;
+ QModelIndex parent() const;
+ QModelIndex sibling(int row, int column) const;
+ QModelIndex child(int row, int column) const;
+ QVariant data(int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags() const;
+ const QAbstractItemModel *model() const;
+ bool isValid() const;
+private:
+ QPersistentModelIndexData *d;
+ friend uint qHash(const QPersistentModelIndex &);
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QPersistentModelIndex, Q_MOVABLE_TYPE);
+
+inline uint qHash(const QPersistentModelIndex &index)
+{ return qHash(index.d); }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
+#endif
+
+template<typename T> class QList;
+typedef QList<QModelIndex> QModelIndexList;
+
+class QMimeData;
+class QAbstractItemModelPrivate;
+template <class Key, class T> class QMap;
+
+
+class Q_CORE_EXPORT QAbstractItemModel : public QObject
+{
+ Q_OBJECT
+
+ friend class QPersistentModelIndexData;
+ friend class QAbstractItemViewPrivate;
+public:
+
+ explicit QAbstractItemModel(QObject *parent = 0);
+ virtual ~QAbstractItemModel();
+
+ bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ virtual QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual QModelIndex parent(const QModelIndex &child) const = 0;
+
+ inline QModelIndex sibling(int row, int column, const QModelIndex &idx) const
+ { return index(row, column, parent(idx)); }
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
+
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
+ virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+ virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
+ int role = Qt::EditRole);
+
+ virtual QMap<int, QVariant> itemData(const QModelIndex &index) const;
+ virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
+
+ virtual QStringList mimeTypes() const;
+ virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+ virtual Qt::DropActions supportedDropActions() const;
+
+ Qt::DropActions supportedDragActions() const;
+ void setSupportedDragActions(Qt::DropActions);
+
+ 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());
+
+ 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());
+
+ virtual void fetchMore(const QModelIndex &parent);
+ virtual bool canFetchMore(const QModelIndex &parent) const;
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+ virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+ virtual QModelIndex buddy(const QModelIndex &index) const;
+ virtual QModelIndexList match(const QModelIndex &start, int role,
+ const QVariant &value, int hits = 1,
+ Qt::MatchFlags flags =
+ Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
+ virtual QSize span(const QModelIndex &index) const;
+
+ const QHash<int,QByteArray> &roleNames() const;
+
+#ifdef Q_NO_USING_KEYWORD
+ inline QObject *parent() const { return QObject::parent(); }
+#else
+ using QObject::parent;
+#endif
+
+Q_SIGNALS:
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void headerDataChanged(Qt::Orientation orientation, int first, int last);
+ void layoutChanged();
+ void layoutAboutToBeChanged();
+
+#if !defined(Q_MOC_RUN) && !defined(qdoc)
+private: // can only be emitted by QAbstractItemModel
+#endif
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void rowsInserted(const QModelIndex &parent, int first, int last);
+
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void rowsRemoved(const QModelIndex &parent, int first, int last);
+
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void columnsInserted(const QModelIndex &parent, int first, int last);
+
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void columnsRemoved(const QModelIndex &parent, int first, int last);
+
+ void modelAboutToBeReset();
+ void modelReset();
+
+ void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow );
+ void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row );
+
+ void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn );
+ void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column );
+
+
+public Q_SLOTS:
+ virtual bool submit();
+ virtual void revert();
+
+protected:
+ QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent = 0);
+
+ inline QModelIndex createIndex(int row, int column, void *data = 0) const;
+ inline QModelIndex createIndex(int row, int column, int id) const;
+ inline QModelIndex createIndex(int row, int column, quint32 id) const;
+
+ void encodeData(const QModelIndexList &indexes, QDataStream &stream) const;
+ bool decodeData(int row, int column, const QModelIndex &parent, QDataStream &stream);
+
+ void beginInsertRows(const QModelIndex &parent, int first, int last);
+ void endInsertRows();
+
+ void beginRemoveRows(const QModelIndex &parent, int first, int last);
+ void endRemoveRows();
+
+ bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow);
+ void endMoveRows();
+
+ void beginInsertColumns(const QModelIndex &parent, int first, int last);
+ void endInsertColumns();
+
+ void beginRemoveColumns(const QModelIndex &parent, int first, int last);
+ void endRemoveColumns();
+
+ bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationColumn);
+ void endMoveColumns();
+
+ void reset();
+
+ void beginResetModel();
+ void endResetModel();
+
+ void changePersistentIndex(const QModelIndex &from, const QModelIndex &to);
+ void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
+ QModelIndexList persistentIndexList() const;
+
+ void setRoleNames(const QHash<int,QByteArray> &roleNames);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractItemModel)
+ Q_DISABLE_COPY(QAbstractItemModel)
+};
+
+inline bool QAbstractItemModel::insertRow(int arow, const QModelIndex &aparent)
+{ return insertRows(arow, 1, aparent); }
+inline bool QAbstractItemModel::insertColumn(int acolumn, const QModelIndex &aparent)
+{ return insertColumns(acolumn, 1, aparent); }
+inline bool QAbstractItemModel::removeRow(int arow, const QModelIndex &aparent)
+{ return removeRows(arow, 1, aparent); }
+inline bool QAbstractItemModel::removeColumn(int acolumn, const QModelIndex &aparent)
+{ return removeColumns(acolumn, 1, aparent); }
+
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, void *adata) const
+{ return QModelIndex(arow, acolumn, adata, this); }
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, int aid) const
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // avoid conversion warning on 64-bit
+#endif
+{ return QModelIndex(arow, acolumn, reinterpret_cast<void*>(aid), this); }
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, quint32 aid) const
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // avoid conversion warning on 64-bit
+#endif
+{ return QModelIndex(arow, acolumn, reinterpret_cast<void*>(aid), this); }
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+
+
+class Q_CORE_EXPORT QAbstractTableModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit QAbstractTableModel(QObject *parent = 0);
+ ~QAbstractTableModel();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+protected:
+ QAbstractTableModel(QAbstractItemModelPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractTableModel)
+ QModelIndex parent(const QModelIndex &child) const;
+ bool hasChildren(const QModelIndex &parent) const;
+};
+
+class Q_CORE_EXPORT QAbstractListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit QAbstractListModel(QObject *parent = 0);
+ ~QAbstractListModel();
+
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+protected:
+ QAbstractListModel(QAbstractItemModelPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractListModel)
+ QModelIndex parent(const QModelIndex &child) const;
+ int columnCount(const QModelIndex &parent) const;
+ bool hasChildren(const QModelIndex &parent) const;
+};
+
+// inline implementations
+
+inline QModelIndex::QModelIndex(int arow, int acolumn, void *adata,
+ const QAbstractItemModel *amodel)
+ : r(arow), c(acolumn), p(adata), m(amodel) {}
+
+inline QModelIndex QModelIndex::parent() const
+{ return m ? m->parent(*this) : QModelIndex(); }
+
+inline QModelIndex QModelIndex::sibling(int arow, int acolumn) const
+{ return m ? (r == arow && c == acolumn) ? *this : m->index(arow, acolumn, m->parent(*this)) : QModelIndex(); }
+
+inline QModelIndex QModelIndex::child(int arow, int acolumn) const
+{ return m ? m->index(arow, acolumn, *this) : QModelIndex(); }
+
+inline QVariant QModelIndex::data(int arole) const
+{ return m ? m->data(*this, arole) : QVariant(); }
+
+inline Qt::ItemFlags QModelIndex::flags() const
+{ return m ? m->flags(*this) : Qt::ItemFlags(0); }
+
+inline uint qHash(const QModelIndex &index)
+{ return uint((index.row() << 4) + index.column() + index.internalId()); }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTITEMMODEL_H
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
new file mode 100644
index 0000000000..dfe5cef86a
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTITEMMODEL_P_H
+#define QABSTRACTITEMMODEL_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 "private/qobject_p.h"
+#include "QtCore/qstack.h"
+#include "QtCore/qset.h"
+#include "QtCore/qhash.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPersistentModelIndexData
+{
+public:
+ QPersistentModelIndexData() : model(0) {}
+ QPersistentModelIndexData(const QModelIndex &idx) : index(idx), model(idx.model()) {}
+ QModelIndex index;
+ QAtomicInt ref;
+ const QAbstractItemModel *model;
+ static QPersistentModelIndexData *create(const QModelIndex &index);
+ static void destroy(QPersistentModelIndexData *data);
+};
+
+class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractItemModel)
+
+public:
+ QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {}
+ void removePersistentIndexData(QPersistentModelIndexData *data);
+ void movePersistentIndexes(QVector<QPersistentModelIndexData *> indexes, int change, const QModelIndex &parent, Qt::Orientation orientation);
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void rowsInserted(const QModelIndex &parent, int first, int last);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void rowsRemoved(const QModelIndex &parent, int first, int last);
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void columnsInserted(const QModelIndex &parent, int first, int last);
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void columnsRemoved(const QModelIndex &parent, int first, int last);
+ static QAbstractItemModel *staticEmptyModel();
+ static bool variantLessThan(const QVariant &v1, const QVariant &v2);
+
+ void itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation);
+ 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);
+
+ inline QModelIndex createIndex(int row, int column, void *data = 0) const {
+ return q_func()->createIndex(row, column, data);
+ }
+
+ inline QModelIndex createIndex(int row, int column, int id) const {
+ return q_func()->createIndex(row, column, id);
+ }
+
+ inline bool indexValid(const QModelIndex &index) const {
+ return (index.row() >= 0) && (index.column() >= 0) && (index.model() == q_func());
+ }
+
+ inline void invalidatePersistentIndexes() {
+ foreach (QPersistentModelIndexData *data, persistent.indexes) {
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+ persistent.indexes.clear();
+ }
+
+ /*!
+ \internal
+ clean the QPersistentModelIndex relative to the index if there is one.
+ To be used before an index is invalided
+ */
+ inline void invalidatePersistentIndex(const QModelIndex &index) {
+ QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = persistent.indexes.find(index);
+ if(it != persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(it);
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+ }
+
+ struct Change {
+ Change() : first(-1), last(-1) {}
+ Change(const Change &c) : parent(c.parent), first(c.first), last(c.last), needsAdjust(c.needsAdjust) {}
+ Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l), needsAdjust(false) {}
+ QModelIndex parent;
+ int first, last;
+
+
+ // In cases such as this:
+ // - A
+ // - B
+ // - C
+ // - - D
+ // - - E
+ // - - F
+ //
+ // If B is moved to above E, C is the source parent in the signal and its row is 2. When the move is
+ // completed however, C is at row 1 and there is no row 2 at the same level in the model at all.
+ // The QModelIndex is adjusted to correct that in those cases before reporting it though the
+ // rowsMoved signal.
+ bool needsAdjust;
+
+ bool isValid() { return first >= 0 && last >= 0; }
+ };
+ QStack<Change> changes;
+
+ struct Persistent {
+ Persistent() {}
+ QHash<QModelIndex, QPersistentModelIndexData *> indexes;
+ QStack<QVector<QPersistentModelIndexData *> > moved;
+ QStack<QVector<QPersistentModelIndexData *> > invalidated;
+ void insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data);
+ } persistent;
+
+ Qt::DropActions supportedDragActions;
+
+ QHash<int,QByteArray> roleNames;
+ static const QHash<int,QByteArray> &defaultRoleNames();
+};
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTITEMMODEL_P_H
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
new file mode 100644
index 0000000000..6924848773
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasictimer.h"
+#include "qcoreapplication.h"
+#include "qabstracteventdispatcher.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBasicTimer
+ \brief The QBasicTimer class provides timer events for objects.
+
+ \ingroup events
+
+ This is a fast, lightweight, and low-level class used by Qt
+ internally. We recommend using the higher-level QTimer class
+ rather than this class if you want to use timers in your
+ applications. Note that this timer is a repeating timer that
+ will send subsequent timer events unless the stop() function is called.
+
+ To use this class, create a QBasicTimer, and call its start()
+ function with a timeout interval and with a pointer to a QObject
+ subclass. When the timer times out it will send a timer event to
+ the QObject subclass. The timer can be stopped at any time using
+ stop(). isActive() returns true for a timer that is running;
+ i.e. it has been started, has not reached the timeout time, and
+ has not been stopped. The timer's ID can be retrieved using
+ timerId().
+
+ The \l{widgets/wiggly}{Wiggly} example uses QBasicTimer to repaint
+ a widget at regular intervals.
+
+ \sa QTimer, QTimerEvent, QObject::timerEvent(), Timers, {Wiggly Example}
+*/
+
+
+/*!
+ \fn QBasicTimer::QBasicTimer()
+
+ Contructs a basic timer.
+
+ \sa start()
+*/
+/*!
+ \fn QBasicTimer::~QBasicTimer()
+
+ Destroys the basic timer.
+*/
+
+/*!
+ \fn bool QBasicTimer::isActive() const
+
+ Returns true if the timer is running and has not been stopped; otherwise
+ returns false.
+
+ \sa start() stop()
+*/
+
+/*!
+ \fn int QBasicTimer::timerId() const
+
+ Returns the timer's ID.
+
+ \sa QTimerEvent::timerId()
+*/
+
+/*!
+ \fn void QBasicTimer::start(int msec, QObject *object)
+
+ Starts (or restarts) the timer with a \a msec milliseconds
+ timeout.
+
+ The given \a object will receive timer events.
+
+ \sa stop() isActive() QObject::timerEvent()
+ */
+void QBasicTimer::start(int msec, QObject *obj)
+{
+ stop();
+ if (obj)
+ id = obj->startTimer(msec);
+}
+
+/*!
+ Stops the timer.
+
+ \sa start() isActive()
+*/
+void QBasicTimer::stop()
+{
+ if (id) {
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ if (eventDispatcher)
+ eventDispatcher->unregisterTimer(id);
+ }
+ id = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h
new file mode 100644
index 0000000000..2b56624086
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICTIMER_H
+#define QBASICTIMER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QObject;
+
+class Q_CORE_EXPORT QBasicTimer
+{
+ int id;
+public:
+ inline QBasicTimer() : id(0) {}
+ inline ~QBasicTimer() { if (id) stop(); }
+
+ inline bool isActive() const { return id != 0; }
+ inline int timerId() const { return id; }
+
+ void start(int msec, QObject *obj);
+ void stop();
+};
+Q_DECLARE_TYPEINFO(QBasicTimer, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBASICTIMER_H
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp
new file mode 100644
index 0000000000..7b3f35e308
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qcore_mac_p.h>
+#include <new>
+#include "qvarlengtharray.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QCFString::toQString(CFStringRef str)
+{
+ if(!str)
+ return QString();
+ CFIndex length = CFStringGetLength(str);
+ const UniChar *chars = CFStringGetCharactersPtr(str);
+ if (chars)
+ return QString(reinterpret_cast<const QChar *>(chars), length);
+
+ QVarLengthArray<UniChar> buffer(length);
+ CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
+ return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
+}
+
+QCFString::operator QString() const
+{
+ if (string.isEmpty() && type)
+ const_cast<QCFString*>(this)->string = toQString(type);
+ return string;
+}
+
+CFStringRef QCFString::toCFStringRef(const QString &string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+ string.length());
+}
+
+QCFString::operator CFStringRef() const
+{
+ if (!type)
+ const_cast<QCFString*>(this)->type = toCFStringRef(string);
+ return type;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
new file mode 100644
index 0000000000..f7f6bfe483
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCORE_MAC_P_H
+#define QCORE_MAC_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.
+//
+
+#ifndef __IMAGECAPTURE__
+# define __IMAGECAPTURE__
+#endif
+
+#undef OLD_DEBUG
+#ifdef DEBUG
+# define OLD_DEBUG DEBUG
+# undef DEBUG
+#endif
+#define DEBUG 0
+#ifdef qDebug
+# define old_qDebug qDebug
+# undef qDebug
+#endif
+
+#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED)
+#include <ApplicationServices/ApplicationServices.h>
+#else
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#ifndef QT_NO_CORESERVICES
+#include <CoreServices/CoreServices.h>
+#endif
+
+#undef DEBUG
+#ifdef OLD_DEBUG
+# define DEBUG OLD_DEBUG
+# undef OLD_DEBUG
+#endif
+
+#ifdef old_qDebug
+# undef qDebug
+# define qDebug QT_NO_QDEBUG_MACRO
+# undef old_qDebug
+#endif
+
+#include "qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Helper class that automates refernce counting for CFtypes.
+ After constructing the QCFType object, it can be copied like a
+ value-based type.
+
+ Note that you must own the object you are wrapping.
+ This is typically the case if you get the object from a Core
+ Foundation function with the word "Create" or "Copy" in it. If
+ you got the object from a "Get" function, either retain it or use
+ constructFromGet(). One exception to this rule is the
+ HIThemeGet*Shape functions, which in reality are "Copy" functions.
+*/
+template <typename T>
+class Q_CORE_EXPORT QCFType
+{
+public:
+ inline QCFType(const T &t = 0) : type(t) {}
+ inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
+ inline ~QCFType() { if (type) CFRelease(type); }
+ inline operator T() { return type; }
+ inline QCFType operator =(const QCFType &helper)
+ {
+ if (helper.type)
+ CFRetain(helper.type);
+ CFTypeRef type2 = type;
+ type = helper.type;
+ if (type2)
+ CFRelease(type2);
+ return *this;
+ }
+ inline T *operator&() { return &type; }
+ static QCFType constructFromGet(const T &t)
+ {
+ CFRetain(t);
+ return QCFType<T>(t);
+ }
+protected:
+ T type;
+};
+
+class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
+{
+public:
+ 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;
+ static QString toQString(CFStringRef cfstr);
+ static CFStringRef toCFStringRef(const QString &str);
+private:
+ QString string;
+};
+
+QT_END_NAMESPACE
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
+#ifndef __LP64__
+ typedef float CGFloat;
+ typedef int NSInteger;
+ typedef unsigned int NSUInteger;
+ #define SRefCon SInt32
+ #define URefCon UInt32
+#endif
+#endif
+
+#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp
new file mode 100644
index 0000000000..c717cb9f69
--- /dev/null
+++ b/src/corelib/kernel/qcore_symbian_p.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <exception>
+#include <e32base.h>
+#include <e32uid.h>
+#include "qcore_symbian_p.h"
+#include <string>
+#include <in_sock.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Helper function for calling into Symbian classes that expect a TDes&.
+ This function converts a QString to a TDes by allocating memory that
+ must be deleted by the caller.
+*/
+
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString)
+{
+ HBufC *buffer;
+#ifdef QT_NO_UNICODE
+ TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString.toLocal8Bit().constData()));
+#else
+ TPtrC16 ptr(qt_QString2TPtrC(aString));
+#endif
+ buffer = HBufC::New(ptr.Length());
+ Q_CHECK_PTR(buffer);
+ buffer->Des().Copy(ptr);
+ return buffer;
+}
+
+Q_CORE_EXPORT QString qt_TDesC2QString(const TDesC& aDescriptor)
+{
+#ifdef QT_NO_UNICODE
+ return QString::fromLocal8Bit(aDescriptor.Ptr(), aDescriptor.Length());
+#else
+ return QString(reinterpret_cast<const QChar *>(aDescriptor.Ptr()), aDescriptor.Length());
+#endif
+}
+
+QHBufC::QHBufC()
+ : m_hBufC(0)
+{
+}
+
+QHBufC::QHBufC(const QHBufC &src)
+ : m_hBufC(src.m_hBufC->Alloc())
+{
+ Q_CHECK_PTR(m_hBufC);
+}
+
+/*!
+ \internal
+ Constructs a QHBufC from an HBufC. Note that the QHBufC instance takes
+ ownership of the HBufC.
+*/
+QHBufC::QHBufC(HBufC *src)
+ : m_hBufC(src)
+{
+}
+
+QHBufC::QHBufC(const QString &src)
+{
+ m_hBufC = qt_QString2HBufC(src);
+}
+
+QHBufC::~QHBufC()
+{
+ if (m_hBufC)
+ delete m_hBufC;
+}
+
+class QS60PluginResolver
+{
+public:
+ QS60PluginResolver()
+ : initTried(false) {}
+
+ ~QS60PluginResolver() {
+ lib.Close();
+ }
+
+ TLibraryFunction resolve(int ordinal) {
+ if (!initTried) {
+ init();
+ initTried = true;
+ }
+
+ if (lib.Handle())
+ return lib.Lookup(ordinal);
+ else
+ return reinterpret_cast<TLibraryFunction>(NULL);
+ }
+
+private:
+ void init()
+ {
+ _LIT(KLibName_3_1, "qts60plugin_3_1" QT_LIBINFIX_UNICODE L".dll");
+ _LIT(KLibName_3_2, "qts60plugin_3_2" QT_LIBINFIX_UNICODE L".dll");
+ _LIT(KLibName_5_0, "qts60plugin_5_0" QT_LIBINFIX_UNICODE L".dll");
+
+ TPtrC libName;
+ TInt uidValue;
+ switch (QSysInfo::s60Version()) {
+ case QSysInfo::SV_S60_3_1:
+ libName.Set(KLibName_3_1);
+ uidValue = 0x2001E620;
+ break;
+ case QSysInfo::SV_S60_3_2:
+ libName.Set(KLibName_3_2);
+ uidValue = 0x2001E621;
+ break;
+ case QSysInfo::SV_S60_5_0: // Fall through to default
+ default:
+ // Default to 5.0 version, as any unknown platform is likely to be newer than that
+ libName.Set(KLibName_5_0);
+ uidValue = 0x2001E622;
+ break;
+ }
+
+ TUidType libUid(KDynamicLibraryUid, KSharedLibraryUid, TUid::Uid(uidValue));
+ lib.Load(libName, libUid);
+
+ // Duplicate lib handle to enable process wide access to it. Since Duplicate overwrites
+ // existing handle without closing it, store original for subsequent closing.
+ RLibrary origHandleCloser = lib;
+ lib.Duplicate(RThread(), EOwnerProcess);
+ origHandleCloser.Close();
+ }
+
+ RLibrary lib;
+ bool initTried;
+};
+
+Q_GLOBAL_STATIC(QS60PluginResolver, qt_s60_plugin_resolver);
+
+/*!
+ \internal
+ Resolves a platform version specific function from S60 plugin.
+ If plugin is missing or resolving fails for another reason, NULL is returned.
+*/
+Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal)
+{
+ return qt_s60_plugin_resolver()->resolve(ordinal);
+}
+
+class QS60RFsSession
+{
+public:
+ QS60RFsSession() {
+ qt_symbian_throwIfError(iFs.Connect());
+ qt_symbian_throwIfError(iFs.ShareProtected());
+ }
+
+ ~QS60RFsSession() {
+ iFs.Close();
+ }
+
+ RFs& GetRFs() {
+ return iFs;
+ }
+
+private:
+
+ RFs iFs;
+};
+
+uint qHash(const RSubSessionBase& key)
+{
+ return qHash(key.SubSessionHandle());
+}
+
+Q_GLOBAL_STATIC(QS60RFsSession, qt_s60_RFsSession);
+
+Q_CORE_EXPORT RFs& qt_s60GetRFs()
+{
+ return qt_s60_RFsSession()->GetRFs();
+}
+
+QSymbianSocketManager::QSymbianSocketManager() :
+ iNextSocket(0), iDefaultConnection(0)
+{
+ TSessionPref preferences;
+ // ### In future this could be changed to KAfInet6 when that is more common than IPv4
+ preferences.iAddrFamily = KAfInet;
+ preferences.iProtocol = KProtocolInetIp;
+ //use global message pool, as we do not know how many sockets app will use
+ //TODO: is this the right choice?
+ qt_symbian_throwIfError(iSocketServ.Connect(preferences, -1));
+ qt_symbian_throwIfError(iSocketServ.ShareAuto());
+}
+
+QSymbianSocketManager::~QSymbianSocketManager()
+{
+ iSocketServ.Close();
+ if(!socketMap.isEmpty()) {
+ qWarning("leaked %d sockets on exit", socketMap.count());
+ }
+}
+
+RSocketServ& QSymbianSocketManager::getSocketServer() {
+ return iSocketServ;
+}
+
+int QSymbianSocketManager::addSocket(const RSocket& socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ Q_ASSERT(!socketMap.contains(sock));
+ if(socketMap.contains(sock))
+ return socketMap.value(sock);
+ // allocate socket number
+ int guard = 0;
+ while(reverseSocketMap.contains(iNextSocket)) {
+ iNextSocket++;
+ iNextSocket %= max_sockets;
+ guard++;
+ if(guard > max_sockets)
+ return -1;
+ }
+ int id = iNextSocket;
+
+ socketMap[sock] = id;
+ reverseSocketMap[id] = sock;
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::removeSocket(const RSocket &socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return false;
+ int id = socketMap.value(sock);
+ socketMap.remove(sock);
+ reverseSocketMap.remove(id);
+ return true;
+}
+
+int QSymbianSocketManager::lookupSocket(const RSocket& socket) const {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return -1;
+ int id = socketMap.value(sock);
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const {
+ QMutexLocker l(&iMutex);
+ int id = fd - socket_offset;
+ if(!reverseSocketMap.contains(id))
+ return false;
+ socket = reverseSocketMap.value(id);
+ return true;
+}
+
+void QSymbianSocketManager::setDefaultConnection(RConnection* con)
+{
+ iDefaultConnection = con;
+}
+
+RConnection* QSymbianSocketManager::defaultConnection() const
+{
+ return iDefaultConnection;
+}
+
+Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager);
+
+QSymbianSocketManager& QSymbianSocketManager::instance()
+{
+ return *(qt_symbianSocketManager());
+}
+
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer()
+{
+ return QSymbianSocketManager::instance().getSocketServer();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h
new file mode 100644
index 0000000000..cbe84a8aa1
--- /dev/null
+++ b/src/corelib/kernel/qcore_symbian_p.h
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCORE_SYMBIAN_P_H
+#define QCORE_SYMBIAN_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 <e32std.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qmutex.h>
+#include <qstring.h>
+#include <qrect.h>
+#include <qhash.h>
+#include <f32file.h>
+#include <es_sock.h>
+
+#define QT_LSTRING2(x) L##x
+#define QT_LSTRING(x) QT_LSTRING2(x)
+
+#if defined(QT_LIBINFIX)
+# define QT_LIBINFIX_UNICODE QT_LSTRING(QT_LIBINFIX)
+#else
+# define QT_LIBINFIX_UNICODE L""
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString);
+
+Q_CORE_EXPORT QString qt_TDesC2QString(const TDesC& aDescriptor);
+inline QString qt_TDes2QString(const TDes& aDescriptor) { return qt_TDesC2QString(aDescriptor); }
+
+static inline QSize qt_TSize2QSize(const TSize& ts)
+{
+ return QSize(ts.iWidth, ts.iHeight);
+}
+
+static inline TSize qt_QSize2TSize(const QSize& qs)
+{
+ return TSize(qs.width(), qs.height());
+}
+
+static inline QRect qt_TRect2QRect(const TRect& tr)
+{
+ return QRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
+}
+
+static inline TRect qt_QRect2TRect(const QRect& qr)
+{
+ return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height()));
+}
+
+// Returned TPtrC is valid as long as the given parameter is valid and unmodified
+static inline TPtrC qt_QString2TPtrC( const QString& string )
+{
+ return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
+}
+
+/*!
+ \internal
+ This class is a wrapper around the Symbian HBufC descriptor class.
+ It makes sure that the heap allocated HBufC class is freed when it is
+ destroyed.
+*/
+class Q_CORE_EXPORT QHBufC
+{
+public:
+ QHBufC();
+ QHBufC(const QHBufC &src);
+ QHBufC(HBufC *src);
+ QHBufC(const QString &src);
+ ~QHBufC();
+
+ inline operator HBufC *() { return m_hBufC; }
+ inline operator const HBufC *() const { return m_hBufC; }
+ inline HBufC *data() { return m_hBufC; }
+ inline const HBufC *data() const { return m_hBufC; }
+ inline HBufC & operator*() { return *m_hBufC; }
+ inline const HBufC & operator*() const { return *m_hBufC; }
+ inline HBufC * operator->() { return m_hBufC; }
+ inline const HBufC * operator->() const { return m_hBufC; }
+
+ inline bool operator==(const QHBufC &param) const { return data() == param.data(); }
+ inline bool operator!=(const QHBufC &param) const { return data() != param.data(); }
+
+private:
+ HBufC *m_hBufC;
+};
+
+inline uint qHash(TUid uid)
+{
+ return qHash(uid.iUid);
+}
+
+// S60 version specific function ordinals that can be resolved
+enum S60PluginFuncOrdinals
+{
+ S60Plugin_TimeFormatL = 1,
+ S60Plugin_GetTimeFormatSpec = 2,
+ S60Plugin_GetLongDateFormatSpec = 3,
+ S60Plugin_GetShortDateFormatSpec = 4,
+ S60Plugin_LocalizedDirectoryName = 5,
+ S60Plugin_GetSystemDrive = 6
+};
+
+Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal);
+
+Q_CORE_EXPORT RFs& qt_s60GetRFs();
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer();
+
+// Defined in qlocale_symbian.cpp.
+Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code);
+
+template <typename R>
+struct QScopedPointerRCloser
+{
+ static inline void cleanup(R *rPointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the section on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(R) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ if (rPointer)
+ rPointer->Close();
+ }
+};
+
+//Wrapper for RSocket so it can be used as a key in QHash or QMap
+class QHashableSocket : public RSocket
+{
+public:
+ bool operator==(const QHashableSocket &other) const
+ {
+ return SubSessionHandle() == other.SubSessionHandle()
+ && Session().Handle() == other.Session().Handle();
+ }
+ bool operator<(const QHashableSocket &other) const
+ {
+ if (Session().Handle() == other.Session().Handle())
+ return SubSessionHandle() < other.SubSessionHandle();
+ return Session().Handle() < other.Session().Handle();
+ }
+};
+
+uint qHash(const RSubSessionBase& key);
+
+/*!
+ \internal
+ This class exists in QtCore for the benefit of QSocketNotifier, which uses integer
+ file descriptors in its public API.
+ So we need a way to map between int and RSocket.
+ Additionally, it is used to host the global RSocketServ session
+*/
+class Q_CORE_EXPORT QSymbianSocketManager
+{
+public:
+ QSymbianSocketManager();
+ ~QSymbianSocketManager();
+
+ /*!
+ \internal
+ \return handle to the socket server
+ */
+ RSocketServ& getSocketServer();
+ /*!
+ \internal
+ Adds a symbian socket to the global map
+ \param an open socket
+ \return pseudo file descriptor, -1 if out of resources
+ */
+ int addSocket(const RSocket &sock);
+ /*!
+ \internal
+ Removes a symbian socket from the global map
+ \param an open socket
+ \return true if the socket was in the map
+ */
+ bool removeSocket(const RSocket &sock);
+ /*!
+ \internal
+ Get pseudo file descriptor for a socket
+ \param an open socket
+ \return integer handle, or -1 if not in map
+ */
+ int lookupSocket(const RSocket &sock) const;
+ /*!
+ \internal
+ Get socket for a pseudo file descriptor
+ \param an open socket fd
+ \param sock (out) socket handle
+ \return true on success or false if not in map
+ */
+ bool lookupSocket(int fd, RSocket& sock) const;
+
+ /*!
+ \internal
+ Set the default connection to use for new sockets
+ \param an open connection
+ */
+ void setDefaultConnection(RConnection* con);
+ /*!
+ \internal
+ Get the default connection to use for new sockets
+ \return the connection, or null pointer if there is none set
+ */
+ RConnection *defaultConnection() const;
+
+ /*!
+ \internal
+ Gets a reference to the singleton socket manager
+ */
+ static QSymbianSocketManager& instance();
+private:
+ int allocateSocket();
+
+ const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first
+ const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors
+ int iNextSocket;
+ QHash<QHashableSocket, int> socketMap;
+ QHash<int, RSocket> reverseSocketMap;
+ mutable QMutex iMutex;
+ RSocketServ iSocketServ;
+ RConnection *iDefaultConnection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QCORE_SYMBIAN_P_H
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
new file mode 100644
index 0000000000..834f05b208
--- /dev/null
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcore_unix_p.h"
+#include "qelapsedtimer.h"
+
+#ifdef Q_OS_NACL
+#elif !defined (Q_OS_VXWORKS)
+# if !defined(Q_OS_HPUX) || defined(__ia64)
+# include <sys/select.h>
+# endif
+# include <sys/time.h>
+#else
+# include <selectLib.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef Q_OS_MAC
+#include <mach/mach_time.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static inline bool time_update(struct timeval *tv, const struct timeval &start,
+ const struct timeval &timeout)
+{
+ if (!QElapsedTimer::isMonotonic()) {
+ // we cannot recalculate the timeout without a monotonic clock as the time may have changed
+ return false;
+ }
+
+ // clock source is monotonic, so we can recalculate how much timeout is left
+ struct timeval now = qt_gettime();
+ *tv = timeout + start - now;
+ return tv->tv_sec >= 0;
+}
+
+int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *orig_timeout)
+{
+ if (!orig_timeout) {
+ // no timeout -> block forever
+ register int ret;
+ EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
+ return ret;
+ }
+
+ timeval start = qt_gettime();
+ timeval timeout = *orig_timeout;
+
+ // loop and recalculate the timeout as needed
+ int ret;
+ forever {
+ ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
+ if (ret != -1 || errno != EINTR)
+ return ret;
+
+ // recalculate the timeout
+ if (!time_update(&timeout, start, *orig_timeout)) {
+ // timeout during update
+ // or clock reset, fake timeout error
+ return 0;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
new file mode 100644
index 0000000000..33df0daab4
--- /dev/null
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCORE_UNIX_P_H
+#define QCORE_UNIX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt code on Unix. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qplatformdefs.h"
+
+#ifndef Q_OS_UNIX
+# error "qcore_unix_p.h included on a non-Unix system"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if defined(Q_OS_VXWORKS)
+# include <ioLib.h>
+#endif
+
+struct sockaddr;
+
+#if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
+# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
+QT_BEGIN_NAMESPACE
+namespace QtLibcSupplement {
+ inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
+ { errno = ENOSYS; return -1; }
+ inline int dup3(int, int, int)
+ { errno = ENOSYS; return -1; }
+ inline int pipe2(int [], int )
+ { errno = ENOSYS; return -1; }
+}
+QT_END_NAMESPACE
+using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
+
+#else
+# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
+#endif
+
+#define EINTR_LOOP(var, cmd) \
+ do { \
+ var = cmd; \
+ } while (var == -1 && errno == EINTR)
+
+QT_BEGIN_NAMESPACE
+
+// Internal operator functions for timevals
+inline timeval &normalizedTimeval(timeval &t)
+{
+ while (t.tv_usec > 1000000l) {
+ ++t.tv_sec;
+ t.tv_usec -= 1000000l;
+ }
+ while (t.tv_usec < 0l) {
+ --t.tv_sec;
+ t.tv_usec += 1000000l;
+ }
+ return t;
+}
+inline bool operator<(const timeval &t1, const timeval &t2)
+{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); }
+inline bool operator==(const timeval &t1, const timeval &t2)
+{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; }
+inline timeval &operator+=(timeval &t1, const timeval &t2)
+{
+ t1.tv_sec += t2.tv_sec;
+ t1.tv_usec += t2.tv_usec;
+ return normalizedTimeval(t1);
+}
+inline timeval operator+(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec + t2.tv_sec;
+ tmp.tv_usec = t1.tv_usec + t2.tv_usec;
+ return normalizedTimeval(tmp);
+}
+inline timeval operator-(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
+ tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000);
+ return normalizedTimeval(tmp);
+}
+inline timeval operator*(const timeval &t1, int mul)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec * mul;
+ tmp.tv_usec = t1.tv_usec * mul;
+ return normalizedTimeval(tmp);
+}
+
+// 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)
+{
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ register int fd;
+ EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
+
+ // unknown flags are ignored, so we have no way of verifying if
+ // O_CLOEXEC was accepted
+ if (fd != -1)
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ return fd;
+}
+#undef QT_OPEN
+#define QT_OPEN qt_safe_open
+
+#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
+// don't call ::pipe
+// call qt_safe_pipe
+static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
+{
+#ifdef O_CLOEXEC
+ Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0);
+#else
+ Q_ASSERT((flags & ~O_NONBLOCK) == 0);
+#endif
+
+ register int ret;
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+ // use pipe2
+ flags |= O_CLOEXEC;
+ ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+#endif
+
+ ret = ::pipe(pipefd);
+ if (ret == -1)
+ return -1;
+
+ ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
+ ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
+
+ // set non-block too?
+ if (flags & O_NONBLOCK) {
+ ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
+ ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
+ }
+
+ return 0;
+}
+
+#endif // Q_OS_VXWORKS
+
+// don't call dup or fcntl(F_DUPFD)
+static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
+{
+ Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
+
+ register int ret;
+#ifdef F_DUPFD_CLOEXEC
+ // use this fcntl
+ if (flags & FD_CLOEXEC) {
+ ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
+ if (ret != -1 || errno != EINVAL)
+ return ret;
+ }
+#endif
+
+ // use F_DUPFD
+ ret = ::fcntl(oldfd, F_DUPFD, atleast);
+
+ if (flags && ret != -1)
+ ::fcntl(ret, F_SETFD, flags);
+ return ret;
+}
+
+// don't call dup2
+// call qt_safe_dup2
+static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
+{
+ Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
+
+ register int ret;
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+ // use dup3
+ if (flags & FD_CLOEXEC) {
+ EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+ }
+#endif
+ EINTR_LOOP(ret, ::dup2(oldfd, newfd));
+ if (ret == -1)
+ return -1;
+
+ if (flags)
+ ::fcntl(newfd, F_SETFD, flags);
+ return 0;
+}
+
+static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
+{
+ qint64 ret = 0;
+ EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
+ return ret;
+}
+#undef QT_READ
+#define QT_READ qt_safe_read
+
+static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
+{
+ qint64 ret = 0;
+ EINTR_LOOP(ret, QT_WRITE(fd, data, len));
+ return ret;
+}
+#undef QT_WRITE
+#define QT_WRITE qt_safe_write
+
+static inline int qt_safe_close(int fd)
+{
+ register int ret;
+ EINTR_LOOP(ret, QT_CLOSE(fd));
+ return ret;
+}
+#undef QT_CLOSE
+#define QT_CLOSE qt_safe_close
+
+// - Open C does not (yet?) implement these on Symbian OS
+// - VxWorks doesn't have processes
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_VXWORKS)
+static inline int qt_safe_execve(const char *filename, char *const argv[],
+ char *const envp[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execve(filename, argv, envp));
+ return ret;
+}
+
+static inline int qt_safe_execv(const char *path, char *const argv[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execv(path, argv));
+ return ret;
+}
+
+static inline int qt_safe_execvp(const char *file, char *const argv[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execvp(file, argv));
+ return ret;
+}
+#endif
+
+#ifndef Q_OS_VXWORKS // no processes on VxWorks
+static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
+{
+ register int ret;
+ EINTR_LOOP(ret, ::waitpid(pid, status, options));
+ return ret;
+}
+
+#endif // Q_OS_VXWORKS
+
+#if !defined(_POSIX_MONOTONIC_CLOCK)
+# define _POSIX_MONOTONIC_CLOCK -1
+#endif
+
+timeval qt_gettime(); // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
+
+Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *tv);
+
+// according to X/OPEN we have to define semun ourselves
+// we use prefix as on some systems sem.h will have it
+struct semid_ds;
+union qt_semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
new file mode 100644
index 0000000000..be86c58d47
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -0,0 +1,2730 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreevent.h"
+#include "qeventloop.h"
+#include "qcorecmdlineargs_p.h"
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qhash.h>
+#include <private/qprocess_p.h>
+#include <qtextcodec.h>
+#include <qthread.h>
+#include <qthreadpool.h>
+#include <qthreadstorage.h>
+#include <private/qthread_p.h>
+#include <qelapsedtimer.h>
+#include <qlibraryinfo.h>
+#include <qvarlengtharray.h>
+#include <private/qfactoryloader_p.h>
+#include <private/qfunctions_p.h>
+#include <private/qlocale_p.h>
+
+#ifdef Q_OS_SYMBIAN
+# include <exception>
+# include <f32file.h>
+# include <e32ldr.h>
+# include "qeventdispatcher_symbian_p.h"
+# include "private/qcore_symbian_p.h"
+# include "private/qfilesystemengine_p.h"
+# include <apacmdln.h>
+#elif defined(Q_OS_UNIX)
+# if !defined(QT_NO_GLIB)
+# include "qeventdispatcher_glib_p.h"
+# endif
+# include "qeventdispatcher_unix_p.h"
+#endif
+
+#ifdef Q_OS_WIN
+# include "qeventdispatcher_win_p.h"
+#endif
+
+#ifdef Q_OS_MAC
+# include "qcore_mac_p.h"
+#endif
+
+#include <stdlib.h>
+
+#ifdef Q_OS_UNIX
+# include <locale.h>
+#endif
+
+#ifdef Q_OS_VXWORKS
+# include <taskLib.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QMutexUnlocker
+{
+public:
+ inline explicit QMutexUnlocker(QMutex *m)
+ : mtx(m)
+ { }
+ inline ~QMutexUnlocker() { unlock(); }
+ inline void unlock() { if (mtx) mtx->unlock(); mtx = 0; }
+
+private:
+ Q_DISABLE_COPY(QMutexUnlocker)
+
+ QMutex *mtx;
+};
+
+#ifdef Q_OS_SYMBIAN
+typedef TDriveNumber (*SystemDriveFunc)(RFs&);
+static SystemDriveFunc PtrGetSystemDrive = 0;
+static CApaCommandLine* apaCommandLine = 0;
+static char *apaTail = 0;
+static QVector<char *> *apaArgv = 0;
+
+static void qt_cleanup_apa_cmd_line()
+{
+ delete apaCommandLine;
+ apaCommandLine = 0;
+ delete apaArgv;
+ apaArgv = 0;
+ delete apaTail;
+ apaTail = 0;
+}
+
+static inline void qt_init_symbian_apa_arguments(int &argc, char **&argv)
+{
+ // If app is launched via CApaCommandLine::StartApp(), normal arguments only contain
+ // application name.
+ if (argc == 1) {
+ CApaCommandLine* commandLine = QCoreApplicationPrivate::symbianCommandLine();
+ if(commandLine) {
+ TPtrC8 apaCmdLine = commandLine->TailEnd();
+ int tailLen = apaCmdLine.Length();
+ if (tailLen) {
+ apaTail = reinterpret_cast<char *>(qMalloc(tailLen + 1));
+ qMemCopy(apaTail, reinterpret_cast<const char *>(apaCmdLine.Ptr()), tailLen);
+ apaTail[tailLen] = '\0';
+ apaArgv = new QVector<char *>(8);
+ // Reuse windows command line parsing
+ *apaArgv = qWinCmdLine<char>(apaTail, tailLen, argc);
+ apaArgv->insert(0, argv[0]);
+ argc++;
+ argv = apaArgv->data();
+ }
+ }
+ }
+}
+
+CApaCommandLine* QCoreApplicationPrivate::symbianCommandLine()
+{
+ // Getting of Apa command line needs to be static as it can only be called successfully
+ // once per process.
+ if (!apaCommandLine) {
+ TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(apaCommandLine);
+ if (err == KErrNone) {
+ qAddPostRoutine(qt_cleanup_apa_cmd_line);
+ }
+ }
+ return apaCommandLine;
+}
+
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+extern QString qAppFileName();
+#endif
+
+int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0
+#if defined(QT3_SUPPORT)
+bool QCoreApplicationPrivate::useQt3Support = true;
+#endif
+
+#if !defined(Q_OS_WIN)
+#ifdef Q_OS_MAC
+QString QCoreApplicationPrivate::macMenuBarName()
+{
+ QString bundleName;
+ CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("CFBundleName"));
+ if (string)
+ bundleName = QCFString::toQString(static_cast<CFStringRef>(string));
+ return bundleName;
+}
+#endif
+QString QCoreApplicationPrivate::appName() const
+{
+ static QString applName;
+#ifdef Q_OS_MAC
+ applName = macMenuBarName();
+#endif
+ if (applName.isEmpty() && argv[0]) {
+ char *p = strrchr(argv[0], '/');
+ applName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
+ }
+ return applName;
+}
+#endif
+
+bool QCoreApplicationPrivate::checkInstance(const char *function)
+{
+ bool b = (QCoreApplication::self != 0);
+ if (!b)
+ qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
+ return b;
+}
+
+// Support for introspection
+
+QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };
+
+void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set)
+{
+ qt_signal_spy_callback_set = callback_set;
+}
+
+extern "C" void Q_CORE_EXPORT qt_startup_hook()
+{
+}
+
+typedef QList<QtCleanUpFunction> QVFuncList;
+Q_GLOBAL_STATIC(QVFuncList, postRList)
+
+void qAddPostRoutine(QtCleanUpFunction p)
+{
+ QVFuncList *list = postRList();
+ if (!list)
+ return;
+ list->prepend(p);
+}
+
+void qRemovePostRoutine(QtCleanUpFunction p)
+{
+ QVFuncList *list = postRList();
+ if (!list)
+ return;
+ list->removeAll(p);
+}
+
+void Q_CORE_EXPORT qt_call_post_routines()
+{
+ QVFuncList *list = 0;
+ QT_TRY {
+ list = postRList();
+ } QT_CATCH(const std::bad_alloc &) {
+ // ignore - if we can't allocate a post routine list,
+ // there's a high probability that there's no post
+ // routine to be executed :)
+ }
+ if (!list)
+ return;
+ while (!list->isEmpty())
+ (list->takeFirst())();
+}
+
+
+// app starting up if false
+bool QCoreApplicationPrivate::is_app_running = false;
+ // app closing down if true
+bool QCoreApplicationPrivate::is_app_closing = false;
+// initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
+Q_CORE_EXPORT bool qt_locale_initialized = false;
+
+
+Q_CORE_EXPORT uint qGlobalPostedEventsCount()
+{
+ QThreadData *currentThreadData = QThreadData::current();
+ return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
+}
+
+
+void qt_set_current_thread_to_main_thread()
+{
+ QCoreApplicationPrivate::theMainThread = QThread::currentThread();
+}
+
+
+
+QCoreApplication *QCoreApplication::self = 0;
+QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
+uint QCoreApplicationPrivate::attribs;
+
+#ifdef Q_OS_UNIX
+Qt::HANDLE qt_application_thread_id = 0;
+#endif
+
+struct QCoreApplicationData {
+ QCoreApplicationData() {
+#ifndef QT_NO_LIBRARY
+ app_libpaths = 0;
+#endif
+ }
+ ~QCoreApplicationData() {
+#ifndef QT_NO_LIBRARY
+ delete app_libpaths;
+#endif
+
+ // cleanup the QAdoptedThread created for the main() thread
+ if (QCoreApplicationPrivate::theMainThread) {
+ QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread);
+ QCoreApplicationPrivate::theMainThread = 0;
+ data->deref(); // deletes the data and the adopted thread
+ }
+ }
+ QString orgName, orgDomain, application;
+ QString applicationVersion;
+
+#ifndef QT_NO_LIBRARY
+ QStringList *app_libpaths;
+#endif
+
+};
+
+Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
+
+QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
+ : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0),
+ in_exec(false), aboutToQuitEmitted(false)
+{
+ app_compile_version = flags & 0xffffff;
+#if defined(QT3_SUPPORT)
+ useQt3Support = !(flags & 0x01000000);
+#endif
+ static const char *const empty = "";
+ if (argc == 0 || argv == 0) {
+ argc = 0;
+ argv = (char **)&empty; // ouch! careful with QCoreApplication::argv()!
+ }
+ QCoreApplicationPrivate::is_app_closing = false;
+
+#ifdef Q_OS_SYMBIAN
+ qt_init_symbian_apa_arguments(argc, argv);
+#endif
+
+#ifdef Q_OS_UNIX
+ qt_application_thread_id = QThread::currentThreadId();
+#endif
+
+ // note: this call to QThread::currentThread() may end up setting theMainThread!
+ if (QThread::currentThread() != theMainThread)
+ qWarning("WARNING: QApplication was not created in the main() thread.");
+}
+
+QCoreApplicationPrivate::~QCoreApplicationPrivate()
+{
+ if (threadData) {
+#ifndef QT_NO_THREAD
+ void *data = &threadData->tls;
+ QThreadStorageData::finish((void **)data);
+#endif
+
+ // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
+ QMutexLocker locker(&threadData->postEventList.mutex);
+ for (int i = 0; i < threadData->postEventList.size(); ++i) {
+ const QPostEvent &pe = threadData->postEventList.at(i);
+ if (pe.event) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ }
+ }
+ threadData->postEventList.clear();
+ threadData->postEventList.recursion = 0;
+ threadData->quitNow = false;
+ }
+}
+
+void QCoreApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QCoreApplication);
+#if defined(Q_OS_SYMBIAN)
+ eventDispatcher = new QEventDispatcherSymbian(q);
+#elif defined(Q_OS_UNIX)
+# if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
+ eventDispatcher = new QEventDispatcherGlib(q);
+ else
+# endif
+ eventDispatcher = new QEventDispatcherUNIX(q);
+#elif defined(Q_OS_WIN)
+ eventDispatcher = new QEventDispatcherWin32(q);
+#else
+# error "QEventDispatcher not yet ported to this platform"
+#endif
+}
+
+QThread *QCoreApplicationPrivate::theMainThread = 0;
+QThread *QCoreApplicationPrivate::mainThread()
+{
+ Q_ASSERT(theMainThread != 0);
+ return theMainThread;
+}
+
+#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD)
+void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
+{
+ QThread *currentThread = QThread::currentThread();
+ QThread *thr = receiver->thread();
+ Q_ASSERT_X(currentThread == thr || !thr,
+ "QCoreApplication::sendEvent",
+ QString::fromLatin1("Cannot send events to objects owned by a different thread. "
+ "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
+ .arg(QString::number((quintptr) currentThread, 16))
+ .arg(receiver->objectName())
+ .arg(QLatin1String(receiver->metaObject()->className()))
+ .arg(QString::number((quintptr) thr, 16))
+ .toLocal8Bit().data());
+ Q_UNUSED(currentThread);
+ Q_UNUSED(thr);
+}
+#elif defined(Q_OS_SYMBIAN) && defined (QT_NO_DEBUG)
+// no implementation in release builds, but keep the symbol present
+void QCoreApplicationPrivate::checkReceiverThread(QObject * /* receiver */)
+{
+}
+#endif
+
+void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QStringList *app_libpaths = coreappdata()->app_libpaths;
+ Q_ASSERT(app_libpaths);
+# if defined(Q_OS_SYMBIAN)
+ QString app_location( QCoreApplication::applicationDirPath() );
+ // File existence check for application's private dir requires additional '\' or
+ // platform security will not allow it.
+ if (app_location != QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location + QLatin1Char('\\')) && !app_libpaths->contains(app_location))
+# else
+ QString app_location( QCoreApplication::applicationFilePath() );
+ app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
+ app_location = QDir(app_location).canonicalPath();
+ if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
+# endif
+ app_libpaths->append(app_location);
+#endif
+}
+
+QString qAppName()
+{
+ if (!QCoreApplicationPrivate::checkInstance("qAppName"))
+ return QString();
+ return QCoreApplication::instance()->d_func()->appName();
+}
+
+/*!
+ \class QCoreApplication
+ \brief The QCoreApplication class provides an event loop for console Qt
+ applications.
+
+ This class is used by non-GUI applications to provide their event
+ loop. For non-GUI application that uses Qt, there should be exactly
+ one QCoreApplication object. For GUI applications, see
+ QApplication.
+
+ QCoreApplication contains the main event loop, where all events
+ from the operating system (e.g., timer and network events) and
+ other sources are processed and dispatched. It also handles the
+ application's initialization and finalization, as well as
+ system-wide and application-wide settings.
+
+ \section1 The Event Loop and Event Handling
+
+ The event loop is started with a call to exec(). Long running
+ operations can call processEvents() to keep the application
+ responsive.
+
+ In general, we recommend that you create a QCoreApplication or a
+ QApplication object in your \c main() function as early as
+ possible. exec() will not return until the event loop exits; e.g.,
+ when quit() is called.
+
+ Several static convenience functions are also provided. The
+ QCoreApplication object is available from instance(). Events can
+ be sent or posted using sendEvent(), postEvent(), and
+ sendPostedEvents(). Pending events can be removed with
+ removePostedEvents() or flushed with flush().
+
+ The class provides a quit() slot and an aboutToQuit() signal.
+
+ \section1 Application and Library Paths
+
+ An application has an applicationDirPath() and an
+ applicationFilePath(). Library paths (see QLibrary) can be retrieved
+ with libraryPaths() and manipulated by setLibraryPaths(), addLibraryPath(),
+ and removeLibraryPath().
+
+ \section1 Internationalization and Translations
+
+ 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().
+
+ \section1 Accessing Command Line Arguments
+
+ The command line arguments which are passed to QCoreApplication's
+ constructor should be accessed using the arguments() function.
+ Note that some arguments supplied by the user may have been
+ processed and removed by QCoreApplication.
+
+ In cases where command line arguments need to be obtained using the
+ argv() function, you must convert them from the local string encoding
+ using QString::fromLocal8Bit().
+
+ \section1 Locale Settings
+
+ On Unix/Linux Qt is configured to use the system locale settings by
+ default. This can cause a conflict when using POSIX functions, for
+ instance, when converting between data types such as floats and
+ strings, since the notation may differ between locales. To get
+ around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")}
+ right after initializing QApplication or QCoreApplication to reset
+ the locale that is used for number formatting to "C"-locale.
+
+ \sa QApplication, QAbstractEventDispatcher, QEventLoop,
+ {Semaphores Example}, {Wait Conditions Example}
+*/
+
+/*!
+ \fn static QCoreApplication *QCoreApplication::instance()
+
+ Returns a pointer to the application's QCoreApplication (or
+ QApplication) instance.
+
+ If no instance has been allocated, \c null is returned.
+*/
+
+/*!\internal
+ */
+QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
+ : QObject(p, 0)
+{
+ init();
+ // note: it is the subclasses' job to call
+ // QCoreApplicationPrivate::eventDispatcher->startingUp();
+}
+
+/*!
+ Flushes the platform specific event queues.
+
+ If you are doing graphical changes inside a loop that does not
+ return to the event loop on asynchronous window systems like X11
+ or double buffered window systems like Mac OS X, and you want to
+ visualize these changes immediately (e.g. Splash Screens), call
+ this function.
+
+ \sa sendPostedEvents()
+*/
+void QCoreApplication::flush()
+{
+ if (self && self->d_func()->eventDispatcher)
+ self->d_func()->eventDispatcher->flush();
+}
+
+/*!
+ Constructs a Qt kernel application. Kernel applications are
+ applications without a graphical user interface. These type of
+ applications are used at the console or as server processes.
+
+ The \a argc and \a argv arguments are processed by the application,
+ and made available in a more convenient form by the arguments()
+ function.
+
+ \warning The data referred to by \a argc and \a argv must stay valid
+ for the entire lifetime of the QCoreApplication object. In addition,
+ \a argc must be greater than zero and \a argv must contain at least
+ one valid character string.
+*/
+QCoreApplication::QCoreApplication(int &argc, char **argv)
+ : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000))
+{
+ init();
+ QCoreApplicationPrivate::eventDispatcher->startingUp();
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_LIBRARY)
+ // Refresh factoryloader, as text codecs are requested during lib path
+ // resolving process and won't be therefore properly loaded.
+ // Unknown if this is symbian specific issue.
+ QFactoryLoader::refreshAll();
+#endif
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+ d_func()->symbianInit();
+#endif
+}
+
+QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal)
+: QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
+{
+ init();
+ QCoreApplicationPrivate::eventDispatcher->startingUp();
+#if defined(Q_OS_SYMBIAN)
+#ifndef QT_NO_LIBRARY
+ // Refresh factoryloader, as text codecs are requested during lib path
+ // resolving process and won't be therefore properly loaded.
+ // Unknown if this is symbian specific issue.
+ QFactoryLoader::refreshAll();
+#endif
+#ifndef QT_NO_SYSTEMLOCALE
+ d_func()->symbianInit();
+#endif
+#endif //Q_OS_SYMBIAN
+}
+
+
+// ### move to QCoreApplicationPrivate constructor?
+void QCoreApplication::init()
+{
+ Q_D(QCoreApplication);
+
+#ifdef Q_OS_UNIX
+ setlocale(LC_ALL, ""); // use correct char set mapping
+ qt_locale_initialized = true;
+#endif
+
+ Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
+ QCoreApplication::self = this;
+
+#ifdef Q_OS_SYMBIAN
+ //ensure temp and working directories exist
+ QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::tempPath()), true);
+ QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::currentPath()), true);
+#endif
+
+#ifndef QT_NO_THREAD
+ QThread::initialize();
+#endif
+
+ // use the event dispatcher created by the app programmer (if any)
+ if (!QCoreApplicationPrivate::eventDispatcher)
+ QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
+ // otherwise we create one
+ if (!QCoreApplicationPrivate::eventDispatcher)
+ d->createEventDispatcher();
+ Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
+
+ if (!QCoreApplicationPrivate::eventDispatcher->parent())
+ QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
+
+ d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ if (!coreappdata()->app_libpaths) {
+ // make sure that library paths is initialized
+ libraryPaths();
+ } else {
+ d->appendApplicationPathToLibraryPaths();
+ }
+#endif
+
+#if defined(Q_OS_UNIX) && !(defined(QT_NO_PROCESS))
+ // Make sure the process manager thread object is created in the main
+ // thread.
+ QProcessPrivate::initializeProcessManager();
+#endif
+
+#ifdef QT_EVAL
+ extern void qt_core_eval_init(uint);
+ qt_core_eval_init(d->application_type);
+#endif
+
+#if defined(Q_OS_SYMBIAN) \
+ && defined(Q_CC_NOKIAX86) \
+ && defined(QT_DEBUG)
+ /**
+ * Prevent the executable from being locked in the Symbian emulator. The
+ * code dramatically simplifies debugging on Symbian, but beyond that has
+ * no impact.
+ *
+ * Force the ZLazyUnloadTimer to fire and therefore unload code segments
+ * immediately. The code affects Symbian's file server and on the other
+ * hand needs only to be run once in each emulator run.
+ */
+ {
+ RLoader loader;
+ CleanupClosePushL(loader);
+ User::LeaveIfError(loader.Connect());
+ User::LeaveIfError(loader.CancelLazyDllUnload());
+ CleanupStack::PopAndDestroy(&loader);
+ }
+#endif
+
+ qt_startup_hook();
+}
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+void QCoreApplicationPrivate::symbianInit()
+{
+ if (!environmentChangeNotifier)
+ environmentChangeNotifier.reset(new QEnvironmentChangeNotifier);
+}
+#endif
+
+
+/*!
+ Destroys the QCoreApplication object.
+*/
+QCoreApplication::~QCoreApplication()
+{
+ qt_call_post_routines();
+
+ self = 0;
+ QCoreApplicationPrivate::is_app_closing = true;
+ QCoreApplicationPrivate::is_app_running = false;
+
+#if !defined(QT_NO_THREAD)
+#if !defined(QT_NO_CONCURRENT)
+ // Synchronize and stop the global thread pool threads.
+ QThreadPool *globalThreadPool = 0;
+ QT_TRY {
+ globalThreadPool = QThreadPool::globalInstance();
+ } QT_CATCH (...) {
+ // swallow the exception, since destructors shouldn't throw
+ }
+ if (globalThreadPool)
+ globalThreadPool->waitForDone();
+#endif
+ QThread::cleanup();
+#endif
+
+ d_func()->threadData->eventDispatcher = 0;
+ if (QCoreApplicationPrivate::eventDispatcher)
+ QCoreApplicationPrivate::eventDispatcher->closingDown();
+ QCoreApplicationPrivate::eventDispatcher = 0;
+
+#ifndef QT_NO_LIBRARY
+ delete coreappdata()->app_libpaths;
+ coreappdata()->app_libpaths = 0;
+#endif
+}
+
+
+/*!
+ Sets the attribute \a attribute if \a on is true;
+ otherwise clears the attribute.
+
+ One of the attributes that can be set with this method is
+ Qt::AA_ImmediateWidgetCreation. It tells Qt to create toplevel
+ windows immediately. Normally, resources for widgets are allocated
+ on demand to improve efficiency and minimize resource usage.
+ Therefore, if it is important to minimize resource consumption, do
+ not set this attribute.
+
+ \sa testAttribute()
+*/
+void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
+{
+ if (on)
+ QCoreApplicationPrivate::attribs |= 1 << attribute;
+ else
+ QCoreApplicationPrivate::attribs &= ~(1 << attribute);
+#ifdef Q_OS_MAC
+ // Turn on the no native menubar here, since we used to
+ // do this implicitly. We DO NOT flip it off if someone sets
+ // it to false.
+ // Ideally, we'd have magic that would be something along the lines of
+ // "follow MacPluginApplication" unless explicitly set.
+ // Considering this attribute isn't only at the beginning
+ // it's unlikely it will ever be a problem, but I want
+ // to have the behavior documented here.
+ if (attribute == Qt::AA_MacPluginApplication && on
+ && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
+ setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ }
+#endif
+}
+
+/*!
+ Returns true if attribute \a attribute is set;
+ otherwise returns false.
+
+ \sa setAttribute()
+ */
+bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
+{
+ return QCoreApplicationPrivate::testAttribute(attribute);
+}
+
+
+/*!
+ \internal
+
+ 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)
+{
+ // Make it possible for Qt Jambi and QSA to hook into events even
+ // though QApplication is subclassed...
+ bool result = false;
+ void *cbdata[] = { receiver, event, &result };
+ if (QInternal::activateCallbacks(QInternal::EventNotifyCallback, cbdata)) {
+ return result;
+ }
+
+ // Qt enforces the rule that events can only be sent to objects in
+ // the current thread, so receiver->d_func()->threadData is
+ // equivalent to QThreadData::current(), just without the function
+ // call overhead.
+ QObjectPrivate *d = receiver->d_func();
+ QThreadData *threadData = d->threadData;
+ ++threadData->loopLevel;
+
+#ifdef QT_JAMBI_BUILD
+ int deleteWatch = 0;
+ int *oldDeleteWatch = QObjectPrivate::setDeleteWatch(d, &deleteWatch);
+
+ bool inEvent = d->inEventHandler;
+ d->inEventHandler = true;
+#endif
+
+ bool returnValue;
+ QT_TRY {
+ returnValue = notify(receiver, event);
+ } QT_CATCH (...) {
+ --threadData->loopLevel;
+ QT_RETHROW;
+ }
+
+#ifdef QT_JAMBI_BUILD
+ // Restore the previous state if the object was not deleted..
+ if (!deleteWatch) {
+ d->inEventHandler = inEvent;
+ }
+ QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
+#endif
+ --threadData->loopLevel;
+ return returnValue;
+}
+
+
+/*!
+ Sends \a event to \a receiver: \a {receiver}->event(\a event).
+ Returns the value that is returned from the receiver's event
+ handler. Note that this function is called for all events sent to
+ any object in any thread.
+
+ For certain types of events (e.g. mouse and key events),
+ the event will be propagated to the receiver's parent and so on up to
+ the top-level object if the receiver is not interested in the event
+ (i.e., it returns false).
+
+ There are five different ways that events can be processed;
+ reimplementing this virtual function is just one of them. All five
+ approaches are listed below:
+ \list 1
+ \i Reimplementing paintEvent(), mousePressEvent() and so
+ on. This is the commonest, easiest and least powerful way.
+
+ \i Reimplementing this function. This is very powerful, providing
+ complete control; but only one subclass can be active at a time.
+
+ \i Installing an event filter on QCoreApplication::instance(). Such
+ an event filter is able to process all events for all widgets, so
+ it's just as powerful as reimplementing notify(); furthermore, it's
+ possible to have more than one application-global event filter.
+ Global event filters even see mouse events for
+ \l{QWidget::isEnabled()}{disabled widgets}. Note that application
+ event filters are only called for objects that live in the main
+ thread.
+
+ \i Reimplementing QObject::event() (as QWidget does). If you do
+ this you get Tab key presses, and you get to see the events before
+ any widget-specific event filters.
+
+ \i Installing an event filter on the object. Such an event filter gets all
+ the events, including Tab and Shift+Tab key press events, as long as they
+ do not change the focus widget.
+ \endlist
+
+ \sa QObject::event(), installEventFilter()
+*/
+
+bool QCoreApplication::notify(QObject *receiver, QEvent *event)
+{
+ Q_D(QCoreApplication);
+ // no events are delivered after ~QCoreApplication() has started
+ if (QCoreApplicationPrivate::is_app_closing)
+ return true;
+
+ if (receiver == 0) { // serious error
+ qWarning("QCoreApplication::notify: Unexpected null receiver");
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ d->checkReceiverThread(receiver);
+#endif
+
+ return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
+}
+
+bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
+{
+ if (receiver->d_func()->threadData == this->threadData) {
+ // application event filters are only called for objects in the GUI thread
+ for (int i = 0; i < eventFilters.size(); ++i) {
+ register QObject *obj = eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != threadData) {
+ qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(receiver, event))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
+{
+ Q_Q(QCoreApplication);
+ if (receiver != q) {
+ for (int i = 0; i < receiver->d_func()->eventFilters.size(); ++i) {
+ register QObject *obj = receiver->d_func()->eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != receiver->d_func()->threadData) {
+ qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(receiver, event))
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!\internal
+
+ Helper function called by notify()
+ */
+bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
+{
+ // send to all application event filters
+ if (sendThroughApplicationEventFilters(receiver, event))
+ return true;
+ // send to all receiver event filters
+ if (sendThroughObjectEventFilters(receiver, event))
+ return true;
+ // deliver the event
+ return receiver->event(event);
+}
+
+/*!
+ Returns true if an application object has not been created yet;
+ otherwise returns false.
+
+ \sa closingDown()
+*/
+
+bool QCoreApplication::startingUp()
+{
+ return !QCoreApplicationPrivate::is_app_running;
+}
+
+/*!
+ Returns true if the application objects are being destroyed;
+ otherwise returns false.
+
+ \sa startingUp()
+*/
+
+bool QCoreApplication::closingDown()
+{
+ return QCoreApplicationPrivate::is_app_closing;
+}
+
+
+/*!
+ Processes all pending events for the calling thread according to
+ the specified \a flags until there are no more events to process.
+
+ You can call this function occasionally when your program is busy
+ performing a long operation (e.g. copying a file).
+
+ In event you are running a local loop which calls this function
+ continuously, without an event loop, the
+ \l{QEvent::DeferredDelete}{DeferredDelete} events will
+ not be processed. This can affect the behaviour of widgets,
+ e.g. QToolTip, that rely on \l{QEvent::DeferredDelete}{DeferredDelete}
+ events to function properly. An alternative would be to call
+ \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from
+ within that local loop.
+
+ Calling this function processes events only for the calling thread.
+
+ \threadsafe
+
+ \sa exec(), QTimer, QEventLoop::processEvents(), flush(), sendPostedEvents()
+*/
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data->eventDispatcher)
+ return;
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ data->eventDispatcher->processEvents(flags);
+}
+
+/*!
+ \overload processEvents()
+
+ Processes pending events for the calling thread for \a maxtime
+ milliseconds or until there are no more events to process,
+ whichever is shorter.
+
+ You can call this function occasionally when you program is busy
+ doing a long operation (e.g. copying a file).
+
+ Calling this function processes events only for the calling thread.
+
+ \threadsafe
+
+ \sa exec(), QTimer, QEventLoop::processEvents()
+*/
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data->eventDispatcher)
+ return;
+ QElapsedTimer start;
+ start.start();
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
+ if (start.elapsed() > maxtime)
+ break;
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+/*****************************************************************************
+ Main event loop wrappers
+ *****************************************************************************/
+
+/*!
+ Enters the main event loop and waits until exit() is called.
+ Returns the value that was set to exit() (which is 0 if exit() is
+ called via quit()).
+
+ It is necessary to call this function to start event handling. The
+ main event loop receives events from the window system and
+ dispatches these to the application widgets.
+
+ 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 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
+ your application's \c{main()} function because on some platforms the
+ QCoreApplication::exec() call may not return. For example, on Windows
+ when the user logs off, the system terminates the process after Qt
+ closes all top-level windows. Hence, there is no guarantee that the
+ application will have time to exit its event loop and execute code at
+ the end of the \c{main()} function after the QCoreApplication::exec()
+ call.
+
+ \sa quit(), exit(), processEvents(), QApplication::exec()
+*/
+int QCoreApplication::exec()
+{
+ if (!QCoreApplicationPrivate::checkInstance("exec"))
+ return -1;
+
+ QThreadData *threadData = self->d_func()->threadData;
+ if (threadData != QThreadData::current()) {
+ qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
+ return -1;
+ }
+ if (!threadData->eventLoops.isEmpty()) {
+ qWarning("QCoreApplication::exec: The event loop is already running");
+ return -1;
+ }
+
+ threadData->quitNow = false;
+ QEventLoop eventLoop;
+ self->d_func()->in_exec = true;
+ self->d_func()->aboutToQuitEmitted = false;
+ int returnCode = eventLoop.exec();
+ threadData->quitNow = false;
+ if (self) {
+ self->d_func()->in_exec = false;
+ if (!self->d_func()->aboutToQuitEmitted)
+ emit self->aboutToQuit();
+ self->d_func()->aboutToQuitEmitted = true;
+ sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+
+ return returnCode;
+}
+
+
+/*!
+ Tells the application to exit with a return code.
+
+ After this function has been called, the application leaves the
+ main event loop and returns from the call to exec(). The exec()
+ function returns \a returnCode. If the event loop is not running,
+ this function does nothing.
+
+ By convention, a \a returnCode of 0 means success, and any non-zero
+ value indicates an error.
+
+ Note that unlike the C library function of the same name, this
+ function \e does return to the caller -- it is event processing that
+ stops.
+
+ \sa quit(), exec()
+*/
+void QCoreApplication::exit(int returnCode)
+{
+ if (!self)
+ return;
+ QThreadData *data = self->d_func()->threadData;
+ data->quitNow = true;
+ for (int i = 0; i < data->eventLoops.size(); ++i) {
+ QEventLoop *eventLoop = data->eventLoops.at(i);
+ eventLoop->exit(returnCode);
+ }
+}
+
+/*****************************************************************************
+ QCoreApplication management of posted events
+ *****************************************************************************/
+
+/*!
+ \fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+
+ Sends event \a event directly to receiver \a receiver, using the
+ notify() function. Returns the value that was returned from the
+ event handler.
+
+ The event is \e not deleted when the event has been sent. The normal
+ approach is to create the event on the stack, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 0
+
+ \sa postEvent(), notify()
+*/
+
+/*!
+ Adds the event \a event, with the object \a receiver as the
+ receiver of the event, to an event queue and returns immediately.
+
+ The event must be allocated on the heap since the post event queue
+ will take ownership of the event and delete it once it has been
+ posted. It is \e {not safe} to access the event after
+ it has been posted.
+
+ When control returns to the main event loop, all events that are
+ stored in the queue will be sent using the notify() function.
+
+ Events are processed in the order posted. For more control over
+ the processing order, use the postEvent() overload below, which
+ takes a priority argument. This function posts all event with a
+ Qt::NormalEventPriority.
+
+ \threadsafe
+
+ \sa sendEvent(), notify(), sendPostedEvents()
+*/
+
+void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
+{
+ postEvent(receiver, event, Qt::NormalEventPriority);
+}
+
+
+/*!
+ \overload postEvent()
+ \since 4.3
+
+ Adds the event \a event, with the object \a receiver as the
+ receiver of the event, to an event queue and returns immediately.
+
+ The event must be allocated on the heap since the post event queue
+ will take ownership of the event and delete it once it has been
+ posted. It is \e {not safe} to access the event after
+ it has been posted.
+
+ When control returns to the main event loop, all events that are
+ stored in the queue will be sent using the notify() function.
+
+ Events are sorted in descending \a priority order, i.e. events
+ with a high \a priority are queued before events with a lower \a
+ priority. The \a priority can be any integer value, i.e. between
+ INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more
+ details. Events with equal \a priority will be processed in the
+ order posted.
+
+ \threadsafe
+
+ \sa sendEvent(), notify(), sendPostedEvents(), Qt::EventPriority
+*/
+void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
+{
+ if (receiver == 0) {
+ qWarning("QCoreApplication::postEvent: Unexpected null receiver");
+ delete event;
+ return;
+ }
+
+ QThreadData * volatile * pdata = &receiver->d_func()->threadData;
+ QThreadData *data = *pdata;
+ if (!data) {
+ // posting during destruction? just delete the event to prevent a leak
+ delete event;
+ return;
+ }
+
+ // lock the post event mutex
+ data->postEventList.mutex.lock();
+
+ // if object has moved to another thread, follow it
+ while (data != *pdata) {
+ data->postEventList.mutex.unlock();
+
+ data = *pdata;
+ if (!data) {
+ // posting during destruction? just delete the event to prevent a leak
+ delete event;
+ return;
+ }
+
+ data->postEventList.mutex.lock();
+ }
+
+ QMutexUnlocker locker(&data->postEventList.mutex);
+
+ // if this is one of the compressible events, do compression
+ if (receiver->d_func()->postedEvents
+ && self && self->compressEvent(event, receiver, &data->postEventList)) {
+ return;
+ }
+
+ if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
+ // remember the current running eventloop for DeferredDelete
+ // events posted in the receiver's thread
+ event->d = reinterpret_cast<QEventPrivate *>(quintptr(data->loopLevel));
+ }
+
+ // delete the event on exceptions to protect against memory leaks till the event is
+ // properly owned in the postEventList
+ QScopedPointer<QEvent> eventDeleter(event);
+ if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) {
+ // optimization: we can simply append if the last event in
+ // the queue has higher or equal priority
+ data->postEventList.append(QPostEvent(receiver, event, priority));
+ } 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 begin = data->postEventList.begin()
+ + data->postEventList.insertionOffset,
+ end = data->postEventList.end();
+ QPostEventList::iterator at = qUpperBound(begin, end, priority);
+ data->postEventList.insert(at, QPostEvent(receiver, event, priority));
+ }
+ eventDeleter.take();
+ event->posted = true;
+ ++receiver->d_func()->postedEvents;
+ data->canWait = false;
+ locker.unlock();
+
+ if (data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+}
+
+/*!
+ \internal
+ Returns true if \a event was compressed away (possibly deleted) and should not be added to the list.
+*/
+bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
+{
+#ifdef Q_WS_WIN
+ Q_ASSERT(event);
+ Q_ASSERT(receiver);
+ Q_ASSERT(postedEvents);
+
+ // 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) {
+ delete event;
+ return true;
+ }
+ }
+ } else
+#endif
+ if ((event->type() == QEvent::DeferredDelete
+ || event->type() == QEvent::Quit)
+ && receiver->d_func()->postedEvents > 0) {
+ for (int i = 0; i < postedEvents->size(); ++i) {
+ const QPostEvent &cur = postedEvents->at(i);
+ if (cur.receiver != receiver
+ || cur.event == 0
+ || cur.event->type() != event->type())
+ continue;
+ // found an event for this receiver
+ delete event;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \fn void QCoreApplication::sendPostedEvents()
+ \overload sendPostedEvents()
+
+ Dispatches all posted events, i.e. empties the event queue.
+*/
+
+/*!
+ Immediately dispatches all events which have been previously queued
+ with QCoreApplication::postEvent() and which are for the object \a receiver
+ and have the event type \a event_type.
+
+ Events from the window system are \e not dispatched by this
+ function, but by processEvents().
+
+ If \a receiver is null, the events of \a event_type are sent for all
+ objects. If \a event_type is 0, all the events are sent for \a receiver.
+
+ \note This method must be called from the same thread as its QObject parameter, \a receiver.
+
+ \sa flush(), postEvent()
+*/
+
+void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
+{
+ QThreadData *data = QThreadData::current();
+
+ QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
+}
+
+void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type,
+ QThreadData *data)
+{
+ if (event_type == -1) {
+ // we were called by an obsolete event dispatcher.
+ event_type = 0;
+ }
+
+ if (receiver && receiver->d_func()->threadData != data) {
+ qWarning("QCoreApplication::sendPostedEvents: Cannot send "
+ "posted events for objects in another thread");
+ return;
+ }
+
+ ++data->postEventList.recursion;
+
+#ifdef QT3_SUPPORT
+ if (event_type == QEvent::ChildInserted) {
+ if (receiver) {
+ // optimize sendPostedEvents(w, QEvent::ChildInserted) calls away
+ receiver->d_func()->sendPendingChildInsertedEvents();
+ --data->postEventList.recursion;
+ return;
+ }
+
+ // ChildInserted events are sent in response to *Request
+ event_type = QEvent::ChildInsertedRequest;
+ }
+#endif
+
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ // by default, we assume that the event dispatcher can go to sleep after
+ // processing all events. if any new events are posted while we send
+ // events, canWait will be set to false.
+ data->canWait = (data->postEventList.size() == 0);
+
+ if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
+ --data->postEventList.recursion;
+ return;
+ }
+
+ data->canWait = true;
+
+ // 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;
+ data->postEventList.insertionOffset = data->postEventList.size();
+
+ while (i < data->postEventList.size()) {
+ // avoid live-lock
+ if (i >= data->postEventList.insertionOffset)
+ break;
+
+ const QPostEvent &pe = data->postEventList.at(i);
+ ++i;
+
+ if (!pe.event)
+ continue;
+ if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
+ data->canWait = false;
+ continue;
+ }
+
+ if (pe.event->type() == QEvent::DeferredDelete) {
+ // DeferredDelete events are only sent when we are explicitly asked to
+ // (s.a. QEvent::DeferredDelete), and then only if the event loop that
+ // posted the event has returned.
+ const bool allowDeferredDelete =
+ (quintptr(pe.event->d) > unsigned(data->loopLevel)
+ || (!quintptr(pe.event->d) && data->loopLevel > 0)
+ || (event_type == QEvent::DeferredDelete
+ && quintptr(pe.event->d) == unsigned(data->loopLevel)));
+ if (!allowDeferredDelete) {
+ // cannot send deferred delete
+ if (!event_type && !receiver) {
+ // don't lose the event
+ data->postEventList.append(pe);
+ const_cast<QPostEvent &>(pe).event = 0;
+ }
+ continue;
+ }
+ }
+
+ // 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;
+ QEvent * e = pe.event;
+ QObject * r = pe.receiver;
+
+ --r->d_func()->postedEvents;
+ Q_ASSERT(r->d_func()->postedEvents >= 0);
+
+ // next, update the data structure so that we're ready
+ // for the next event.
+ const_cast<QPostEvent &>(pe).event = 0;
+
+ locker.unlock();
+ // after all that work, it's time to deliver the event.
+#ifdef QT_NO_EXCEPTIONS
+ QCoreApplication::sendEvent(r, e);
+#else
+ try {
+ QCoreApplication::sendEvent(r, e);
+ } catch (...) {
+ delete e;
+ locker.relock();
+
+ // since we were interrupted, we need another pass to make sure we clean everything up
+ data->canWait = false;
+
+ // uglehack: copied from below
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+ throw; // rethrow
+ }
+#endif
+
+ delete e;
+ locker.relock();
+
+ // careful when adding anything below this point - the
+ // sendEvent() call might invalidate any invariants this
+ // function depends on.
+ }
+
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+
+ // clear the global list, i.e. remove everything that was
+ // delivered.
+ if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
+ const QPostEventList::iterator it = data->postEventList.begin();
+ data->postEventList.erase(it, it + data->postEventList.startOffset);
+ data->postEventList.insertionOffset -= data->postEventList.startOffset;
+ Q_ASSERT(data->postEventList.insertionOffset >= 0);
+ data->postEventList.startOffset = 0;
+ }
+}
+
+/*!
+ Removes all events posted using postEvent() for \a receiver.
+
+ The events are \e not dispatched, instead they are removed from the
+ queue. You should never need to call this function. If you do call it,
+ be aware that killing events may cause \a receiver to break one or
+ more invariants.
+
+ \threadsafe
+*/
+
+void QCoreApplication::removePostedEvents(QObject *receiver)
+{
+ removePostedEvents(receiver, 0);
+}
+
+/*!
+ \overload removePostedEvents()
+ \since 4.3
+
+ Removes all events of the given \a eventType that were posted
+ using postEvent() for \a receiver.
+
+ The events are \e not dispatched, instead they are removed from
+ the queue. You should never need to call this function. If you do
+ call it, be aware that killing events may cause \a receiver to
+ break one or more invariants.
+
+ If \a receiver is null, the events of \a eventType are removed for
+ all objects. If \a eventType is 0, all the events are removed for
+ \a receiver.
+
+ \threadsafe
+*/
+
+void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
+{
+#ifdef QT3_SUPPORT
+ if (eventType == QEvent::ChildInserted)
+ eventType = QEvent::ChildInsertedRequest;
+#endif
+
+ QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current();
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ // the QObject destructor calls this function directly. this can
+ // happen while the event loop is in the middle of posting events,
+ // and when we get here, we may not have any more posted events
+ // for this object.
+ if (receiver && !receiver->d_func()->postedEvents)
+ return;
+
+ //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;
+
+ for (int 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;
+#ifdef QT3_SUPPORT
+ if (pe.event->type() == QEvent::ChildInsertedRequest)
+ pe.receiver->d_func()->pendingChildInsertedEvents.clear();
+#endif
+ pe.event->posted = false;
+ events.append(pe.event);
+ const_cast<QPostEvent &>(pe).event = 0;
+ } else if (!data->postEventList.recursion) {
+ if (i != j)
+ data->postEventList.swap(i, j);
+ ++j;
+ }
+ }
+
+#ifdef QT_DEBUG
+ if (receiver && eventType == 0) {
+ Q_ASSERT(!receiver->d_func()->postedEvents);
+ }
+#endif
+
+ if (!data->postEventList.recursion) {
+ // truncate list
+ data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
+ }
+
+ locker.unlock();
+ for (int i = 0; i < events.count(); ++i) {
+ delete events[i];
+ }
+}
+
+/*!
+ Removes \a event from the queue of posted events, and emits a
+ warning message if appropriate.
+
+ \warning This function can be \e really slow. Avoid using it, if
+ possible.
+
+ \threadsafe
+*/
+
+void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
+{
+ if (!event || !event->posted)
+ return;
+
+ QThreadData *data = QThreadData::current();
+
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ if (data->postEventList.size() == 0) {
+#if defined(QT_DEBUG)
+ qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
+ (void*)event, event->type());
+ return;
+#endif
+ }
+
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent & pe = data->postEventList.at(i);
+ if (pe.event == event) {
+#ifndef QT_NO_DEBUG
+ qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
+ event->type(),
+ pe.receiver->metaObject()->className(),
+ pe.receiver->objectName().toLocal8Bit().data());
+#endif
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+
+/*!\reimp
+
+*/
+bool QCoreApplication::event(QEvent *e)
+{
+ if (e->type() == QEvent::Quit) {
+ quit();
+ return true;
+ }
+ return QObject::event(e);
+}
+
+/*! \enum QCoreApplication::Encoding
+
+ This enum type defines the 8-bit encoding of character string
+ arguments to translate():
+
+ \value CodecForTr The encoding specified by
+ QTextCodec::codecForTr() (Latin-1 if none has
+ been set).
+ \value UnicodeUTF8 UTF-8.
+ \value DefaultCodec (Obsolete) Use CodecForTr instead.
+
+ \sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8()
+*/
+
+/*!
+ Tells the application to exit with return code 0 (success).
+ Equivalent to calling QCoreApplication::exit(0).
+
+ It's common to connect the QApplication::lastWindowClosed() signal
+ to quit(), and you also often connect e.g. QAbstractButton::clicked() or
+ signals in QAction, QMenu, or QMenuBar to it.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 1
+
+ \sa exit(), aboutToQuit(), QApplication::lastWindowClosed()
+*/
+
+void QCoreApplication::quit()
+{
+ exit(0);
+}
+
+/*!
+ \fn void QCoreApplication::aboutToQuit()
+
+ This signal is emitted when the application is about to quit the
+ main event loop, e.g. when the event loop level drops to zero.
+ This may happen either after a call to quit() from inside the
+ application or when the users shuts down the entire desktop session.
+
+ The signal is particularly useful if your application has to do some
+ last-second cleanup. Note that no user interaction is possible in
+ this state.
+
+ \sa quit()
+*/
+
+#ifndef QT_NO_TRANSLATION
+/*!
+ Adds the translation file \a translationFile to the list of
+ translation files to be used for translations.
+
+ Multiple translation files can be installed. Translations are
+ searched for in the reverse order in which they were installed,
+ so the most recently installed translation file is searched first
+ and the first translation file installed is searched last.
+ The search stops as soon as a translation containing a matching
+ string is found.
+
+ Installing or removing a QTranslator, or changing an installed QTranslator
+ generates a \l{QEvent::LanguageChange}{LanguageChange} event for the
+ QCoreApplication instance. A QApplication instance will propagate the event
+ to all toplevel windows, 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 \l{Qt Designer} provide a \c retranslateUi() function that can be
+ called.
+
+ \sa removeTranslator() translate() QTranslator::load() {Dynamic Translation}
+*/
+
+void QCoreApplication::installTranslator(QTranslator *translationFile)
+{
+ if (!translationFile)
+ return;
+
+ if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
+ return;
+ QCoreApplicationPrivate *d = self->d_func();
+ d->translators.prepend(translationFile);
+
+#ifndef QT_NO_TRANSLATION_BUILDER
+ if (translationFile->isEmpty())
+ return;
+#endif
+
+ QEvent ev(QEvent::LanguageChange);
+ QCoreApplication::sendEvent(self, &ev);
+}
+
+/*!
+ Removes the translation file \a translationFile from the list of
+ translation files used by this application. (It does not delete the
+ translation file from the file system.)
+
+ \sa installTranslator() translate(), QObject::tr()
+*/
+
+void QCoreApplication::removeTranslator(QTranslator *translationFile)
+{
+ if (!translationFile)
+ return;
+ if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
+ return;
+ QCoreApplicationPrivate *d = self->d_func();
+ if (d->translators.removeAll(translationFile) && !self->closingDown()) {
+ QEvent ev(QEvent::LanguageChange);
+ QCoreApplication::sendEvent(self, &ev);
+ }
+}
+
+/*!
+ \overload translate()
+*/
+QString QCoreApplication::translate(const char *context, const char *sourceText,
+ const char *disambiguation, Encoding encoding)
+{
+ return translate(context, sourceText, disambiguation, encoding, -1);
+}
+
+static void replacePercentN(QString *result, int n)
+{
+ if (n >= 0) {
+ int percentPos = 0;
+ int len = 0;
+ while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) {
+ len = 1;
+ QString fmt;
+ if (result->at(percentPos + len) == QLatin1Char('L')) {
+ ++len;
+ fmt = QLatin1String("%L1");
+ } else {
+ fmt = QLatin1String("%1");
+ }
+ if (result->at(percentPos + len) == QLatin1Char('n')) {
+ fmt = fmt.arg(n);
+ ++len;
+ result->replace(percentPos, len, fmt);
+ len = fmt.length();
+ }
+ }
+ }
+}
+
+/*!
+ \reentrant
+ \since 4.5
+
+ Returns the translation text for \a sourceText, by querying the
+ installed translation files. The translation files are searched
+ from the most recently installed file back to the first
+ installed file.
+
+ QObject::tr() and QObject::trUtf8() provide this functionality
+ more conveniently.
+
+ \a context is typically a class name (e.g., "MyDialog") and \a
+ sourceText is either English text or a short identifying text.
+
+ \a disambiguation is an identifying string, for when the same \a
+ sourceText is used in different roles within the same context. By
+ default, it is null.
+
+ See the \l QTranslator and \l QObject::tr() documentation for
+ more information about contexts, disambiguations and comments.
+
+ \a encoding indicates the 8-bit encoding of character strings.
+
+ \a n is used in conjunction with \c %n to support plural forms.
+ See QObject::tr() for details.
+
+ If none of the translation files contain a translation for \a
+ sourceText in \a context, this function returns a QString
+ equivalent of \a sourceText. The encoding of \a sourceText is
+ specified by \e encoding; it defaults to CodecForTr.
+
+ This function is not virtual. You can use alternative translation
+ techniques by subclassing \l QTranslator.
+
+ \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 most likely result in crashes or other undesirable
+ behavior.
+
+ \sa QObject::tr() installTranslator() QTextCodec::codecForTr()
+*/
+
+
+QString QCoreApplication::translate(const char *context, const char *sourceText,
+ const char *disambiguation, Encoding encoding, int n)
+{
+ QString result;
+
+ if (!sourceText)
+ return result;
+
+ if (self && !self->d_func()->translators.isEmpty()) {
+ QList<QTranslator*>::ConstIterator it;
+ QTranslator *translationFile;
+ for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
+ translationFile = *it;
+ result = translationFile->translate(context, sourceText, disambiguation, n);
+ if (!result.isEmpty())
+ break;
+ }
+ }
+
+ if (result.isEmpty()) {
+#ifdef QT_NO_TEXTCODEC
+ Q_UNUSED(encoding)
+#else
+ if (encoding == UnicodeUTF8)
+ result = QString::fromUtf8(sourceText);
+ else if (QTextCodec::codecForTr() != 0)
+ result = QTextCodec::codecForTr()->toUnicode(sourceText);
+ else
+#endif
+ result = QString::fromLatin1(sourceText);
+ }
+
+ replacePercentN(&result, n);
+ return result;
+}
+
+// Declared in qglobal.h
+QString qtTrId(const char *id, int n)
+{
+ return QCoreApplication::translate(0, id, 0, QCoreApplication::UnicodeUTF8, n);
+}
+
+bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
+{
+ return QCoreApplication::self
+ && QCoreApplication::self->d_func()->translators.contains(translator);
+}
+
+#endif //QT_NO_TRANSLATE
+
+/*!
+ Returns the directory that contains the application executable.
+
+ For example, if you have installed Qt in the \c{C:\Trolltech\Qt}
+ directory, and you run the \c{regexp} example, this function will
+ return "C:/Trolltech/Qt/examples/tools/regexp".
+
+ On Mac OS X this will point to the directory actually containing the
+ executable, which may be inside of an application bundle (if the
+ application is bundled).
+
+ \warning On Linux, this function will try to get the path from the
+ \c {/proc} file system. If that fails, it assumes that \c
+ {argv[0]} contains the absolute file name of the executable. The
+ function also assumes that the current directory has not been
+ changed by the application.
+
+ In Symbian this function will return the application private directory,
+ not the path to executable itself, as those are always in \c {/sys/bin}.
+ If the application is in a read only drive, i.e. ROM, then the private path
+ on the system drive will be returned.
+
+ \sa applicationFilePath()
+*/
+QString QCoreApplication::applicationDirPath()
+{
+ if (!self) {
+ qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
+ return QString();
+ }
+
+ QCoreApplicationPrivate *d = self->d_func();
+ if (d->cachedApplicationDirPath.isNull())
+#if defined(Q_OS_SYMBIAN)
+ {
+ QString appPath;
+ RFs& fs = qt_s60GetRFs();
+ TChar driveChar;
+ QChar qDriveChar;
+ driveChar = (RProcess().FileName())[0];
+
+ //Check if the process is installed in a read only drive (typically ROM),
+ //and use the system drive (typically C:) if so.
+ TInt drive;
+ TDriveInfo driveInfo;
+ TInt err = fs.CharToDrive(driveChar, drive);
+ if (err == KErrNone) {
+ err = fs.Drive(driveInfo, drive);
+ }
+ if (err != KErrNone || (driveInfo.iDriveAtt & KDriveAttRom) || (driveInfo.iMediaAtt
+ & KMediaAttWriteProtected)) {
+ if(!PtrGetSystemDrive)
+ PtrGetSystemDrive = reinterpret_cast<SystemDriveFunc>(qt_resolveS60PluginFunc(S60Plugin_GetSystemDrive));
+ Q_ASSERT(PtrGetSystemDrive);
+ drive = PtrGetSystemDrive(fs);
+ fs.DriveToChar(drive, driveChar);
+ }
+
+ qDriveChar = QChar(QLatin1Char(driveChar)).toUpper();
+
+ TFileName privatePath;
+ fs.PrivatePath(privatePath);
+ appPath = qt_TDesC2QString(privatePath);
+ appPath.prepend(QLatin1Char(':')).prepend(qDriveChar);
+
+ // Create the appPath if it doesn't exist. Non-existing appPath will cause
+ // Platform Security violations later on if the app doesn't have AllFiles capability.
+ err = fs.CreatePrivatePath(drive);
+ if (err != KErrNone)
+ qWarning("QCoreApplication::applicationDirPath: Failed to create private path.");
+
+ d->cachedApplicationDirPath = QFileInfo(appPath).path();
+ }
+#else
+ d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
+#endif
+ return d->cachedApplicationDirPath;
+}
+
+/*!
+ Returns the file path of the application executable.
+
+ For example, if you have installed Qt in the \c{/usr/local/qt}
+ directory, and you run the \c{regexp} example, this function will
+ return "/usr/local/qt/examples/tools/regexp/regexp".
+
+ \warning On Linux, this function will try to get the path from the
+ \c {/proc} file system. If that fails, it assumes that \c
+ {argv[0]} contains the absolute file name of the executable. The
+ function also assumes that the current directory has not been
+ changed by the application.
+
+ \sa applicationDirPath()
+*/
+QString QCoreApplication::applicationFilePath()
+{
+ if (!self) {
+ qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
+ return QString();
+ }
+
+ QCoreApplicationPrivate *d = self->d_func();
+ if (!d->cachedApplicationFilePath.isNull())
+ return d->cachedApplicationFilePath;
+
+#if defined(Q_WS_WIN)
+ d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath();
+ return d->cachedApplicationFilePath;
+#elif defined(Q_WS_MAC)
+ QString qAppFileName_str = qAppFileName();
+ if(!qAppFileName_str.isEmpty()) {
+ QFileInfo fi(qAppFileName_str);
+ d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
+ return d->cachedApplicationFilePath;
+ }
+#endif
+#if defined(Q_OS_SYMBIAN)
+ QString appPath;
+ RProcess proc;
+ TInt err = proc.Open(proc.Id());
+ if (err == KErrNone) {
+ TFileName procName = proc.FileName();
+ appPath.append(QString(reinterpret_cast<const QChar*>(procName.Ptr()), procName.Length()));
+ proc.Close();
+ }
+
+ d->cachedApplicationFilePath = appPath;
+ return d->cachedApplicationFilePath;
+
+#elif defined( Q_OS_UNIX )
+# ifdef Q_OS_LINUX
+ // 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()) {
+ d->cachedApplicationFilePath = pfi.canonicalFilePath();
+ return d->cachedApplicationFilePath;
+ }
+# endif
+
+ QString argv0 = QFile::decodeName(QByteArray(argv()[0]));
+ QString absPath;
+
+ if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
+ /*
+ If argv0 starts with a slash, it is already an absolute
+ file path.
+ */
+ absPath = argv0;
+ } else if (argv0.contains(QLatin1Char('/'))) {
+ /*
+ If argv0 contains one or more slashes, it is a file path
+ relative to the current directory.
+ */
+ absPath = QDir::current().absoluteFilePath(argv0);
+ } else {
+ /*
+ Otherwise, the file path has to be determined using the
+ PATH environment variable.
+ */
+ QByteArray pEnv = qgetenv("PATH");
+ QDir currentDir = QDir::current();
+ QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
+ for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
+ if ((*p).isEmpty())
+ continue;
+ QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
+ QFileInfo candidate_fi(candidate);
+ if (candidate_fi.exists() && !candidate_fi.isDir()) {
+ absPath = candidate;
+ break;
+ }
+ }
+ }
+
+ absPath = QDir::cleanPath(absPath);
+
+ QFileInfo fi(absPath);
+ d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
+ return d->cachedApplicationFilePath;
+#endif
+}
+
+/*!
+ \since 4.4
+
+ Returns the current process ID for the application.
+*/
+qint64 QCoreApplication::applicationPid()
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return GetCurrentProcessId();
+#elif defined(Q_OS_VXWORKS)
+ return (pid_t) taskIdCurrent;
+#else
+ return getpid();
+#endif
+}
+
+/*!
+ \obsolete
+
+ Use arguments().size() instead.
+*/
+int QCoreApplication::argc()
+{
+ if (!self) {
+ qWarning("QCoreApplication::argc: Please instantiate the QApplication object first");
+ return 0;
+ }
+ return self->d_func()->argc;
+}
+
+
+/*!
+ \obsolete
+
+ Use arguments() instead.
+*/
+char **QCoreApplication::argv()
+{
+ if (!self) {
+ qWarning("QCoreApplication::argv: Please instantiate the QApplication object first");
+ return 0;
+ }
+ return self->d_func()->argv;
+}
+
+/*!
+ \since 4.1
+
+ Returns the list of command-line arguments.
+
+ Usually arguments().at(0) is the program name, arguments().at(1)
+ is the first argument, and arguments().last() is the last
+ argument. See the note below about Windows.
+
+ Calling this function is slow - you should store the result in a variable
+ when parsing the command line.
+
+ \warning On Unix, this list is built from the argc and argv parameters passed
+ to the constructor in the main() function. The string-data in argv is
+ interpreted using QString::fromLocal8Bit(); hence it is not possible to
+ pass, for example, Japanese command line arguments on a system that runs in a
+ Latin1 locale. Most modern Unix systems do not have this limitation, as they are
+ Unicode-based.
+
+ On NT-based Windows, this limitation does not apply either.
+ On Windows, the arguments() are not built from the contents of argv/argc, as
+ the content does not support Unicode. Instead, the arguments() are constructed
+ from the return value of
+ \l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{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.
+
+ For Symbian applications started with \c RApaLsSession::StartApp one can specify
+ arguments using \c CApaCommandLine::SetTailEndL function. Such arguments are only
+ available via this method; they will not be passed to \c main function. Also note
+ that only 8-bit string data set with \c CApaCommandLine::SetTailEndL is supported
+ by this function.
+
+ \sa applicationFilePath()
+*/
+
+QStringList QCoreApplication::arguments()
+{
+ QStringList list;
+
+ if (!self) {
+ qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
+ return list;
+ }
+#ifdef Q_OS_WIN
+ QString cmdline = QString::fromWCharArray(GetCommandLine());
+
+#if defined(Q_OS_WINCE)
+ wchar_t tempFilename[MAX_PATH+1];
+ if (GetModuleFileName(0, tempFilename, MAX_PATH)) {
+ tempFilename[MAX_PATH] = 0;
+ cmdline.prepend(QLatin1Char('\"') + QString::fromWCharArray(tempFilename) + QLatin1String("\" "));
+ }
+#endif // Q_OS_WINCE
+
+ list = qWinCmdArgs(cmdline);
+ if (self->d_func()->application_type) { // GUI app? Skip known - see qapplication.cpp
+ QStringList stripped;
+ for (int a = 0; a < list.count(); ++a) {
+ QString arg = list.at(a);
+ QByteArray l1arg = arg.toLatin1();
+ if (l1arg == "-qdevel" ||
+ l1arg == "-qdebug" ||
+ l1arg == "-reverse" ||
+ l1arg == "-stylesheet" ||
+ l1arg == "-widgetcount")
+ ;
+ else if (l1arg.startsWith("-style=") ||
+ l1arg.startsWith("-qmljsdebugger="))
+ ;
+ else if (l1arg == "-style" ||
+ l1arg == "-session" ||
+ l1arg == "-graphicssystem" ||
+ l1arg == "-testability")
+ ++a;
+ else
+ stripped += arg;
+ }
+ list = stripped;
+ }
+#else
+ const int ac = self->d_func()->argc;
+ char ** const av = self->d_func()->argv;
+ for (int a = 0; a < ac; ++a) {
+ list << QString::fromLocal8Bit(av[a]);
+ }
+#endif
+
+ return list;
+}
+
+/*!
+ \property QCoreApplication::organizationName
+ \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
+ information each time a QSettings object is created.
+
+ On Mac, QSettings uses organizationDomain() as the organization
+ if it's not an empty string; otherwise it uses
+ organizationName(). On all other platforms, QSettings uses
+ organizationName() as the organization.
+
+ \sa organizationDomain applicationName
+*/
+
+void QCoreApplication::setOrganizationName(const QString &orgName)
+{
+ coreappdata()->orgName = orgName;
+}
+
+QString QCoreApplication::organizationName()
+{
+ return coreappdata()->orgName;
+}
+
+/*!
+ \property QCoreApplication::organizationDomain
+ \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
+ information each time a QSettings object is created.
+
+ On Mac, QSettings uses organizationDomain() as the organization
+ if it's not an empty string; otherwise it uses organizationName().
+ On all other platforms, QSettings uses organizationName() as the
+ organization.
+
+ \sa organizationName applicationName applicationVersion
+*/
+void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
+{
+ coreappdata()->orgDomain = orgDomain;
+}
+
+QString QCoreApplication::organizationDomain()
+{
+ return coreappdata()->orgDomain;
+}
+
+/*!
+ \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.
+
+ \sa organizationName organizationDomain applicationVersion
+*/
+void QCoreApplication::setApplicationName(const QString &application)
+{
+ coreappdata()->application = application;
+}
+
+QString QCoreApplication::applicationName()
+{
+ return coreappdata()->application;
+}
+
+/*!
+ \property QCoreApplication::applicationVersion
+ \since 4.4
+ \brief the version of this application
+
+ \sa applicationName organizationName organizationDomain
+*/
+void QCoreApplication::setApplicationVersion(const QString &version)
+{
+ coreappdata()->applicationVersion = version;
+}
+
+QString QCoreApplication::applicationVersion()
+{
+ return coreappdata()->applicationVersion;
+}
+
+#ifndef QT_NO_LIBRARY
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
+
+/*!
+ Returns a list of paths that the application will search when
+ dynamically loading libraries.
+
+ Qt provides default library paths, but they can also be set using
+ a \l{Using qt.conf}{qt.conf} file. Paths specified in this file
+ will override default values.
+
+ This list will include the installation directory for plugins if
+ it exists (the default installation directory for plugins is \c
+ INSTALL/plugins, where \c INSTALL is the directory where Qt was
+ installed). The directory of the application executable (NOT the
+ working directory) is always added, as well as the colon separated
+ entries of the QT_PLUGIN_PATH environment variable.
+
+ If you want to iterate over the list, you can use the \l foreach
+ pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 2
+
+ \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
+ {How to Create Qt Plugins}
+*/
+QStringList QCoreApplication::libraryPaths()
+{
+ QMutexLocker locker(libraryPathMutex());
+ if (!coreappdata()->app_libpaths) {
+ QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList;
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+#if defined(Q_OS_SYMBIAN)
+ // Add existing path on all drives for relative PluginsPath in Symbian
+ if (installPathPlugins.at(1) != QChar(QLatin1Char(':'))) {
+ QString tempPath = installPathPlugins;
+ if (tempPath.at(tempPath.length() - 1) != QDir::separator()) {
+ tempPath += QDir::separator();
+ }
+ RFs& fs = qt_s60GetRFs();
+ TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData()));
+ TFindFile finder(fs);
+ TInt err = finder.FindByDir(tempPathPtr, tempPathPtr);
+ while (err == KErrNone) {
+ QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()),
+ finder.File().Length());
+ foundDir = QDir(foundDir).canonicalPath();
+ if (!app_libpaths->contains(foundDir))
+ app_libpaths->append(foundDir);
+ err = finder.Find();
+ }
+ }
+#else
+ if (QFile::exists(installPathPlugins)) {
+ // Make sure we convert from backslashes to slashes.
+ installPathPlugins = QDir(installPathPlugins).canonicalPath();
+ if (!app_libpaths->contains(installPathPlugins))
+ app_libpaths->append(installPathPlugins);
+ }
+#endif
+
+ // If QCoreApplication is not yet instantiated,
+ // make sure we add the application path when we construct the QCoreApplication
+ if (self) self->d_func()->appendApplicationPathToLibraryPaths();
+
+ const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
+ if (!libPathEnv.isEmpty()) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ QLatin1Char pathSep(';');
+#else
+ QLatin1Char pathSep(':');
+#endif
+ QStringList paths = QString::fromLatin1(libPathEnv).split(pathSep, QString::SkipEmptyParts);
+ for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
+ QString canonicalPath = QDir(*it).canonicalPath();
+ if (!canonicalPath.isEmpty()
+ && !app_libpaths->contains(canonicalPath)) {
+ app_libpaths->append(canonicalPath);
+ }
+ }
+ }
+ }
+ return *(coreappdata()->app_libpaths);
+}
+
+
+
+/*!
+
+ 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.
+
+ In Symbian this function is only useful for setting paths for
+ finding Qt extension plugin stubs, since the OS can only
+ load libraries from the \c{/sys/bin} directory.
+
+ \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
+ */
+void QCoreApplication::setLibraryPaths(const QStringList &paths)
+{
+ QMutexLocker locker(libraryPathMutex());
+ if (!coreappdata()->app_libpaths)
+ coreappdata()->app_libpaths = new QStringList;
+ *(coreappdata()->app_libpaths) = paths;
+ locker.unlock();
+ QFactoryLoader::refreshAll();
+}
+
+/*!
+ Prepends \a path to the beginning of the library path list, ensuring that
+ 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.
+
+ In Symbian this function is only useful for adding paths for
+ finding Qt extension plugin stubs, since the OS can only
+ load libraries from the \c{/sys/bin} directory.
+
+ \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
+ */
+void QCoreApplication::addLibraryPath(const QString &path)
+{
+ if (path.isEmpty())
+ return;
+
+ QMutexLocker locker(libraryPathMutex());
+
+ // make sure that library paths is initialized
+ libraryPaths();
+
+ QString canonicalPath = QDir(path).canonicalPath();
+ if (!canonicalPath.isEmpty()
+ && !coreappdata()->app_libpaths->contains(canonicalPath)) {
+ coreappdata()->app_libpaths->prepend(canonicalPath);
+ locker.unlock();
+ QFactoryLoader::refreshAll();
+ }
+}
+
+/*!
+ Removes \a path from the library path list. If \a path is empty or not
+ in the path list, the list is not changed.
+
+ \sa addLibraryPath(), libraryPaths(), setLibraryPaths()
+*/
+void QCoreApplication::removeLibraryPath(const QString &path)
+{
+ if (path.isEmpty())
+ return;
+
+ QMutexLocker locker(libraryPathMutex());
+
+ // make sure that library paths is initialized
+ libraryPaths();
+
+ QString canonicalPath = QDir(path).canonicalPath();
+ coreappdata()->app_libpaths->removeAll(canonicalPath);
+ QFactoryLoader::refreshAll();
+}
+
+#endif //QT_NO_LIBRARY
+
+/*!
+ \typedef QCoreApplication::EventFilter
+
+ A function with the following signature that can be used as an
+ event filter:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 3
+
+ \sa setEventFilter()
+*/
+
+/*!
+ \fn EventFilter QCoreApplication::setEventFilter(EventFilter filter)
+
+ Replaces the event filter function for the QCoreApplication with
+ \a filter and returns the pointer to the replaced event filter
+ function. Only the current event filter function is called. If you
+ want to use both filter functions, save the replaced EventFilter
+ in a place where yours can call it.
+
+ The event filter function set here is called for all messages
+ received by all threads meant for all Qt objects. It is \e not
+ called for messages that are not meant for Qt objects.
+
+ The event filter function should return true if the message should
+ be filtered, (i.e. stopped). It should return false to allow
+ processing the message to continue.
+
+ By default, no event filter function is set (i.e., this function
+ returns a null EventFilter the first time it is called).
+
+ \note The filter function set here receives native messages,
+ i.e. MSG or XEvent structs, that are going to Qt objects. It is
+ called by QCoreApplication::filterEvent(). If the filter function
+ returns false to indicate the message should be processed further,
+ the native message can then be translated into a QEvent and
+ handled by the standard Qt \l{QEvent} {event} filering, e.g.
+ QObject::installEventFilter().
+
+ \note The filter function set here is different form the filter
+ function set via QAbstractEventDispatcher::setEventFilter(), which
+ gets all messages received by its thread, even messages meant for
+ objects that are not handled by Qt.
+
+ \sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter()
+*/
+QCoreApplication::EventFilter
+QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter)
+{
+ Q_D(QCoreApplication);
+ EventFilter old = d->eventFilter;
+ d->eventFilter = filter;
+ return old;
+}
+
+/*!
+ Sends \a message through the event filter that was set by
+ setEventFilter(). If no event filter has been set, this function
+ returns false; otherwise, this function returns the result of the
+ event filter function in the \a result parameter.
+
+ \sa setEventFilter()
+*/
+bool QCoreApplication::filterEvent(void *message, long *result)
+{
+ Q_D(QCoreApplication);
+ if (result)
+ *result = 0;
+ if (d->eventFilter)
+ return d->eventFilter(message, result);
+#ifdef Q_OS_WIN
+ return winEventFilter(reinterpret_cast<MSG *>(message), result);
+#else
+ return false;
+#endif
+}
+
+/*!
+ This function returns true if there are pending events; otherwise
+ returns false. Pending events can be either from the window
+ system or posted events using postEvent().
+
+ \sa QAbstractEventDispatcher::hasPendingEvents()
+*/
+bool QCoreApplication::hasPendingEvents()
+{
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ if (eventDispatcher)
+ return eventDispatcher->hasPendingEvents();
+ return false;
+}
+
+#ifdef QT3_SUPPORT
+/*! \fn void QCoreApplication::lock()
+
+ In Qt 3, this function locked the Qt library mutex, allowing
+ non-GUI threads to perform basic printing operations using
+ QPainter.
+
+ In Qt 4, this is no longer supported, since painting is only
+ supported from within a paint event handler. This function does
+ nothing.
+
+ \sa QWidget::paintEvent()
+*/
+
+/*! \fn void QCoreApplication::unlock(bool wakeUpGui)
+
+ In Qt 3, this function unlocked the Qt library mutex. The mutex
+ allowed non-GUI threads to perform basic printing operations
+ using QPainter.
+
+ In Qt 4, this is no longer supported, since painting is only
+ supported from within a paint event handler. This function does
+ nothing.
+*/
+
+/*! \fn bool QCoreApplication::locked()
+
+ This function does nothing. It is there to keep old code working.
+ It always returns false.
+
+ See lock() for details.
+*/
+
+/*! \fn bool QCoreApplication::tryLock()
+
+ This function does nothing. It is there to keep old code working.
+ It always returns false.
+
+ See lock() for details.
+*/
+
+/*! \fn void QCoreApplication::processOneEvent()
+ \obsolete
+
+ Waits for an event to occur, processes it, then returns.
+
+ This function is useful for adapting Qt to situations where the
+ event processing must be grafted onto existing program loops.
+
+ Using this function in new applications may be an indication of design
+ problems.
+
+ \sa processEvents(), exec(), QTimer
+*/
+
+/*! \obsolete
+
+ This function enters the main event loop (recursively). Do not call
+ it unless you really know what you are doing.
+*/
+int QCoreApplication::enter_loop()
+{
+ if (!QCoreApplicationPrivate::checkInstance("enter_loop"))
+ return -1;
+ if (QThreadData::current() != self->d_func()->threadData) {
+ qWarning("QCoreApplication::enter_loop: Must be called from the main thread");
+ return -1;
+ }
+ QEventLoop eventLoop;
+ int returnCode = eventLoop.exec();
+ return returnCode;
+}
+
+/*! \obsolete
+
+ This function exits from a recursive call to the main event loop.
+ Do not call it unless you are an expert.
+*/
+void QCoreApplication::exit_loop()
+{
+ if (!QCoreApplicationPrivate::checkInstance("exit_loop"))
+ return;
+ QThreadData *data = QThreadData::current();
+ if (data != self->d_func()->threadData) {
+ qWarning("QCoreApplication::exit_loop: Must be called from the main thread");
+ return;
+ }
+ if (!data->eventLoops.isEmpty())
+ data->eventLoops.top()->exit();
+}
+
+/*! \obsolete
+
+ Returns the current loop level.
+*/
+int QCoreApplication::loopLevel()
+{
+ if (!QCoreApplicationPrivate::checkInstance("loopLevel"))
+ return -1;
+ return self->d_func()->threadData->eventLoops.size();
+}
+#endif
+
+/*
+ \fn void QCoreApplication::watchUnixSignal(int signal, bool watch)
+ \internal
+*/
+
+/*!
+ \fn void QCoreApplication::unixSignal(int number)
+ \internal
+
+ This signal is emitted whenever a Unix signal is received by the
+ application. The Unix signal received is specified by its \a number.
+*/
+
+/*!
+ \fn void qAddPostRoutine(QtCleanUpFunction ptr)
+ \relates QCoreApplication
+
+ Adds a global routine that will be called from the QApplication
+ destructor. This function is normally used to add cleanup routines
+ for program-wide functionality.
+
+ The function specified by \a ptr should take no arguments and should
+ return nothing. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 4
+
+ Note that for an application- or module-wide cleanup,
+ qAddPostRoutine() is often not suitable. For example, if the
+ program is split into dynamically loaded modules, the relevant
+ module may be unloaded long before the QApplication destructor is
+ called.
+
+ For modules and libraries, using a reference-counted
+ initialization manager or Qt's parent-child deletion mechanism may
+ be better. Here is an example of a private class that uses the
+ parent-child mechanism to call a cleanup function at the right
+ time:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 5
+
+ By selecting the right parent object, this can often be made to
+ clean up the module's data at the right moment.
+*/
+
+/*!
+ \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:
+
+ \snippet doc/src/snippets/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.
+
+ Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
+ class definition (before the first \c{public:} or \c{protected:}).
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 7
+
+ The \a context parameter is normally the class name, but it can
+ be any string.
+
+ \sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
new file mode 100644
index 0000000000..3957158d83
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREAPPLICATION_H
+#define QCOREAPPLICATION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qeventloop.h>
+
+#ifdef QT_INCLUDE_COMPAT
+#include <QtCore/qstringlist.h>
+#endif
+
+#if defined(Q_WS_WIN) && !defined(tagMSG)
+typedef struct tagMSG MSG;
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QCoreApplicationPrivate;
+class QTextCodec;
+class QTranslator;
+class QPostEventList;
+class QStringList;
+
+#define qApp QCoreApplication::instance()
+
+class Q_CORE_EXPORT QCoreApplication : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName)
+ Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion)
+ Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName)
+ Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain)
+
+ Q_DECLARE_PRIVATE(QCoreApplication)
+public:
+ enum { ApplicationFlags = QT_VERSION
+#if !defined(QT3_SUPPORT)
+ | 0x01000000
+#endif
+ };
+
+#if defined(QT_BUILD_CORE_LIB) || defined(qdoc)
+ QCoreApplication(int &argc, char **argv); // ### Qt5 remove
+#endif
+#if !defined(qdoc)
+ QCoreApplication(int &argc, char **argv, int
+#if !defined(QT_BUILD_CORE_LIB)
+ = ApplicationFlags
+#endif
+ );
+#endif
+
+ ~QCoreApplication();
+
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED static int argc();
+ QT_DEPRECATED static char **argv();
+#endif
+ static QStringList arguments();
+
+ static void setAttribute(Qt::ApplicationAttribute attribute, bool on = true);
+ static bool testAttribute(Qt::ApplicationAttribute attribute);
+
+ static void setOrganizationDomain(const QString &orgDomain);
+ static QString organizationDomain();
+ static void setOrganizationName(const QString &orgName);
+ static QString organizationName();
+ static void setApplicationName(const QString &application);
+ static QString applicationName();
+ static void setApplicationVersion(const QString &version);
+ static QString applicationVersion();
+
+ static QCoreApplication *instance() { return self; }
+
+ 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 bool sendEvent(QObject *receiver, QEvent *event);
+ static void postEvent(QObject *receiver, QEvent *event);
+ static void postEvent(QObject *receiver, QEvent *event, int priority);
+ static void sendPostedEvents(QObject *receiver, int event_type);
+ static void sendPostedEvents();
+ static void removePostedEvents(QObject *receiver);
+ static void removePostedEvents(QObject *receiver, int eventType);
+ static bool hasPendingEvents();
+
+ virtual bool notify(QObject *, QEvent *);
+
+ static bool startingUp();
+ static bool closingDown();
+
+ static QString applicationDirPath();
+ static QString applicationFilePath();
+ static qint64 applicationPid();
+
+#ifndef QT_NO_LIBRARY
+ static void setLibraryPaths(const QStringList &);
+ static QStringList libraryPaths();
+ static void addLibraryPath(const QString &);
+ static void removeLibraryPath(const QString &);
+#endif // QT_NO_LIBRARY
+
+#ifndef QT_NO_TRANSLATION
+ static void installTranslator(QTranslator * messageFile);
+ static void removeTranslator(QTranslator * messageFile);
+#endif
+ enum Encoding { CodecForTr, UnicodeUTF8, DefaultCodec = CodecForTr };
+ // ### Qt 5: merge
+ static QString translate(const char * context,
+ const char * key,
+ const char * disambiguation = 0,
+ Encoding encoding = CodecForTr);
+ static QString translate(const char * context,
+ const char * key,
+ const char * disambiguation,
+ Encoding encoding, int n);
+
+ static void flush();
+
+#if defined(QT3_SUPPORT)
+ inline QT3_SUPPORT void lock() {}
+ inline QT3_SUPPORT void unlock(bool = true) {}
+ inline QT3_SUPPORT bool locked() { return false; }
+ inline QT3_SUPPORT bool tryLock() { return false; }
+
+ static inline QT3_SUPPORT void processOneEvent()
+ { processEvents(QEventLoop::WaitForMoreEvents); }
+ static QT3_SUPPORT int enter_loop();
+ static QT3_SUPPORT void exit_loop();
+ static QT3_SUPPORT int loopLevel();
+#endif
+
+#if defined(Q_WS_WIN)
+ virtual bool winEventFilter(MSG *message, long *result);
+#endif
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ static void watchUnixSignal(int signal, bool watch);
+#endif
+
+ typedef bool (*EventFilter)(void *message, long *result);
+ EventFilter setEventFilter(EventFilter filter);
+ bool filterEvent(void *message, long *result);
+
+public Q_SLOTS:
+ static void quit();
+
+Q_SIGNALS:
+ void aboutToQuit();
+ void unixSignal(int);
+
+protected:
+ bool event(QEvent *);
+
+ virtual bool compressEvent(QEvent *, QObject *receiver, QPostEventList *);
+
+protected:
+ QCoreApplication(QCoreApplicationPrivate &p);
+
+private:
+ static bool sendSpontaneousEvent(QObject *receiver, QEvent *event);
+ bool notifyInternal(QObject *receiver, QEvent *event);
+
+ void init();
+
+ static QCoreApplication *self;
+
+ Q_DISABLE_COPY(QCoreApplication)
+
+ friend class QEventDispatcherUNIXPrivate;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QETWidget;
+ friend class Q3AccelManager;
+ friend class QShortcutMap;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+ friend Q_CORE_EXPORT QString qAppName();
+ friend class QClassFactory;
+};
+
+inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
+
+inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{ if (event) event->spont = true; return self ? self->notifyInternal(receiver, event) : false; }
+
+inline void QCoreApplication::sendPostedEvents() { sendPostedEvents(0, 0); }
+
+#ifdef QT_NO_TRANSLATION
+// Simple versions
+inline QString QCoreApplication::translate(const char *, const char *sourceText,
+ const char *, Encoding encoding)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (encoding == UnicodeUTF8)
+ return QString::fromUtf8(sourceText);
+#else
+ Q_UNUSED(encoding)
+#endif
+ return QString::fromLatin1(sourceText);
+}
+
+// Simple versions
+inline QString QCoreApplication::translate(const char *, const char *sourceText,
+ const char *, Encoding encoding, int)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (encoding == UnicodeUTF8)
+ return QString::fromUtf8(sourceText);
+#else
+ Q_UNUSED(encoding)
+#endif
+ return QString::fromLatin1(sourceText);
+}
+#endif
+
+// ### merge the four functions into two (using "int n = -1")
+#define Q_DECLARE_TR_FUNCTIONS(context) \
+public: \
+ static inline QString tr(const char *sourceText, const char *disambiguation = 0) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation); } \
+ static inline QString trUtf8(const char *sourceText, const char *disambiguation = 0) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::UnicodeUTF8); } \
+ static inline QString tr(const char *sourceText, const char *disambiguation, int n) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::CodecForTr, n); } \
+ static inline QString trUtf8(const char *sourceText, const char *disambiguation, int n) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::UnicodeUTF8, n); } \
+private:
+
+typedef void (*QtCleanUpFunction)();
+
+Q_CORE_EXPORT void qAddPostRoutine(QtCleanUpFunction);
+Q_CORE_EXPORT void qRemovePostRoutine(QtCleanUpFunction);
+Q_CORE_EXPORT QString qAppName(); // get application name
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QString decodeMSG(const MSG &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const MSG &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOREAPPLICATION_H
diff --git a/src/corelib/kernel/qcoreapplication_mac.cpp b/src/corelib/kernel/qcoreapplication_mac.cpp
new file mode 100644
index 0000000000..0734c6ccd4
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_mac.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "private/qcoreapplication_p.h"
+#include <private/qcore_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*****************************************************************************
+ QCoreApplication utility functions
+ *****************************************************************************/
+QString qAppFileName()
+{
+ static QString appFileName;
+ if (appFileName.isEmpty()) {
+ QCFType<CFURLRef> bundleURL(CFBundleCopyExecutableURL(CFBundleGetMainBundle()));
+ if(bundleURL) {
+ QCFString cfPath(CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle));
+ 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
new file mode 100644
index 0000000000..add2a3553e
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREAPPLICATION_P_H
+#define QCOREAPPLICATION_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/qcoreapplication.h"
+#include "QtCore/qtranslator.h"
+#include "private/qobject_p.h"
+
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QTranslator*> QTranslatorList;
+
+#if defined(Q_OS_SYMBIAN)
+# if !defined(QT_NO_SYSTEMLOCALE)
+class QEnvironmentChangeNotifier;
+# endif
+class CApaCommandLine;
+#endif
+class QAbstractEventDispatcher;
+
+class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QCoreApplication)
+
+public:
+ QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
+ ~QCoreApplicationPrivate();
+
+ bool sendThroughApplicationEventFilters(QObject *, QEvent *);
+ bool sendThroughObjectEventFilters(QObject *, QEvent *);
+ bool notify_helper(QObject *, QEvent *);
+
+ virtual QString appName() const;
+ virtual void createEventDispatcher();
+ static void removePostedEvent(QEvent *);
+#ifdef Q_OS_WIN
+ static void removePostedTimerEvent(QObject *object, int timerId);
+#endif
+
+#ifdef Q_OS_MAC
+ static QString macMenuBarName();
+#endif
+
+ static QThread *theMainThread;
+ static QThread *mainThread();
+ static bool checkInstance(const char *method);
+ static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data);
+
+#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) || defined (Q_OS_SYMBIAN)
+ void checkReceiverThread(QObject *receiver);
+#endif
+ int &argc;
+ char **argv;
+ void appendApplicationPathToLibraryPaths(void);
+
+#ifndef QT_NO_TRANSLATION
+ QTranslatorList translators;
+#endif
+ uint application_type;
+
+ QCoreApplication::EventFilter eventFilter;
+
+ bool in_exec;
+ bool aboutToQuitEmitted;
+ QString cachedApplicationDirPath;
+ QString cachedApplicationFilePath;
+#if defined(Q_OS_SYMBIAN)
+# if !defined(QT_NO_SYSTEMLOCALE)
+ QScopedPointer<QEnvironmentChangeNotifier> environmentChangeNotifier;
+ void symbianInit();
+# endif
+ static CApaCommandLine* symbianCommandLine();
+#endif
+
+ static bool isTranslatorInstalled(QTranslator *translator);
+
+ static QAbstractEventDispatcher *eventDispatcher;
+ static bool is_app_running;
+ static bool is_app_closing;
+
+ static uint attribs;
+ static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }
+ static int app_compile_version;
+#if defined(QT3_SUPPORT)
+ static bool useQt3Support;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOREAPPLICATION_P_H
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
new file mode 100644
index 0000000000..a6f43a8900
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -0,0 +1,1060 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qstringlist.h"
+#include "qt_windows.h"
+#include "qvector.h"
+#include "qmutex.h"
+#include "qfileinfo.h"
+#include "qcorecmdlineargs_p.h"
+#include <private/qthread_p.h>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+bool usingWinMain = false; // whether the qWinMain() is used or not
+int appCmdShow = 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
+{
+#if defined(Q_OS_WINCE)
+ return appCmdShow;
+#else
+ STARTUPINFO startupInfo;
+ GetStartupInfo(&startupInfo);
+
+ return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
+ ? startupInfo.wShowWindow
+ : SW_SHOWDEFAULT;
+#endif
+}
+
+Q_CORE_EXPORT QString qAppFileName() // get application file name
+{
+ // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths
+ // up to, and including MAX_PATH size perfectly fine with string termination, as well
+ // as easily detect if the file path is indeed larger than MAX_PATH, in which case we
+ // need to use the heap instead. This is a work-around, since contrary to what the
+ // MSDN documentation states, GetModuleFileName sometimes doesn't set the
+ // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if
+ // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH.
+ // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal
+ // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use
+ // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok).
+ wchar_t buffer[MAX_PATH + 2];
+ DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1);
+ buffer[MAX_PATH + 1] = 0;
+
+ if (v == 0)
+ return QString();
+ else if (v <= MAX_PATH)
+ return QString::fromWCharArray(buffer);
+
+ // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap
+ wchar_t *b = 0;
+ int i = 1;
+ size_t size;
+ do {
+ ++i;
+ size = MAX_PATH * i;
+ b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t)));
+ if (b)
+ v = GetModuleFileName(NULL, b, size);
+ } while (b && v == size);
+
+ if (b)
+ *(b + size) = 0;
+ QString res = QString::fromWCharArray(b);
+ free(b);
+
+ return res;
+}
+
+QString QCoreApplicationPrivate::appName() const
+{
+ return QFileInfo(qAppFileName()).baseName();
+}
+
+class QWinMsgHandlerCriticalSection
+{
+ CRITICAL_SECTION cs;
+public:
+ QWinMsgHandlerCriticalSection()
+ { InitializeCriticalSection(&cs); }
+ ~QWinMsgHandlerCriticalSection()
+ { DeleteCriticalSection(&cs); }
+
+ void lock()
+ { EnterCriticalSection(&cs); }
+ void unlock()
+ { LeaveCriticalSection(&cs); }
+};
+
+Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
+{
+ Q_UNUSED(t);
+ // OutputDebugString is not threadsafe.
+
+ // cannot use QMutex here, because qWarning()s in the QMutex
+ // implementation may cause this function to recurse
+ static QWinMsgHandlerCriticalSection staticCriticalSection;
+
+ if (!str)
+ str = "(null)";
+
+ staticCriticalSection.lock();
+
+ QString s(QString::fromLocal8Bit(str));
+ s += QLatin1Char('\n');
+ OutputDebugString((wchar_t*)s.utf16());
+
+ staticCriticalSection.unlock();
+}
+
+
+/*****************************************************************************
+ qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
+ *****************************************************************************/
+
+#if defined(Q_OS_WINCE)
+Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#else
+Q_CORE_EXPORT
+void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#endif
+{
+ static bool already_called = false;
+
+ if (already_called) {
+ qWarning("Qt: Internal error: qWinMain should be called only once");
+ return;
+ }
+ already_called = true;
+ usingWinMain = true;
+
+ // Install default debug handler
+ qInstallMsgHandler(qWinMsgHandler);
+
+ // Create command line
+ argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
+
+ appCmdShow = cmdShow;
+
+ // Ignore Windows parameters
+ Q_UNUSED(instance);
+ Q_UNUSED(prevInstance);
+}
+
+/*!
+ The message procedure calls this function for every message
+ received. Reimplement this function if you want to process window
+ messages \a msg that are not processed by Qt. If you don't want
+ the event to be processed by Qt, then return true and set \a result
+ to the value that the window procedure should return. Otherwise
+ return false.
+
+ It is only directly addressed messages that are filtered. To
+ handle system wide messages, such as messages from a registered
+ hot key, you need to install an event filter on the event
+ dispatcher, which is returned from
+ QAbstractEventDispatcher::instance().
+*/
+bool QCoreApplication::winEventFilter(MSG *msg, long *result) // Windows event filter
+{
+ Q_UNUSED(msg);
+ Q_UNUSED(result);
+ return false;
+}
+
+void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
+{
+ QThreadData *data = object->d_func()->threadData;
+
+ QMutexLocker locker(&data->postEventList.mutex);
+ if (data->postEventList.size() == 0)
+ return;
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent & pe = data->postEventList.at(i);
+ if (pe.receiver == object
+ && pe.event
+ && (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;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
+/*****************************************************************************
+ Convenience functions for convert WM_* messages into human readable strings,
+ including a nifty QDebug operator<< for simpel QDebug() << msg output.
+ *****************************************************************************/
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <windowsx.h>
+#include "qdebug.h"
+QT_END_INCLUDE_NAMESPACE
+
+#if !defined(GET_X_LPARAM)
+# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+# define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif
+#ifdef _WIN32_WCE
+# ifndef WM_NCACTIVATE
+# define WM_NCACTIVATE 0x86
+# endif
+#endif
+
+// The values below should never change. Note that none of the usual
+// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
+// WM_... representations
+struct KnownWM {
+ uint WM;
+ const char* str;
+} knownWM[] =
+{{ 0x0000, "WM_NULL" },
+ { 0x0001, "WM_CREATE" },
+ { 0x0002, "WM_DESTROY" },
+ { 0x0003, "WM_MOVE" },
+ { 0x0005, "WM_SIZE" },
+ { 0x0006, "WM_ACTIVATE" },
+ { 0x0007, "WM_SETFOCUS" },
+ { 0x0008, "WM_KILLFOCUS" },
+ { 0x000A, "WM_ENABLE" },
+ { 0x000B, "WM_SETREDRAW" },
+ { 0x000C, "WM_SETTEXT" },
+ { 0x000D, "WM_GETTEXT" },
+ { 0x000E, "WM_GETTEXTLENGTH" },
+ { 0x000F, "WM_PAINT" },
+ { 0x0010, "WM_CLOSE" },
+ { 0x0011, "WM_QUERYENDSESSION" },
+ { 0x0013, "WM_QUERYOPEN" },
+ { 0x0016, "WM_ENDSESSION" },
+ { 0x0012, "WM_QUIT" },
+ { 0x0014, "WM_ERASEBKGND" },
+ { 0x0015, "WM_SYSCOLORCHANGE" },
+ { 0x0018, "WM_SHOWWINDOW" },
+ { 0x001A, "WM_WININICHANGE" },
+ { 0x001B, "WM_DEVMODECHANGE" },
+ { 0x001C, "WM_ACTIVATEAPP" },
+ { 0x001D, "WM_FONTCHANGE" },
+ { 0x001E, "WM_TIMECHANGE" },
+ { 0x001F, "WM_CANCELMODE" },
+ { 0x0020, "WM_SETCURSOR" },
+ { 0x0021, "WM_MOUSEACTIVATE" },
+ { 0x0022, "WM_CHILDACTIVATE" },
+ { 0x0023, "WM_QUEUESYNC" },
+ { 0x0024, "WM_GETMINMAXINFO" },
+ { 0x0026, "WM_PAINTICON" },
+ { 0x0027, "WM_ICONERASEBKGND" },
+ { 0x0028, "WM_NEXTDLGCTL" },
+ { 0x002A, "WM_SPOOLERSTATUS" },
+ { 0x002B, "WM_DRAWITEM" },
+ { 0x002C, "WM_MEASUREITEM" },
+ { 0x002D, "WM_DELETEITEM" },
+ { 0x002E, "WM_VKEYTOITEM" },
+ { 0x002F, "WM_CHARTOITEM" },
+ { 0x0030, "WM_SETFONT" },
+ { 0x0031, "WM_GETFONT" },
+ { 0x0032, "WM_SETHOTKEY" },
+ { 0x0033, "WM_GETHOTKEY" },
+ { 0x0037, "WM_QUERYDRAGICON" },
+ { 0x0039, "WM_COMPAREITEM" },
+ { 0x003D, "WM_GETOBJECT" },
+ { 0x0041, "WM_COMPACTING" },
+ { 0x0044, "WM_COMMNOTIFY" },
+ { 0x0046, "WM_WINDOWPOSCHANGING" },
+ { 0x0047, "WM_WINDOWPOSCHANGED" },
+ { 0x0048, "WM_POWER" },
+ { 0x004A, "WM_COPYDATA" },
+ { 0x004B, "WM_CANCELJOURNAL" },
+ { 0x004E, "WM_NOTIFY" },
+ { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
+ { 0x0051, "WM_INPUTLANGCHANGE" },
+ { 0x0052, "WM_TCARD" },
+ { 0x0053, "WM_HELP" },
+ { 0x0054, "WM_USERCHANGED" },
+ { 0x0055, "WM_NOTIFYFORMAT" },
+ { 0x007B, "WM_CONTEXTMENU" },
+ { 0x007C, "WM_STYLECHANGING" },
+ { 0x007D, "WM_STYLECHANGED" },
+ { 0x007E, "WM_DISPLAYCHANGE" },
+ { 0x007F, "WM_GETICON" },
+ { 0x0080, "WM_SETICON" },
+ { 0x0081, "WM_NCCREATE" },
+ { 0x0082, "WM_NCDESTROY" },
+ { 0x0083, "WM_NCCALCSIZE" },
+ { 0x0084, "WM_NCHITTEST" },
+ { 0x0085, "WM_NCPAINT" },
+ { 0x0086, "WM_NCACTIVATE" },
+ { 0x0087, "WM_GETDLGCODE" },
+ { 0x0088, "WM_SYNCPAINT" },
+ { 0x00A0, "WM_NCMOUSEMOVE" },
+ { 0x00A1, "WM_NCLBUTTONDOWN" },
+ { 0x00A2, "WM_NCLBUTTONUP" },
+ { 0x00A3, "WM_NCLBUTTONDBLCLK" },
+ { 0x00A4, "WM_NCRBUTTONDOWN" },
+ { 0x00A5, "WM_NCRBUTTONUP" },
+ { 0x00A6, "WM_NCRBUTTONDBLCLK" },
+ { 0x00A7, "WM_NCMBUTTONDOWN" },
+ { 0x00A8, "WM_NCMBUTTONUP" },
+ { 0x00A9, "WM_NCMBUTTONDBLCLK" },
+ { 0x00AB, "WM_NCXBUTTONDOWN" },
+ { 0x00AC, "WM_NCXBUTTONUP" },
+ { 0x00AD, "WM_NCXBUTTONDBLCLK" },
+ { 0x00FF, "WM_INPUT" },
+ { 0x0100, "WM_KEYDOWN" },
+ { 0x0101, "WM_KEYUP" },
+ { 0x0102, "WM_CHAR" },
+ { 0x0103, "WM_DEADCHAR" },
+ { 0x0104, "WM_SYSKEYDOWN" },
+ { 0x0105, "WM_SYSKEYUP" },
+ { 0x0106, "WM_SYSCHAR" },
+ { 0x0107, "WM_SYSDEADCHAR" },
+ { 0x0109, "WM_UNICHAR" },
+ { 0x010D, "WM_IME_STARTCOMPOSITION" },
+ { 0x010E, "WM_IME_ENDCOMPOSITION" },
+ { 0x010F, "WM_IME_COMPOSITION" },
+ { 0x0110, "WM_INITDIALOG" },
+ { 0x0111, "WM_COMMAND" },
+ { 0x0112, "WM_SYSCOMMAND" },
+ { 0x0113, "WM_TIMER" },
+ { 0x0114, "WM_HSCROLL" },
+ { 0x0115, "WM_VSCROLL" },
+ { 0x0116, "WM_INITMENU" },
+ { 0x0117, "WM_INITMENUPOPUP" },
+ { 0x011F, "WM_MENUSELECT" },
+ { 0x0120, "WM_MENUCHAR" },
+ { 0x0121, "WM_ENTERIDLE" },
+ { 0x0122, "WM_MENURBUTTONUP" },
+ { 0x0123, "WM_MENUDRAG" },
+ { 0x0124, "WM_MENUGETOBJECT" },
+ { 0x0125, "WM_UNINITMENUPOPUP" },
+ { 0x0126, "WM_MENUCOMMAND" },
+ { 0x0127, "WM_CHANGEUISTATE" },
+ { 0x0128, "WM_UPDATEUISTATE" },
+ { 0x0129, "WM_QUERYUISTATE" },
+ { 0x0132, "WM_CTLCOLORMSGBOX" },
+ { 0x0133, "WM_CTLCOLOREDIT" },
+ { 0x0134, "WM_CTLCOLORLISTBOX" },
+ { 0x0135, "WM_CTLCOLORBTN" },
+ { 0x0136, "WM_CTLCOLORDLG" },
+ { 0x0137, "WM_CTLCOLORSCROLLBAR" },
+ { 0x0138, "WM_CTLCOLORSTATIC" },
+ { 0x0200, "WM_MOUSEMOVE" },
+ { 0x0201, "WM_LBUTTONDOWN" },
+ { 0x0202, "WM_LBUTTONUP" },
+ { 0x0203, "WM_LBUTTONDBLCLK" },
+ { 0x0204, "WM_RBUTTONDOWN" },
+ { 0x0205, "WM_RBUTTONUP" },
+ { 0x0206, "WM_RBUTTONDBLCLK" },
+ { 0x0207, "WM_MBUTTONDOWN" },
+ { 0x0208, "WM_MBUTTONUP" },
+ { 0x0209, "WM_MBUTTONDBLCLK" },
+ { 0x020A, "WM_MOUSEWHEEL" },
+ { 0x020B, "WM_XBUTTONDOWN" },
+ { 0x020C, "WM_XBUTTONUP" },
+ { 0x020D, "WM_XBUTTONDBLCLK" },
+ { 0x020E, "WM_MOUSEHWHEEL" },
+ { 0x0210, "WM_PARENTNOTIFY" },
+ { 0x0211, "WM_ENTERMENULOOP" },
+ { 0x0212, "WM_EXITMENULOOP" },
+ { 0x0213, "WM_NEXTMENU" },
+ { 0x0214, "WM_SIZING" },
+ { 0x0215, "WM_CAPTURECHANGED" },
+ { 0x0216, "WM_MOVING" },
+ { 0x0218, "WM_POWERBROADCAST" },
+ { 0x0219, "WM_DEVICECHANGE" },
+ { 0x0220, "WM_MDICREATE" },
+ { 0x0221, "WM_MDIDESTROY" },
+ { 0x0222, "WM_MDIACTIVATE" },
+ { 0x0223, "WM_MDIRESTORE" },
+ { 0x0224, "WM_MDINEXT" },
+ { 0x0225, "WM_MDIMAXIMIZE" },
+ { 0x0226, "WM_MDITILE" },
+ { 0x0227, "WM_MDICASCADE" },
+ { 0x0228, "WM_MDIICONARRANGE" },
+ { 0x0229, "WM_MDIGETACTIVE" },
+ { 0x0230, "WM_MDISETMENU" },
+ { 0x0231, "WM_ENTERSIZEMOVE" },
+ { 0x0232, "WM_EXITSIZEMOVE" },
+ { 0x0233, "WM_DROPFILES" },
+ { 0x0234, "WM_MDIREFRESHMENU" },
+ { 0x0281, "WM_IME_SETCONTEXT" },
+ { 0x0282, "WM_IME_NOTIFY" },
+ { 0x0283, "WM_IME_CONTROL" },
+ { 0x0284, "WM_IME_COMPOSITIONFULL" },
+ { 0x0285, "WM_IME_SELECT" },
+ { 0x0286, "WM_IME_CHAR" },
+ { 0x0288, "WM_IME_REQUEST" },
+ { 0x0290, "WM_IME_KEYDOWN" },
+ { 0x0291, "WM_IME_KEYUP" },
+ { 0x02A0, "WM_NCMOUSEHOVER" },
+ { 0x02A1, "WM_MOUSEHOVER" },
+ { 0x02A2, "WM_NCMOUSELEAVE" },
+ { 0x02A3, "WM_MOUSELEAVE" },
+ { 0x02B1, "WM_WTSSESSION_CHANGE" },
+ { 0x02C0, "WM_TABLET_FIRST" },
+ { 0x02C1, "WM_TABLET_FIRST + 1" },
+ { 0x02C2, "WM_TABLET_FIRST + 2" },
+ { 0x02C3, "WM_TABLET_FIRST + 3" },
+ { 0x02C4, "WM_TABLET_FIRST + 4" },
+ { 0x02C5, "WM_TABLET_FIRST + 5" },
+ { 0x02C6, "WM_TABLET_FIRST + 6" },
+ { 0x02C7, "WM_TABLET_FIRST + 7" },
+ { 0x02C8, "WM_TABLET_FIRST + 8" },
+ { 0x02C9, "WM_TABLET_FIRST + 9" },
+ { 0x02CA, "WM_TABLET_FIRST + 10" },
+ { 0x02CB, "WM_TABLET_FIRST + 11" },
+ { 0x02CC, "WM_TABLET_FIRST + 12" },
+ { 0x02CD, "WM_TABLET_FIRST + 13" },
+ { 0x02CE, "WM_TABLET_FIRST + 14" },
+ { 0x02CF, "WM_TABLET_FIRST + 15" },
+ { 0x02D0, "WM_TABLET_FIRST + 16" },
+ { 0x02D1, "WM_TABLET_FIRST + 17" },
+ { 0x02D2, "WM_TABLET_FIRST + 18" },
+ { 0x02D3, "WM_TABLET_FIRST + 19" },
+ { 0x02D4, "WM_TABLET_FIRST + 20" },
+ { 0x02D5, "WM_TABLET_FIRST + 21" },
+ { 0x02D6, "WM_TABLET_FIRST + 22" },
+ { 0x02D7, "WM_TABLET_FIRST + 23" },
+ { 0x02D8, "WM_TABLET_FIRST + 24" },
+ { 0x02D9, "WM_TABLET_FIRST + 25" },
+ { 0x02DA, "WM_TABLET_FIRST + 26" },
+ { 0x02DB, "WM_TABLET_FIRST + 27" },
+ { 0x02DC, "WM_TABLET_FIRST + 28" },
+ { 0x02DD, "WM_TABLET_FIRST + 29" },
+ { 0x02DE, "WM_TABLET_FIRST + 30" },
+ { 0x02DF, "WM_TABLET_LAST" },
+ { 0x0300, "WM_CUT" },
+ { 0x0301, "WM_COPY" },
+ { 0x0302, "WM_PASTE" },
+ { 0x0303, "WM_CLEAR" },
+ { 0x0304, "WM_UNDO" },
+ { 0x0305, "WM_RENDERFORMAT" },
+ { 0x0306, "WM_RENDERALLFORMATS" },
+ { 0x0307, "WM_DESTROYCLIPBOARD" },
+ { 0x0308, "WM_DRAWCLIPBOARD" },
+ { 0x0309, "WM_PAINTCLIPBOARD" },
+ { 0x030A, "WM_VSCROLLCLIPBOARD" },
+ { 0x030B, "WM_SIZECLIPBOARD" },
+ { 0x030C, "WM_ASKCBFORMATNAME" },
+ { 0x030D, "WM_CHANGECBCHAIN" },
+ { 0x030E, "WM_HSCROLLCLIPBOARD" },
+ { 0x030F, "WM_QUERYNEWPALETTE" },
+ { 0x0310, "WM_PALETTEISCHANGING" },
+ { 0x0311, "WM_PALETTECHANGED" },
+ { 0x0312, "WM_HOTKEY" },
+ { 0x0317, "WM_PRINT" },
+ { 0x0318, "WM_PRINTCLIENT" },
+ { 0x0319, "WM_APPCOMMAND" },
+ { 0x031A, "WM_THEMECHANGED" },
+ { 0x0358, "WM_HANDHELDFIRST" },
+ { 0x0359, "WM_HANDHELDFIRST + 1" },
+ { 0x035A, "WM_HANDHELDFIRST + 2" },
+ { 0x035B, "WM_HANDHELDFIRST + 3" },
+ { 0x035C, "WM_HANDHELDFIRST + 4" },
+ { 0x035D, "WM_HANDHELDFIRST + 5" },
+ { 0x035E, "WM_HANDHELDFIRST + 6" },
+ { 0x035F, "WM_HANDHELDLAST" },
+ { 0x0360, "WM_AFXFIRST" },
+ { 0x0361, "WM_AFXFIRST + 1" },
+ { 0x0362, "WM_AFXFIRST + 2" },
+ { 0x0363, "WM_AFXFIRST + 3" },
+ { 0x0364, "WM_AFXFIRST + 4" },
+ { 0x0365, "WM_AFXFIRST + 5" },
+ { 0x0366, "WM_AFXFIRST + 6" },
+ { 0x0367, "WM_AFXFIRST + 7" },
+ { 0x0368, "WM_AFXFIRST + 8" },
+ { 0x0369, "WM_AFXFIRST + 9" },
+ { 0x036A, "WM_AFXFIRST + 10" },
+ { 0x036B, "WM_AFXFIRST + 11" },
+ { 0x036C, "WM_AFXFIRST + 12" },
+ { 0x036D, "WM_AFXFIRST + 13" },
+ { 0x036E, "WM_AFXFIRST + 14" },
+ { 0x036F, "WM_AFXFIRST + 15" },
+ { 0x0370, "WM_AFXFIRST + 16" },
+ { 0x0371, "WM_AFXFIRST + 17" },
+ { 0x0372, "WM_AFXFIRST + 18" },
+ { 0x0373, "WM_AFXFIRST + 19" },
+ { 0x0374, "WM_AFXFIRST + 20" },
+ { 0x0375, "WM_AFXFIRST + 21" },
+ { 0x0376, "WM_AFXFIRST + 22" },
+ { 0x0377, "WM_AFXFIRST + 23" },
+ { 0x0378, "WM_AFXFIRST + 24" },
+ { 0x0379, "WM_AFXFIRST + 25" },
+ { 0x037A, "WM_AFXFIRST + 26" },
+ { 0x037B, "WM_AFXFIRST + 27" },
+ { 0x037C, "WM_AFXFIRST + 28" },
+ { 0x037D, "WM_AFXFIRST + 29" },
+ { 0x037E, "WM_AFXFIRST + 30" },
+ { 0x037F, "WM_AFXLAST" },
+ { 0x0380, "WM_PENWINFIRST" },
+ { 0x0381, "WM_PENWINFIRST + 1" },
+ { 0x0382, "WM_PENWINFIRST + 2" },
+ { 0x0383, "WM_PENWINFIRST + 3" },
+ { 0x0384, "WM_PENWINFIRST + 4" },
+ { 0x0385, "WM_PENWINFIRST + 5" },
+ { 0x0386, "WM_PENWINFIRST + 6" },
+ { 0x0387, "WM_PENWINFIRST + 7" },
+ { 0x0388, "WM_PENWINFIRST + 8" },
+ { 0x0389, "WM_PENWINFIRST + 9" },
+ { 0x038A, "WM_PENWINFIRST + 10" },
+ { 0x038B, "WM_PENWINFIRST + 11" },
+ { 0x038C, "WM_PENWINFIRST + 12" },
+ { 0x038D, "WM_PENWINFIRST + 13" },
+ { 0x038E, "WM_PENWINFIRST + 14" },
+ { 0x038F, "WM_PENWINLAST" },
+ { 0x0400, "WM_USER" },
+ { 0x8000, "WM_APP" },
+ { 0,0 }}; // End of known messages
+
+// Looks up the WM_ message in the table above
+static const char* findWMstr(uint msg)
+{
+ uint i = 0;
+ const char* result = 0;
+ // Known WM_'s
+ while (knownWM[i].str && (knownWM[i].WM != msg))
+ ++i;
+ result = knownWM[i].str;
+ return result;
+};
+
+// Convenience function for converting flags and values into readable strings
+struct FLAG_STRING_STRUCT
+{
+ uint value;
+ const char* str;
+};
+
+FLAG_STRING_STRUCT FLAG_STRING(int value = 0, const char *c = 0)
+{
+ FLAG_STRING_STRUCT s = {value, c};
+ return s;
+}
+
+#define FLGSTR(x) FLAG_STRING(x, #x)
+
+// Returns an ORed (" | ") together string for the flags active in the actual
+// value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
+// value in the list passed to the function
+QString flagCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ int count = 0;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
+ if ((actual & v.value) == v.value) {
+ if (count++)
+ result += QLatin1String(" | ");
+ result += QString::fromLatin1(v.str);
+ }
+ }
+ va_end(ap);
+ return result;
+};
+
+// Returns the string representation of the value in 'actual'. (...) must
+// consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
+// passed to the function
+QString valueCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
+ ;
+ result = QString::fromLatin1(v.str);
+
+ va_end(ap);
+ return result;
+};
+
+#ifdef Q_CC_BOR
+
+QString decodeMSG(const MSG& msg)
+{
+ return QString::fromLatin1("THis is not supported on Borland");
+}
+
+#else
+
+// Returns a "human readable" string representation of the MSG and the
+// information it points to
+QString decodeMSG(const MSG& msg)
+{
+ const WPARAM wParam = msg.wParam;
+ const LPARAM lParam = msg.lParam;
+ QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
+ // Unknown WM_, so use number
+ if (wmmsg.isEmpty())
+ wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
+
+ QString rawParameters;
+ rawParameters.sprintf("hwnd(0x%p) ", (void *)msg.hwnd);
+
+ // Custom WM_'s
+ if (msg.message > WM_APP)
+ wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
+ else if (msg.message > WM_USER)
+ wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+
+ QString parameters;
+ switch (msg.message) {
+#ifdef WM_ACTIVATE
+ case WM_ACTIVATE:
+ {
+ QString activation = valueCheck(wParam,
+ FLAG_STRING(WA_ACTIVE, "Activate"),
+ FLAG_STRING(WA_INACTIVE, "Deactivate"),
+ FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
+ FLAG_STRING());
+ parameters.sprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
+ }
+ break;
+#endif
+#ifdef WM_CAPTURECHANGED
+ case WM_CAPTURECHANGED:
+ parameters.sprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
+ break;
+#endif
+#ifdef WM_CREATE
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
+ QString styles = flagCheck(lpcs->style,
+ FLGSTR(WS_BORDER),
+ FLGSTR(WS_CAPTION),
+ FLGSTR(WS_CHILD),
+ FLGSTR(WS_CLIPCHILDREN),
+ FLGSTR(WS_CLIPSIBLINGS),
+ FLGSTR(WS_DISABLED),
+ FLGSTR(WS_DLGFRAME),
+ FLGSTR(WS_GROUP),
+ FLGSTR(WS_HSCROLL),
+ FLGSTR(WS_OVERLAPPED),
+#if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+#endif
+#ifdef WS_ICONIC
+ FLGSTR(WS_ICONIC),
+#endif
+ FLGSTR(WS_MAXIMIZE),
+ FLGSTR(WS_MAXIMIZEBOX),
+ FLGSTR(WS_MINIMIZE),
+ FLGSTR(WS_MINIMIZEBOX),
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+ FLGSTR(WS_POPUP),
+#ifdef WS_POPUPWINDOW
+ FLGSTR(WS_POPUPWINDOW),
+#endif
+ FLGSTR(WS_SIZEBOX),
+ FLGSTR(WS_SYSMENU),
+ FLGSTR(WS_TABSTOP),
+ FLGSTR(WS_THICKFRAME),
+#ifdef WS_TILED
+ FLGSTR(WS_TILED),
+#endif
+#ifdef WS_TILEDWINDOW
+ FLGSTR(WS_TILEDWINDOW),
+#endif
+ FLGSTR(WS_VISIBLE),
+ FLGSTR(WS_VSCROLL),
+ FLAG_STRING());
+
+ QString exStyles = flagCheck(lpcs->dwExStyle,
+#ifdef WS_EX_ACCEPTFILES
+ FLGSTR(WS_EX_ACCEPTFILES),
+#endif
+#ifdef WS_EX_APPWINDOW
+ FLGSTR(WS_EX_APPWINDOW),
+#endif
+ FLGSTR(WS_EX_CLIENTEDGE),
+ FLGSTR(WS_EX_DLGMODALFRAME),
+#ifdef WS_EX_LEFT
+ FLGSTR(WS_EX_LEFT),
+#endif
+ FLGSTR(WS_EX_LEFTSCROLLBAR),
+#ifdef WS_EX_LTRREADING
+ FLGSTR(WS_EX_LTRREADING),
+#endif
+#ifdef WS_EX_MDICHILD
+ FLGSTR(WS_EX_MDICHILD),
+#endif
+#ifdef WS_EX_NOACTIVATE
+ FLGSTR(WS_EX_NOACTIVATE),
+#endif
+#ifdef WS_EX_NOANIMATION
+ FLGSTR(WS_EX_NOANIMATION),
+#endif
+ FLGSTR(WS_EX_NOPARENTNOTIFY),
+ FLGSTR(WS_EX_OVERLAPPEDWINDOW),
+#ifdef WS_EX_PALETTEWINDOW
+ FLGSTR(WS_EX_PALETTEWINDOW),
+#endif
+#ifdef WS_EX_RIGHT
+ FLGSTR(WS_EX_RIGHT),
+#endif
+#ifdef WS_EX_RIGHTSCROLLBAR
+ FLGSTR(WS_EX_RIGHTSCROLLBAR),
+#endif
+#ifdef WS_EX_RTLREADING
+ FLGSTR(WS_EX_RTLREADING),
+#endif
+ FLGSTR(WS_EX_STATICEDGE),
+ FLGSTR(WS_EX_TOOLWINDOW),
+ FLGSTR(WS_EX_TOPMOST),
+#ifdef WS_EX_TRANSPARENT
+ FLGSTR(WS_EX_TRANSPARENT),
+#endif
+ FLGSTR(WS_EX_WINDOWEDGE),
+#ifdef WS_EX_CAPTIONOKBTN
+ FLGSTR(WS_EX_CAPTIONOKBTN),
+#endif
+ FLAG_STRING());
+
+ QString className;
+ if (lpcs->lpszClass != 0) {
+ if (HIWORD(lpcs->lpszClass) == 0) // Atom
+ className = QString::number(LOWORD(lpcs->lpszClass), 16);
+ else // String
+ className = QString((QChar*)lpcs->lpszClass,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
+ }
+
+ QString windowName;
+ if (lpcs->lpszName != 0)
+ windowName = QString((QChar*)lpcs->lpszName,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
+
+ parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
+ lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
+ windowName.toLatin1().data(), (void *)lpcs->hwndParent,
+ styles.toLatin1().data(), exStyles.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_DESTROY
+ case WM_DESTROY:
+ parameters.sprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
+ break;
+#endif
+#ifdef WM_IME_NOTIFY
+ case WM_IME_NOTIFY:
+ {
+ QString imnCommand = valueCheck(wParam,
+ FLGSTR(IMN_CHANGECANDIDATE),
+ FLGSTR(IMN_CLOSECANDIDATE),
+ FLGSTR(IMN_CLOSESTATUSWINDOW),
+ FLGSTR(IMN_GUIDELINE),
+ FLGSTR(IMN_OPENCANDIDATE),
+ FLGSTR(IMN_OPENSTATUSWINDOW),
+ FLGSTR(IMN_SETCANDIDATEPOS),
+ FLGSTR(IMN_SETCOMPOSITIONFONT),
+ FLGSTR(IMN_SETCOMPOSITIONWINDOW),
+ FLGSTR(IMN_SETCONVERSIONMODE),
+ FLGSTR(IMN_SETOPENSTATUS),
+ FLGSTR(IMN_SETSENTENCEMODE),
+ FLGSTR(IMN_SETSTATUSWINDOWPOS),
+ FLAG_STRING());
+ parameters.sprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
+ }
+ break;
+#endif
+#ifdef WM_IME_SETCONTEXT
+ case WM_IME_SETCONTEXT:
+ {
+ bool fSet = (BOOL)wParam;
+ DWORD fShow = (DWORD)lParam;
+ QString showFlgs = flagCheck(fShow,
+#ifdef ISC_SHOWUICOMPOSITIONWINDOW
+ FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
+#endif
+#ifdef ISC_SHOWUIGUIDWINDOW
+ FLGSTR(ISC_SHOWUIGUIDWINDOW),
+#endif
+#ifdef ISC_SHOWUISOFTKBD
+ FLGSTR(ISC_SHOWUISOFTKBD),
+#endif
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
+ FLAG_STRING());
+ parameters.sprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_KILLFOCUS
+ case WM_KILLFOCUS:
+ parameters.sprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_CHAR
+ case WM_CHAR:
+#endif
+#ifdef WM_IME_CHAR
+ case WM_IME_CHAR:
+#endif
+#ifdef WM_KEYDOWN
+ case WM_KEYDOWN:
+#endif
+#ifdef WM_KEYUP
+ case WM_KEYUP:
+ {
+ int nVirtKey = (int)wParam;
+ long lKeyData = (long)lParam;
+ int repCount = (lKeyData & 0xffff); // Bit 0-15
+ int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
+ bool contextCode = (lKeyData && 0x20000000); // Bit 29
+ bool prevState = (lKeyData && 0x40000000); // Bit 30
+ bool transState = (lKeyData && 0x80000000); // Bit 31
+ parameters.sprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
+ nVirtKey, scanCode, repCount, contextCode, prevState, transState);
+ }
+ break;
+#endif
+#ifdef WM_NCACTIVATE
+ case WM_NCACTIVATE:
+ {
+ parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
+ }
+ break;
+#endif
+#ifdef WM_MOUSEACTIVATE
+ case WM_MOUSEACTIVATE:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOUSELEAVE
+ case WM_MOUSELEAVE:
+ break; // wParam & lParam not used
+#endif
+#ifdef WM_MOUSEHOVER
+ case WM_MOUSEHOVER:
+#endif
+#ifdef WM_MOUSEWHEEL
+ case WM_MOUSEWHEEL:
+#endif
+#ifdef WM_MOUSEHWHEEL
+ case WM_MOUSEHWHEEL:
+#endif
+#ifdef WM_LBUTTONDBLCLK
+ case WM_LBUTTONDBLCLK:
+#endif
+#ifdef WM_LBUTTONDOWN
+ case WM_LBUTTONDOWN:
+#endif
+#ifdef WM_LBUTTONUP
+ case WM_LBUTTONUP:
+#endif
+#ifdef WM_MBUTTONDBLCLK
+ case WM_MBUTTONDBLCLK:
+#endif
+#ifdef WM_MBUTTONDOWN
+ case WM_MBUTTONDOWN:
+#endif
+#ifdef WM_MBUTTONUP
+ case WM_MBUTTONUP:
+#endif
+#ifdef WM_RBUTTONDBLCLK
+ case WM_RBUTTONDBLCLK:
+#endif
+#ifdef WM_RBUTTONDOWN
+ case WM_RBUTTONDOWN:
+#endif
+#ifdef WM_RBUTTONUP
+ case WM_RBUTTONUP:
+#endif
+#ifdef WM_MOUSEMOVE
+ case WM_MOUSEMOVE:
+ {
+ QString vrtKeys = flagCheck(wParam,
+ FLGSTR(MK_CONTROL),
+ FLGSTR(MK_LBUTTON),
+ FLGSTR(MK_MBUTTON),
+ FLGSTR(MK_RBUTTON),
+ FLGSTR(MK_SHIFT),
+#ifdef MK_XBUTTON1
+ FLGSTR(MK_XBUTTON1),
+#endif
+#ifdef MK_XBUTTON2
+ FLGSTR(MK_XBUTTON2),
+#endif
+ FLAG_STRING());
+ parameters.sprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOVE
+ case WM_MOVE:
+ parameters.sprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
+ break;
+#endif
+#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
+ case WM_ERASEBKGND:
+ case WM_PAINT:
+ parameters.sprintf("hdc(0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_QUERYNEWPALETTE
+ case WM_QUERYNEWPALETTE:
+ break; // lParam & wParam are unused
+#endif
+#ifdef WM_SETCURSOR
+ case WM_SETCURSOR:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_SETFOCUS
+ case WM_SETFOCUS:
+ parameters.sprintf("Lost Focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_SETTEXT
+ case WM_SETTEXT:
+ parameters.sprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
+ break;
+#endif
+#ifdef WM_SIZE
+ case WM_SIZE:
+ {
+ QString showMode = valueCheck(wParam,
+ FLGSTR(SIZE_MAXHIDE),
+ FLGSTR(SIZE_MAXIMIZED),
+ FLGSTR(SIZE_MAXSHOW),
+ FLGSTR(SIZE_MINIMIZED),
+ FLGSTR(SIZE_RESTORED),
+ FLAG_STRING());
+
+ parameters.sprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_WINDOWPOSCHANGED
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
+ if (!winPos)
+ break;
+ QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
+ FLAG_STRING((qptrdiff)HWND_BOTTOM, "HWND_BOTTOM"),
+ FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
+ FLAG_STRING((qptrdiff)HWND_TOP, "HWND_TOP"),
+ FLAG_STRING((qptrdiff)HWND_TOPMOST, "HWND_TOPMOST"),
+ FLAG_STRING());
+ if (hwndAfter.isEmpty())
+ hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
+ QString flags = flagCheck(winPos->flags,
+ FLGSTR(SWP_DRAWFRAME),
+ FLGSTR(SWP_FRAMECHANGED),
+ FLGSTR(SWP_HIDEWINDOW),
+ FLGSTR(SWP_NOACTIVATE),
+#ifdef SWP_NOCOPYBITS
+ FLGSTR(SWP_NOCOPYBITS),
+#endif
+ FLGSTR(SWP_NOMOVE),
+ FLGSTR(SWP_NOOWNERZORDER),
+ FLGSTR(SWP_NOREDRAW),
+ FLGSTR(SWP_NOREPOSITION),
+#ifdef SWP_NOSENDCHANGING
+ FLGSTR(SWP_NOSENDCHANGING),
+#endif
+ FLGSTR(SWP_NOSIZE),
+ FLGSTR(SWP_NOZORDER),
+ FLGSTR(SWP_SHOWWINDOW),
+ FLAG_STRING());
+ parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(%s)", winPos->x, winPos->y, winPos->cx, winPos->cy, flags.toLatin1().data(), hwndAfter.toLatin1().data());
+ }
+ break;
+#endif
+ default:
+ parameters.sprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
+ break;
+ }
+ // Yes, we want to give the WM_ names 20 chars of space before showing the
+ // decoded message, since some of the common messages are quite long, and
+ // we don't want the decoded information to vary in output position
+ QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
+ message += rawParameters;
+ message += parameters;
+ return message;
+}
+
+#endif
+
+QDebug operator<<(QDebug dbg, const MSG &msg)
+{
+ dbg << decodeMSG(msg);
+ return dbg.nospace();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
new file mode 100644
index 0000000000..cdde7828f7
--- /dev/null
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCORECMDLINEARGS_P_H
+#define QCORECMDLINEARGS_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/qstring.h"
+#include "QtCore/qstringlist.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "QtCore/qvector.h"
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+# include "qt_windows.h"
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+// template implementation of the parsing algorithm
+// this is used from qcoreapplication_win.cpp and the tools (rcc, uic...)
+
+template<typename Char>
+static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc)
+{
+ QVector<Char*> argv(8);
+ Char *p = cmdParam;
+ Char *p_end = p + length;
+
+ argc = 0;
+
+ while (*p && p < p_end) { // parse cmd line arguments
+ while (QChar((short)(*p)).isSpace()) // skip white space
+ p++;
+ if (*p && p < p_end) { // arg starts
+ int quote;
+ Char *start, *r;
+ if (*p == Char('\"') || *p == Char('\'')) { // " or ' quote
+ quote = *p;
+ start = ++p;
+ } else {
+ quote = 0;
+ start = p;
+ }
+ r = start;
+ while (*p && p < p_end) {
+ if (quote) {
+ if (*p == quote) {
+ p++;
+ if (QChar((short)(*p)).isSpace())
+ break;
+ quote = 0;
+ }
+ }
+ if (*p == '\\') { // escape char?
+ p++;
+ if (*p == Char('\"') || *p == Char('\''))
+ ; // yes
+ else
+ p--; // treat \ literally
+ } else {
+ if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
+ quote = *p++;
+ continue;
+ } else if (QChar((short)(*p)).isSpace() && !quote)
+ break;
+ }
+ if (*p)
+ *r++ = *p++;
+ }
+ if (*p && p < p_end)
+ p++;
+ *r = Char('\0');
+
+ if (argc >= (int)argv.size()-1) // expand array
+ argv.resize(argv.size()*2);
+ argv[argc++] = start;
+ }
+ }
+ argv[argc] = 0;
+
+ return argv;
+}
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this might be modified
+{
+ QStringList args;
+
+ int argc = 0;
+ QVector<wchar_t*> argv = qWinCmdLine<wchar_t>((wchar_t *)cmdLine.utf16(), cmdLine.length(), argc);
+ for (int a = 0; a < argc; ++a) {
+ args << QString::fromWCharArray(argv[a]);
+ }
+
+ return args;
+}
+
+static inline QStringList qCmdLineArgs(int argc, char *argv[])
+{
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+ QString cmdLine = QString::fromWCharArray(GetCommandLine());
+ return qWinCmdArgs(cmdLine);
+}
+#endif
+#else // !Q_OS_WIN || !Q_OS_SYMBIAN
+
+static inline QStringList qCmdLineArgs(int argc, char *argv[])
+{
+ QStringList args;
+ for (int i = 0; i != argc; ++i)
+ args += QString::fromLocal8Bit(argv[i]);
+ return args;
+}
+
+#endif // Q_OS_WIN || Q_OS_SYMBIAN
+
+QT_END_NAMESPACE
+
+#endif // QCORECMDLINEARGS_WIN_P_H
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
new file mode 100644
index 0000000000..fbb08faaf9
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreevent.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+
+#include "qmutex.h"
+#include "qset.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEvent
+ \brief The QEvent class is the base class of all
+ event classes. Event objects contain event parameters.
+
+ \ingroup events
+
+ Qt's main event loop (QCoreApplication::exec()) fetches native
+ window system events from the event queue, translates them into
+ QEvents, and sends the translated events to \l{QObject}s.
+
+ In general, events come from the underlying window system
+ (spontaneous() returns true), but it is also possible to manually
+ send events using QCoreApplication::sendEvent() and
+ QCoreApplication::postEvent() (spontaneous() returns false).
+
+ QObjects receive events by having their QObject::event() function
+ called. The function can be reimplemented in subclasses to
+ customize event handling and add additional event types;
+ QWidget::event() is a notable example. By default, events are
+ dispatched to event handlers like QObject::timerEvent() and
+ QWidget::mouseMoveEvent(). QObject::installEventFilter() allows an
+ object to intercept events destined for another object.
+
+ The basic QEvent contains only an event type parameter and an
+ "accept" flag. The accept flag set with accept(), and cleared
+ with ignore(). It is set by default, but don't rely on this as
+ subclasses may choose to clear it in their constructor.
+
+ Subclasses of QEvent contain additional parameters that describe
+ the particular event.
+
+ \sa QObject::event(), QObject::installEventFilter(),
+ QWidget::event(), QCoreApplication::sendEvent(),
+ QCoreApplication::postEvent(), QCoreApplication::processEvents()
+*/
+
+
+/*!
+ \enum QEvent::Type
+
+ This enum type defines the valid event types in Qt. The event
+ types and the specialized classes for each type are as follows:
+
+ \value None Not an event.
+ \value AccessibilityDescription Used to query accessibility description texts (QAccessibleEvent).
+ \value AccessibilityHelp Used to query accessibility help texts (QAccessibleEvent).
+ \value AccessibilityPrepare Accessibility information is requested.
+ \value ActionAdded A new action has been added (QActionEvent).
+ \value ActionChanged An action has been changed (QActionEvent).
+ \value ActionRemoved An action has been removed (QActionEvent).
+ \value ActivationChange A widget's top-level window activation state has changed.
+ \value ApplicationActivate The application has been made available to the user.
+ \value ApplicationActivated This enum has been deprecated. Use ApplicationActivate instead.
+ \value ApplicationDeactivate The application has been suspended, and is unavailable to the user.
+ \value ApplicationFontChange The default application font has changed.
+ \value ApplicationLayoutDirectionChange The default application layout direction has changed.
+ \value ApplicationPaletteChange The default application palette has changed.
+ \value ApplicationWindowIconChange The application's icon has changed.
+ \value ChildAdded An object gets a child (QChildEvent).
+ \value ChildInserted An object gets a child (QChildEvent). Qt3Support only, use ChildAdded instead.
+ \value ChildPolished A widget child gets polished (QChildEvent).
+ \value ChildRemoved An object loses a child (QChildEvent).
+ \value Clipboard The clipboard contents have changed (QClipboardEvent).
+ \value Close Widget was closed (QCloseEvent).
+ \value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP).
+ \value ContentsRectChange The margins of the widget's content rect changed.
+ \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.
+ \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).
+ \value Drop A drag and drop operation is completed (QDropEvent).
+ \value EnabledChange Widget's enabled state has changed.
+ \value Enter Mouse enters widget's boundaries.
+ \value EnterEditFocus An editor widget gains focus for editing.
+ \value EnterWhatsThisMode Send to toplevel widgets when the application enters "What's This?" mode.
+ \value FileOpen File open request (QFileOpenEvent).
+ \value FocusIn Widget gains keyboard focus (QFocusEvent).
+ \value FocusOut Widget loses keyboard focus (QFocusEvent).
+ \value FontChange Widget's font has changed.
+ \value GrabKeyboard Item gains keyboard grab (QGraphicsItem only).
+ \value GrabMouse Item gains mouse grab (QGraphicsItem only).
+ \value GraphicsSceneContextMenu Context popup menu over a graphics scene (QGraphicsSceneContextMenuEvent).
+ \value GraphicsSceneDragEnter The cursor enters a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDragLeave The cursor leaves a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDragMove A drag and drop operation is in progress over a scene (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDrop A drag and drop operation is completed over a scene (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneHelp The user requests help for a graphics scene (QHelpEvent).
+ \value GraphicsSceneHoverEnter The mouse cursor enters a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneHoverLeave The mouse cursor leaves a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneHoverMove The mouse cursor moves inside a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneMouseDoubleClick Mouse press again (double click) in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMouseMove Move mouse in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMousePress Mouse press in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMouseRelease Mouse release in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMove Widget was moved (QGraphicsSceneMoveEvent).
+ \value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent).
+ \value GraphicsSceneWheel Mouse wheel rolled in 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).
+ \value HoverLeave The mouse cursor leaves a hover widget (QHoverEvent).
+ \value HoverMove The mouse cursor moves inside a hover widget (QHoverEvent).
+ \value IconDrag The main icon of a window has been dragged away (QIconDragEvent).
+ \value IconTextChange Widget's icon text has been changed.
+ \value InputMethod An input method is being used (QInputMethodEvent).
+ \value KeyPress Key press (QKeyEvent).
+ \value KeyRelease Key release (QKeyEvent).
+ \value LanguageChange The application translation changed.
+ \value LayoutDirectionChange The direction of layouts changed.
+ \value LayoutRequest Widget layout needs to be redone.
+ \value Leave Mouse leaves widget's boundaries.
+ \value LeaveEditFocus An editor widget loses focus for editing.
+ \value LeaveWhatsThisMode Send to toplevel widgets when the application leaves "What's This?" mode.
+ \value LocaleChange The system locale has changed.
+ \value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area.
+ \value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area.
+ \value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
+ \value NonClientAreaMouseMove A mouse move occurred outside the client area.
+ \value MacSizeChange The user changed his widget sizes (Mac OS X only).
+ \value MenubarUpdated The window's menu bar has been updated.
+ \value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
+ \value ModifiedChange Widgets modification state has been changed.
+ \value MouseButtonDblClick Mouse press again (QMouseEvent).
+ \value MouseButtonPress Mouse press (QMouseEvent).
+ \value MouseButtonRelease Mouse release (QMouseEvent).
+ \value MouseMove Mouse move (QMouseEvent).
+ \value MouseTrackingChange The mouse tracking state has changed.
+ \value Move Widget's position changed (QMoveEvent).
+ \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 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.
+ \value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
+ \value Resize Widget's size changed (QResizeEvent).
+ \value Shortcut Key press in child for shortcut key handling (QShortcutEvent).
+ \value ShortcutOverride Key press in child, for overriding shortcut key handling (QKeyEvent).
+ \value Show Widget was shown on screen (QShowEvent).
+ \value ShowToParent A child widget has been shown.
+ \value SockAct Socket activated, used to implement QSocketNotifier.
+ \value StateMachineSignal A signal delivered to a state machine (QStateMachine::SignalEvent).
+ \value StateMachineWrapped The event is a wrapper for, i.e., contains, another event (QStateMachine::WrappedEvent).
+ \value StatusTip A status tip is requested (QStatusTipEvent).
+ \value StyleChange Widget's style has been changed.
+ \value TabletMove Wacom tablet move (QTabletEvent).
+ \value TabletPress Wacom tablet press (QTabletEvent).
+ \value TabletRelease Wacom tablet release (QTabletEvent).
+ \value OkRequest Ok button in decoration pressed. Supported only for Windows CE.
+ \value TabletEnterProximity Wacom tablet enter proximity event (QTabletEvent), sent to QApplication.
+ \value TabletLeaveProximity Wacom tablet leave proximity event (QTabletEvent), sent to QApplication.
+ \value Timer Regular timer events (QTimerEvent).
+ \value ToolBarChange The toolbar button is toggled on Mac OS X.
+ \value ToolTip A tooltip was requested (QHelpEvent).
+ \value ToolTipChange The widget's tooltip has changed.
+ \value UngrabKeyboard Item loses keyboard grab (QGraphicsItem only).
+ \value UngrabMouse Item loses mouse grab (QGraphicsItem only).
+ \value UpdateLater The widget should be queued to be repainted at a later time.
+ \value UpdateRequest The widget should be repainted.
+ \value WhatsThis The widget should reveal "What's This?" help (QHelpEvent).
+ \value WhatsThisClicked A link in a widget's "What's This?" help was clicked.
+ \value Wheel Mouse wheel rolled (QWheelEvent).
+ \value WinEventAct A Windows-specific activation event has occurred.
+ \value WindowActivate Window was activated.
+ \value WindowBlocked The window is blocked by a modal dialog.
+ \value WindowDeactivate Window was deactivated.
+ \value WindowIconChange The window's icon has changed.
+ \value WindowStateChange The \l{QWidget::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 ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
+ \value KeyboardLayoutChange The keyboard layout has changed.
+ \value DynamicPropertyChange A dynamic property was added, changed or removed from the object.
+ \value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent)
+ \value TouchUpdate Touch-screen event (QTouchEvent)
+ \value TouchEnd End of touch-event sequence (QTouchEvent)
+ \value WinIdChange The window system identifer for this native widget has changed
+ \value Gesture A gesture was triggered (QGestureEvent)
+ \value GestureOverride A gesture override was triggered (QGestureEvent)
+ \value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent)
+ \value Scroll The object needs to scroll to the supplied position (QScrollEvent)
+
+ User events should have values between \c User and \c{MaxUser}:
+
+ \value User User-defined event.
+ \value MaxUser Last user event ID.
+
+ For convenience, you can use the registerEventType() function to
+ register and reserve a custom event type for your
+ application. Doing so will allow you to avoid accidentally
+ re-using a custom event type already in use elsewhere in your
+ application.
+
+ \omitvalue Accel
+ \omitvalue AccelAvailable
+ \omitvalue AccelOverride
+ \omitvalue AcceptDropsChange
+ \omitvalue ActivateControl
+ \omitvalue CaptionChange
+ \omitvalue ChildInsertedRequest
+ \omitvalue ChildInserted
+ \omitvalue Create
+ \omitvalue DeactivateControl
+ \omitvalue Destroy
+ \omitvalue DragResponse
+ \omitvalue EmbeddingControl
+ \omitvalue HelpRequest
+ \omitvalue IconChange
+ \omitvalue LayoutHint
+ \omitvalue Quit
+ \omitvalue Reparent
+ \omitvalue ShowWindowRequest
+ \omitvalue Speech
+ \omitvalue Style
+ \omitvalue ThreadChange
+ \omitvalue ZeroTimerEvent
+ \omitvalue ApplicationActivated
+ \omitvalue ApplicationDeactivated
+ \omitvalue MacGLWindowChange
+ \omitvalue MacGLClearDrawable
+ \omitvalue NetworkReplyUpdated
+ \omitvalue FutureCallOut
+ \omitvalue UpdateSoftKeys
+ \omitvalue NativeGesture
+*/
+
+/*!
+ Contructs an event object of type \a type.
+*/
+QEvent::QEvent(Type type)
+ : d(0), t(type), posted(false), spont(false), m_accept(true)
+{}
+
+/*!
+ Destroys the event. If it was \link
+ QCoreApplication::postEvent() posted \endlink,
+ it will be removed from the list of events to be posted.
+*/
+
+QEvent::~QEvent()
+{
+ if (posted && QCoreApplication::instance())
+ QCoreApplicationPrivate::removePostedEvent(this);
+}
+
+
+/*!
+ \property QEvent::accepted
+ 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
+ widget. By default, isAccepted() is set to true, but don't rely on
+ this as subclasses may choose to clear it in their constructor.
+
+ For convenience, the accept flag can also be set with accept(),
+ and cleared with ignore().
+*/
+
+/*!
+ \fn void QEvent::accept()
+
+ Sets the accept flag of the event object, the equivalent of
+ calling setAccepted(true).
+
+ Setting the accept parameter indicates that the event receiver
+ wants the event. Unwanted events might be propagated to the parent
+ widget.
+
+ \sa ignore()
+*/
+
+
+/*!
+ \fn void QEvent::ignore()
+
+ Clears the accept flag parameter of the event object, the
+ equivalent of calling setAccepted(false).
+
+ Clearing the accept parameter indicates that the event receiver
+ does not want the event. Unwanted events might be propagated to the
+ parent widget.
+
+ \sa accept()
+*/
+
+
+/*!
+ \fn QEvent::Type QEvent::type() const
+
+ Returns the event type.
+*/
+
+/*!
+ \fn bool QEvent::spontaneous() const
+
+ Returns true if the event originated outside the application (a
+ system event); otherwise returns false.
+
+ The return value of this function is not defined for paint events.
+*/
+
+class QEventUserEventRegistration
+{
+public:
+ QMutex mutex;
+ QSet<int> set;
+};
+Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
+
+/*!
+ \since 4.4
+ \threadsafe
+
+ Registers and returns a custom event type. The \a hint provided
+ will be used if it is available, otherwise it will return a value
+ between QEvent::User and QEvent::MaxUser that has not yet been
+ registered. The \a hint is ignored if its value is not between
+ QEvent::User and QEvent::MaxUser.
+*/
+int QEvent::registerEventType(int hint)
+{
+ QEventUserEventRegistration *userEventRegistration
+ = userEventRegistrationHelper();
+ if (!userEventRegistration)
+ return -1;
+
+ QMutexLocker locker(&userEventRegistration->mutex);
+
+ // if the type hint hasn't been registered yet, take it
+ if (hint >= QEvent::User && hint <= QEvent::MaxUser && !userEventRegistration->set.contains(hint)) {
+ userEventRegistration->set.insert(hint);
+ return hint;
+ }
+
+ // find a free event type, starting at MaxUser and decreasing
+ int id = QEvent::MaxUser;
+ while (userEventRegistration->set.contains(id) && id >= QEvent::User)
+ --id;
+ if (id >= QEvent::User) {
+ userEventRegistration->set.insert(id);
+ return id;
+ }
+ return -1;
+}
+
+/*!
+ \class QTimerEvent
+ \brief The QTimerEvent class contains parameters that describe a
+ timer event.
+
+ \ingroup events
+
+ Timer events are sent at regular intervals to objects that have
+ 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
+ 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(),
+ QObject::killTimer()
+*/
+
+/*!
+ Constructs a timer event object with the timer identifier set to
+ \a timerId.
+*/
+QTimerEvent::QTimerEvent(int timerId)
+ : QEvent(Timer), id(timerId)
+{}
+
+/*! \internal
+*/
+QTimerEvent::~QTimerEvent()
+{
+}
+
+/*!
+ \fn int QTimerEvent::timerId() const
+
+ Returns the unique timer identifier, which is the same identifier
+ as returned from QObject::startTimer().
+*/
+
+/*!
+ \class QChildEvent
+ \brief The QChildEvent class contains event parameters for child object
+ events.
+
+ \ingroup events
+
+ Child events are sent immediately to objects when children are
+ added or removed.
+
+ In both cases you can only rely on the child being a QObject (or,
+ if QObject::isWidgetType() returns true, a QWidget). This is
+ because in the QEvent::ChildAdded case the child is not yet fully
+ constructed; in the QEvent::ChildRemoved case it might have
+ already been destructed.
+
+ The handler for these events is QObject::childEvent().
+*/
+
+/*!
+ Constructs a child event object of a particular \a type for the
+ \a child.
+
+ \a type can be QEvent::ChildAdded, QEvent::ChildRemoved,
+ QEvent::ChildPolished, or QEvent::ChildRemoved.
+
+ \sa child()
+*/
+QChildEvent::QChildEvent(Type type, QObject *child)
+ : QEvent(type), c(child)
+{}
+
+/*! \internal
+*/
+QChildEvent::~QChildEvent()
+{
+}
+
+/*!
+ \fn QObject *QChildEvent::child() const
+
+ Returns the child object that was added or removed.
+*/
+
+/*!
+ \fn bool QChildEvent::added() const
+
+ Returns true if type() is QEvent::ChildAdded; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QChildEvent::removed() const
+
+ Returns true if type() is QEvent::ChildRemoved; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QChildEvent::polished() const
+
+ Returns true if type() is QEvent::ChildPolished; otherwise returns
+ false.
+*/
+
+/*!
+ \class QCustomEvent
+ \brief The QCustomEvent class provides support for custom events.
+
+ \compat
+
+ QCustomEvent has a \c{void *} that can be used to store custom
+ data.
+
+ In Qt 3, QObject::customEvent() took a QCustomEvent pointer. We
+ found out that this approach was unsatisfactory, because
+ there was often no safe way of deleting the data held in the
+ \c{void *}.
+
+ In Qt 4, QObject::customEvent() takes a plain QEvent pointer.
+ You can add custom data by subclassing.
+
+ \sa QObject::customEvent(), QCoreApplication::notify()
+*/
+
+/*!
+ \fn QCustomEvent::QCustomEvent(int type, void *data)
+
+ Constructs a custom event object with the event \a type and a
+ pointer to \a data. The value of \a type must be at least as
+ large as QEvent::User. By default, the data pointer is set to 0.
+*/
+#ifdef QT3_SUPPORT
+QCustomEvent::QCustomEvent(int type, void *data)
+ : QEvent(static_cast<Type>(type))
+{
+ d = reinterpret_cast<QEventPrivate *>(data);
+}
+
+/*! \internal
+*/
+QCustomEvent::~QCustomEvent()
+{
+}
+#endif
+/*!
+ \fn void QCustomEvent::setData(void *data)
+
+ \compat
+
+ Sets the generic data pointer to \a data.
+
+ \sa data()
+*/
+
+/*!
+ \fn void *QCustomEvent::data() const
+
+ \compat
+
+ Returns a pointer to the generic event data.
+
+ \sa setData()
+*/
+
+/*!
+ \fn bool QChildEvent::inserted() const
+
+ \compat
+
+ A child has been inserted if the event's type() is ChildInserted.
+*/
+
+/*!
+ \class QDynamicPropertyChangeEvent
+ \since 4.2
+ \brief The QDynamicPropertyChangeEvent class contains event parameters for dynamic
+ property change events.
+
+ \ingroup events
+
+ Dynamic property change events are sent to objects when properties are
+ dynamically added, changed or removed using QObject::setProperty().
+*/
+
+/*!
+ Constructs a dynamic property change event object with the property name set to
+ \a name.
+*/
+QDynamicPropertyChangeEvent::QDynamicPropertyChangeEvent(const QByteArray &name)
+ : QEvent(QEvent::DynamicPropertyChange), n(name)
+{
+}
+
+/*!
+ \internal
+*/
+QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
+{
+}
+
+/*!
+ \fn QByteArray QDynamicPropertyChangeEvent::propertyName() const
+
+ Returns the name of the dynamic property that was added, changed or
+ removed.
+
+ \sa QObject::setProperty(), QObject::dynamicPropertyNames()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
new file mode 100644
index 0000000000..c9d311ae35
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.h
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREEVENT_H
+#define QCOREEVENT_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventPrivate;
+class Q_CORE_EXPORT QEvent // event base class
+{
+ Q_GADGET
+ QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ /*
+ If you get a strange compiler error on the line with None,
+ it's probably because you're also including X11 headers,
+ which #define the symbol None. Put the X11 includes after
+ the Qt includes to solve this problem.
+ */
+ None = 0, // invalid event
+ Timer = 1, // timer event
+ MouseButtonPress = 2, // mouse button pressed
+ MouseButtonRelease = 3, // mouse button released
+ MouseButtonDblClick = 4, // mouse button double click
+ MouseMove = 5, // mouse move
+ KeyPress = 6, // key pressed
+ KeyRelease = 7, // key released
+ FocusIn = 8, // keyboard focus received
+ FocusOut = 9, // keyboard focus lost
+ Enter = 10, // mouse enters widget
+ Leave = 11, // mouse leaves widget
+ Paint = 12, // paint widget
+ Move = 13, // move widget
+ Resize = 14, // resize widget
+ Create = 15, // after widget creation
+ Destroy = 16, // during widget destruction
+ Show = 17, // widget is shown
+ Hide = 18, // widget is hidden
+ Close = 19, // request to close widget
+ Quit = 20, // request to quit application
+ ParentChange = 21, // widget has been reparented
+ ParentAboutToChange = 131, // sent just before the parent change is done
+#ifdef QT3_SUPPORT
+ Reparent = ParentChange,
+#endif
+ ThreadChange = 22, // object has changed threads
+ WindowActivate = 24, // window was activated
+ WindowDeactivate = 25, // window was deactivated
+ ShowToParent = 26, // widget is shown to parent
+ HideToParent = 27, // widget is hidden to parent
+ Wheel = 31, // wheel event
+ WindowTitleChange = 33, // window title changed
+ WindowIconChange = 34, // icon changed
+ ApplicationWindowIconChange = 35, // application icon changed
+ ApplicationFontChange = 36, // application font changed
+ ApplicationLayoutDirectionChange = 37, // application layout direction changed
+ ApplicationPaletteChange = 38, // application palette changed
+ PaletteChange = 39, // widget palette changed
+ Clipboard = 40, // internal clipboard event
+ Speech = 42, // reserved for speech input
+ MetaCall = 43, // meta call event
+ SockAct = 50, // socket activation
+ WinEventAct = 132, // win event activation
+ DeferredDelete = 52, // deferred delete event
+ DragEnter = 60, // drag moves into widget
+ DragMove = 61, // drag moves in widget
+ DragLeave = 62, // drag leaves or is cancelled
+ Drop = 63, // actual drop
+ DragResponse = 64, // drag accepted/rejected
+ ChildAdded = 68, // new child widget
+ ChildPolished = 69, // polished child widget
+#ifdef QT3_SUPPORT
+ ChildInsertedRequest = 67, // send ChildInserted compatibility events to receiver
+ ChildInserted = 70, // compatibility child inserted
+ LayoutHint = 72, // compatibility relayout request
+#endif
+ ChildRemoved = 71, // deleted child widget
+ ShowWindowRequest = 73, // widget's window should be mapped
+ PolishRequest = 74, // widget should be polished
+ Polish = 75, // widget is polished
+ LayoutRequest = 76, // widget should be relayouted
+ UpdateRequest = 77, // widget should be repainted
+ UpdateLater = 78, // request update() later
+
+ EmbeddingControl = 79, // ActiveX embedding
+ ActivateControl = 80, // ActiveX activation
+ DeactivateControl = 81, // ActiveX deactivation
+ ContextMenu = 82, // context popup menu
+ InputMethod = 83, // input method
+ AccessibilityPrepare = 86, // accessibility information is requested
+ TabletMove = 87, // Wacom tablet event
+ LocaleChange = 88, // the system locale changed
+ LanguageChange = 89, // the application language changed
+ LayoutDirectionChange = 90, // the layout direction changed
+ Style = 91, // internal style event
+ TabletPress = 92, // tablet press
+ TabletRelease = 93, // tablet release
+ OkRequest = 94, // CE (Ok) button pressed
+ HelpRequest = 95, // CE (?) button pressed
+
+ IconDrag = 96, // proxy icon dragged
+
+ FontChange = 97, // font has changed
+ EnabledChange = 98, // enabled state has changed
+ ActivationChange = 99, // window activation has changed
+ StyleChange = 100, // style has changed
+ IconTextChange = 101, // icon text has changed
+ ModifiedChange = 102, // modified state has changed
+ MouseTrackingChange = 109, // mouse tracking state has changed
+
+ WindowBlocked = 103, // window is about to be blocked modally
+ WindowUnblocked = 104, // windows modal blocking has ended
+ WindowStateChange = 105,
+
+ ToolTip = 110,
+ WhatsThis = 111,
+ StatusTip = 112,
+
+ ActionChanged = 113,
+ ActionAdded = 114,
+ ActionRemoved = 115,
+
+ FileOpen = 116, // file open request
+
+ Shortcut = 117, // shortcut triggered
+ ShortcutOverride = 51, // shortcut override request
+
+#ifdef QT3_SUPPORT
+ Accel = 30, // accelerator event
+ AccelAvailable = 32, // accelerator available event
+ AccelOverride = ShortcutOverride, // accelerator override event
+#endif
+
+ WhatsThisClicked = 118,
+
+#ifdef QT3_SUPPORT
+ CaptionChange = WindowTitleChange,
+ IconChange = WindowIconChange,
+#endif
+ ToolBarChange = 120, // toolbar visibility toggled
+
+ ApplicationActivate = 121, // application has been changed to active
+ ApplicationActivated = ApplicationActivate, // deprecated
+ ApplicationDeactivate = 122, // application has been changed to inactive
+ ApplicationDeactivated = ApplicationDeactivate, // deprecated
+
+ QueryWhatsThis = 123, // query what's this widget help
+ EnterWhatsThisMode = 124,
+ LeaveWhatsThisMode = 125,
+
+ ZOrderChange = 126, // child widget has had its z-order changed
+
+ HoverEnter = 127, // mouse cursor enters a hover widget
+ HoverLeave = 128, // mouse cursor leaves a hover widget
+ HoverMove = 129, // mouse cursor move inside a hover widget
+
+ AccessibilityHelp = 119, // accessibility help text request
+ AccessibilityDescription = 130, // accessibility description text request
+
+ // last event id used = 132
+
+#ifdef QT_KEYPAD_NAVIGATION
+ EnterEditFocus = 150, // enter edit mode in keypad navigation
+ LeaveEditFocus = 151, // enter edit mode in keypad navigation
+#endif
+ AcceptDropsChange = 152,
+
+ MenubarUpdated = 153, // Support event for Q3MainWindow, which needs to
+ // knwow when QMenubar is updated.
+
+ ZeroTimerEvent = 154, // Used for Windows Zero timer events
+
+ GraphicsSceneMouseMove = 155, // GraphicsView
+ GraphicsSceneMousePress = 156,
+ GraphicsSceneMouseRelease = 157,
+ GraphicsSceneMouseDoubleClick = 158,
+ GraphicsSceneContextMenu = 159,
+ GraphicsSceneHoverEnter = 160,
+ GraphicsSceneHoverMove = 161,
+ GraphicsSceneHoverLeave = 162,
+ GraphicsSceneHelp = 163,
+ GraphicsSceneDragEnter = 164,
+ GraphicsSceneDragMove = 165,
+ GraphicsSceneDragLeave = 166,
+ GraphicsSceneDrop = 167,
+ GraphicsSceneWheel = 168,
+
+ KeyboardLayoutChange = 169, // keyboard layout changed
+
+ DynamicPropertyChange = 170, // A dynamic property was changed through setProperty/property
+
+ TabletEnterProximity = 171,
+ TabletLeaveProximity = 172,
+
+ NonClientAreaMouseMove = 173,
+ NonClientAreaMouseButtonPress = 174,
+ NonClientAreaMouseButtonRelease = 175,
+ NonClientAreaMouseButtonDblClick = 176,
+
+ MacSizeChange = 177, // when the Qt::WA_Mac{Normal,Small,Mini}Size changes
+
+ ContentsRectChange = 178, // sent by QWidget::setContentsMargins (internal)
+
+ MacGLWindowChange = 179, // Internal! the window of the GLWidget has changed
+
+ FutureCallOut = 180,
+
+ GraphicsSceneResize = 181,
+ GraphicsSceneMove = 182,
+
+ CursorChange = 183,
+ ToolTipChange = 184,
+
+ NetworkReplyUpdated = 185, // Internal for QNetworkReply
+
+ GrabMouse = 186,
+ UngrabMouse = 187,
+ GrabKeyboard = 188,
+ UngrabKeyboard = 189,
+ MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
+
+ StateMachineSignal = 192,
+ StateMachineWrapped = 193,
+
+ TouchBegin = 194,
+ TouchUpdate = 195,
+ TouchEnd = 196,
+
+#ifndef QT_NO_GESTURES
+ NativeGesture = 197, // Internal for platform gesture support
+#endif
+ RequestSoftwareInputPanel = 199,
+ CloseSoftwareInputPanel = 200,
+
+ UpdateSoftKeys = 201, // Internal for compressing soft key updates
+
+ WinIdChange = 203,
+#ifndef QT_NO_GESTURES
+ Gesture = 198,
+ GestureOverride = 202,
+#endif
+ ScrollPrepare = 204,
+ Scroll = 205,
+
+ // 512 reserved for Qt Jambi's MetaCall event
+ // 513 reserved for Qt Jambi's DeleteOnMainThread event
+
+ User = 1000, // first user event id
+ MaxUser = 65535 // last user event id
+ };
+
+ QEvent(Type type);
+ virtual ~QEvent();
+ inline Type type() const { return static_cast<Type>(t); }
+ inline bool spontaneous() const { return spont; }
+
+ inline 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; }
+
+ static int registerEventType(int hint = -1);
+
+protected:
+ QEventPrivate *d;
+ ushort t;
+
+private:
+ ushort posted : 1;
+ ushort spont : 1;
+ ushort m_accept : 1;
+ ushort reserved : 13;
+
+ friend class QCoreApplication;
+ friend class QCoreApplicationPrivate;
+ friend class QThreadData;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class Q3AccelManager;
+ friend class QShortcutMap;
+ friend class QETWidget;
+ friend class QGraphicsView;
+ friend class QGraphicsViewPrivate;
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+#ifndef QT_NO_GESTURES
+ friend class QGestureManager;
+#endif
+};
+
+class Q_CORE_EXPORT QTimerEvent : public QEvent
+{
+public:
+ QTimerEvent( int timerId );
+ ~QTimerEvent();
+ int timerId() const { return id; }
+protected:
+ int id;
+};
+
+class QObject;
+
+class Q_CORE_EXPORT QChildEvent : public QEvent
+{
+public:
+ QChildEvent( Type type, QObject *child );
+ ~QChildEvent();
+ QObject *child() const { return c; }
+ bool added() const { return type() == ChildAdded; }
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT bool inserted() const { return type() == ChildInserted; }
+#endif
+ bool polished() const { return type() == ChildPolished; }
+ bool removed() const { return type() == ChildRemoved; }
+protected:
+ QObject *c;
+};
+
+#ifdef QT3_SUPPORT
+class Q_CORE_EXPORT QCustomEvent : public QEvent
+{
+public:
+ QT3_SUPPORT_CONSTRUCTOR QCustomEvent(int type, void *data = 0);
+ ~QCustomEvent();
+ QT3_SUPPORT void *data() const { return d; }
+ QT3_SUPPORT void setData(void* aData) { d = reinterpret_cast<QEventPrivate *>(aData); }
+};
+#endif
+
+class Q_CORE_EXPORT QDynamicPropertyChangeEvent : public QEvent
+{
+public:
+ QDynamicPropertyChangeEvent(const QByteArray &name);
+ ~QDynamicPropertyChangeEvent();
+
+ inline QByteArray propertyName() const { return n; }
+
+private:
+ QByteArray n;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOREEVENT_H
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
new file mode 100644
index 0000000000..d90b46cb26
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreglobaldata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QCoreGlobalData, globalInstance)
+
+QCoreGlobalData *QCoreGlobalData::instance()
+{
+ return globalInstance();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreglobaldata_p.h b/src/corelib/kernel/qcoreglobaldata_p.h
new file mode 100644
index 0000000000..aeb7bd8840
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qmap.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qreadwritelock.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QCoreGlobalData {
+ QMap<QString, QStringList> dirSearchPaths;
+ QReadWriteLock dirSearchPathsLock;
+
+ static QCoreGlobalData *instance();
+};
+
+
+QT_END_NAMESPACE
+#endif // QCOREGLOBALDATA_P_H
+
diff --git a/src/corelib/kernel/qcrashhandler.cpp b/src/corelib/kernel/qcrashhandler.cpp
new file mode 100644
index 0000000000..fbdbac0b5c
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*************************************************************************
+ *
+ * stacktrace.c 1.2 1998/12/21
+ *
+ * Copyright (c) 1998 by Bjorn Reese <breese@imada.ou.dk>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
+ *
+ ************************************************************************/
+
+#include "qplatformdefs.h"
+#include "private/qcrashhandler_p.h"
+#include "qbytearray.h" // for qvsnprintf()
+
+#ifndef QT_NO_CRASHHANDLER
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+QtCrashHandler QSegfaultHandler::callback = 0;
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include "qstring.h"
+# include <execinfo.h>
+QT_END_INCLUDE_NAMESPACE
+
+static void print_backtrace(FILE *outb)
+{
+ void *stack[128];
+ int stack_size = backtrace(stack, sizeof(stack) / sizeof(void *));
+ char **stack_symbols = backtrace_symbols(stack, stack_size);
+ fprintf(outb, "Stack [%d]:\n", stack_size);
+ if(FILE *cppfilt = popen("c++filt", "rw")) {
+ dup2(fileno(outb), fileno(cppfilt));
+ for(int i = stack_size-1; i>=0; --i)
+ fwrite(stack_symbols[i], 1, strlen(stack_symbols[i]), cppfilt);
+ pclose(cppfilt);
+ } else {
+ for(int i = stack_size-1; i>=0; --i)
+ fprintf(outb, "#%d %p [%s]\n", i, stack[i], stack_symbols[i]);
+ }
+}
+static void init_backtrace(char **, int)
+{
+}
+
+#else /* Don't use the GLIBC callback */
+/* Code sourced from: */
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#if defined(Q_OS_IRIX) && defined(USE_LIBEXC)
+# include <libexc.h>
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+
+static char *globalProgName = NULL;
+static bool backtrace_command(FILE *outb, const char *format, ...)
+{
+
+ bool ret = false;
+ char buffer[50];
+
+ /*
+ * Please note that vsnprintf() is not ASync safe (ie. cannot safely
+ * be used from a signal handler.) If this proves to be a problem
+ * then the cmd string can be built by more basic functions such as
+ * strcpy, strcat, and a home-made integer-to-ascii function.
+ */
+ va_list args;
+ char cmd[512];
+ va_start(args, format);
+ qvsnprintf(cmd, 512, format, args);
+ va_end(args);
+
+ char *foo = cmd;
+#if 0
+ foo = "echo hi";
+#endif
+ if(FILE *inb = popen(foo, "r")) {
+ while(!feof(inb)) {
+ int len = fread(buffer, 1, sizeof(buffer), inb);
+ if(!len)
+ break;
+ if(!ret) {
+ fwrite("Output from ", 1, strlen("Output from "), outb);
+ strtok(cmd, " ");
+ fwrite(cmd, 1, strlen(cmd), outb);
+ fwrite("\n", 1, 1, outb);
+ ret = true;
+ }
+ fwrite(buffer, 1, len, outb);
+ }
+ fclose(inb);
+ }
+ return ret;
+}
+
+static void init_backtrace(char **argv, int argc)
+{
+ if(argc >= 1)
+ globalProgName = argv[0];
+}
+
+static void print_backtrace(FILE *outb)
+{
+ /*
+ * In general dbx seems to do a better job than gdb.
+ *
+ * Different dbx implementations require different flags/commands.
+ */
+#if defined(Q_OS_AIX)
+ if(backtrace_command(outb, "dbx -a %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_FREEBSD)
+ /*
+ * FreeBSD insists on sending a SIGSTOP to the process we
+ * attach to, so we let the debugger send a SIGCONT to that
+ * process after we have detached.
+ */
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "shell kill -CONT %d\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid(), (int)getpid()))
+ return;
+#elif defined(Q_OS_HPUX)
+ /*
+ * HP decided to call their debugger xdb.
+ *
+ * This does not seem to work properly yet. The debugger says
+ * "Note: Stack traces may not be possible until you are
+ * stopped in user code." on HP-UX 09.01
+ *
+ * -L = line-oriented interface.
+ * "T [depth]" gives a stacktrace with local variables.
+ * The final "y" is confirmation to the quit command.
+ */
+ if(backtrace_command(outb, "xdb -P %d -L %s 2>&1 <<EOF\n"
+ "T 50\n"
+ "q\ny\n"
+ "EOF\n",
+ (int)getpid(), globalProgName))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_IRIX)
+ /*
+ * "set $page=0" drops hold mode
+ * "dump ." displays the contents of the variables
+ */
+ if(backtrace_command(outb, "dbx -p %d 2>/dev/null <<EOF\n"
+ "set \\$page=0\n"
+ "where\n"
+# if !defined(__GNUC__)
+ /* gcc does not generate this information */
+ "dump .\n"
+# endif
+ "detach\n"
+ "EOF\n",
+ (int)getpid()))
+ return;
+
+# if defined(USE_LIBEXC)
+ if(trace_back_stack_and_print())
+ return;
+# endif
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "echo ---\\n\n"
+ "frame 5\n" /* Skip signal handler frames */
+ "set \\$x = 50\n"
+ "while (\\$x)\n" /* Print local variables for each frame */
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_OSF)
+ if(backtrace_command(outb, "dbx -pid %d %s 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ (int)getpid(), globalProgName))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_SCO)
+ /*
+ * SCO OpenServer dbx is like a catch-22. The 'detach' command
+ * depends on whether ptrace(S) support detaching or not. If it
+ * is supported then 'detach' must be used, otherwise the process
+ * will be killed upon dbx exit. If it isn't supported then 'detach'
+ * will cause the process to be killed. We do not want it to be
+ * killed.
+ *
+ * Out of two evils, the omission of 'detach' was chosen because
+ * it worked on our system.
+ */
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "quit\nEOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_SOLARIS)
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "echo ---\\n\n"
+ "frame 5\n" /* Skip signal handler frames */
+ "set \\$x = 50\n"
+ "while (\\$x)\n" /* Print local variables for each frame */
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "/usr/proc/bin/pstack %d",
+ (int)getpid()))
+ return;
+ /*
+ * Other Unices (AIX, HPUX, SCO) also have adb, but
+ * they seem unable to attach to a running process.)
+ */
+ if(backtrace_command(outb, "adb %s 2>&1 <<EOF\n"
+ "0t%d:A\n" /* Attach to pid */
+ "\\$c\n" /* print stacktrace */
+ ":R\n" /* Detach */
+ "\\$q\n" /* Quit */
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_INTEGRITY)
+ /* abort */
+ CheckSuccess(Failure);
+#else /* All other platforms */
+ /*
+ * TODO: SCO/UnixWare 7 must be something like (not tested)
+ * debug -i c <pid> <<EOF\nstack -f 4\nquit\nEOF\n
+ */
+# if !defined(__GNUC__)
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+# endif
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+#if 0
+ "echo ---\\n\n"
+ "frame 4\n"
+ "set \\$x = 50\n"
+ "while (\\$x)\n"
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+#endif
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#endif
+ const char debug_err[] = "No debugger found\n";
+ fwrite(debug_err, strlen(debug_err), 1, outb);
+}
+/* end of copied code */
+#endif
+
+
+void qt_signal_handler(int sig)
+{
+ signal(sig, SIG_DFL);
+ if(QSegfaultHandler::callback) {
+ (*QSegfaultHandler::callback)();
+ _exit(1);
+ }
+ FILE *outb = stderr;
+ if(char *crash_loc = ::getenv("QT_CRASH_OUTPUT")) {
+ if(FILE *new_outb = fopen(crash_loc, "w")) {
+ fprintf(stderr, "Crash (backtrace written to %s)!!!\n", crash_loc);
+ outb = new_outb;
+ }
+ } else {
+ fprintf(outb, "Crash!!!\n");
+ }
+ print_backtrace(outb);
+ if(outb != stderr)
+ fclose(outb);
+ _exit(1);
+}
+
+
+void
+QSegfaultHandler::initialize(char **argv, int argc)
+{
+ init_backtrace(argv, argc);
+
+ struct sigaction SignalAction;
+ SignalAction.sa_flags = 0;
+ SignalAction.sa_handler = qt_signal_handler;
+ sigemptyset(&SignalAction.sa_mask);
+ sigaction(SIGSEGV, &SignalAction, NULL);
+ sigaction(SIGBUS, &SignalAction, NULL);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CRASHHANDLER
diff --git a/src/corelib/kernel/qcrashhandler_p.h b/src/corelib/kernel/qcrashhandler_p.h
new file mode 100644
index 0000000000..1d41a3c693
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCRASHHANDLER_P_H
+#define QCRASHHANDLER_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>
+
+#ifndef QT_NO_CRASHHANDLER
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*QtCrashHandler)();
+
+class Q_CORE_EXPORT QSegfaultHandler
+{
+ friend void qt_signal_handler(int);
+ static QtCrashHandler callback;
+public:
+ static void initialize(char **, int);
+
+ inline static void installCrashHandler(QtCrashHandler h) { callback = h; }
+ inline static QtCrashHandler crashHandler() { return callback; }
+
+private:
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CRASHHANDLER
+
+#endif // QCRASHHANDLER_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
new file mode 100644
index 0000000000..4e19414231
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_glib_p.h"
+#include "qeventdispatcher_unix_p.h"
+
+#include <private/qmutexpool_p.h>
+#include <private/qthread_p.h>
+
+#include "qcoreapplication.h"
+#include "qsocketnotifier.h"
+
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+
+#include <glib.h>
+
+QT_BEGIN_NAMESPACE
+
+struct GPollFDWithQSocketNotifier
+{
+ GPollFD pollfd;
+ QSocketNotifier *socketNotifier;
+};
+
+struct GSocketNotifierSource
+{
+ GSource source;
+ QList<GPollFDWithQSocketNotifier *> pollfds;
+};
+
+static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout)
+{
+ if (timeout)
+ *timeout = -1;
+ return false;
+}
+
+static gboolean socketNotifierSourceCheck(GSource *source)
+{
+ GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
+
+ bool pending = false;
+ for (int i = 0; !pending && i < src->pollfds.count(); ++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" };
+ qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
+ p->pollfd.fd, t[int(p->socketNotifier->type())]);
+ // ### note, modifies src->pollfds!
+ p->socketNotifier->setEnabled(false);
+ }
+
+ pending = ((p->pollfd.revents & p->pollfd.events) != 0);
+ }
+
+ return pending;
+}
+
+static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ 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);
+
+ if ((p->pollfd.revents & p->pollfd.events) != 0)
+ QCoreApplication::sendEvent(p->socketNotifier, &event);
+ }
+
+ return true; // ??? don't remove, right?
+}
+
+static GSourceFuncs socketNotifierSourceFuncs = {
+ socketNotifierSourcePrepare,
+ socketNotifierSourceCheck,
+ socketNotifierSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GTimerSource
+{
+ GSource source;
+ QTimerInfoList timerList;
+ QEventLoop::ProcessEventsFlags processEventsFlags;
+ bool runWithIdlePriority;
+};
+
+static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout)
+{
+ timeval tv = { 0l, 0l };
+ if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv))
+ *timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+ else
+ *timeout = -1;
+
+ return (*timeout == 0);
+}
+
+static gboolean timerSourceCheckHelper(GTimerSource *src)
+{
+ if (src->timerList.isEmpty()
+ || (src->processEventsFlags & QEventLoop::X11ExcludeTimers))
+ return false;
+
+ if (src->timerList.updateCurrentTime() < src->timerList.first()->timeout)
+ return false;
+
+ return true;
+}
+
+static gboolean timerSourcePrepare(GSource *source, gint *timeout)
+{
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority) {
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(src, timeout);
+}
+
+static gboolean timerSourceCheck(GSource *source)
+{
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority)
+ return false;
+ return timerSourceCheckHelper(src);
+}
+
+static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(source);
+ if (timerSource->processEventsFlags & QEventLoop::X11ExcludeTimers)
+ return true;
+ timerSource->runWithIdlePriority = true;
+ (void) timerSource->timerList.activateTimers();
+ return true; // ??? don't remove, right again?
+}
+
+static GSourceFuncs timerSourceFuncs = {
+ timerSourcePrepare,
+ timerSourceCheck,
+ timerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GIdleTimerSource
+{
+ GSource source;
+ GTimerSource *timerSource;
+};
+
+static gboolean idleTimerSourcePrepare(GSource *source, gint *timeout)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(timerSource, timeout);
+}
+
+static gboolean idleTimerSourceCheck(GSource *source)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ return false;
+ }
+ return timerSourceCheckHelper(timerSource);
+}
+
+static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GTimerSource *timerSource = reinterpret_cast<GIdleTimerSource *>(source)->timerSource;
+ (void) timerSourceDispatch(&timerSource->source, 0, 0);
+ return true;
+}
+
+static GSourceFuncs idleTimerSourceFuncs = {
+ idleTimerSourcePrepare,
+ idleTimerSourceCheck,
+ idleTimerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GPostEventSource
+{
+ GSource source;
+ QAtomicInt serialNumber;
+ int lastSerialNumber;
+ QEventDispatcherGlibPrivate *d;
+};
+
+static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data)
+ return false;
+
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+ *timeout = data->canWait ? -1 : 0;
+
+ GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
+ return (!data->canWait
+ || (source->serialNumber != source->lastSerialNumber));
+}
+
+static gboolean postEventSourceCheck(GSource *source)
+{
+ return postEventSourcePrepare(source, 0);
+}
+
+static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
+{
+ GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
+ source->lastSerialNumber = source->serialNumber;
+ QCoreApplication::sendPostedEvents();
+ source->d->runTimersOnceWithNormalPriority();
+ return true; // i dunno, george...
+}
+
+static GSourceFuncs postEventSourceFuncs = {
+ postEventSourcePrepare,
+ postEventSourceCheck,
+ postEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+
+QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
+ : mainContext(context)
+{
+ if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) {
+ static int dummyValue = 0; // only used for its address
+ QMutexLocker locker(QMutexPool::instance()->get(&dummyValue));
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ }
+
+ if (mainContext) {
+ g_main_context_ref(mainContext);
+ } else {
+ QCoreApplication *app = QCoreApplication::instance();
+ if (app && QThread::currentThread() == app->thread()) {
+ mainContext = g_main_context_default();
+ g_main_context_ref(mainContext);
+ } else {
+ mainContext = g_main_context_new();
+ }
+ }
+
+#if GLIB_CHECK_VERSION (2, 22, 0)
+ g_main_context_push_thread_default (mainContext);
+#endif
+
+ // setup post event source
+ postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
+ sizeof(GPostEventSource)));
+ postEventSource->serialNumber = 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)));
+ (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)));
+ (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)));
+ idleTimerSource->timerSource = timerSource;
+ g_source_set_can_recurse(&idleTimerSource->source, true);
+ g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
+ g_source_attach(&idleTimerSource->source, mainContext);
+}
+
+void QEventDispatcherGlibPrivate::runTimersOnceWithNormalPriority()
+{
+ timerSource->runWithIdlePriority = false;
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent)
+ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate), parent)
+{
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent)
+ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent)
+{ }
+
+QEventDispatcherGlib::~QEventDispatcherGlib()
+{
+ Q_D(QEventDispatcherGlib);
+
+ // destroy all timer sources
+ qDeleteAll(d->timerSource->timerList);
+ d->timerSource->timerList.~QTimerInfoList();
+ g_source_destroy(&d->timerSource->source);
+ g_source_unref(&d->timerSource->source);
+ d->timerSource = 0;
+ g_source_destroy(&d->idleTimerSource->source);
+ g_source_unref(&d->idleTimerSource->source);
+ d->idleTimerSource = 0;
+
+ // destroy socket notifier source
+ for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds[i];
+ g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
+ delete p;
+ }
+ d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
+ g_source_destroy(&d->socketNotifierSource->source);
+ g_source_unref(&d->socketNotifierSource->source);
+ d->socketNotifierSource = 0;
+
+ // destroy post event source
+ g_source_destroy(&d->postEventSource->source);
+ g_source_unref(&d->postEventSource->source);
+ d->postEventSource = 0;
+
+ Q_ASSERT(d->mainContext != 0);
+#if GLIB_CHECK_VERSION (2, 22, 0)
+ g_main_context_pop_thread_default (d->mainContext);
+#endif
+ g_main_context_unref(d->mainContext);
+ d->mainContext = 0;
+}
+
+bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherGlib);
+
+ const bool canWait = (flags & QEventLoop::WaitForMoreEvents);
+ if (canWait)
+ emit aboutToBlock();
+ else
+ emit awake();
+
+ // tell postEventSourcePrepare() and timerSource about any new flags
+ QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
+ d->timerSource->processEventsFlags = flags;
+
+ if (!(flags & QEventLoop::EventLoopExec)) {
+ // force timers to be sent at normal priority
+ d->timerSource->runWithIdlePriority = false;
+ }
+
+ bool result = g_main_context_iteration(d->mainContext, canWait);
+ while (!result && canWait)
+ result = g_main_context_iteration(d->mainContext, canWait);
+
+ d->timerSource->processEventsFlags = savedFlags;
+
+ if (canWait)
+ emit awake();
+
+ 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 type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+
+
+ GPollFDWithQSocketNotifier *p = new GPollFDWithQSocketNotifier;
+ p->pollfd.fd = sockfd;
+ switch (type) {
+ case QSocketNotifier::Read:
+ p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ break;
+ case QSocketNotifier::Write:
+ p->pollfd.events = G_IO_OUT | G_IO_ERR;
+ break;
+ case QSocketNotifier::Exception:
+ p->pollfd.events = G_IO_PRI | G_IO_ERR;
+ break;
+ }
+ p->socketNotifier = notifier;
+
+ d->socketNotifierSource->pollfds.append(p);
+
+ g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
+}
+
+void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+#ifndef QT_NO_DEBUG
+ int sockfd = notifier->socket();
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+
+ for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
+ if (p->socketNotifier == notifier) {
+ // found it
+ g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
+
+ d->socketNotifierSource->pollfds.removeAt(i);
+ delete p;
+
+ return;
+ }
+ }
+}
+
+void QEventDispatcherGlib::registerTimer(int timerId, int interval, QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !object) {
+ qWarning("QEventDispatcherGlib::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ d->timerSource->timerList.registerTimer(timerId, interval, object);
+}
+
+bool QEventDispatcherGlib::unregisterTimer(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QEventDispatcherGlib::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ return d->timerSource->timerList.unregisterTimer(timerId);
+}
+
+bool QEventDispatcherGlib::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherGlib::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ return d->timerSource->timerList.unregisterTimers(object);
+}
+
+QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherGlib);
+ return d->timerSource->timerList.registeredTimers(object);
+}
+
+void QEventDispatcherGlib::interrupt()
+{
+ wakeUp();
+}
+
+void QEventDispatcherGlib::wakeUp()
+{
+ Q_D(QEventDispatcherGlib);
+ d->postEventSource->serialNumber.ref();
+ 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)
+ return false;
+#else
+ return ((GLIB_MAJOR_VERSION << 16) + (GLIB_MINOR_VERSION << 8) + GLIB_MICRO_VERSION) >= 0x020301;
+#endif
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
new file mode 100644
index 0000000000..65eff72fca
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_GLIB_P_H
+#define QEVENTDISPATCHER_GLIB_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qabstracteventdispatcher.h"
+#include "qabstracteventdispatcher_p.h"
+
+#include <QtCore/qhash.h>
+
+typedef struct _GMainContext GMainContext;
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherGlibPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherGlib)
+
+public:
+ explicit QEventDispatcherGlib(QObject *parent = 0);
+ explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0);
+ ~QEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *socketNotifier);
+ void unregisterSocketNotifier(QSocketNotifier *socketNotifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ static bool versionSupported();
+
+protected:
+ QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent);
+};
+
+struct GPostEventSource;
+struct GSocketNotifierSource;
+struct GTimerSource;
+struct GIdleTimerSource;
+
+class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate
+{
+
+public:
+ QEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GMainContext *mainContext;
+ GPostEventSource *postEventSource;
+ GSocketNotifierSource *socketNotifierSource;
+ GTimerSource *timerSource;
+ GIdleTimerSource *idleTimerSource;
+
+ void runTimersOnceWithNormalPriority();
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_GLIB_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
new file mode 100644
index 0000000000..e0eeb0819a
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -0,0 +1,1310 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_symbian_p.h"
+#include <private/qthread_p.h>
+#include <qcoreapplication.h>
+#include <private/qcoreapplication_p.h>
+#include <qsemaphore.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+// when the system UI is Qt based, priority drop is not needed as CPU starved processes will not be killed.
+#undef QT_SYMBIAN_PRIORITY_DROP
+#else
+#define QT_SYMBIAN_PRIORITY_DROP
+#endif
+
+#define WAKE_UP_PRIORITY CActive::EPriorityStandard
+#define TIMER_PRIORITY CActive::EPriorityHigh
+#define NULLTIMER_PRIORITY CActive::EPriorityLow
+#define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle
+
+static inline int qt_pipe_write(int socket, const char *data, qint64 len)
+{
+ return ::write(socket, data, len);
+}
+#if defined(write)
+# undef write
+#endif
+
+static inline int qt_pipe_close(int socket)
+{
+ return ::close(socket);
+}
+#if defined(close)
+# undef close
+#endif
+
+static inline int qt_pipe_fcntl(int socket, int command)
+{
+ return ::fcntl(socket, command);
+}
+static inline int qt_pipe2_fcntl(int socket, int command, int option)
+{
+ return ::fcntl(socket, command, option);
+}
+#if defined(fcntl)
+# undef fcntl
+#endif
+
+static inline int qt_socket_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+ return ::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+// This simply interrupts the select and locks the mutex until destroyed.
+class QSelectMutexGrabber
+{
+public:
+ QSelectMutexGrabber(int writeFd, int readFd, QMutex *mutex)
+ : m_mutex(mutex)
+ {
+ if (m_mutex->tryLock())
+ return;
+
+ char dummy = 0;
+ qt_pipe_write(writeFd, &dummy, 1);
+
+ m_mutex->lock();
+
+ char buffer;
+ while (::read(readFd, &buffer, 1) > 0) {}
+ }
+
+ ~QSelectMutexGrabber()
+ {
+ m_mutex->unlock();
+ }
+
+private:
+ QMutex *m_mutex;
+};
+
+/*
+ * This class is designed to aid in implementing event handling in a more round robin fashion. We
+ * cannot change active objects that we do not own, but the active objects that Qt owns will use
+ * this as a base class with convenience functions.
+ *
+ * Here is how it works: On every RunL, the deriving class should call maybeQueueForLater().
+ * This will return whether the active object has been queued, or whether it should run immediately.
+ * Queued objects will run again after other events have been processed.
+ *
+ * The QCompleteDeferredAOs class is a special object that runs after all others, which will
+ * reactivate the objects that were previously not run.
+ */
+QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
+ : CActive(priority),
+ m_dispatcher(dispatcher),
+ m_hasAlreadyRun(false),
+ m_hasRunAgain(false),
+ m_iterationCount(1)
+{
+}
+
+QActiveObject::~QActiveObject()
+{
+ if (m_hasRunAgain)
+ m_dispatcher->removeDeferredActiveObject(this);
+}
+
+bool QActiveObject::maybeQueueForLater()
+{
+ Q_ASSERT(!m_hasRunAgain);
+
+ if (!m_hasAlreadyRun || m_dispatcher->iterationCount() != m_iterationCount) {
+ // First occurrence of this event in this iteration.
+ m_hasAlreadyRun = true;
+ m_iterationCount = m_dispatcher->iterationCount();
+ return false;
+ } else {
+ // The event has already occurred.
+ m_dispatcher->addDeferredActiveObject(this);
+ m_hasRunAgain = true;
+ return true;
+ }
+}
+
+bool QActiveObject::maybeDeferSocketEvent()
+{
+ Q_ASSERT(!m_hasRunAgain);
+ Q_ASSERT(m_dispatcher);
+ if (!m_dispatcher->areSocketEventsBlocked()) {
+ return false;
+ }
+ m_hasRunAgain = true;
+ m_dispatcher->addDeferredSocketActiveObject(this);
+ return true;
+}
+
+void QActiveObject::reactivateAndComplete()
+{
+ TInt error = iStatus.Int();
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, error);
+
+ m_hasRunAgain = false;
+ m_hasAlreadyRun = false;
+}
+
+QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
+ : QActiveObject(WAKE_UP_PRIORITY, dispatcher)
+{
+ m_hostThreadId = RThread().Id();
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QWakeUpActiveObject::~QWakeUpActiveObject()
+{
+ Cancel();
+}
+
+void QWakeUpActiveObject::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ } else if (IsActive() && m_hostThreadId != RThread().Id()) {
+ // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with
+ // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit.
+ // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation
+ // the thread semaphore will be one count down.
+ // It is possible for this problem to affect other active objects. They symptom would be that finished signals
+ // from adopted threads are not sent, or they arrive much later than they should.
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+}
+
+void QWakeUpActiveObject::RunL()
+{
+ if (maybeQueueForLater())
+ return;
+
+ iStatus = KRequestPending;
+ SetActive();
+ QT_TRYCATCH_LEAVING(m_dispatcher->wakeUpWasCalled());
+}
+
+QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
+ : QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
+ m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
+{
+ // start the timeout timer to ensure initialisation
+ m_timeoutTimer.start();
+}
+
+QTimerActiveObject::~QTimerActiveObject()
+{
+ Cancel();
+ m_rTimer.Close(); //close of null handle is safe
+}
+
+void QTimerActiveObject::DoCancel()
+{
+ if (m_timerInfo->interval > 0) {
+ m_rTimer.Cancel();
+ } else {
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+ }
+}
+
+void QTimerActiveObject::RunL()
+{
+ int error = KErrNone;
+ if (iStatus == KErrNone) {
+ QT_TRYCATCH_ERROR(error, Run());
+ } else {
+ error = iStatus.Int();
+ }
+ // All Symbian error codes are negative.
+ if (error < 0) {
+ CActiveScheduler::Current()->Error(error); // stop and report here, as this timer will be deleted on scope exit
+ }
+}
+
+#define MAX_SYMBIAN_TIMEOUT_MS 2000000
+void QTimerActiveObject::StartTimer()
+{
+ if (m_timerInfo->msLeft > MAX_SYMBIAN_TIMEOUT_MS) {
+ //There is loss of accuracy anyway due to needing to restart the timer every 33 minutes,
+ //so the 1/64s res of After() is acceptable for these very long timers.
+ m_rTimer.After(iStatus, MAX_SYMBIAN_TIMEOUT_MS * 1000);
+ m_timerInfo->msLeft -= MAX_SYMBIAN_TIMEOUT_MS;
+ } else {
+ // this algorithm implements drift correction for repeating timers
+ // calculate how late we are for this event
+ int timeSinceLastEvent = m_timeoutTimer.restart();
+ int overshoot = timeSinceLastEvent - m_expectedTimeSinceLastEvent;
+ if (overshoot > m_timerInfo->msLeft) {
+ // we skipped a whole timeout, restart from here
+ overshoot = 0;
+ }
+ // calculate when the next event should happen
+ int waitTime = m_timerInfo->msLeft - overshoot;
+ m_expectedTimeSinceLastEvent = waitTime;
+ // limit the actual ms wait time to avoid wild corrections
+ // this will cause the real event time to slowly drift back to the expected event time
+ // measurements show that Symbian timers always fire 1 or 2 ms late
+ const int limit = 4;
+ waitTime = qMax(m_timerInfo->msLeft - limit, waitTime);
+ m_rTimer.HighRes(iStatus, waitTime * 1000);
+ m_timerInfo->msLeft = 0;
+ }
+ SetActive();
+}
+
+void QTimerActiveObject::Run()
+{
+ //restart timer immediately, if the timeout has been split because it overflows max for platform.
+ if (m_timerInfo->msLeft > 0) {
+ StartTimer();
+ return;
+ }
+
+ if (maybeQueueForLater())
+ return;
+
+ if (m_timerInfo->interval > 0) {
+ // Start a new timer immediately so that we don't lose time.
+ m_timerInfo->msLeft = m_timerInfo->interval;
+ StartTimer();
+
+ m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId);
+ } else {
+ // However, we only complete zero timers after the event has finished,
+ // in order to prevent busy looping when doing nested loops.
+
+ // Keep the refpointer around in order to avoid deletion until the end of this function.
+ SymbianTimerInfoPtr timerInfoPtr(m_timerInfo);
+
+ m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId);
+
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QTimerActiveObject::Start()
+{
+ CActiveScheduler::Add(this);
+ m_timerInfo->msLeft = m_timerInfo->interval;
+ if (m_timerInfo->interval > 0) {
+ if (!m_rTimer.Handle()) {
+ qt_symbian_throwIfError(m_rTimer.CreateLocal());
+ }
+ m_timeoutTimer.start();
+ m_expectedTimeSinceLastEvent = 0;
+ StartTimer();
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+SymbianTimerInfo::SymbianTimerInfo()
+ : timerAO(0)
+{
+}
+
+SymbianTimerInfo::~SymbianTimerInfo()
+{
+ delete timerAO;
+}
+
+QCompleteDeferredAOs::QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher)
+ : CActive(COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY),
+ m_dispatcher(dispatcher)
+{
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QCompleteDeferredAOs::~QCompleteDeferredAOs()
+{
+ Cancel();
+}
+
+void QCompleteDeferredAOs::complete()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QCompleteDeferredAOs::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QCompleteDeferredAOs::RunL()
+{
+ iStatus = KRequestPending;
+ SetActive();
+
+ QT_TRYCATCH_LEAVING(m_dispatcher->reactivateDeferredActiveObjects());
+}
+
+QSelectThread::QSelectThread()
+ : m_quit(false)
+{
+ if (::pipe(m_pipeEnds) != 0) {
+ qWarning("Select thread was unable to open a pipe, errno: %i", errno);
+ } else {
+ int flags0 = qt_pipe_fcntl(m_pipeEnds[0], F_GETFL);
+ int flags1 = qt_pipe_fcntl(m_pipeEnds[1], F_GETFL);
+ // We should check the error code here, but Open C has a bug that returns
+ // failure even though the operation was successful.
+ qt_pipe2_fcntl(m_pipeEnds[0], F_SETFL, flags0 | O_NONBLOCK);
+ qt_pipe2_fcntl(m_pipeEnds[1], F_SETFL, flags1 | O_NONBLOCK);
+ }
+}
+
+QSelectThread::~QSelectThread()
+{
+ qt_pipe_close(m_pipeEnds[1]);
+ qt_pipe_close(m_pipeEnds[0]);
+}
+
+void QSelectThread::run()
+{
+ Q_D(QThread);
+
+ m_mutex.lock();
+
+ while (!m_quit) {
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptionfds;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptionfds);
+
+ int maxfd = 0;
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Read, &readfds));
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Write, &writefds));
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Exception, &exceptionfds));
+ maxfd = qMax(maxfd, m_pipeEnds[0]);
+ maxfd++;
+
+ FD_SET(m_pipeEnds[0], &readfds);
+
+ int ret;
+ int savedSelectErrno;
+ ret = qt_socket_select(maxfd, &readfds, &writefds, &exceptionfds, 0);
+ savedSelectErrno = errno;
+
+ if(ret == 0) {
+ // do nothing
+ } else if (ret < 0) {
+ switch (savedSelectErrno) {
+ case EBADF:
+ case EINVAL:
+ case ENOMEM:
+ case EFAULT:
+ qWarning("::select() returned an error: %i", savedSelectErrno);
+ break;
+ case ECONNREFUSED:
+ case EPIPE:
+ qWarning("::select() returned an error: %i (go through sockets)", savedSelectErrno);
+ // prepare to go through all sockets
+ // mark in fd sets both:
+ // good ones
+ // ones that return -1 in select
+ // after loop update notifiers for all of them
+
+ // as we don't have "exception" notifier type
+ // we should force monitoring fd_set of this
+ // type as well
+
+ // clean @ start
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptionfds);
+ for (QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+
+ fd_set onefds;
+ FD_ZERO(&onefds);
+ FD_SET(i.key()->socket(), &onefds);
+
+ fd_set excfds;
+ FD_ZERO(&excfds);
+ FD_SET(i.key()->socket(), &excfds);
+
+ maxfd = i.key()->socket() + 1;
+
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ ret = 0;
+
+ if(i.key()->type() == QSocketNotifier::Read) {
+ ret = ::select(maxfd, &onefds, 0, &excfds, &timeout);
+ if(ret != 0) FD_SET(i.key()->socket(), &readfds);
+ } else if(i.key()->type() == QSocketNotifier::Write) {
+ ret = ::select(maxfd, 0, &onefds, &excfds, &timeout);
+ if(ret != 0) FD_SET(i.key()->socket(), &writefds);
+ }
+
+ } // end for
+
+ // traversed all, so update
+ updateActivatedNotifiers(QSocketNotifier::Exception, &exceptionfds);
+ updateActivatedNotifiers(QSocketNotifier::Read, &readfds);
+ updateActivatedNotifiers(QSocketNotifier::Write, &writefds);
+
+ break;
+ case EINTR: // Should never occur on Symbian, but this is future proof!
+ default:
+ qWarning("::select() returned an unknown error: %i", savedSelectErrno);
+
+ break;
+ }
+ } else {
+ updateActivatedNotifiers(QSocketNotifier::Exception, &exceptionfds);
+ updateActivatedNotifiers(QSocketNotifier::Read, &readfds);
+ updateActivatedNotifiers(QSocketNotifier::Write, &writefds);
+ }
+
+ if (FD_ISSET(m_pipeEnds[0], &readfds))
+ m_waitCond.wait(&m_mutex);
+ }
+
+ m_mutex.unlock();
+}
+
+void QSelectThread::requestSocketEvents ( QSocketNotifier *notifier, TRequestStatus *status )
+{
+ Q_D(QThread);
+
+ if (!isRunning()) {
+ start();
+ }
+
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ Q_ASSERT(!m_AOStatuses.contains(notifier));
+
+ m_AOStatuses.insert(notifier, status);
+
+ m_waitCond.wakeAll();
+}
+
+void QSelectThread::cancelSocketEvents ( QSocketNotifier *notifier )
+{
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ m_AOStatuses.remove(notifier);
+
+ m_waitCond.wakeAll();
+}
+
+void QSelectThread::restart()
+{
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ m_waitCond.wakeAll();
+}
+
+int QSelectThread::updateSocketSet(QSocketNotifier::Type type, fd_set *fds)
+{
+ int maxfd = 0;
+ if(m_AOStatuses.isEmpty()) {
+ /*
+ * Wonder if should return -1
+ * to signal that no descriptors
+ * added to fds
+ */
+ return maxfd;
+ }
+ for ( QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+ if (i.key()->type() == type) {
+ FD_SET(i.key()->socket(), fds);
+ maxfd = qMax(maxfd, i.key()->socket());
+ } else if(type == QSocketNotifier::Exception) {
+ /*
+ * We are registering existing sockets
+ * always to exception set
+ *
+ * Doing double FD_SET shouldn't
+ * matter
+ */
+ FD_SET(i.key()->socket(), fds);
+ maxfd = qMax(maxfd, i.key()->socket());
+ }
+ }
+
+ return maxfd;
+}
+
+void QSelectThread::updateActivatedNotifiers(QSocketNotifier::Type type, fd_set *fds)
+{
+ Q_D(QThread);
+ if(m_AOStatuses.isEmpty()) {
+ return;
+ }
+ QList<QSocketNotifier *> toRemove;
+ for (QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+ if (i.key()->type() == type && FD_ISSET(i.key()->socket(), fds)) {
+ toRemove.append(i.key());
+ TRequestStatus *status = i.value();
+ // Thread data is still owned by the main thread.
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ } else if(type == QSocketNotifier::Exception && FD_ISSET(i.key()->socket(), fds)) {
+ /*
+ * check if socket is in exception set
+ * then signal RequestComplete for it
+ */
+ qWarning("exception on %d [will close the socket handle - hack]", i.key()->socket());
+ // quick fix; there is a bug
+ // when doing read on socket
+ // errors not preoperly mapped
+ // after offline-ing the device
+ // on some devices we do get exception
+ ::close(i.key()->socket());
+ toRemove.append(i.key());
+ TRequestStatus *status = i.value();
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ }
+ }
+
+ for (int c = 0; c < toRemove.size(); ++c) {
+ m_AOStatuses.remove(toRemove[c]);
+ }
+}
+
+void QSelectThread::stop()
+{
+ m_quit = true;
+ restart();
+ wait();
+}
+
+QSocketActiveObject::QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier)
+ : QActiveObject(CActive::EPriorityStandard, dispatcher),
+ m_notifier(notifier),
+ m_inSocketEvent(false),
+ m_deleteLater(false)
+{
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QSocketActiveObject::~QSocketActiveObject()
+{
+ Cancel();
+}
+
+void QSocketActiveObject::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QSocketActiveObject::RunL()
+{
+ if (maybeDeferSocketEvent())
+ return;
+ if (maybeQueueForLater())
+ return;
+
+ QT_TRYCATCH_LEAVING(run());
+}
+
+void QSocketActiveObject::run()
+{
+ QEvent e(QEvent::SockAct);
+ m_inSocketEvent = true;
+ QCoreApplication::sendEvent(m_notifier, &e);
+ m_inSocketEvent = false;
+
+ if (m_deleteLater) {
+ delete this;
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ m_dispatcher->reactivateSocketNotifier(m_notifier);
+ }
+}
+
+void QSocketActiveObject::deleteLater()
+{
+ if (m_inSocketEvent) {
+ m_deleteLater = true;
+ } else {
+ delete this;
+ }
+}
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+class QIdleDetectorThread
+{
+public:
+ QIdleDetectorThread()
+ : m_state(STATE_RUN), m_stop(false), m_running(false)
+ {
+ start();
+ }
+
+ ~QIdleDetectorThread()
+ {
+ stop();
+ }
+
+ void start()
+ {
+ QMutexLocker lock(&m_mutex);
+ if (m_running)
+ return;
+ m_stop = false;
+ m_state = STATE_RUN;
+ TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this);
+ if (err != KErrNone)
+ return; // Fail silently on error. Next kick will try again. Exception might stop the event being processed
+ m_idleDetectorThread.SetPriority(EPriorityAbsoluteBackgroundNormal);
+ m_idleDetectorThread.Resume();
+ m_running = true;
+ // get a callback from QCoreApplication destruction to stop this thread
+ qAddPostRoutine(StopIdleDetectorThread);
+ }
+
+ void stop()
+ {
+ QMutexLocker lock(&m_mutex);
+ if (!m_running)
+ return;
+ // close down the idle thread because if corelib is loaded temporarily, this would leak threads into the host process
+ m_stop = true;
+ m_kick.release();
+ m_idleDetectorThread.SetPriority(EPriorityNormal);
+ TRequestStatus s;
+ m_idleDetectorThread.Logon(s);
+ User::WaitForRequest(s);
+ m_idleDetectorThread.Close();
+ m_running = false;
+ }
+
+ void kick()
+ {
+ start();
+ m_state = STATE_KICKED;
+ m_kick.release();
+ }
+
+ bool hasRun()
+ {
+ return m_state == STATE_RUN;
+ }
+
+private:
+ static TInt idleDetectorThreadFunc(TAny* self)
+ {
+ User::RenameThread(_L("IdleDetectorThread"));
+ static_cast<QIdleDetectorThread*>(self)->IdleLoop();
+ return KErrNone;
+ }
+
+ void IdleLoop()
+ {
+ while (!m_stop) {
+ m_kick.acquire();
+ m_state = STATE_RUN;
+ }
+ }
+
+ static void StopIdleDetectorThread();
+
+private:
+ enum IdleStates {STATE_KICKED, STATE_RUN} m_state;
+ bool m_stop;
+ bool m_running;
+ RThread m_idleDetectorThread;
+ QSemaphore m_kick;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QIdleDetectorThread, idleDetectorThread);
+
+void QIdleDetectorThread::StopIdleDetectorThread()
+{
+ idleDetectorThread()->stop();
+}
+
+const int maxBusyTime = 2000; // maximum time we allow idle detector to be blocked before worrying, in milliseconds
+const int baseDelay = 1000; // minimum delay time used when backing off to allow idling, in microseconds
+#endif
+
+QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent)
+ : QAbstractEventDispatcher(parent),
+ m_selectThread(0),
+ m_activeScheduler(0),
+ m_wakeUpAO(0),
+ m_completeDeferredAOs(0),
+ m_interrupt(false),
+ m_wakeUpDone(0),
+ m_iterationCount(0),
+ m_insideTimerEvent(false),
+ m_noSocketEvents(false)
+{
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ m_delay = baseDelay;
+ m_avgEventTime = 0;
+ idleDetectorThread();
+#endif
+}
+
+QEventDispatcherSymbian::~QEventDispatcherSymbian()
+{
+}
+
+void QEventDispatcherSymbian::startingUp()
+{
+ if( !CActiveScheduler::Current() ) {
+ m_activeScheduler = q_check_ptr(new CQtActiveScheduler()); // CBase derived class needs to be checked on new
+ CActiveScheduler::Install(m_activeScheduler);
+ }
+ m_wakeUpAO = q_check_ptr(new QWakeUpActiveObject(this));
+ m_completeDeferredAOs = q_check_ptr(new QCompleteDeferredAOs(this));
+ // We already might have posted events, wakeup once to process them
+ wakeUp();
+}
+
+QSelectThread& QEventDispatcherSymbian::selectThread() {
+ if (!m_selectThread)
+ m_selectThread = new QSelectThread;
+ return *m_selectThread;
+}
+
+void QEventDispatcherSymbian::closingDown()
+{
+ if (m_selectThread && m_selectThread->isRunning()) {
+ m_selectThread->stop();
+ }
+ delete m_selectThread;
+ m_selectThread = 0;
+
+ delete m_completeDeferredAOs;
+ delete m_wakeUpAO;
+ if (m_activeScheduler) {
+ delete m_activeScheduler;
+ }
+}
+
+bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags )
+{
+ bool handledAnyEvent = false;
+ bool oldNoSocketEventsValue = m_noSocketEvents;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+
+ m_insideTimerEvent = false;
+
+ QT_TRY {
+ Q_D(QAbstractEventDispatcher);
+
+ // It is safe if this counter overflows. The main importance is that each
+ // iteration count is different from the last.
+ m_iterationCount++;
+
+ RThread &thread = d->threadData->symbian_thread_handle;
+
+ bool block;
+ if (flags & QEventLoop::WaitForMoreEvents) {
+ block = true;
+ emit aboutToBlock();
+ } else {
+ block = false;
+ }
+
+ if (flags & QEventLoop::ExcludeSocketNotifiers) {
+ m_noSocketEvents = true;
+ } else {
+ m_noSocketEvents = false;
+ handledAnyEvent = sendDeferredSocketEvents();
+ }
+
+ bool handledSymbianEvent = false;
+ m_interrupt = false;
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ QElapsedTimer eventTimer;
+#endif
+
+ while (1) {
+ if (block) {
+ // This is where Qt will spend most of its time.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ } else {
+ if (thread.RequestCount() == 0) {
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ if (idleDetectorThread()->hasRun()) {
+ m_lastIdleRequestTimer.start();
+ idleDetectorThread()->kick();
+ } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) {
+ User::AfterHighRes(m_delay);
+ }
+#endif
+ break;
+ }
+ // This one should return without delay.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ }
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ if (idleDetectorThread()->hasRun()) {
+ if (m_delay > baseDelay)
+ m_delay -= baseDelay;
+ m_lastIdleRequestTimer.start();
+ idleDetectorThread()->kick();
+ } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) {
+ User::AfterHighRes(m_delay);
+ // allow delay to be up to 1/4 of execution time
+ if (!idleDetectorThread()->hasRun() && m_delay*3 < m_avgEventTime)
+ m_delay += baseDelay;
+ }
+ eventTimer.start();
+#endif
+
+ TInt error;
+ handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt);
+ if (error) {
+ qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
+ CActiveScheduler::Current()->Error(error);
+ }
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ int eventDur = eventTimer.elapsed()*1000;
+ // average is calcualted as a 5% decaying exponential average
+ m_avgEventTime = (m_avgEventTime * 95 + eventDur * 5) / 100;
+#endif
+
+ if (!handledSymbianEvent) {
+ qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
+ }
+ handledAnyEvent = true;
+ if (m_interrupt) {
+ break;
+ }
+ block = false;
+ };
+
+ emit awake();
+ } QT_CATCH (const std::exception& ex) {
+#ifndef QT_NO_EXCEPTIONS
+ CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex));
+#endif
+ }
+
+ m_noSocketEvents = oldNoSocketEventsValue;
+ m_insideTimerEvent = oldInsideTimerEventValue;
+
+ return handledAnyEvent;
+}
+
+void QEventDispatcherSymbian::timerFired(int timerId)
+{
+ QHash<int, SymbianTimerInfoPtr>::iterator i = m_timerList.find(timerId);
+ if (i == m_timerList.end()) {
+ // The timer has been deleted. Ignore this event.
+ return;
+ }
+
+ SymbianTimerInfoPtr timerInfo = *i;
+
+ // Prevent infinite timer recursion.
+ if (timerInfo->inTimerEvent) {
+ return;
+ }
+
+ timerInfo->inTimerEvent = true;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+ m_insideTimerEvent = true;
+
+ QTimerEvent event(timerInfo->timerId);
+ QCoreApplication::sendEvent(timerInfo->receiver, &event);
+
+ m_insideTimerEvent = oldInsideTimerEventValue;
+ timerInfo->inTimerEvent = false;
+
+ return;
+}
+
+void QEventDispatcherSymbian::wakeUpWasCalled()
+{
+ // The reactivation should happen in RunL, right before the call to this function.
+ // This is because m_wakeUpDone is the "signal" that the object can be completed
+ // once more.
+ // Also, by dispatching the posted events after resetting m_wakeUpDone, we guarantee
+ // that no posted event notification will be lost. If we did it the other way
+ // around, it would be possible for another thread to post an event right after
+ // the sendPostedEvents was done, but before the object was ready to be completed
+ // again. This could deadlock the application if there are no other posted events.
+ m_wakeUpDone.fetchAndStoreOrdered(0);
+ sendPostedEvents();
+}
+
+void QEventDispatcherSymbian::interrupt()
+{
+ m_interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherSymbian::wakeUp()
+{
+ Q_D(QAbstractEventDispatcher);
+
+ if (m_wakeUpAO && m_wakeUpDone.testAndSetAcquire(0, 1)) {
+ TRequestStatus *status = &m_wakeUpAO->iStatus;
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ }
+}
+
+bool QEventDispatcherSymbian::sendPostedEvents()
+{
+ Q_D(QAbstractEventDispatcher);
+
+ // moveToThread calls this and canWait == true -> Events will never get processed
+ // if we check for d->threadData->canWait
+ //
+ // QCoreApplication::postEvent sets canWait = false, but after the object and events
+ // are moved to a new thread, the canWait in new thread is true i.e. not changed to reflect
+ // the flag on old thread. That's why events in a new thread will not get processed.
+ // This migth be actually bug in moveToThread functionality, but because other platforms
+ // do not check canWait in wakeUp (where we essentially are now) - decided to remove it from
+ // here as well.
+
+ //if (!d->threadData->canWait) {
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ return true;
+ //}
+ //return false;
+}
+
+inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *object)
+{
+ queueDeferredActiveObjectsCompletion();
+ m_deferredActiveObjects.append(object);
+}
+
+inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object)
+{
+ m_deferredActiveObjects.removeAll(object);
+ m_deferredSocketEvents.removeAll(object);
+}
+
+inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject *object)
+{
+ m_deferredSocketEvents.append(object);
+}
+
+void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion()
+{
+ m_completeDeferredAOs->complete();
+}
+
+void QEventDispatcherSymbian::reactivateDeferredActiveObjects()
+{
+ while (!m_deferredActiveObjects.isEmpty()) {
+ QActiveObject *object = m_deferredActiveObjects.takeFirst();
+ object->reactivateAndComplete();
+ }
+
+ // We do this because we want to return from processEvents. This is because
+ // each invocation of processEvents should only run each active object once.
+ // The active scheduler should run them continously, however.
+ m_interrupt = true;
+}
+
+bool QEventDispatcherSymbian::sendDeferredSocketEvents()
+{
+ bool sentAnyEvents = false;
+ while (!m_deferredSocketEvents.isEmpty()) {
+ sentAnyEvents = true;
+ QActiveObject *object = m_deferredSocketEvents.takeFirst();
+ object->reactivateAndComplete();
+ }
+
+ return sentAnyEvents;
+}
+
+void QEventDispatcherSymbian::flush()
+{
+}
+
+bool QEventDispatcherSymbian::hasPendingEvents()
+{
+ Q_D(QAbstractEventDispatcher);
+ return (d->threadData->symbian_thread_handle.RequestCount() != 0
+ || !d->threadData->canWait || !m_deferredSocketEvents.isEmpty());
+}
+
+void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier )
+{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
+ QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier);
+ Q_CHECK_PTR(socketAO);
+ m_notifiers.insert(notifier, socketAO);
+ selectThread().requestSocketEvents(notifier, &socketAO->iStatus);
+}
+
+void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier )
+{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
+ if (m_selectThread)
+ m_selectThread->cancelSocketEvents(notifier);
+ if (m_notifiers.contains(notifier)) {
+ QSocketActiveObject *sockObj = *m_notifiers.find(notifier);
+ m_deferredSocketEvents.removeAll(sockObj);
+ sockObj->deleteLater();
+ m_notifiers.remove(notifier);
+ }
+}
+
+void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier)
+{
+ selectThread().requestSocketEvents(notifier, &m_notifiers[notifier]->iStatus);
+}
+
+void QEventDispatcherSymbian::registerTimer ( int timerId, int interval, QObject * object )
+{
+ if (interval < 0) {
+ qWarning("Timer interval < 0");
+ interval = 0;
+ }
+
+ SymbianTimerInfoPtr timer(new SymbianTimerInfo);
+ timer->timerId = timerId;
+ timer->interval = interval;
+ timer->inTimerEvent = false;
+ timer->receiver = object;
+ timer->dispatcher = this;
+ timer->timerAO = q_check_ptr(new QTimerActiveObject(this, timer.data()));
+ m_timerList.insert(timerId, timer);
+
+ timer->timerAO->Start();
+
+ if (m_insideTimerEvent)
+ // If we are inside a timer event, we need to prevent event starvation
+ // by preventing newly created timers from running in the same event processing
+ // iteration. Do this by calling the maybeQueueForLater() function to "fake" that we have
+ // already run once. This will cause the next run to be added to the deferred
+ // queue instead.
+ timer->timerAO->maybeQueueForLater();
+}
+
+bool QEventDispatcherSymbian::unregisterTimer ( int timerId )
+{
+ if (!m_timerList.contains(timerId)) {
+ return false;
+ }
+
+ SymbianTimerInfoPtr timerInfo = m_timerList.take(timerId);
+
+ if (!QObjectPrivate::get(timerInfo->receiver)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
+
+ return true;
+}
+
+bool QEventDispatcherSymbian::unregisterTimers ( QObject * object )
+{
+ if (m_timerList.isEmpty())
+ return false;
+
+ bool unregistered = false;
+ for (QHash<int, SymbianTimerInfoPtr>::iterator i = m_timerList.begin(); i != m_timerList.end(); ) {
+ if ((*i)->receiver == object) {
+ i = m_timerList.erase(i);
+ unregistered = true;
+ } else {
+ ++i;
+ }
+ }
+
+ return unregistered;
+}
+
+QList<QEventDispatcherSymbian::TimerInfo> QEventDispatcherSymbian::registeredTimers ( QObject * object ) const
+{
+ QList<TimerInfo> list;
+ for (QHash<int, SymbianTimerInfoPtr>::const_iterator i = m_timerList.begin(); i != m_timerList.end(); ++i) {
+ if ((*i)->receiver == object) {
+ list.push_back(TimerInfo((*i)->timerId, (*i)->interval));
+ }
+ }
+
+ return list;
+}
+
+/*
+ * This active scheduler class implements a simple report and continue policy, for Symbian OS leaves
+ * or exceptions from Qt that fall back to the scheduler.
+ * It will be used in cases where there is no existing active scheduler installed.
+ * Apps which link to qts60main.lib will have the UI active scheduler installed in the main thread
+ * instead of this one. But this would be used in other threads in the UI.
+ * An app could replace this behaviour by installing an alternative active scheduler.
+ */
+void CQtActiveScheduler::Error(TInt aError) const
+{
+ QT_TRY {
+ qWarning("Error from active scheduler %d", aError);
+ }
+ QT_CATCH (const std::bad_alloc&) {} // ignore alloc fails, nothing more can be done
+}
+
+bool QActiveObject::wait(CActive* ao, int ms)
+{
+ if (!ao->IsActive())
+ return true; //request already complete
+ bool timedout = false;
+ if (ms > 0) {
+ TRequestStatus tstat;
+ RTimer t;
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ User::WaitForRequest(tstat, ao->iStatus);
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ } else {
+ User::WaitForRequest(ao->iStatus);
+ }
+ if (timedout)
+ return false;
+
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+
+ return true;
+}
+
+bool QActiveObject::wait(QList<CActive*> aos, int ms)
+{
+ QVector<TRequestStatus*> stati;
+ stati.reserve(aos.count() + 1);
+ foreach (CActive* ao, aos) {
+ if (!ao->IsActive())
+ return true; //request already complete
+ stati.append(&(ao->iStatus));
+ }
+ bool timedout = false;
+ TRequestStatus tstat;
+ RTimer t;
+ if (ms > 0) {
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ stati.append(&tstat);
+ }
+ User::WaitForNRequest(stati.data(), stati.count());
+ if (ms > 0) {
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ }
+ if (timedout)
+ return false;
+
+ foreach (CActive* ao, aos) {
+ if (ao->iStatus != KRequestPending) {
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+ break; //only call one
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qeventdispatcher_symbian_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
new file mode 100644
index 0000000000..6fdd4b248d
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -0,0 +1,327 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_SYMBIAN_P_H
+#define QEVENTDISPATCHER_SYMBIAN_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 <qhash.h>
+#include <qset.h>
+#include <qshareddata.h>
+#include <qabstracteventdispatcher.h>
+#include <private/qabstracteventdispatcher_p.h>
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <qsocketnotifier.h>
+#include <qdatetime.h>
+#include <qelapsedtimer.h>
+
+#include <e32base.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QEventDispatcherSymbian;
+class QTimerActiveObject;
+
+class Q_CORE_EXPORT QActiveObject : public CActive
+{
+public:
+ QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher);
+ ~QActiveObject();
+
+ bool maybeQueueForLater();
+ bool maybeDeferSocketEvent();
+
+ void reactivateAndComplete();
+
+ static bool wait(CActive* ao, int ms);
+ static bool wait(QList<CActive*> aos, int ms);
+protected:
+ QEventDispatcherSymbian *m_dispatcher;
+
+private:
+ bool m_hasAlreadyRun : 1;
+ bool m_hasRunAgain : 1;
+ int m_iterationCount;
+};
+
+class QWakeUpActiveObject : public QActiveObject
+{
+public:
+ QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher);
+ ~QWakeUpActiveObject();
+
+ void Complete();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ TThreadId m_hostThreadId;
+};
+
+struct SymbianTimerInfo : public QSharedData
+{
+ SymbianTimerInfo();
+ ~SymbianTimerInfo();
+
+ int timerId;
+ int interval;
+ int msLeft;
+ bool inTimerEvent;
+ QObject *receiver;
+ QTimerActiveObject *timerAO;
+ QEventDispatcherSymbian *dispatcher;
+};
+
+typedef QExplicitlySharedDataPointer<SymbianTimerInfo> SymbianTimerInfoPtr;
+
+// This is a bit of a proxy class. See comments in SetActive and Start for details.
+class QTimerActiveObject : public QActiveObject
+{
+public:
+ QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo);
+ ~QTimerActiveObject();
+
+ void Start();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ void Run();
+ void StartTimer();
+
+private:
+ SymbianTimerInfo *m_timerInfo;
+ QElapsedTimer m_timeoutTimer;
+ int m_expectedTimeSinceLastEvent;
+ RTimer m_rTimer;
+};
+
+class QCompleteDeferredAOs : public CActive
+{
+public:
+ QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher);
+ ~QCompleteDeferredAOs();
+
+ void complete();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ QEventDispatcherSymbian *m_dispatcher;
+};
+
+class QSocketActiveObject : public QActiveObject
+{
+public:
+ QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier);
+ ~QSocketActiveObject();
+
+ void deleteLater();
+
+protected:
+ void DoCancel();
+ void RunL();
+ void run();
+
+private:
+ QSocketNotifier *m_notifier;
+ bool m_inSocketEvent;
+ bool m_deleteLater;
+
+ friend class QEventDispatcherSymbian;
+};
+
+class QSelectThread : public QThread
+{
+ Q_DECLARE_PRIVATE(QThread)
+
+public:
+ QSelectThread();
+ ~QSelectThread();
+
+ void requestSocketEvents ( QSocketNotifier *notifier, TRequestStatus *status );
+ void cancelSocketEvents ( QSocketNotifier *notifier );
+ void restart();
+ void stop();
+
+protected:
+ void run();
+
+private:
+ int updateSocketSet(QSocketNotifier::Type type, fd_set *fds);
+ void updateActivatedNotifiers(QSocketNotifier::Type type, fd_set *fds);
+
+private:
+ int m_pipeEnds[2];
+ QHash<QSocketNotifier *, TRequestStatus *> m_AOStatuses;
+ QMutex m_mutex;
+ QWaitCondition m_waitCond;
+ bool m_quit;
+};
+
+class Q_CORE_EXPORT CQtActiveScheduler : public CActiveScheduler
+{
+public: // from CActiveScheduler
+ virtual void Error(TInt aError) const;
+};
+
+class Q_CORE_EXPORT QEventDispatcherSymbian : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractEventDispatcher)
+
+public:
+ QEventDispatcherSymbian(QObject *parent = 0);
+ ~QEventDispatcherSymbian();
+
+ void flush();
+ bool hasPendingEvents();
+ void interrupt();
+ bool processEvents ( QEventLoop::ProcessEventsFlags flags );
+ void registerSocketNotifier ( QSocketNotifier * notifier );
+ void registerTimer ( int timerId, int interval, QObject * object );
+ QList<TimerInfo> registeredTimers ( QObject * object ) const;
+ void unregisterSocketNotifier ( QSocketNotifier * notifier );
+ bool unregisterTimer ( int timerId );
+ bool unregisterTimers ( QObject * object );
+ void wakeUp();
+
+ void startingUp();
+ void closingDown();
+
+ void timerFired(int timerId);
+ void wakeUpWasCalled();
+ void reactivateSocketNotifier(QSocketNotifier *notifier);
+
+ void addDeferredActiveObject(QActiveObject *object);
+ void removeDeferredActiveObject(QActiveObject *object);
+ void queueDeferredActiveObjectsCompletion();
+ // Can be overridden to activate local active objects too, but do call baseclass!
+ virtual void reactivateDeferredActiveObjects();
+
+ inline int iterationCount() const { return m_iterationCount; }
+
+ void addDeferredSocketActiveObject(QActiveObject *object);
+ inline bool areSocketEventsBlocked() const { return m_noSocketEvents; }
+
+ static void RequestComplete(TRequestStatus *&status, TInt reason);
+ static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason);
+
+private:
+ bool sendPostedEvents();
+ bool sendDeferredSocketEvents();
+
+ QSelectThread& selectThread();
+private:
+ QSelectThread *m_selectThread;
+
+ CQtActiveScheduler *m_activeScheduler;
+
+ QHash<int, SymbianTimerInfoPtr> m_timerList;
+ QHash<QSocketNotifier *, QSocketActiveObject *> m_notifiers;
+
+ QWakeUpActiveObject *m_wakeUpAO;
+ QCompleteDeferredAOs *m_completeDeferredAOs;
+
+ volatile bool m_interrupt;
+ QAtomicInt m_wakeUpDone;
+
+ unsigned char m_iterationCount;
+ bool m_insideTimerEvent;
+ bool m_noSocketEvents;
+ //deferred until socket events are enabled
+ QList<QActiveObject *> m_deferredSocketEvents;
+ //deferred until idle
+ QList<QActiveObject *> m_deferredActiveObjects;
+
+ int m_delay;
+ int m_avgEventTime;
+ QElapsedTimer m_lastIdleRequestTimer;
+};
+
+#ifdef QT_DEBUG
+# define VERIFY_PENDING_REQUEST_STATUS \
+ Q_ASSERT(status->Int() == KRequestPending);
+#else
+# define VERIFY_PENDING_REQUEST_STATUS
+#endif
+
+// Convenience functions for doing some sanity checking on our own complete code.
+// Unless QT_DEBUG is defined, it is exactly equivalent to the Symbian version.
+inline void QEventDispatcherSymbian::RequestComplete(TRequestStatus *&status, TInt reason)
+{
+ VERIFY_PENDING_REQUEST_STATUS
+ User::RequestComplete(status, reason);
+}
+inline void QEventDispatcherSymbian::RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason)
+{
+ VERIFY_PENDING_REQUEST_STATUS
+ threadHandle.RequestComplete(status, reason);
+}
+
+#undef VERIFY_PENDING_REQUEST_STATUS
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_SYMBIAN_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
new file mode 100644
index 0000000000..dceb51d181
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -0,0 +1,979 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qcoreapplication.h"
+#include "qpair.h"
+#include "qsocketnotifier.h"
+#include "qthread.h"
+#include "qelapsedtimer.h"
+
+#include "qeventdispatcher_unix_p.h"
+#include <private/qthread_p.h>
+#include <private/qcoreapplication_p.h>
+#include <private/qcore_unix_p.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// 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 <selectLib.h>
+#endif
+
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
+# include <sys/times.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
+
+/*****************************************************************************
+ UNIX signal handling
+ *****************************************************************************/
+
+static sig_atomic_t signal_received;
+static sig_atomic_t signals_fired[NSIG];
+
+static void signalHandler(int sig)
+{
+ signals_fired[sig] = 1;
+ signal_received = 1;
+}
+
+
+#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS)
+static void initThreadPipeFD(int fd)
+{
+ int ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to init thread pipe");
+
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");
+
+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");
+}
+#endif
+
+QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
+{
+ extern Qt::HANDLE qt_application_thread_id;
+ mainThread = (QThread::currentThreadId() == qt_application_thread_id);
+ bool pipefail = false;
+
+ // initialize the common parts of the event loop
+#if defined(Q_OS_NACL)
+ // do nothing.
+#elif defined(Q_OS_INTEGRITY)
+ // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead
+ if (socketpair(AF_INET, SOCK_STREAM, 0, thread_pipe) == -1) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair");
+ pipefail = true;
+ } else {
+ initThreadPipeFD(thread_pipe[0]);
+ initThreadPipeFD(thread_pipe[1]);
+ }
+#elif defined(Q_OS_VXWORKS)
+ char name[20];
+ qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent));
+
+ // make sure there is no pipe with this name
+ pipeDevDelete(name, true);
+ // create the pipe
+ if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device");
+ pipefail = true;
+ } else {
+ if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
+ pipefail = true;
+ } else {
+ initThreadPipeFD(thread_pipe[0]);
+ thread_pipe[1] = thread_pipe[0];
+ }
+ }
+#else
+ if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
+ pipefail = true;
+ }
+#endif
+
+ if (pipefail)
+ qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
+
+ sn_highest = -1;
+
+ interrupt = false;
+}
+
+QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
+{
+#if defined(Q_OS_NACL)
+ // do nothing.
+#elif defined(Q_OS_VXWORKS)
+ close(thread_pipe[0]);
+
+ char name[20];
+ qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent));
+
+ pipeDevDelete(name, true);
+#else
+ // cleanup the common parts of the event loop
+ close(thread_pipe[0]);
+ close(thread_pipe[1]);
+#endif
+
+ // cleanup timers
+ qDeleteAll(timerList);
+}
+
+int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout)
+{
+ Q_Q(QEventDispatcherUNIX);
+
+ // needed in QEventDispatcherUNIX::select()
+ timerList.updateCurrentTime();
+
+ int nsel;
+ do {
+ if (mainThread) {
+ while (signal_received) {
+ signal_received = 0;
+ for (int i = 0; i < NSIG; ++i) {
+ if (signals_fired[i]) {
+ signals_fired[i] = 0;
+ emit QCoreApplication::instance()->unixSignal(i);
+ }
+ }
+ }
+ }
+
+ // Process timers and socket notifiers - the common UNIX stuff
+ int highest = 0;
+ if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {
+ // return the highest fd we can wait for input on
+ sn_vec[0].select_fds = sn_vec[0].enabled_fds;
+ sn_vec[1].select_fds = sn_vec[1].enabled_fds;
+ sn_vec[2].select_fds = sn_vec[2].enabled_fds;
+ highest = sn_highest;
+ } else {
+ FD_ZERO(&sn_vec[0].select_fds);
+ FD_ZERO(&sn_vec[1].select_fds);
+ FD_ZERO(&sn_vec[2].select_fds);
+ }
+
+ FD_SET(thread_pipe[0], &sn_vec[0].select_fds);
+ highest = qMax(highest, thread_pipe[0]);
+
+ nsel = q->select(highest + 1,
+ &sn_vec[0].select_fds,
+ &sn_vec[1].select_fds,
+ &sn_vec[2].select_fds,
+ timeout);
+ } while (nsel == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (nsel == -1) {
+ if (errno == EBADF) {
+ // it seems a socket notifier has a bad fd... find out
+ // which one it is and disable it
+ fd_set fdset;
+ timeval tm;
+ tm.tv_sec = tm.tv_usec = 0l;
+
+ for (int type = 0; type < 3; ++type) {
+ QSockNotType::List &list = sn_vec[type].list;
+ if (list.size() == 0)
+ continue;
+
+ for (int i = 0; i < list.size(); ++i) {
+ QSockNot *sn = list[i];
+
+ FD_ZERO(&fdset);
+ FD_SET(sn->fd, &fdset);
+
+ int ret = -1;
+ do {
+ switch (type) {
+ case 0: // read
+ ret = select(sn->fd + 1, &fdset, 0, 0, &tm);
+ break;
+ case 1: // write
+ ret = select(sn->fd + 1, 0, &fdset, 0, &tm);
+ break;
+ case 2: // except
+ ret = select(sn->fd + 1, 0, 0, &fdset, &tm);
+ break;
+ }
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (ret == -1 && errno == EBADF) {
+ // disable the invalid socket notifier
+ static const char *t[] = { "Read", "Write", "Exception" };
+ qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
+ sn->fd, t[type]);
+ sn->obj->setEnabled(false);
+ }
+ }
+ }
+ } else {
+ // EINVAL... shouldn't happen, so let's complain to stderr
+ // and hope someone sends us a bug report
+ perror("select");
+ }
+ }
+
+ // some other thread woke us up... consume the data on the thread pipe so that
+ // select doesn't immediately return next time
+ int nevents = 0;
+ if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) {
+#if defined(Q_OS_VXWORKS)
+ char c[16];
+ ::read(thread_pipe[0], c, sizeof(c));
+ ::ioctl(thread_pipe[0], FIOFLUSH, 0);
+#else
+ char c[16];
+ while (::read(thread_pipe[0], c, sizeof(c)) > 0)
+ ;
+#endif
+ if (!wakeUps.testAndSetRelease(1, 0)) {
+ // hopefully, this is dead code
+ qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
+ }
+ ++nevents;
+ }
+
+ // activate socket notifiers
+ if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) {
+ // if select says data is ready on any socket, then set the socket notifier
+ // to pending
+ for (int i=0; i<3; i++) {
+ QSockNotType::List &list = sn_vec[i].list;
+ for (int j = 0; j < list.size(); ++j) {
+ QSockNot *sn = list[j];
+ if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))
+ q->setSocketNotifierPending(sn->obj);
+ }
+ }
+ }
+ return (nevents + q->activateSocketNotifiers());
+}
+
+/*
+ * Internal functions for manipulating timer data structures. The
+ * 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_usec = 0;
+ previousTicks = 0;
+ ticksPerSecond = 0;
+ msPerTick = 0;
+ }
+#endif
+
+ firstTimerInfo = 0;
+}
+
+timeval QTimerInfoList::updateCurrentTime()
+{
+ return (currentTime = qt_gettime());
+}
+
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
+
+template <>
+timeval qAbs(const timeval &t)
+{
+ timeval tmp = t;
+ if (tmp.tv_sec < 0) {
+ tmp.tv_sec = -tmp.tv_sec - 1;
+ tmp.tv_usec -= 1000000;
+ }
+ if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
+ tmp.tv_usec = -tmp.tv_usec;
+ }
+ return normalizedTimeval(tmp);
+}
+
+/*
+ Returns 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(timeval *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;
+ timeval elapsedTime = currentTime - previousTime;
+
+ timeval elapsedTimeTicks;
+ elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
+ elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
+
+ timeval 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.
+ timeval tickGranularity;
+ tickGranularity.tv_sec = 0;
+ tickGranularity.tv_usec = msPerTick * 1000;
+ return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10);
+}
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+ if (QElapsedTimer::isMonotonic())
+ return;
+ timeval delta;
+ if (timeChanged(&delta))
+ timerRepair(delta);
+}
+
+#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+}
+
+#endif
+
+/*
+ insert timer info into list
+*/
+void QTimerInfoList::timerInsert(QTimerInfo *ti)
+{
+ int index = size();
+ while (index--) {
+ register const QTimerInfo * const t = at(index);
+ if (!(ti->timeout < t->timeout))
+ break;
+ }
+ insert(index+1, ti);
+}
+
+/*
+ repair broken timer
+*/
+void QTimerInfoList::timerRepair(const timeval &diff)
+{
+ // repair all timers
+ for (int i = 0; i < size(); ++i) {
+ register QTimerInfo *t = at(i);
+ t->timeout = t->timeout + diff;
+ }
+}
+
+/*
+ Returns the time to wait for the next timer, or null if no timers
+ are waiting.
+*/
+bool QTimerInfoList::timerWait(timeval &tm)
+{
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+ // Find first waiting timer not already active
+ QTimerInfo *t = 0;
+ 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 = t->timeout - currentTime;
+ } else {
+ // no time to wait
+ tm.tv_sec = 0;
+ tm.tv_usec = 0;
+ }
+
+ return true;
+}
+
+void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object)
+{
+ QTimerInfo *t = new QTimerInfo;
+ t->id = timerId;
+ t->interval.tv_sec = interval / 1000;
+ t->interval.tv_usec = (interval % 1000) * 1000;
+ t->timeout = updateCurrentTime() + t->interval;
+ t->obj = object;
+ t->activateRef = 0;
+
+ timerInsert(t);
+}
+
+bool QTimerInfoList::unregisterTimer(int timerId)
+{
+ // set timer inactive
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->id == timerId) {
+ // found it
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
+
+ delete t;
+ return true;
+ }
+ }
+ // id not found
+ return false;
+}
+
+bool QTimerInfoList::unregisterTimers(QObject *object)
+{
+ if (isEmpty())
+ return false;
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->obj == object) {
+ // object found
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(t->id);
+
+ delete t;
+ // move back one so that we don't skip the new current item
+ --i;
+ }
+ }
+ return true;
+}
+
+QList<QPair<int, int> > QTimerInfoList::registeredTimers(QObject *object) const
+{
+ QList<QPair<int, int> > list;
+ for (int i = 0; i < count(); ++i) {
+ register const QTimerInfo * const t = at(i);
+ if (t->obj == object)
+ list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000);
+ }
+ return list;
+}
+
+/*
+ Activate pending timers, returning how many where activated.
+*/
+int QTimerInfoList::activateTimers()
+{
+ if (qt_disable_lowpriority_timers || isEmpty())
+ return 0; // nothing to do
+
+ int n_act = 0, maxCount = 0;
+ firstTimerInfo = 0;
+
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+
+ // Find out how many timer have expired
+ for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
+ if (currentTime < (*it)->timeout)
+ break;
+ maxCount++;
+ }
+
+ //fire the timers.
+ while (maxCount--) {
+ if (isEmpty())
+ break;
+
+ QTimerInfo *currentTimerInfo = first();
+ if (currentTime < currentTimerInfo->timeout)
+ break; // no timer has expired
+
+ if (!firstTimerInfo) {
+ firstTimerInfo = currentTimerInfo;
+ } else if (firstTimerInfo == currentTimerInfo) {
+ // avoid sending the same timer multiple times
+ break;
+ } else if (currentTimerInfo->interval < firstTimerInfo->interval
+ || currentTimerInfo->interval == firstTimerInfo->interval) {
+ firstTimerInfo = currentTimerInfo;
+ }
+
+ // remove from list
+ removeFirst();
+
+ // determine next timeout time
+ currentTimerInfo->timeout += currentTimerInfo->interval;
+ if (currentTimerInfo->timeout < currentTime)
+ currentTimerInfo->timeout = currentTime + currentTimerInfo->interval;
+
+ // reinsert timer
+ timerInsert(currentTimerInfo);
+ if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0)
+ n_act++;
+
+ if (!currentTimerInfo->activateRef) {
+ // send event, but don't allow it to recurse
+ currentTimerInfo->activateRef = &currentTimerInfo;
+
+ QTimerEvent e(currentTimerInfo->id);
+ QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
+
+ if (currentTimerInfo)
+ currentTimerInfo->activateRef = 0;
+ }
+ }
+
+ firstTimerInfo = 0;
+ return n_act;
+}
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
+{ }
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{ }
+
+QEventDispatcherUNIX::~QEventDispatcherUNIX()
+{
+ Q_D(QEventDispatcherUNIX);
+ d->threadData->eventDispatcher = 0;
+}
+
+int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+/*!
+ \internal
+*/
+void QEventDispatcherUNIX::registerTimer(int timerId, int interval, QObject *obj)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !obj) {
+ qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments");
+ return;
+ } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ d->timerList.registerTimer(timerId, interval, obj);
+}
+
+/*!
+ \internal
+*/
+bool QEventDispatcherUNIX::unregisterTimer(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.unregisterTimer(timerId);
+}
+
+/*!
+ \internal
+*/
+bool QEventDispatcherUNIX::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.unregisterTimers(object);
+}
+
+QList<QEventDispatcherUNIX::TimerInfo>
+QEventDispatcherUNIX::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherUNIX);
+ return d->timerList.registeredTimers(object);
+}
+
+/*****************************************************************************
+ Socket notifier type
+ *****************************************************************************/
+QSockNotType::QSockNotType()
+{
+ FD_ZERO(&select_fds);
+ FD_ZERO(&enabled_fds);
+ FD_ZERO(&pending_fds);
+}
+
+QSockNotType::~QSockNotType()
+{
+ for (int i = 0; i < list.size(); ++i)
+ delete list[i];
+}
+
+/*****************************************************************************
+ QEventDispatcher implementations for UNIX
+ *****************************************************************************/
+
+void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ fd_set *fds = &d->sn_vec[type].enabled_fds;
+ QSockNot *sn;
+
+ sn = new QSockNot;
+ sn->obj = notifier;
+ sn->fd = sockfd;
+ sn->queue = &d->sn_vec[type].pending_fds;
+
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ QSockNot *p = list[i];
+ if (p->fd < sockfd)
+ break;
+ if (p->fd == sockfd) {
+ static const char *t[] = { "Read", "Write", "Exception" };
+ qWarning("QSocketNotifier: Multiple socket notifiers for "
+ "same socket %d and type %s", sockfd, t[type]);
+ }
+ }
+ list.insert(i, sn);
+
+ FD_SET(sockfd, fds);
+ d->sn_highest = qMax(d->sn_highest, sockfd);
+}
+
+void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ fd_set *fds = &d->sn_vec[type].enabled_fds;
+ QSockNot *sn = 0;
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ sn = list[i];
+ if(sn->obj == notifier && sn->fd == sockfd)
+ break;
+ }
+ if (i == list.size()) // not found
+ return;
+
+ FD_CLR(sockfd, fds); // clear fd bit
+ FD_CLR(sockfd, sn->queue);
+ d->sn_pending_list.removeAll(sn); // remove from activation list
+ list.removeAt(i); // remove notifier found above
+ delete sn;
+
+ if (d->sn_highest == sockfd) { // find highest fd
+ d->sn_highest = -1;
+ for (int i=0; i<3; i++) {
+ if (!d->sn_vec[i].list.isEmpty())
+ d->sn_highest = qMax(d->sn_highest, // list is fd-sorted
+ d->sn_vec[i].list[0]->fd);
+ }
+ }
+}
+
+void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ }
+ Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread());
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ QSockNot *sn = 0;
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ sn = list[i];
+ if(sn->obj == notifier && sn->fd == sockfd)
+ break;
+ }
+ if (i == list.size()) // not found
+ return;
+
+ // We choose a random activation order to be more fair under high load.
+ // If a constant order is used and a peer early in the list can
+ // saturate the IO, it might grab our attention completely.
+ // Also, if we're using a straight list, the callback routines may
+ // delete other entries from the list before those other entries are
+ // processed.
+ if (! FD_ISSET(sn->fd, sn->queue)) {
+ if (d->sn_pending_list.isEmpty()) {
+ d->sn_pending_list.append(sn);
+ } else {
+ d->sn_pending_list.insert((qrand() & 0xff) %
+ (d->sn_pending_list.size()+1), sn);
+ }
+ FD_SET(sn->fd, sn->queue);
+ }
+}
+
+int QEventDispatcherUNIX::activateTimers()
+{
+ Q_ASSERT(thread() == QThread::currentThread());
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.activateTimers();
+}
+
+int QEventDispatcherUNIX::activateSocketNotifiers()
+{
+ Q_D(QEventDispatcherUNIX);
+ if (d->sn_pending_list.isEmpty())
+ return 0;
+
+ // activate entries
+ int n_act = 0;
+ QEvent event(QEvent::SockAct);
+ while (!d->sn_pending_list.isEmpty()) {
+ QSockNot *sn = d->sn_pending_list.takeFirst();
+ if (FD_ISSET(sn->fd, sn->queue)) {
+ FD_CLR(sn->fd, sn->queue);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ ++n_act;
+ }
+ }
+ return n_act;
+}
+
+bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherUNIX);
+ d->interrupt = false;
+
+ // we are awake, broadcast it
+ emit awake();
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+
+ int nevents = 0;
+ const bool canWait = (d->threadData->canWait
+ && !d->interrupt
+ && (flags & QEventLoop::WaitForMoreEvents));
+
+ if (canWait)
+ emit aboutToBlock();
+
+ if (!d->interrupt) {
+ // return the maximum time we can wait for an event.
+ timeval *tm = 0;
+ timeval wait_tm = { 0l, 0l };
+ if (!(flags & QEventLoop::X11ExcludeTimers)) {
+ if (d->timerList.timerWait(wait_tm))
+ tm = &wait_tm;
+ }
+
+ if (!canWait) {
+ if (!tm)
+ tm = &wait_tm;
+
+ // no time to wait
+ tm->tv_sec = 0l;
+ tm->tv_usec = 0l;
+ }
+
+ nevents = d->doSelect(flags, tm);
+
+ // activate timers
+ if (! (flags & QEventLoop::X11ExcludeTimers)) {
+ nevents += activateTimers();
+ }
+ }
+ // return true if we handled events, false otherwise
+ return (nevents > 0);
+}
+
+bool QEventDispatcherUNIX::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return qGlobalPostedEventsCount();
+}
+
+void QEventDispatcherUNIX::wakeUp()
+{
+ Q_D(QEventDispatcherUNIX);
+ if (d->wakeUps.testAndSetAcquire(0, 1)) {
+ char c = 0;
+ qt_safe_write( d->thread_pipe[1], &c, 1 );
+ }
+}
+
+void QEventDispatcherUNIX::interrupt()
+{
+ Q_D(QEventDispatcherUNIX);
+ d->interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherUNIX::flush()
+{ }
+
+
+
+
+void QCoreApplication::watchUnixSignal(int sig, bool watch)
+{
+ if (sig < NSIG) {
+ struct sigaction sa;
+ sigemptyset(&(sa.sa_mask));
+ sa.sa_flags = 0;
+ if (watch)
+ sa.sa_handler = signalHandler;
+ else
+ sa.sa_handler = SIG_DFL;
+ sigaction(sig, &sa, 0);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
new file mode 100644
index 0000000000..96a3e4a276
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_UNIX_P_H
+#define QEVENTDISPATCHER_UNIX_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/qabstracteventdispatcher.h"
+#include "QtCore/qlist.h"
+#include "private/qabstracteventdispatcher_p.h"
+#include "private/qcore_unix_p.h"
+#include "private/qpodlist_p.h"
+#include "QtCore/qvarlengtharray.h"
+
+#if defined(Q_OS_VXWORKS)
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+# if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL)
+# include <sys/select.h>
+# endif
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// internal timer info
+struct QTimerInfo {
+ int id; // - timer identifier
+ timeval interval; // - timer interval
+ timeval timeout; // - when to sent event
+ QObject *obj; // - object to receive event
+ QTimerInfo **activateRef; // - ref from activateTimers
+};
+
+class QTimerInfoList : public QList<QTimerInfo*>
+{
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
+ timeval previousTime;
+ clock_t previousTicks;
+ int ticksPerSecond;
+ int msPerTick;
+
+ bool timeChanged(timeval *delta);
+#endif
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo;
+
+public:
+ QTimerInfoList();
+
+ timeval currentTime;
+ timeval updateCurrentTime();
+
+ // must call updateCurrentTime() first!
+ void repairTimersIfNeeded();
+
+ bool timerWait(timeval &);
+ void timerInsert(QTimerInfo *);
+ void timerRepair(const timeval &);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<QPair<int, int> > registeredTimers(QObject *object) const;
+
+ int activateTimers();
+};
+
+struct QSockNot
+{
+ QSocketNotifier *obj;
+ int fd;
+ fd_set *queue;
+};
+
+class QSockNotType
+{
+public:
+ QSockNotType();
+ ~QSockNotType();
+
+ typedef QPodList<QSockNot*, 32> List;
+
+ List list;
+ fd_set select_fds;
+ fd_set enabled_fds;
+ fd_set pending_fds;
+
+};
+
+class QEventDispatcherUNIXPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherUNIX)
+
+public:
+ explicit QEventDispatcherUNIX(QObject *parent = 0);
+ ~QEventDispatcherUNIX();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+protected:
+ QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0);
+
+ void setSocketNotifierPending(QSocketNotifier *notifier);
+
+ int activateTimers();
+ int activateSocketNotifiers();
+
+ virtual int select(int nfds,
+ fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherUNIX)
+
+public:
+ QEventDispatcherUNIXPrivate();
+ ~QEventDispatcherUNIXPrivate();
+
+ int doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout);
+
+ bool mainThread;
+ int thread_pipe[2];
+
+ // highest fd for all socket notifiers
+ int sn_highest;
+ // 3 socket notifier types - read, write and exception
+ QSockNotType sn_vec[3];
+
+ QTimerInfoList timerList;
+
+ // pending socket notifiers list
+ QSockNotType::List sn_pending_list;
+
+ QAtomicInt wakeUps;
+ bool interrupt;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_UNIX_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
new file mode 100644
index 0000000000..6badb6a2f8
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -0,0 +1,1158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_win_p.h"
+
+#include "qcoreapplication.h"
+#include "qhash.h"
+#include <private/qsystemlibrary_p.h>
+#include "qpair.h"
+#include "qset.h"
+#include "qsocketnotifier.h"
+#include "qvarlengtharray.h"
+#include "qwineventnotifier_p.h"
+
+#include "qabstracteventdispatcher_p.h"
+#include "qcoreapplication_p.h"
+#include <private/qthread_p.h>
+#include <private/qmutexpool_p.h>
+
+QT_BEGIN_NAMESPACE
+
+HINSTANCE qWinAppInst();
+extern uint qGlobalPostedEventsCount();
+
+#ifndef TIME_KILL_SYNCHRONOUS
+# define TIME_KILL_SYNCHRONOUS 0x0100
+#endif
+
+#ifndef QS_RAWINPUT
+# ifdef Q_OS_WINCE
+# define QS_RAWINPUT 0x0000
+# else
+# define QS_RAWINPUT 0x0400
+# endif
+#endif
+
+#ifndef WM_TOUCH
+# define WM_TOUCH 0x0240
+#endif
+#ifndef QT_NO_GESTURES
+#ifndef WM_GESTURE
+# define WM_GESTURE 0x0119
+#endif
+#ifndef WM_GESTURENOTIFY
+# define WM_GESTURENOTIFY 0x011A
+#endif
+#endif // QT_NO_GESTURES
+
+enum {
+ WM_QT_SOCKETNOTIFIER = WM_USER,
+ WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
+ SendPostedEventsWindowsTimerId = ~1u
+};
+
+#if defined(Q_OS_WINCE)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <winsock.h>
+// Asynchronous Winsocks ------------------------------------------
+#ifndef QT_NO_THREAD
+#include <qthread.h>
+#include <qmap.h>
+#include <qmutex.h>
+QT_END_INCLUDE_NAMESPACE
+
+//#define QCE_ASYNC_DEBUG
+
+namespace {
+ class SocketAsyncHandler;
+
+ class SocketAsyncHandler : public QThread
+ {
+ public:
+ SocketAsyncHandler();
+ ~SocketAsyncHandler();
+ void run();
+ void select(SOCKET sock, HWND handle, unsigned int msg, long ev);
+ void removeSelect(SOCKET sock);
+ void safeRemove(SOCKET sock);
+ private:
+ struct SockInfo {
+ HWND handle;
+ unsigned int msg;
+ long ev;
+ };
+ QMap<SOCKET, SockInfo> sockets;
+ QMutex mutex;
+ QWaitCondition cond;
+ bool supposedToDie;
+ };
+
+ SocketAsyncHandler::SocketAsyncHandler()
+ : supposedToDie(false)
+ {
+ }
+
+ SocketAsyncHandler::~SocketAsyncHandler()
+ {
+ mutex.lock();
+ supposedToDie = true;
+ mutex.unlock();
+ cond.wakeOne();
+ wait();
+ while (sockets.size() > 0)
+ removeSelect(sockets.begin().key());
+ }
+
+ void SocketAsyncHandler::removeSelect(SOCKET sock)
+ {
+ if (!sockets.contains(sock))
+ return;
+ sockets.remove(sock);
+ return;
+ }
+
+ void SocketAsyncHandler::safeRemove(SOCKET sock)
+ {
+ QMutexLocker locker(&mutex);
+ removeSelect(sock);
+ }
+
+ void SocketAsyncHandler::select(SOCKET sock, HWND handle, unsigned int msg, long ev)
+ {
+ QMutexLocker locker(&mutex);
+
+ if (sockets.contains(sock))
+ sockets.remove(sock);
+
+ SockInfo info;
+ info.handle = handle;
+ info.msg = msg;
+ info.ev = ev;
+ sockets.insert(sock, info);
+ cond.wakeOne();
+ }
+
+ void SocketAsyncHandler::run()
+ {
+ do {
+ mutex.lock();
+
+ while (!supposedToDie && sockets.isEmpty()) {
+ cond.wait(&mutex);
+ }
+
+ if (supposedToDie) {
+ mutex.unlock();
+ break;
+ }
+
+ // Copy current items to reduce lock time
+ // and to be able to use SendMessage
+ QMap<SOCKET, SockInfo> currentSockets = sockets;
+ mutex.unlock();
+
+ fd_set readS, writeS, exS;
+ FD_ZERO(&readS);
+ FD_ZERO(&writeS);
+ FD_ZERO(&exS);
+
+ int maxFd = 0;
+
+ for (QMap<SOCKET, SockInfo>::iterator it = currentSockets.begin(); it != currentSockets.end(); ++it) {
+ const SockInfo &info = it.value();
+ int socket = it.key();
+ maxFd = qMax(maxFd, socket);
+
+ if ((info.ev & FD_READ) || (info.ev & FD_CLOSE) || (info.ev & FD_ACCEPT))
+ FD_SET(socket, &readS);
+ if ((info.ev & FD_WRITE)|| (info.ev & FD_CONNECT))
+ FD_SET(socket, &writeS);
+ if (info.ev & FD_OOB)
+ FD_SET(socket, &exS);
+ }
+
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50000;
+ int result = ::select(maxFd + 1, &readS, &writeS, &exS, &timeout);
+ if (result > 0) {
+ HWND handle;
+ unsigned int tmpMsg;
+ SOCKET sock;
+ HRESULT ret;
+ for (QMap<SOCKET, SockInfo>::const_iterator it = currentSockets.constBegin();
+ it != currentSockets.constEnd(); ++it) {
+ handle = (*it).handle;
+ tmpMsg = (*it).msg;
+ sock = it.key();
+ if (FD_ISSET(sock, &readS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_READ);
+
+ if (FD_ISSET(sock, &writeS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_WRITE);
+
+ if (FD_ISSET(sock, &exS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_OOB);
+ }
+ }
+
+#ifdef QCE_ASYNC_DEBUG
+ else if (result == 0) { //timeout
+ qDebug(" WSAAsync select timeout");
+ } else if (result < 0) { // SocketError
+ // This might happen because of two reasons
+ // 1. We already closed a socket in between the copy and the select
+ // and thus select() returns an error
+ // 2. Something is really wrong, then
+ // ### Loop on all descriptors, try to select and remove the
+ // ### broken one.
+ qWarning("WSAAsync select error %d", WSAGetLastError());
+ }
+#endif
+ } while(true);
+ }
+} // namespace
+
+Q_GLOBAL_STATIC(SocketAsyncHandler, qt_async_handler)
+
+int WSAAsyncSelect(SOCKET sock, HWND handle, unsigned int msg, long ev)
+{
+ if (sock == 0 || handle == 0 || handle == INVALID_HANDLE_VALUE) {
+ WSASetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+
+ if (msg == 0 && ev == 0)
+ qt_async_handler()->safeRemove(sock);
+ else
+ qt_async_handler()->select(sock, handle, msg, ev);
+
+ qt_async_handler()->start(QThread::LowPriority);
+ WSASetLastError(0);
+ return 0;
+}
+#else // QT_NO_THREAD
+int WSAAsyncSelect(SOCKET, HWND, unsigned int, long)
+{
+ return SOCKET_ERROR;
+}
+#endif
+#endif // Q_OS_WINCE
+
+class QEventDispatcherWin32Private;
+
+struct QSockNot {
+ QSocketNotifier *obj;
+ int fd;
+};
+typedef QHash<int, QSockNot *> QSNDict;
+
+struct WinTimerInfo { // internal timer info
+ QObject *dispatcher;
+ int timerId;
+ int interval;
+ QObject *obj; // - object to receive events
+ bool inTimerEvent;
+ int fastTimerId;
+};
+
+class QZeroTimerEvent : public QTimerEvent
+{
+public:
+ inline QZeroTimerEvent(int timerId)
+ : QTimerEvent(timerId)
+ { t = QEvent::ZeroTimerEvent; }
+};
+
+typedef QList<WinTimerInfo*> WinTimerVec; // vector of TimerInfo structs
+typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
+
+#if !defined(DWORD_PTR) && !defined(Q_WS_WIN64)
+#define DWORD_PTR DWORD
+#endif
+
+typedef MMRESULT(WINAPI *ptimeSetEvent)(UINT, UINT, LPTIMECALLBACK, DWORD_PTR, UINT);
+typedef MMRESULT(WINAPI *ptimeKillEvent)(UINT);
+
+static ptimeSetEvent qtimeSetEvent = 0;
+static ptimeKillEvent qtimeKillEvent = 0;
+
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+
+static void resolveTimerAPI()
+{
+ static bool triedResolve = false;
+ if (!triedResolve) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ if (triedResolve)
+ return;
+#endif
+ triedResolve = true;
+#if !defined(Q_OS_WINCE)
+ qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeKillEvent");
+#else
+ qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent");
+#endif
+ }
+}
+
+
+class QEventDispatcherWin32Private : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherWin32)
+public:
+ QEventDispatcherWin32Private();
+ ~QEventDispatcherWin32Private();
+
+ DWORD threadId;
+
+ bool interrupt;
+
+ // internal window handle used for socketnotifiers/timers/etc
+ HWND internalHwnd;
+ HHOOK getMessageHook;
+
+ // for controlling when to send posted events
+ QAtomicInt serialNumber;
+ int lastSerialNumber, sendPostedEventsWindowsTimerId;
+ QAtomicInt wakeUps;
+
+ // timers
+ WinTimerVec timerVec;
+ WinTimerDict timerDict;
+ void registerTimer(WinTimerInfo *t);
+ void unregisterTimer(WinTimerInfo *t, bool closingDown = false);
+ void sendTimerEvent(int timerId);
+
+ // socket notifiers
+ QSNDict sn_read;
+ QSNDict sn_write;
+ QSNDict sn_except;
+ void doWsaAsyncSelect(int socket);
+
+ QList<QWinEventNotifier *> winEventNotifierList;
+ void activateEventNotifier(QWinEventNotifier * wen);
+
+ QList<MSG> queuedUserInputEvents;
+ QList<MSG> queuedSocketEvents;
+};
+
+QEventDispatcherWin32Private::QEventDispatcherWin32Private()
+ : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0),
+ serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0)
+{
+ resolveTimerAPI();
+}
+
+QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
+{
+ if (internalHwnd)
+ DestroyWindow(internalHwnd);
+ QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
+ UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
+}
+
+void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
+{
+ QEvent event(QEvent::WinEventAct);
+ QCoreApplication::sendEvent(wen, &event);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax, UINT wRemoveMsg)
+{
+ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return PostMessage(hWnd, msg, wParam, lParam);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax)
+{
+ return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+
+// 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*/)
+{
+ if (!timerId) // sanity check
+ return;
+ WinTimerInfo *t = (WinTimerInfo*)user;
+ Q_ASSERT(t);
+ QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
+}
+
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
+{
+ if (message == WM_NCCREATE)
+ return true;
+
+ MSG msg;
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.wParam = wp;
+ msg.lParam = lp;
+ QCoreApplication *app = QCoreApplication::instance();
+ long result;
+ if (!app) {
+ if (message == WM_TIMER)
+ KillTimer(hwnd, wp);
+ return 0;
+ } else if (app->filterEvent(&msg, &result)) {
+ return result;
+ }
+
+#ifdef GWLP_USERDATA
+ QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#else
+ QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
+#endif
+ QEventDispatcherWin32Private *d = 0;
+ if (q != 0)
+ d = q->d_func();
+
+ if (message == WM_QT_SOCKETNOTIFIER) {
+ // socket notifier message
+ int type = -1;
+ switch (WSAGETSELECTEVENT(lp)) {
+ case FD_READ:
+ case FD_CLOSE:
+ case FD_ACCEPT:
+ type = 0;
+ break;
+ case FD_WRITE:
+ case FD_CONNECT:
+ type = 1;
+ break;
+ case FD_OOB:
+ type = 2;
+ break;
+ }
+ if (type >= 0) {
+ Q_ASSERT(d != 0);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+
+ QSockNot *sn = dict ? dict->value(wp) : 0;
+ if (sn) {
+ QEvent event(QEvent::SockAct);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ }
+ }
+ return 0;
+ } else if (message == WM_QT_SENDPOSTEDEVENTS
+ // we also use a Windows timer to send posted events when the message queue is full
+ || (message == WM_TIMER
+ && d->sendPostedEventsWindowsTimerId != 0
+ && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
+ int localSerialNumber = d->serialNumber;
+ if (localSerialNumber != d->lastSerialNumber) {
+ d->lastSerialNumber = localSerialNumber;
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ }
+ return 0;
+ } else if (message == WM_TIMER) {
+ Q_ASSERT(d != 0);
+ d->sendTimerEvent(wp);
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wp, lp);
+}
+
+LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
+{
+ if (wp == PM_REMOVE) {
+ QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
+ Q_ASSERT(q != 0);
+ if (q) {
+ MSG *msg = (MSG *) lp;
+ QEventDispatcherWin32Private *d = q->d_func();
+ int localSerialNumber = d->serialNumber;
+ if (HIWORD(GetQueueStatus(QS_TIMER | QS_INPUT | QS_RAWINPUT)) == 0) {
+ // no more input or timer events in the message queue, we can allow posted events to be sent normally now
+ if (d->sendPostedEventsWindowsTimerId != 0) {
+ // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message
+ KillTimer(d->internalHwnd, d->sendPostedEventsWindowsTimerId);
+ d->sendPostedEventsWindowsTimerId = 0;
+ }
+ (void) d->wakeUps.fetchAndStoreRelease(0);
+ if (localSerialNumber != d->lastSerialNumber
+ // if this message IS the one that triggers sendPostedEvents(), no need to post it again
+ && (msg->hwnd != d->internalHwnd
+ || msg->message != WM_QT_SENDPOSTEDEVENTS)) {
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ }
+ } else if (d->sendPostedEventsWindowsTimerId == 0
+ && localSerialNumber != d->lastSerialNumber) {
+ // start a special timer to continue delivering posted events while
+ // there are still input and timer messages in the message queue
+ d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd,
+ SendPostedEventsWindowsTimerId,
+ 0, // we specify zero, but Windows uses USER_TIMER_MINIMUM
+ NULL);
+ // we don't check the return value of SetTimer()... if creating the timer failed, there's little
+ // we can do. we just have to accept that posted events will be starved
+ }
+ }
+ }
+#ifdef Q_OS_WINCE
+ return 0;
+#else
+ return CallNextHookEx(0, code, wp, lp);
+#endif
+}
+
+static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
+{
+ // make sure that multiple Qt's can coexist in the same process
+ QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
+
+ WNDCLASS wc;
+ wc.style = 0;
+ wc.lpfnWndProc = qt_internal_proc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = qWinAppInst();
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16());
+
+ RegisterClass(&wc);
+ HWND wnd = CreateWindow(wc.lpszClassName, // classname
+ wc.lpszClassName, // window name
+ 0, // style
+ 0, 0, 0, 0, // geometry
+ 0, // parent
+ 0, // menu handle
+ qWinAppInst(), // application
+ 0); // windows creation data.
+
+ if (!wnd) {
+ qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
+ }
+
+#ifdef GWLP_USERDATA
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
+#else
+ SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
+#endif
+
+ return wnd;
+}
+
+void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
+{
+ Q_ASSERT(internalHwnd);
+
+ Q_Q(QEventDispatcherWin32);
+
+ int ok = 0;
+ if (t->interval > 20 || !t->interval || !qtimeSetEvent) {
+ ok = 1;
+ if (!t->interval) // optimization for single-shot-zero-timer
+ QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
+ else
+ ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+ } else {
+ ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
+ TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
+ if (ok == 0) { // fall back to normal timer if no more multimedia timers available
+ ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+ }
+ }
+
+ if (ok == 0)
+ qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
+}
+
+void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t, bool closingDown)
+{
+ // mark timer as unused
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent && !closingDown)
+ QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId);
+
+ if (t->interval == 0) {
+ QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ } else if (t->fastTimerId != 0) {
+ qtimeKillEvent(t->fastTimerId);
+ QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ } else if (internalHwnd) {
+ KillTimer(internalHwnd, t->timerId);
+ }
+ delete t;
+}
+
+void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
+{
+ WinTimerInfo *t = timerDict.value(timerId);
+ if (t && !t->inTimerEvent) {
+ // send event, but don't allow it to recurse
+ t->inTimerEvent = true;
+
+ QTimerEvent e(t->timerId);
+ QCoreApplication::sendEvent(t->obj, &e);
+
+ // timer could have been removed
+ t = timerDict.value(timerId);
+ if (t) {
+ t->inTimerEvent = false;
+ }
+ }
+}
+
+void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
+{
+ Q_ASSERT(internalHwnd);
+ int sn_event = 0;
+ if (sn_read.contains(socket))
+ sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
+ if (sn_write.contains(socket))
+ sn_event |= FD_WRITE | FD_CONNECT;
+ if (sn_except.contains(socket))
+ sn_event |= FD_OOB;
+ // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
+ // This is a BoundsChecker bug and not a Qt bug
+ WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_QT_SOCKETNOTIFIER : 0, sn_event);
+}
+
+void QEventDispatcherWin32::createInternalHwnd()
+{
+ Q_D(QEventDispatcherWin32);
+
+ Q_ASSERT(!d->internalHwnd);
+ if (d->internalHwnd)
+ return;
+ d->internalHwnd = qt_create_internal_window(this);
+
+#ifndef Q_OS_WINCE
+ // setup GetMessage hook needed to drive our posted events
+ d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
+ if (!d->getMessageHook) {
+ qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
+ }
+#endif
+
+ // register all socket notifiers
+ QList<int> sockets = (d->sn_read.keys().toSet()
+ + d->sn_write.keys().toSet()
+ + d->sn_except.keys().toSet()).toList();
+ for (int i = 0; i < sockets.count(); ++i)
+ d->doWsaAsyncSelect(sockets.at(i));
+
+ // start all normal timers
+ for (int i = 0; i < d->timerVec.count(); ++i)
+ d->registerTimer(d->timerVec.at(i));
+
+ // trigger a call to sendPostedEvents()
+ wakeUp();
+}
+
+QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
+{
+}
+
+QEventDispatcherWin32::~QEventDispatcherWin32()
+{
+}
+
+bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherWin32);
+
+ if (!d->internalHwnd)
+ createInternalHwnd();
+
+ d->interrupt = false;
+ emit awake();
+
+ bool canWait;
+ bool retVal = false;
+ bool seenWM_QT_SENDPOSTEDEVENTS = false;
+ bool needWM_QT_SENDPOSTEDEVENTS = false;
+ do {
+ DWORD waitRet = 0;
+ HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
+ QVarLengthArray<MSG> processedTimers;
+ while (!d->interrupt) {
+ DWORD nCount = d->winEventNotifierList.count();
+ Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
+
+ 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()) {
+ // process queued socket events
+ haveMessage = true;
+ msg = d->queuedSocketEvents.takeFirst();
+ } else {
+ haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
+ if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
+ && ((msg.message >= WM_KEYFIRST
+ && msg.message <= WM_KEYLAST)
+ || (msg.message >= WM_MOUSEFIRST
+ && msg.message <= WM_MOUSELAST)
+ || msg.message == WM_MOUSEWHEEL
+ || msg.message == WM_MOUSEHWHEEL
+ || msg.message == WM_TOUCH
+#ifndef QT_NO_GESTURES
+ || msg.message == WM_GESTURE
+ || msg.message == WM_GESTURENOTIFY
+#endif
+ || msg.message == WM_CLOSE)) {
+ // queue user input events for later processing
+ haveMessage = false;
+ d->queuedUserInputEvents.append(msg);
+ }
+ if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
+ && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
+ // queue socket events for later processing
+ haveMessage = false;
+ d->queuedSocketEvents.append(msg);
+ }
+ }
+ if (!haveMessage) {
+ // no message - check for signalled objects
+ for (int i=0; i<(int)nCount; i++)
+ pHandles[i] = d->winEventNotifierList.at(i)->handle();
+ waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
+ if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
+ // a new message has arrived, process it
+ continue;
+ }
+ }
+ if (haveMessage) {
+#ifdef Q_OS_WINCE
+ // WinCE doesn't support hooks at all, so we have to call this by hand :(
+ (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
+#endif
+
+ if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
+ if (seenWM_QT_SENDPOSTEDEVENTS) {
+ // when calling processEvents() "manually", we only want to send posted
+ // events once
+ needWM_QT_SENDPOSTEDEVENTS = true;
+ continue;
+ }
+ seenWM_QT_SENDPOSTEDEVENTS = true;
+ } else if (msg.message == WM_TIMER) {
+ // 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 (!filterEvent(&msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
+ d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ } else {
+ // nothing todo so break
+ break;
+ }
+ retVal = true;
+ }
+
+ // still nothing - wait for message or signalled objects
+ canWait = (!retVal
+ && !d->interrupt
+ && (flags & QEventLoop::WaitForMoreEvents));
+ if (canWait) {
+ DWORD nCount = d->winEventNotifierList.count();
+ Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
+ for (int i=0; i<(int)nCount; i++)
+ pHandles[i] = d->winEventNotifierList.at(i)->handle();
+
+ emit aboutToBlock();
+ waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
+ emit awake();
+ if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
+ d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ retVal = true;
+ }
+ }
+ } while (canWait);
+
+ if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
+ // when called "manually", always send posted events
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ }
+
+ if (needWM_QT_SENDPOSTEDEVENTS)
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+
+ 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();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherWin32);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+
+ if (QCoreApplication::closingDown()) // ### d->exitloop?
+ return; // after sn_cleanup, don't reinitialize.
+
+ if (dict->contains(sockfd)) {
+ 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]);
+ }
+
+ QSockNot *sn = new QSockNot;
+ sn->obj = notifier;
+ sn->fd = sockfd;
+ dict->insert(sn->fd, sn);
+
+ if (d->internalHwnd)
+ d->doWsaAsyncSelect(sockfd);
+}
+
+void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherWin32);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+ QSockNot *sn = dict->value(sockfd);
+ if (!sn)
+ return;
+
+ dict->remove(sockfd);
+ delete sn;
+
+ if (d->internalHwnd)
+ d->doWsaAsyncSelect(sockfd);
+}
+
+void QEventDispatcherWin32::registerTimer(int timerId, int interval, QObject *object)
+{
+ if (timerId < 1 || interval < 0 || !object) {
+ qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ register WinTimerInfo *t = new WinTimerInfo;
+ t->dispatcher = this;
+ t->timerId = timerId;
+ t->interval = interval;
+ t->obj = object;
+ t->inTimerEvent = false;
+ t->fastTimerId = 0;
+
+ if (d->internalHwnd)
+ d->registerTimer(t);
+
+ d->timerVec.append(t); // store in timer vector
+ d->timerDict.insert(t->timerId, t); // store timers in dict
+}
+
+bool QEventDispatcherWin32::unregisterTimer(int timerId)
+{
+ if (timerId < 1) {
+ qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
+ return false;
+ }
+ QThread *currentThread = QThread::currentThread();
+ if (thread() != currentThread) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+ if (d->timerVec.isEmpty() || timerId <= 0)
+ return false;
+
+ WinTimerInfo *t = d->timerDict.value(timerId);
+ if (!t)
+ return false;
+
+ d->timerDict.remove(t->timerId);
+ d->timerVec.removeAll(t);
+ d->unregisterTimer(t);
+ return true;
+}
+
+bool QEventDispatcherWin32::unregisterTimers(QObject *object)
+{
+ if (!object) {
+ qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument");
+ return false;
+ }
+ QThread *currentThread = QThread::currentThread();
+ if (object->thread() != thread() || thread() != currentThread) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+ if (d->timerVec.isEmpty())
+ return false;
+ register 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);
+ d->unregisterTimer(t);
+ --i;
+ }
+ }
+ return true;
+}
+
+QList<QEventDispatcherWin32::TimerInfo>
+QEventDispatcherWin32::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherWin32:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherWin32);
+ QList<TimerInfo> list;
+ for (int i = 0; i < d->timerVec.size(); ++i) {
+ const WinTimerInfo *t = d->timerVec.at(i);
+ if (t && t->obj == object)
+ list << TimerInfo(t->timerId, t->interval);
+ }
+ return list;
+}
+
+bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
+{
+ if (!notifier) {
+ qWarning("QWinEventNotifier: Internal error");
+ return false;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QWinEventNotifier: event notifiers cannot be enabled from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ if (d->winEventNotifierList.contains(notifier))
+ return true;
+
+ if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) {
+ qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2);
+ return false;
+ }
+ d->winEventNotifierList.append(notifier);
+ return true;
+}
+
+void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
+{
+ if (!notifier) {
+ qWarning("QWinEventNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QWinEventNotifier: event notifiers cannot be disabled from another thread");
+ return;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ int i = d->winEventNotifierList.indexOf(notifier);
+ if (i != -1)
+ d->winEventNotifierList.takeAt(i);
+}
+
+void QEventDispatcherWin32::activateEventNotifiers()
+{
+ Q_D(QEventDispatcherWin32);
+ //### this could break if events are removed/added in the activation
+ for (int i=0; i<d->winEventNotifierList.count(); i++) {
+#if !defined(Q_OS_WINCE)
+ if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
+ d->activateEventNotifier(d->winEventNotifierList.at(i));
+#else
+ if (WaitForSingleObject(d->winEventNotifierList.at(i)->handle(), 0) == WAIT_OBJECT_0)
+ d->activateEventNotifier(d->winEventNotifierList.at(i));
+#endif
+ }
+}
+
+void QEventDispatcherWin32::wakeUp()
+{
+ Q_D(QEventDispatcherWin32);
+ d->serialNumber.ref();
+ if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
+ // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ }
+}
+
+void QEventDispatcherWin32::interrupt()
+{
+ Q_D(QEventDispatcherWin32);
+ d->interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherWin32::flush()
+{ }
+
+void QEventDispatcherWin32::startingUp()
+{ }
+
+void QEventDispatcherWin32::closingDown()
+{
+ Q_D(QEventDispatcherWin32);
+
+ // clean up any socketnotifiers
+ while (!d->sn_read.isEmpty())
+ unregisterSocketNotifier((*(d->sn_read.begin()))->obj);
+ while (!d->sn_write.isEmpty())
+ unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
+ while (!d->sn_except.isEmpty())
+ unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
+
+ // clean up any timers
+ for (int i = 0; i < d->timerVec.count(); ++i)
+ d->unregisterTimer(d->timerVec.at(i), true);
+ d->timerVec.clear();
+ d->timerDict.clear();
+
+#ifndef Q_OS_WINCE
+ if (d->getMessageHook)
+ UnhookWindowsHookEx(d->getMessageHook);
+ d->getMessageHook = 0;
+#endif
+}
+
+bool QEventDispatcherWin32::event(QEvent *e)
+{
+ Q_D(QEventDispatcherWin32);
+ if (e->type() == QEvent::ZeroTimerEvent) {
+ QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
+ WinTimerInfo *t = d->timerDict.value(zte->timerId());
+ if (t) {
+ t->inTimerEvent = true;
+
+ QTimerEvent te(zte->timerId());
+ QCoreApplication::sendEvent(t->obj, &te);
+
+ t = d->timerDict.value(zte->timerId());
+ if (t) {
+ if (t->interval == 0 && t->inTimerEvent) {
+ // post the next zero timer event as long as the timer was not restarted
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ }
+
+ t->inTimerEvent = false;
+ }
+ }
+ return true;
+ } else if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ d->sendTimerEvent(te->timerId());
+ }
+ return QAbstractEventDispatcher::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
new file mode 100644
index 0000000000..2e3a5bca19
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_WIN_P_H
+#define QEVENTDISPATCHER_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/qabstracteventdispatcher.h"
+#include "QtCore/qt_windows.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);
+
+class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherWin32)
+
+ void createInternalHwnd();
+ friend class QGuiEventDispatcherWin32;
+
+public:
+ explicit QEventDispatcherWin32(QObject *parent = 0);
+ ~QEventDispatcherWin32();
+
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ bool registerEventNotifier(QWinEventNotifier *notifier);
+ void unregisterEventNotifier(QWinEventNotifier *notifier);
+ void activateEventNotifiers();
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+ bool event(QEvent *e);
+
+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);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_WIN_P_H
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
new file mode 100644
index 0000000000..d213b0e968
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventloop.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qelapsedtimer.h"
+
+#include "qobject_p.h"
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEventLoopPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QEventLoop)
+public:
+ inline QEventLoopPrivate()
+ : exit(true), inExec(false), returnCode(-1)
+ { }
+ bool exit, inExec;
+ int returnCode;
+};
+
+/*!
+ \class QEventLoop
+ \brief The QEventLoop class provides a means of entering and leaving an event loop.
+
+ At any time, you can create a QEventLoop object and call exec()
+ on it to start a local event loop. From within the event loop,
+ calling exit() will force exec() to return.
+
+ \sa QAbstractEventDispatcher
+*/
+
+/*!
+ \enum QEventLoop::ProcessEventsFlag
+
+ This enum controls the types of events processed by the
+ processEvents() functions.
+
+ \value AllEvents All events. Note that
+ \l{QEvent::DeferredDelete}{DeferredDelete} events are processed
+ specially. See QObject::deleteLater() for more details.
+
+ \value ExcludeUserInputEvents Do not process user input events,
+ such as ButtonPress and KeyPress. Note that the events are not
+ discarded; they will be delivered the next time processEvents() is
+ called without the ExcludeUserInputEvents flag.
+
+ \value ExcludeSocketNotifiers Do not process socket notifier
+ events. Note that the events are not discarded; they will be
+ delivered the next time processEvents() is called without the
+ ExcludeSocketNotifiers flag.
+
+ \value WaitForMoreEvents Wait for events if no pending events are
+ available.
+
+ \omitvalue X11ExcludeTimers
+ \omitvalue ExcludeUserInput
+ \omitvalue WaitForMore
+ \omitvalue EventLoopExec
+ \omitvalue DialogExec
+ \value DeferredDeletion deprecated - do not use.
+
+ \sa processEvents()
+*/
+
+/*!
+ Constructs an event loop object with the given \a parent.
+*/
+QEventLoop::QEventLoop(QObject *parent)
+ : QObject(*new QEventLoopPrivate, parent)
+{
+ Q_D(QEventLoop);
+ if (!QCoreApplication::instance()) {
+ qWarning("QEventLoop: Cannot be used without QApplication");
+ } else if (!d->threadData->eventDispatcher) {
+ QThreadPrivate::createEventDispatcher(d->threadData);
+ }
+}
+
+/*!
+ Destroys the event loop object.
+*/
+QEventLoop::~QEventLoop()
+{ }
+
+
+/*!
+ Processes pending events that match \a flags until there are no
+ more events to process. Returns true if pending events were handled;
+ otherwise returns false.
+
+ 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.
+
+ This function is simply a wrapper for
+ QAbstractEventDispatcher::processEvents(). See the documentation
+ for that function for details.
+*/
+bool QEventLoop::processEvents(ProcessEventsFlags flags)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return false;
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ return d->threadData->eventDispatcher->processEvents(flags);
+}
+
+/*!
+ Enters the main event loop and waits until exit() is called.
+ Returns the value that was passed to exit().
+
+ If \a flags are specified, only events of the types allowed by
+ the \a flags will be processed.
+
+ It is necessary to call this function to start event handling. The
+ main event loop receives events from the window system and
+ dispatches these to the application widgets.
+
+ Generally speaking, no user interaction can take place before
+ calling exec(). As a special case, modal widgets like QMessageBox
+ 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().
+
+ \sa QApplication::quit(), exit(), processEvents()
+*/
+int QEventLoop::exec(ProcessEventsFlags flags)
+{
+ Q_D(QEventLoop);
+ //we need to protect from race condition with QThread::exit
+ QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
+ if (d->threadData->quitNow)
+ return -1;
+
+ if (d->inExec) {
+ qWarning("QEventLoop::exec: instance %p has already called exec()", this);
+ return -1;
+ }
+ d->inExec = true;
+ d->exit = false;
+ ++d->threadData->loopLevel;
+ d->threadData->eventLoops.push(this);
+ locker.unlock();
+
+ // remove posted quit events when entering a new event loop
+ QCoreApplication *app = QCoreApplication::instance();
+ if (app && app->thread() == thread())
+ QCoreApplication::removePostedEvents(app, QEvent::Quit);
+
+#if defined(QT_NO_EXCEPTIONS)
+ while (!d->exit)
+ processEvents(flags | WaitForMoreEvents | EventLoopExec);
+#else
+ try {
+ while (!d->exit)
+ processEvents(flags | WaitForMoreEvents | EventLoopExec);
+ } catch (...) {
+ qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
+ "exceptions from an event handler is not supported in Qt. You must\n"
+ "reimplement QApplication::notify() and catch all exceptions there.\n");
+
+ // copied from below
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+
+ throw;
+ }
+#endif
+
+ // copied above
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+
+ return d->returnCode;
+}
+
+/*!
+ 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.
+ 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.
+
+ \bold{Notes:}
+ \list
+ \o This function does not process events continuously; it
+ returns after all available events are processed.
+ \o Specifying the \l WaitForMoreEvents flag makes no sense
+ and will be ignored.
+ \endlist
+*/
+void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+
+ QElapsedTimer start;
+ start.start();
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ while (processEvents(flags & ~WaitForMoreEvents)) {
+ if (start.elapsed() > maxTime)
+ break;
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+/*!
+ Tells the event loop to exit with a return code.
+
+ After this function has been called, the event loop returns from
+ the call to exec(). The exec() function returns \a returnCode.
+
+ By convention, a \a returnCode of 0 means success, and any non-zero
+ value indicates an error.
+
+ Note that unlike the C library function of the same name, this
+ function \e does return to the caller -- it is event processing that
+ stops.
+
+ \sa QCoreApplication::quit(), quit(), exec()
+*/
+void QEventLoop::exit(int returnCode)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+
+ d->returnCode = returnCode;
+ d->exit = true;
+ d->threadData->eventDispatcher->interrupt();
+}
+
+/*!
+ Returns true if the event loop is running; otherwise returns
+ false. The event loop is considered running from the time when
+ exec() is called until exit() is called.
+
+ \sa exec() exit()
+ */
+bool QEventLoop::isRunning() const
+{
+ Q_D(const QEventLoop);
+ return !d->exit;
+}
+
+/*!
+ Wakes up the event loop.
+
+ \sa QAbstractEventDispatcher::wakeUp()
+*/
+void QEventLoop::wakeUp()
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+ d->threadData->eventDispatcher->wakeUp();
+}
+
+/*!
+ Tells the event loop to exit normally.
+
+ Same as exit(0).
+
+ \sa QCoreApplication::quit(), exit()
+*/
+void QEventLoop::quit()
+{ exit(0); }
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h
new file mode 100644
index 0000000000..c0eae714a4
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTLOOP_H
+#define QEVENTLOOP_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventLoopPrivate;
+
+class Q_CORE_EXPORT QEventLoop : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventLoop)
+
+public:
+ explicit QEventLoop(QObject *parent = 0);
+ ~QEventLoop();
+
+ enum ProcessEventsFlag {
+ AllEvents = 0x00,
+ ExcludeUserInputEvents = 0x01,
+ ExcludeSocketNotifiers = 0x02,
+ WaitForMoreEvents = 0x04,
+#ifdef QT3_SUPPORT
+ ExcludeUserInput = ExcludeUserInputEvents,
+ WaitForMore = WaitForMoreEvents,
+#endif
+ X11ExcludeTimers = 0x08
+#ifdef QT_DEPRECATED
+ , DeferredDeletion = 0x10
+#endif
+ , EventLoopExec = 0x20
+ , DialogExec = 0x40
+ };
+ Q_DECLARE_FLAGS(ProcessEventsFlags, ProcessEventsFlag)
+
+ bool processEvents(ProcessEventsFlags flags = AllEvents);
+ void processEvents(ProcessEventsFlags flags, int maximumTime);
+
+ int exec(ProcessEventsFlags flags = AllEvents);
+ void exit(int returnCode = 0);
+ bool isRunning() const;
+
+ void wakeUp();
+
+public Q_SLOTS:
+ void quit();
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QEventLoop::ProcessEventsFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QEVENTLOOP_H
diff --git a/src/corelib/kernel/qfunctions_nacl.cpp b/src/corelib/kernel/qfunctions_nacl.cpp
new file mode 100644
index 0000000000..f3d85ef300
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_nacl.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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
new file mode 100644
index 0000000000..db36ad5bfd
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_nacl.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNACLUNIMPLEMENTED_H
+#define QNACLUNIMPLEMENTED_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_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+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
+
+QT_END_HEADER
+
+#endif //Q_OS_NACL
+
+#endif //QNACLUNIMPLEMENTED_H
diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h
new file mode 100644
index 0000000000..d27fec3a0b
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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 qfunctions_*. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QFUNCTIONS_P_H
+#define QFUNCTIONS_P_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_WINCE)
+# include "QtCore/qfunctions_wince.h"
+#elif defined(Q_OS_VXWORKS)
+# include "QtCore/qfunctions_vxworks.h"
+#elif defined(Q_OS_NACL)
+# include "QtCore/qfunctions_nacl.h"
+#endif
+
+#ifdef Q_CC_RVCT
+// rvct doesn't see static operators when using our qalgorithms
+# define Q_STATIC_GLOBAL_OPERATOR inline
+# define Q_STATIC_GLOBAL_INLINE_OPERATOR inline
+#else
+# define Q_STATIC_GLOBAL_OPERATOR static
+# define Q_STATIC_GLOBAL_INLINE_OPERATOR static inline
+#endif
+
+QT_BEGIN_HEADER
+QT_END_HEADER
+
+#endif
+
diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp
new file mode 100644
index 0000000000..1678ab67a9
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_vxworks.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#ifdef Q_OS_VXWORKS
+
+#include "qplatformdefs.h"
+#include "qfunctions_vxworks.h"
+
+#include <vmLib.h>
+#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)
+int rand_r(unsigned int * /*seedp*/)
+{
+ return rand();
+}
+
+// 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)
+# 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()
+{
+ return vmPageSizeGet();
+}
+
+// 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
new file mode 100644
index 0000000000..78a37210a0
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_vxworks.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUNCTIONS_VXWORKS_H
+#define QFUNCTIONS_VXWORKS_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>
+#include <sys/times.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#ifndef QT_NO_IPV6IFNAME
+#include <net/if.h>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_BUILD_CORE_LIB
+QT_MODULE(Core)
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+
+#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)
+int rand_r(unsigned int * /*seedp*/);
+
+// no usleep() support
+int usleep(unsigned int);
+
+// 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));
+
+// neither getpagesize() or sysconf(_SC_PAGESIZE) are 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_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
new file mode 100644
index 0000000000..2de34c3bdc
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef _WIN32_WCE //Q_OS_WINCE
+
+#include <windows.h>
+#include <winbase.h>
+#include <kfuncs.h>
+#include <stdio.h>
+#include <altcecrt.h>
+
+#include "qplatformdefs.h"
+#include "qfunctions_wince.h"
+#include "qstring.h"
+#include "qbytearray.h"
+#include "qhash.h"
+
+QT_USE_NAMESPACE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+wchar_t* CEPrivConvCharToWide(const char* string)
+{
+ size_t length = strlen(string);
+ wchar_t* wString = new wchar_t[length +1];
+ for (unsigned int i = 0; i < (length +1); i++)
+ wString[i] = string[i];
+ return wString;
+}
+
+// Time -------------------------------------------------------------
+time_t qt_wince_ftToTime_t( const FILETIME ft )
+{
+ ULARGE_INTEGER li;
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+
+ // 100-nanosec to seconds
+ li.QuadPart /= 10000000;
+
+ // FILETIME is from 1601-01-01 T 00:00:00
+ // time_t is from 1970-01-01 T 00:00:00
+ // 1970 - 1601 = 369 year (89 leap years)
+ //
+ // ((369y*365d) + 89d) *24h *60min *60sec
+ // = 11644473600 seconds
+ li.QuadPart -= 11644473600;
+ return li.LowPart;
+}
+
+FILETIME qt_wince_time_tToFt( time_t tt )
+{
+ ULARGE_INTEGER li;
+ li.QuadPart = tt;
+ li.QuadPart += 11644473600;
+ li.QuadPart *= 10000000;
+
+ FILETIME ft;
+ ft.dwLowDateTime = li.LowPart;
+ ft.dwHighDateTime = li.HighPart;
+ return ft;
+}
+
+// File I/O ---------------------------------------------------------
+int errno = 0;
+
+int qt_wince__getdrive( void )
+{
+ return 1;
+}
+
+int qt_wince__waccess( const wchar_t *path, int pmode )
+{
+ DWORD res = GetFileAttributes( path );
+ if ( 0xFFFFFFFF == res )
+ return -1;
+
+ if ( (pmode & W_OK) && (res & FILE_ATTRIBUTE_READONLY) )
+ return -1;
+
+ if ( (pmode & X_OK) && !(res & FILE_ATTRIBUTE_DIRECTORY) ) {
+ QString file = QString::fromWCharArray(path);
+ if ( !(file.endsWith(QString::fromLatin1(".exe")) ||
+ file.endsWith(QString::fromLatin1(".com"))) )
+ return -1;
+ }
+
+ return 0;
+}
+
+int qt_wince_open( const char *filename, int oflag, int pmode )
+{
+ QString fn( QString::fromLatin1(filename) );
+ return _wopen( (wchar_t*)fn.utf16(), oflag, pmode );
+}
+
+int qt_wince__wopen( const wchar_t *filename, int oflag, int /*pmode*/ )
+{
+ wchar_t *flag;
+
+ if ( oflag & _O_APPEND ) {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"a";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"a+";
+ }
+ } else if (oflag & _O_BINARY) {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"wb";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"w+b"; // slightly different from "r+" where the file must exist
+ } else if ( oflag & _O_RDONLY ) {
+ flag = L"rb";
+ } else {
+ flag = L"b";
+ }
+ } else {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"wt";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"w+t"; // slightly different from "r+" where the file must exist
+ } else if ( oflag & _O_RDONLY ) {
+ flag = L"rt";
+ } else {
+ flag = L"t";
+ }
+ }
+
+ int retval = (int)_wfopen( filename, flag );
+ return (retval == NULL) ? -1 : retval;
+}
+
+long qt_wince__lseek( int handle, long offset, int origin )
+{
+ return fseek( (FILE*)handle, offset, origin );
+}
+
+int qt_wince__read( int handle, void *buffer, unsigned int count )
+{
+ return fread( buffer, 1, count, (FILE*)handle );
+}
+
+int qt_wince__write( int handle, const void *buffer, unsigned int count )
+{
+ return fwrite( buffer, 1, count, (FILE*)handle );
+}
+
+int qt_wince__close( int handle )
+{
+ if (!handle)
+ return 0;
+ return fclose( (FILE*)handle );
+}
+
+FILE *qt_wince__fdopen(int handle, const char* /*mode*/)
+{
+ return (FILE*)handle;
+}
+
+FILE *qt_wince_fdopen( int handle, const char* /*mode*/ )
+{
+ return (FILE*)handle;
+}
+
+void qt_wince_rewind( FILE *stream )
+{
+ fseek( stream, 0L, SEEK_SET );
+}
+
+int qt_wince___fileno(FILE *f)
+{
+ return (int) _fileno(f);
+}
+
+FILE *qt_wince_tmpfile( void )
+{
+ static long i = 0;
+ char name[16];
+ sprintf( name, "tmp%i", i++ );
+ return fopen( name, "r+" );
+}
+
+int qt_wince__mkdir(const char *dirname)
+{
+ return CreateDirectory(reinterpret_cast<const wchar_t *> (QString(QString::fromLatin1(dirname)).utf16()), 0) ? 0 : -1;
+}
+
+int qt_wince__rmdir(const char *dirname)
+{
+ return RemoveDirectory(reinterpret_cast<const wchar_t *> (QString::fromLatin1(dirname).utf16())) ? 0 : -1;
+}
+
+int qt_wince__access( const char *path, int pmode )
+{
+ return _waccess(reinterpret_cast<const wchar_t *> (QString::fromLatin1(path).utf16()),pmode);
+}
+
+int qt_wince__rename( const char *oldname, const char *newname )
+{
+ return !MoveFile(reinterpret_cast<const wchar_t *> (QString::fromLatin1(oldname).utf16()), reinterpret_cast<const wchar_t *> (QString::fromLatin1(newname).utf16()));
+}
+
+int qt_wince__remove( const char *name )
+{
+ return !DeleteFile(reinterpret_cast<const wchar_t *> (QString::fromLatin1(name).utf16()));
+}
+
+int qt_wince_stat( const char *path, struct stat *buffer )
+{
+ WIN32_FIND_DATA finfo;
+ HANDLE ff = FindFirstFile( reinterpret_cast<const wchar_t *> (QString::fromLatin1(path).utf16()), &finfo );
+
+ if ( ff == INVALID_HANDLE_VALUE )
+ return -1;
+
+ buffer->st_ctime = qt_wince_ftToTime_t( finfo.ftCreationTime );
+ buffer->st_atime = qt_wince_ftToTime_t( finfo.ftLastAccessTime );
+ buffer->st_mtime = qt_wince_ftToTime_t( finfo.ftLastWriteTime );
+ buffer->st_nlink = 0;
+ buffer->st_size = finfo.nFileSizeLow; // ### missing high!
+ buffer->st_mode = (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
+ buffer->st_mode |= (finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _O_RDONLY : _O_RDWR;
+ return (FindClose(ff) == 0);
+}
+
+int qt_wince__fstat( int handle, struct stat *buffer)
+{
+ BY_HANDLE_FILE_INFORMATION fInfo;
+ BOOL res = GetFileInformationByHandle((HANDLE)handle, &fInfo);
+
+ buffer->st_ctime = qt_wince_ftToTime_t( fInfo.ftCreationTime );
+ buffer->st_atime = qt_wince_ftToTime_t( fInfo.ftLastAccessTime );
+ buffer->st_mtime = qt_wince_ftToTime_t( fInfo.ftLastWriteTime );
+ buffer->st_nlink = 0;
+ buffer->st_size = fInfo.nFileSizeLow; // ### missing high!
+ buffer->st_mode = (fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
+ buffer->st_mode |= (fInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _O_RDONLY : _O_RDWR;
+ return (res == 0);
+}
+
+int qt_wince_SetErrorMode(int newValue)
+{
+ static int oldValue;
+ int result = oldValue;
+ oldValue = newValue;
+ return result;
+}
+
+bool qt_wince__chmod(const char *file, int mode)
+{
+ return _wchmod( reinterpret_cast<const wchar_t *> (QString::fromLatin1(file).utf16()), mode);
+}
+
+bool qt_wince__wchmod(const wchar_t *file, int mode)
+{
+ BOOL success = FALSE;
+ // ### Does not work properly, what about just adding one property?
+ if(mode&_S_IWRITE) {
+ success = SetFileAttributes(file, FILE_ATTRIBUTE_NORMAL);
+ } else if((mode&_S_IREAD) && !(mode&_S_IWRITE)) {
+ success = SetFileAttributes(file, FILE_ATTRIBUTE_READONLY);
+ }
+ return success ? 0 : -1;
+}
+
+HANDLE qt_wince_CreateFileA(LPCSTR filename, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES attr, DWORD dispo, DWORD flags, HANDLE tempFile)
+{
+ return CreateFileW( reinterpret_cast<const wchar_t *>(QString::fromLatin1(filename).utf16()), access, share, attr, dispo, flags, tempFile);
+}
+
+// Graphics ---------------------------------------------------------
+BOOL qt_wince_SetWindowOrgEx( HDC /*hdc*/, int /*X*/, int /*Y*/, LPPOINT /*lpPoint*/) {
+ return TRUE;
+}
+
+// Threading --------------------------------------------------------
+HANDLE qt_wince__beginthread(void( *start_address )( void * ), unsigned stack_size, void *arglist)
+{
+ unsigned initflag = 0;
+ if (stack_size > 0)
+ initflag |= STACK_SIZE_PARAM_IS_A_RESERVATION;
+ return CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, initflag, NULL);
+}
+
+unsigned long qt_wince__beginthreadex( void *security,
+ unsigned stack_size,
+ unsigned (__stdcall *start_address)(void *),
+ void *arglist,
+ unsigned initflag,
+ unsigned *thrdaddr)
+{
+ if (stack_size > 0)
+ initflag |= STACK_SIZE_PARAM_IS_A_RESERVATION;
+ return (unsigned long)
+ CreateThread( (LPSECURITY_ATTRIBUTES)security,
+ (DWORD)stack_size,
+ (LPTHREAD_START_ROUTINE)start_address,
+ (LPVOID)arglist,
+ (DWORD)initflag | CREATE_SUSPENDED,
+ (LPDWORD)thrdaddr);
+}
+
+void qt_wince__endthreadex(unsigned nExitCode) {
+ ExitThread((DWORD)nExitCode);
+}
+
+void *qt_wince_bsearch(const void *key,
+ const void *base,
+ size_t num,
+ size_t size,
+ int (__cdecl *compare)(const void *, const void *))
+{
+ size_t low = 0;
+ size_t high = num - 1;
+ while (low <= high) {
+ size_t mid = (low + high) >> 1;
+ int c = compare(key, (char*)base + mid * size);
+ if (c < 0) {
+ if (!mid)
+ break;
+ high = mid - 1;
+ } else if (c > 0)
+ low = mid + 1;
+ else
+ return (char*) base + mid * size;
+ }
+ return 0;
+}
+
+void *lfind(const void* key, const void* base, size_t* elements, size_t size,
+ int (__cdecl *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;
+}
+
+DWORD qt_wince_GetThreadLocale(void)
+{
+ return GetUserDefaultLCID();
+}
+
+void *qt_wince_calloc( size_t num, size_t size )
+{
+ void *ptr = malloc( num * size );
+ if( ptr )
+ memset( ptr, 0, num * size );
+ return ptr;
+}
+
+// _getpid is currently only used for creating a temporary filename
+int qt_wince__getpid()
+{
+ return qAbs((int)GetCurrentProcessId());
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+// Environment ------------------------------------------------------
+inline QHash<QByteArray, QByteArray>& qt_app_environment()
+{
+ static QHash<QByteArray, QByteArray> internalEnvironment;
+ return internalEnvironment;
+}
+
+errno_t qt_wince_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, const char* varName)
+{
+ if (!sizeNeeded)
+ return EINVAL;
+
+ if (!qt_app_environment().contains(varName)) {
+ if (buffer)
+ buffer[0] = '\0';
+ return ENOENT;
+ }
+
+ QByteArray value = qt_app_environment().value(varName);
+ if (!value.endsWith('\0')) // win32 guarantees terminated string
+ value.append('\0');
+
+ if (bufferSize < (size_t)value.size()) {
+ *sizeNeeded = value.size();
+ return 0;
+ }
+
+ strcpy(buffer, value.constData());
+ return 0;
+}
+
+errno_t qt_wince__putenv_s(const char* varName, const char* value)
+{
+ QByteArray input = value;
+ if (input.isEmpty()) {
+ if (qt_app_environment().contains(varName))
+ qt_app_environment().remove(varName);
+ } else {
+ // win32 guarantees terminated string
+ if (!input.endsWith('\0'))
+ input.append('\0');
+ qt_app_environment()[varName] = input;
+ }
+
+ return 0;
+}
+
+#endif // Q_OS_WINCE
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
new file mode 100644
index 0000000000..fffe407139
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUNCTIONS_WCE_H
+#define QFUNCTIONS_WCE_H
+#ifdef Q_OS_WINCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winuser.h>
+#include <winbase.h>
+#include <objbase.h>
+#include <kfuncs.h>
+#include <ctype.h>
+#include <time.h>
+#include <crtdefs.h>
+#include <altcecrt.h>
+#include <winsock.h>
+#include <ceconfig.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_BUILD_CORE_LIB
+QT_MODULE(Core)
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+
+// The standard SDK misses this define...
+#define _control87 _controlfp
+
+#if !defined __cplusplus
+#define bool int
+#define true 1
+#define false 0
+#endif
+
+// Environment ------------------------------------------------------
+errno_t qt_wince_getenv_s(size_t*, char*, size_t, const char*);
+errno_t qt_wince__putenv_s(const char*, const char*);
+
+#ifdef __cplusplus // have this as tiff plugin is written in C
+extern "C" {
+#endif
+
+#if !defined(NO_ERRNO_H)
+#define NO_ERRNO_H
+#endif
+
+// Environment ------------------------------------------------------
+int qt_wince__getpid(void);
+
+
+// Time -------------------------------------------------------------
+#ifndef _TM_DEFINED
+#define _TM_DEFINED
+struct tm {
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday - [0,6] */
+ int tm_yday; /* days since January 1 - [0,365] */
+ int tm_isdst; /* daylight savings time flag */
+};
+#endif // _TM_DEFINED
+
+FILETIME qt_wince_time_tToFt( time_t tt );
+
+// File I/O ---------------------------------------------------------
+#define _O_RDONLY 0x0001
+#define _O_RDWR 0x0002
+#define _O_WRONLY 0x0004
+#define _O_CREAT 0x0008
+#define _O_TRUNC 0x0010
+#define _O_APPEND 0x0020
+#define _O_EXCL 0x0040
+
+#define O_RDONLY _O_RDONLY
+#define O_RDWR _O_RDWR
+#define O_WRONLY _O_WRONLY
+#define O_CREAT _O_CREAT
+#define O_TRUNC _O_TRUNC
+#define O_APPEND _O_APPEND
+#define O_EXCL _O_EXCL
+
+#define _S_IFMT 0x0600
+#define _S_IFDIR 0x0200
+#define _S_IFCHR 0x0100
+#define _S_IFREG 0x0400
+#define _S_IREAD 0x0010
+#define _S_IWRITE 0x0008
+
+#define S_IFMT _S_IFMT
+#define S_IFDIR _S_IFDIR
+#define S_IFCHR _S_IFCHR
+#define S_IFREG _S_IFREG
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+
+#ifndef _IOFBF
+#define _IOFBF 0x0000
+#endif
+
+#ifndef _IOLBF
+#define _IOLBF 0x0040
+#endif
+
+#ifndef _IONBF
+#define _IONBF 0x0004
+#endif
+
+// Regular Berkeley error constants
+#ifndef _STAT_DEFINED
+#define _STAT_DEFINED
+struct stat
+{
+ int st_mode;
+ int st_size;
+ int st_nlink;
+ time_t st_mtime;
+ time_t st_atime;
+ time_t st_ctime;
+};
+#endif
+
+typedef int mode_t;
+extern int errno;
+
+int qt_wince__getdrive( void );
+int qt_wince__waccess( const wchar_t *path, int pmode );
+int qt_wince__wopen( const wchar_t *filename, int oflag, int pmode );
+long qt_wince__lseek( int handle, long offset, int origin );
+int qt_wince__read( int handle, void *buffer, unsigned int count );
+int qt_wince__write( int handle, const void *buffer, unsigned int count );
+int qt_wince__close( int handle );
+FILE *qt_wince__fdopen(int handle, const char *mode);
+FILE *qt_wince_fdopen(int handle, const char *mode);
+void qt_wince_rewind( FILE *stream );
+int qt_wince___fileno(FILE *);
+FILE *qt_wince_tmpfile( void );
+
+int qt_wince__mkdir(const char *dirname);
+int qt_wince__rmdir(const char *dirname);
+int qt_wince__access( const char *path, int pmode );
+int qt_wince__rename( const char *oldname, const char *newname );
+int qt_wince__remove( const char *name );
+#ifdef __cplusplus
+int qt_wince_open( const char *filename, int oflag, int pmode = 0 );
+#else
+int qt_wince_open( const char *filename, int oflag, int pmode );
+#endif
+int qt_wince_stat( const char *path, struct stat *buffer );
+int qt_wince__fstat( int handle, struct stat *buffer);
+
+#define SEM_FAILCRITICALERRORS 0x0001
+#define SEM_NOOPENFILEERRORBOX 0x0002
+int qt_wince_SetErrorMode(int);
+#ifndef CoInitialize
+#define CoInitialize(x) CoInitializeEx(x, COINIT_MULTITHREADED)
+#endif
+
+bool qt_wince__chmod(const char *file, int mode);
+bool qt_wince__wchmod(const wchar_t *file, int mode);
+
+#pragma warning(disable: 4273)
+HANDLE qt_wince_CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+
+// Printer ----------------------------------------------------------
+#define ETO_GLYPH_INDEX 0x0010
+
+// Graphics ---------------------------------------------------------
+#ifndef SM_CXCURSOR
+# define SM_CXCURSOR 13
+#endif
+#ifndef SM_CYCURSOR
+# define SM_CYCURSOR 14
+#endif
+BOOL qt_wince_SetWindowOrgEx( HDC hdc, int X, int Y, LPPOINT lpPoint );
+
+// Other stuff ------------------------------------------------------
+#define MWMO_ALERTABLE 0x0002
+// ### not the real values
+#define CREATE_NO_WINDOW 2
+#define CF_HDROP 15
+
+void *qt_wince_calloc(size_t num, size_t size);
+#if !defined(TLS_OUT_OF_INDEXES)
+# define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+DWORD qt_wince_GetThreadLocale(void);
+
+HANDLE qt_wince__beginthread(void( *start_address )( void * ), unsigned stack_size, void *arglist);
+
+unsigned long qt_wince__beginthreadex( void *security,
+ unsigned stack_size,
+ unsigned (__stdcall *start_address)(void *),
+ void *arglist,
+ unsigned initflag,
+ unsigned *thrdaddr );
+void qt_wince__endthreadex(unsigned nExitCode);
+
+
+// bsearch is needed for building the tiff plugin
+// otherwise it could go into qguifunctions_wce
+void *qt_wince_bsearch(const void *key,
+ const void *base,
+ size_t num,
+ size_t size,
+ int (__cdecl *compare)(const void *, const void *));
+
+// Missing typedefs
+#ifndef _TIME_T_DEFINED
+typedef unsigned long time_t;
+#define _TIME_T_DEFINED
+#endif
+typedef HANDLE HDROP;
+
+#ifndef WS_THICKFRAME
+#define WS_THICKFRAME WS_DLGFRAME
+#endif
+
+typedef UINT UWORD;
+
+// Missing definitions: not necessary equal to their Win32 values
+// (the goal is to just have a clean compilation of MFC)
+#define WS_MAXIMIZE 0
+#define WS_MINIMIZE 0
+#ifndef WS_EX_TOOLWINDOW
+#define WS_EX_TOOLWINDOW 0
+#endif
+#define WS_EX_NOPARENTNOTIFY 0
+#define WM_ENTERIDLE 0x0121
+#define WM_PRINT WM_PAINT
+#define WM_NCCREATE (0x0081)
+#define WM_PARENTNOTIFY 0
+#define WM_NCDESTROY (WM_APP-1)
+#ifndef SW_RESTORE
+#define SW_RESTORE (SW_SHOWNORMAL)
+#endif
+#define SW_NORMAL (SW_SHOWNORMAL)
+#define WAIT_OBJECT_0 0x00000000L
+#define DEFAULT_GUI_FONT SYSTEM_FONT
+#ifndef SWP_NOREDRAW
+#define SWP_NOREDRAW 0
+#endif
+#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
+#define HWND_TOPMOST ((HWND)-1)
+#define HWND_NOTOPMOST ((HWND)-2)
+#define PS_DOT 2
+#define PD_ALLPAGES 0
+#define PD_USEDEVMODECOPIES 0
+#define PD_NOSELECTION 0
+#define PD_HIDEPRINTTOFILE 0
+#define PD_NOPAGENUMS 0
+#define CF_METAFILEPICT 3
+#define MM_ANISOTROPIC 8
+#define KF_ALTDOWN 0x2000
+#define SPI_GETWORKAREA 48
+
+#ifndef WM_SETCURSOR
+ #define WM_SETCURSOR 0x0020
+ #define IDC_ARROW MAKEINTRESOURCE(32512)
+ #define IDC_IBEAM MAKEINTRESOURCE(32513)
+ #define IDC_WAIT MAKEINTRESOURCE(32514)
+ #define IDC_CROSS MAKEINTRESOURCE(32515)
+ #define IDC_UPARROW MAKEINTRESOURCE(32516)
+ #define IDC_SIZE MAKEINTRESOURCE(32646)
+ #define IDC_ICON MAKEINTRESOURCE(32512)
+ #define IDC_SIZENWSE MAKEINTRESOURCE(32642)
+ #define IDC_SIZENESW MAKEINTRESOURCE(32643)
+ #define IDC_SIZEWE MAKEINTRESOURCE(32644)
+ #define IDC_SIZENS MAKEINTRESOURCE(32645)
+ #define IDC_SIZEALL MAKEINTRESOURCE(32646)
+ #define IDC_NO MAKEINTRESOURCE(32648)
+ #define IDC_APPSTARTING MAKEINTRESOURCE(32650)
+ #define IDC_HELP MAKEINTRESOURCE(32651)
+ #define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+#define GMEM_MOVEABLE LMEM_MOVEABLE
+#define GPTR LPTR
+
+// WinCE: CESYSGEN prunes the following FRP defines,
+// and INTERNET_TRANSFER_TYPE_ASCII breaks in wininet.h
+#undef FTP_TRANSFER_TYPE_ASCII
+#define FTP_TRANSFER_TYPE_ASCII 0x00000001
+#undef FTP_TRANSFER_TYPE_BINARY
+#define FTP_TRANSFER_TYPE_BINARY 0x00000002
+
+typedef DWORD OLE_COLOR;
+
+// Define the Windows Styles which are not defined by MS
+#ifndef WS_POPUPWINDOW
+#define WS_POPUPWINDOW WS_POPUP|WS_BORDER|WS_SYSMENU|WS_CAPTION
+#endif
+
+#ifndef WS_OVERLAPPEDWINDOW
+#define WS_OVERLAPPEDWINDOW WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
+#endif
+
+#ifndef WS_TILED
+#define WS_TILED WS_OVERLAPPED
+#endif
+
+#ifndef WS_TILEDWINDOW
+#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
+#endif
+
+#ifndef WS_EX_CAPTIONOKBTN
+#define WS_EX_CAPTIONOKBTN 0x80000000L
+#endif
+
+#ifndef WS_EX_NODRAG
+#define WS_EX_NODRAG 0x40000000L
+#endif
+
+// As Windows CE lacks some standard functions used in Qt, these got
+// reimplented. Other projects do this as well and to not fill the
+// global namespace with this implementation, prepend qt_wince* and use
+// these versions inside of Qt.
+// The other declarations available in this file are being used per
+// define inside qplatformdefs.h of the corresponding WinCE mkspec.
+#define getenv_s(a,b,c,d) qt_wince_getenv_s(a,b,c,d)
+#define _putenv_s(a,b) qt_wince__putenv_s(a,b)
+#define _getpid() qt_wince__getpid()
+#define time_tToFt(a) qt_wince_time_tToFt(a)
+#define _getdrive() qt_wince__getdrive()
+#define _waccess(a,b) qt_wince__waccess(a,b)
+#define _wopen(a,b,c) qt_wince__wopen(a,b,c)
+#define _fdopen(a,b) qt_wince__fdopen(a,b)
+#define fdopen(a,b) qt_wince_fdopen(a,b)
+#define rewind(a) qt_wince_rewind(a)
+#define tmpfile() qt_wince_tmpfile()
+#define _rename(a,b) qt_wince__rename(a,b)
+#define _remove(a) qt_wince__remove(a)
+#define SetErrorMode(a) qt_wince_SetErrorMode(a)
+#define _chmod(a,b) qt_wince__chmod(a,b)
+#define _wchmod(a,b) qt_wince__wchmod(a,b)
+#define CreateFileA(a,b,c,d,e,f,g) qt_wince_CreateFileA(a,b,c,d,e,f,g)
+#define SetWindowOrgEx(a,b,c,d) qt_wince_SetWindowOrgEx(a,b,c,d)
+#define calloc(a,b) qt_wince_calloc(a,b)
+#define GetThreadLocale() qt_wince_GetThreadLocale()
+#define _beginthread(a,b,c) qt_wince__beginthread(a,b,c)
+#define _beginthreadex(a,b,c,d,e,f) qt_wince__beginthreadex(a,b,c,d,e,f)
+#define _endthreadex(a) qt_wince__endthreadex(a)
+#define bsearch(a,b,c,d,e) qt_wince_bsearch(a,b,c,d,e)
+
+#ifdef __cplusplus
+} // Extern C.
+#endif
+
+#endif // Q_OS_WINCE
+#endif // QFUNCTIONS_WCE_H
diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp
new file mode 100644
index 0000000000..783dbbfa37
--- /dev/null
+++ b/src/corelib/kernel/qmath.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = {
+ qreal(0.0),
+ qreal(0.024541228522912288),
+ qreal(0.049067674327418015),
+ qreal(0.073564563599667426),
+ qreal(0.098017140329560604),
+ qreal(0.1224106751992162),
+ qreal(0.14673047445536175),
+ qreal(0.17096188876030122),
+ qreal(0.19509032201612825),
+ qreal(0.2191012401568698),
+ qreal(0.24298017990326387),
+ qreal(0.26671275747489837),
+ qreal(0.29028467725446233),
+ qreal(0.31368174039889152),
+ qreal(0.33688985339222005),
+ qreal(0.35989503653498811),
+ qreal(0.38268343236508978),
+ qreal(0.40524131400498986),
+ qreal(0.42755509343028208),
+ qreal(0.44961132965460654),
+ qreal(0.47139673682599764),
+ qreal(0.49289819222978404),
+ qreal(0.51410274419322166),
+ qreal(0.53499761988709715),
+ qreal(0.55557023301960218),
+ qreal(0.57580819141784534),
+ qreal(0.59569930449243336),
+ qreal(0.61523159058062682),
+ qreal(0.63439328416364549),
+ qreal(0.65317284295377676),
+ qreal(0.67155895484701833),
+ qreal(0.68954054473706683),
+ qreal(0.70710678118654746),
+ qreal(0.72424708295146689),
+ qreal(0.74095112535495911),
+ qreal(0.75720884650648446),
+ qreal(0.77301045336273699),
+ qreal(0.78834642762660623),
+ qreal(0.80320753148064483),
+ qreal(0.81758481315158371),
+ qreal(0.83146961230254524),
+ qreal(0.84485356524970701),
+ qreal(0.85772861000027212),
+ qreal(0.87008699110871135),
+ qreal(0.88192126434835494),
+ qreal(0.89322430119551532),
+ qreal(0.90398929312344334),
+ qreal(0.91420975570353069),
+ qreal(0.92387953251128674),
+ qreal(0.93299279883473885),
+ qreal(0.94154406518302081),
+ qreal(0.94952818059303667),
+ qreal(0.95694033573220894),
+ qreal(0.96377606579543984),
+ qreal(0.97003125319454397),
+ qreal(0.97570213003852857),
+ qreal(0.98078528040323043),
+ qreal(0.98527764238894122),
+ qreal(0.98917650996478101),
+ qreal(0.99247953459870997),
+ qreal(0.99518472667219682),
+ qreal(0.99729045667869021),
+ qreal(0.99879545620517241),
+ qreal(0.99969881869620425),
+ qreal(1.0),
+ qreal(0.99969881869620425),
+ qreal(0.99879545620517241),
+ qreal(0.99729045667869021),
+ qreal(0.99518472667219693),
+ qreal(0.99247953459870997),
+ qreal(0.98917650996478101),
+ qreal(0.98527764238894122),
+ qreal(0.98078528040323043),
+ qreal(0.97570213003852857),
+ qreal(0.97003125319454397),
+ qreal(0.96377606579543984),
+ qreal(0.95694033573220894),
+ qreal(0.94952818059303667),
+ qreal(0.94154406518302081),
+ qreal(0.93299279883473885),
+ qreal(0.92387953251128674),
+ qreal(0.91420975570353069),
+ qreal(0.90398929312344345),
+ qreal(0.89322430119551521),
+ qreal(0.88192126434835505),
+ qreal(0.87008699110871146),
+ qreal(0.85772861000027212),
+ qreal(0.84485356524970723),
+ qreal(0.83146961230254546),
+ qreal(0.81758481315158371),
+ qreal(0.80320753148064494),
+ qreal(0.78834642762660634),
+ qreal(0.7730104533627371),
+ qreal(0.75720884650648468),
+ qreal(0.74095112535495899),
+ qreal(0.72424708295146689),
+ qreal(0.70710678118654757),
+ qreal(0.68954054473706705),
+ qreal(0.67155895484701855),
+ qreal(0.65317284295377664),
+ qreal(0.63439328416364549),
+ qreal(0.61523159058062693),
+ qreal(0.59569930449243347),
+ qreal(0.57580819141784545),
+ qreal(0.55557023301960218),
+ qreal(0.53499761988709715),
+ qreal(0.51410274419322177),
+ qreal(0.49289819222978415),
+ qreal(0.47139673682599786),
+ qreal(0.44961132965460687),
+ qreal(0.42755509343028203),
+ qreal(0.40524131400498992),
+ qreal(0.38268343236508989),
+ qreal(0.35989503653498833),
+ qreal(0.33688985339222033),
+ qreal(0.31368174039889141),
+ qreal(0.29028467725446239),
+ qreal(0.26671275747489848),
+ qreal(0.24298017990326407),
+ qreal(0.21910124015687005),
+ qreal(0.19509032201612861),
+ qreal(0.17096188876030122),
+ qreal(0.1467304744553618),
+ qreal(0.12241067519921635),
+ qreal(0.098017140329560826),
+ qreal(0.073564563599667732),
+ qreal(0.049067674327417966),
+ qreal(0.024541228522912326),
+ qreal(0.0),
+ qreal(-0.02454122852291208),
+ qreal(-0.049067674327417724),
+ qreal(-0.073564563599667496),
+ qreal(-0.09801714032956059),
+ qreal(-0.1224106751992161),
+ qreal(-0.14673047445536158),
+ qreal(-0.17096188876030097),
+ qreal(-0.19509032201612836),
+ qreal(-0.2191012401568698),
+ qreal(-0.24298017990326382),
+ qreal(-0.26671275747489825),
+ qreal(-0.29028467725446211),
+ qreal(-0.31368174039889118),
+ qreal(-0.33688985339222011),
+ qreal(-0.35989503653498811),
+ qreal(-0.38268343236508967),
+ qreal(-0.40524131400498969),
+ qreal(-0.42755509343028181),
+ qreal(-0.44961132965460665),
+ qreal(-0.47139673682599764),
+ qreal(-0.49289819222978393),
+ qreal(-0.51410274419322155),
+ qreal(-0.53499761988709693),
+ qreal(-0.55557023301960196),
+ qreal(-0.57580819141784534),
+ qreal(-0.59569930449243325),
+ qreal(-0.61523159058062671),
+ qreal(-0.63439328416364527),
+ qreal(-0.65317284295377653),
+ qreal(-0.67155895484701844),
+ qreal(-0.68954054473706683),
+ qreal(-0.70710678118654746),
+ qreal(-0.72424708295146678),
+ qreal(-0.74095112535495888),
+ qreal(-0.75720884650648423),
+ qreal(-0.77301045336273666),
+ qreal(-0.78834642762660589),
+ qreal(-0.80320753148064505),
+ qreal(-0.81758481315158382),
+ qreal(-0.83146961230254524),
+ qreal(-0.84485356524970701),
+ qreal(-0.85772861000027201),
+ qreal(-0.87008699110871135),
+ qreal(-0.88192126434835494),
+ qreal(-0.89322430119551521),
+ qreal(-0.90398929312344312),
+ qreal(-0.91420975570353047),
+ qreal(-0.92387953251128652),
+ qreal(-0.93299279883473896),
+ qreal(-0.94154406518302081),
+ qreal(-0.94952818059303667),
+ qreal(-0.95694033573220882),
+ qreal(-0.96377606579543984),
+ qreal(-0.97003125319454397),
+ qreal(-0.97570213003852846),
+ qreal(-0.98078528040323032),
+ qreal(-0.98527764238894111),
+ qreal(-0.9891765099647809),
+ qreal(-0.99247953459871008),
+ qreal(-0.99518472667219693),
+ qreal(-0.99729045667869021),
+ qreal(-0.99879545620517241),
+ qreal(-0.99969881869620425),
+ qreal(-1.0),
+ qreal(-0.99969881869620425),
+ qreal(-0.99879545620517241),
+ qreal(-0.99729045667869021),
+ qreal(-0.99518472667219693),
+ qreal(-0.99247953459871008),
+ qreal(-0.9891765099647809),
+ qreal(-0.98527764238894122),
+ qreal(-0.98078528040323043),
+ qreal(-0.97570213003852857),
+ qreal(-0.97003125319454397),
+ qreal(-0.96377606579543995),
+ qreal(-0.95694033573220894),
+ qreal(-0.94952818059303679),
+ qreal(-0.94154406518302092),
+ qreal(-0.93299279883473907),
+ qreal(-0.92387953251128663),
+ qreal(-0.91420975570353058),
+ qreal(-0.90398929312344334),
+ qreal(-0.89322430119551532),
+ qreal(-0.88192126434835505),
+ qreal(-0.87008699110871146),
+ qreal(-0.85772861000027223),
+ qreal(-0.84485356524970723),
+ qreal(-0.83146961230254546),
+ qreal(-0.81758481315158404),
+ qreal(-0.80320753148064528),
+ qreal(-0.78834642762660612),
+ qreal(-0.77301045336273688),
+ qreal(-0.75720884650648457),
+ qreal(-0.74095112535495911),
+ qreal(-0.724247082951467),
+ qreal(-0.70710678118654768),
+ qreal(-0.68954054473706716),
+ qreal(-0.67155895484701866),
+ qreal(-0.65317284295377709),
+ qreal(-0.63439328416364593),
+ qreal(-0.61523159058062737),
+ qreal(-0.59569930449243325),
+ qreal(-0.57580819141784523),
+ qreal(-0.55557023301960218),
+ qreal(-0.53499761988709726),
+ qreal(-0.51410274419322188),
+ qreal(-0.49289819222978426),
+ qreal(-0.47139673682599792),
+ qreal(-0.44961132965460698),
+ qreal(-0.42755509343028253),
+ qreal(-0.40524131400499042),
+ qreal(-0.38268343236509039),
+ qreal(-0.359895036534988),
+ qreal(-0.33688985339222),
+ qreal(-0.31368174039889152),
+ qreal(-0.2902846772544625),
+ qreal(-0.26671275747489859),
+ qreal(-0.24298017990326418),
+ qreal(-0.21910124015687016),
+ qreal(-0.19509032201612872),
+ qreal(-0.17096188876030177),
+ qreal(-0.14673047445536239),
+ qreal(-0.12241067519921603),
+ qreal(-0.098017140329560506),
+ qreal(-0.073564563599667412),
+ qreal(-0.049067674327418091),
+ qreal(-0.024541228522912448)
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
new file mode 100644
index 0000000000..27c27dc4d1
--- /dev/null
+++ b/src/corelib/kernel/qmath.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATH_H
+#define QMATH_H
+
+#include <math.h>
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_SYMBIAN
+# include <e32math.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#define QT_SINE_TABLE_SIZE 256
+
+extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE];
+
+inline int qCeil(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return int(ceilf(float(v)));
+ else
+#endif
+ return int(ceil(v));
+}
+
+inline int qFloor(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return int(floorf(float(v)));
+ else
+#endif
+ return int(floor(v));
+}
+
+inline qreal qFabs(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return fabsf(float(v));
+ else
+#endif
+ return fabs(v);
+}
+
+inline qreal qSin(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal sin_v;
+ Math::Sin(sin_v, static_cast<TReal>(v));
+ return static_cast<qreal>(sin_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sinf(float(v));
+ else
+# endif
+ return sin(v);
+#endif
+}
+
+inline qreal qCos(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal cos_v;
+ Math::Cos(cos_v, static_cast<TReal>(v));
+ return static_cast<qreal>(cos_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return cosf(float(v));
+ else
+# endif
+ return cos(v);
+#endif
+}
+
+inline qreal qTan(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal tan_v;
+ Math::Tan(tan_v, static_cast<TReal>(v));
+ return static_cast<qreal>(tan_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return tanf(float(v));
+ else
+# endif
+ return tan(v);
+#endif
+}
+
+inline qreal qAcos(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal acos_v;
+ Math::ACos(acos_v, static_cast<TReal>(v));
+ return static_cast<qreal>(acos_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return acosf(float(v));
+ else
+# endif
+ return acos(v);
+#endif
+}
+
+inline qreal qAsin(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal asin_v;
+ Math::ASin(asin_v, static_cast<TReal>(v));
+ return static_cast<qreal>(asin_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return asinf(float(v));
+ else
+# endif
+ return asin(v);
+#endif
+}
+
+inline qreal qAtan(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal atan_v;
+ Math::ATan(atan_v, static_cast<TReal>(v));
+ return static_cast<qreal>(atan_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return atanf(float(v));
+ else
+# endif
+ return atan(v);
+#endif
+}
+
+inline qreal qAtan2(qreal x, qreal y)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal atan2_v;
+ Math::ATan(atan2_v, static_cast<TReal>(x), static_cast<TReal>(y));
+ return static_cast<qreal>(atan2_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return atan2f(float(x), float(y));
+ else
+# endif
+ return atan2(x, y);
+#endif
+}
+
+inline qreal qSqrt(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal sqrt_v;
+ Math::Sqrt(sqrt_v, static_cast<TReal>(v));
+ return static_cast<qreal>(sqrt_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sqrtf(float(v));
+ else
+# endif
+ return sqrt(v);
+#endif
+}
+
+inline qreal qLn(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return logf(float(v));
+ else
+#endif
+ return log(v);
+}
+
+inline qreal qExp(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal exp_v;
+ Math::Exp(exp_v, static_cast<TReal>(v));
+ return static_cast<qreal>(exp_v);
+#else
+ // only one signature
+ // exists, exp(double)
+ return exp(v);
+#endif
+}
+
+inline qreal qPow(qreal x, qreal y)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal pow_v;
+ Math::Pow(pow_v, static_cast<TReal>(x), static_cast<TReal>(y));
+ return static_cast<qreal>(pow_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return powf(float(x), float(y));
+ else
+# endif
+ return pow(x, y);
+#endif
+}
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+inline qreal qFastSin(qreal x)
+{
+ int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int ci = si + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
+}
+
+inline qreal qFastCos(qreal x)
+{
+ int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int si = ci + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMATH_H
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
new file mode 100644
index 0000000000..91c5f56888
--- /dev/null
+++ b/src/corelib/kernel/qmath.qdoc
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtCore/qmath.h>
+ \title Math Functions
+ \ingroup funclists
+ \brief The <QtCore/qmath.h> header provides various math functions.
+ \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm
+*/
+
+/*!
+ \fn int qCeil(qreal v)
+ Return 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.
+
+ \relates <QtCore/qmath.h>
+ \sa qFloor()
+*/
+
+/*!
+ \fn int qFloor(qreal v)
+ Return 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.
+
+ \relates <QtCore/qmath.h>
+ \sa qCeil()
+*/
+
+/*!
+ \fn qreal qFabs(qreal v)
+ Returns the absolute value of \a v as a qreal.
+*/
+
+/*!
+ \fn qreal qSin(qreal v)
+ Returns the sine of the angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qCos(), qTan()
+*/
+
+/*!
+ \fn qreal qCos(qreal v)
+ Returns the cosine of an angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qTan()
+*/
+
+/*!
+ \fn qreal qTan(qreal v)
+ Returns the tangent of an angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qCos()
+*/
+
+/*!
+ \fn qreal qAcos(qreal v)
+ Returns the arccosine of \a v as an angle in radians.
+ Arccosine is the inverse operation of cosine.
+
+ \relates <QtCore/qmath.h>
+ \sa qAtan(), qAsin(), qCos()
+*/
+
+/*!
+ \fn qreal qAsin(qreal v)
+ Returns the arcsine of \a v as an angle in radians.
+ Arcsine is the inverse operation of sine.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qAtan(), qAcos()
+*/
+
+/*!
+ \fn qreal qAtan(qreal v)
+ Returns the arctangent of \a v as an angle in radians.
+ Arctangent is the inverse operation of tangent.
+
+ \relates <QtCore/qmath.h>
+ \sa qTan(), qAcos(), qAsin()
+*/
+
+/*!
+ \fn qreal qAtan2(qreal x, qreal y)
+ Returns the arctangent of a point specified by the coordinates \a x and \a y.
+ This function will return the angle and its direction.
+
+ \relates <QtCore/qmath.h>
+ \sa qAtan()
+*/
+
+/*!
+ \fn qreal qSqrt(qreal v)
+ Returns the square root of \a v.
+ This function returns a NaN if \a v is a negative number.
+
+ \relates <QtCore/qmath.h>
+ \sa qPow()
+*/
+
+/*!
+ \fn qreal qLn(qreal v)
+ Returns the natural logarithm of \a v. Natural logarithm uses base e.
+
+ \relates <QtCore/qmath.h>
+ \sa qExp()
+*/
+
+/*!
+ \fn qreal qExp(qreal v)
+ Returns the exponential function of \c e to the power of \a v.
+
+ \relates <QtCore/qmath.h>
+ \sa qLn()
+*/
+
+/*!
+ \fn qreal qPow(qreal x, qreal y)
+ Returns the value of \a x raised to the power of \a y.
+ That is, \a x is the base and \a y is the exponent.
+
+ \relates <QtCore/qmath.h>
+ \sa qSqrt()
+*/
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
new file mode 100644
index 0000000000..e671056466
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -0,0 +1,2778 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobject.h"
+#include "qmetatype.h"
+#include "qobject.h"
+
+#include <qcoreapplication.h>
+#include <qcoreevent.h>
+#include <qdatastream.h>
+#include <qstringlist.h>
+#include <qthread.h>
+#include <qvarlengtharray.h>
+#include <qvariant.h>
+#include <qhash.h>
+#include <qdebug.h>
+#include <qsemaphore.h>
+
+#include "private/qobject_p.h"
+#include "private/qmetaobject_p.h"
+
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaObject
+
+ \brief The QMetaObject class contains meta-information about Qt
+ objects.
+
+ \ingroup objectmodel
+
+ The Qt \l{Meta-Object System} in Qt is responsible for the
+ signals and slots inter-object communication mechanism, runtime
+ type information, and the Qt property system. A single
+ QMetaObject instance is created for each QObject subclass that is
+ used in an application, and this instance stores all the
+ meta-information for the QObject subclass. This object is
+ available as QObject::metaObject().
+
+ This class is not normally required for application programming,
+ but it is useful if you write meta-applications, such as scripting
+ engines or GUI builders.
+
+ The functions you are most likely to find useful are these:
+ \list
+ \o className() returns the name of a class.
+ \o superClass() returns the superclass's meta-object.
+ \o method() and methodCount() provide information
+ about a class's meta-methods (signals, slots and other
+ \l{Q_INVOKABLE}{invokable} member functions).
+ \o enumerator() and enumeratorCount() and provide information about
+ a class's enumerators.
+ \o propertyCount() and property() provide information about a
+ class's properties.
+ \o constructor() and constructorCount() provide information
+ about a class's meta-constructors.
+ \endlist
+
+ The index functions indexOfConstructor(), indexOfMethod(),
+ indexOfEnumerator(), and indexOfProperty() map names of constructors,
+ member functions, enumerators, or properties to indexes in the
+ meta-object. For example, Qt uses indexOfMethod() internally when you
+ connect a signal to a slot.
+
+ Classes can also have a list of \e{name}--\e{value} pairs of
+ additional class information, stored in QMetaClassInfo objects.
+ The number of pairs is returned by classInfoCount(), single pairs
+ are returned by classInfo(), and you can search for pairs with
+ indexOfClassInfo().
+
+ \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
+ {Meta-Object System}
+*/
+
+/*!
+ \enum QMetaObject::Call
+
+ \internal
+
+ \value InvokeSlot
+ \value EmitSignal
+ \value ReadProperty
+ \value WriteProperty
+ \value ResetProperty
+ \value QueryPropertyDesignable
+ \value QueryPropertyScriptable
+ \value QueryPropertyStored
+ \value QueryPropertyEditable
+ \value QueryPropertyUser
+ \value CreateInstance
+*/
+
+/*!
+ \enum QMetaMethod::Access
+
+ This enum describes the access level of a method, following the conventions used in C++.
+
+ \value Private
+ \value Protected
+ \value Public
+*/
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+
+
+/*!
+ \since 4.5
+
+ 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,
+ \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
+ no suitable constructor is available.
+
+ Note that only constructors that are declared with the Q_INVOKABLE
+ modifier are made available through the meta-object system.
+
+ \sa Q_ARG(), constructor()
+*/
+QObject *QMetaObject::newInstance(QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9) const
+{
+ 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()};
+
+ int paramCount;
+ for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
+ int len = 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 0;
+
+ QVariant ret(QMetaType::QObjectStar, (void*)0);
+ void *param[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
+ val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
+
+ if (static_metacall(CreateInstance, idx, param) >= 0)
+ return 0;
+ return *reinterpret_cast<QObject**>(param[0]);
+}
+
+/*!
+ \internal
+*/
+int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
+{
+ const QMetaObjectExtraData *extra = reinterpret_cast<const QMetaObjectExtraData *>(d.extradata);
+ if (priv(d.data)->revision >= 6) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ extra->static_metacall(0, cl, idx, argv);
+ return -1;
+ } else if (priv(d.data)->revision >= 2) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ typedef int (*OldMetacall)(QMetaObject::Call, int, void **);
+ OldMetacall o = reinterpret_cast<OldMetacall>(extra->static_metacall);
+ return o(cl, idx, argv);
+ }
+ return 0;
+}
+
+/*!
+ \internal
+*/
+int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
+{
+ if (QMetaObject *mo = object->d_ptr->metaObject)
+ return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
+ else
+ return object->qt_metacall(cl, idx, argv);
+}
+
+/*!
+ \fn const char *QMetaObject::className() const
+
+ Returns the class name.
+
+ \sa superClass()
+*/
+
+/*!
+ \fn QMetaObject *QMetaObject::superClass() const
+
+ Returns the meta-object of the superclass, or 0 if there is no
+ such object.
+
+ \sa className()
+*/
+
+/*!
+ \internal
+
+ Returns \a obj if object \a obj inherits from this
+ meta-object; otherwise returns 0.
+*/
+QObject *QMetaObject::cast(QObject *obj) const
+{
+ if (obj) {
+ const QMetaObject *m = obj->metaObject();
+ do {
+ if (m == this)
+ return obj;
+ } while ((m = m->d.superdata));
+ }
+ return 0;
+}
+
+/*!
+ \internal
+
+ Returns \a obj if object \a obj inherits from this
+ meta-object; otherwise returns 0.
+*/
+const QObject *QMetaObject::cast(const QObject *obj) const
+{
+ if (obj) {
+ const QMetaObject *m = obj->metaObject();
+ do {
+ if (m == this)
+ return obj;
+ } while ((m = m->d.superdata));
+ }
+ return 0;
+}
+
+#ifndef QT_NO_TRANSLATION
+/*!
+ \internal
+*/
+QString QMetaObject::tr(const char *s, const char *c) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::tr(const char *s, const char *c, int n) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::trUtf8(const char *s, const char *c) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::trUtf8(const char *s, const char *c, int n) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8, n);
+}
+#endif // QT_NO_TRANSLATION
+
+/*!
+ Returns the method offset for this class; i.e. the index position
+ of this class's first member function.
+
+ The offset is the sum of all the methods in the class's
+ superclasses (which is always positive since QObject has the
+ deleteLater() slot and a destroyed() signal).
+
+ \sa method(), methodCount(), indexOfMethod()
+*/
+int QMetaObject::methodOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->methodCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+
+/*!
+ Returns the enumerator offset for this class; i.e. the index
+ position of this class's first enumerator.
+
+ If the class has no superclasses with enumerators, the offset is
+ 0; otherwise the offset is the sum of all the enumerators in the
+ class's superclasses.
+
+ \sa enumerator(), enumeratorCount(), indexOfEnumerator()
+*/
+int QMetaObject::enumeratorOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->enumeratorCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ Returns the property offset for this class; i.e. the index
+ position of this class's first property.
+
+ The offset is the sum of all the properties in the class's
+ superclasses (which is always positive since QObject has the
+ name() property).
+
+ \sa property(), propertyCount(), indexOfProperty()
+*/
+int QMetaObject::propertyOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->propertyCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ Returns the class information offset for this class; i.e. the
+ index position of this class's first class information item.
+
+ If the class has no superclasses with class information, the
+ offset is 0; otherwise the offset is the sum of all the class
+ information items in the class's superclasses.
+
+ \sa classInfo(), classInfoCount(), indexOfClassInfo()
+*/
+int QMetaObject::classInfoOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->classInfoCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ \since 4.5
+
+ Returns the number of constructors in this class.
+
+ \sa constructor(), indexOfConstructor()
+*/
+int QMetaObject::constructorCount() const
+{
+ if (priv(d.data)->revision < 2)
+ return 0;
+ return priv(d.data)->constructorCount;
+}
+
+/*!
+ Returns the number of methods in this class, including the number of
+ properties provided by each base class. These include signals and slots
+ as well as normal member functions.
+
+ Use code like the following to obtain a QStringList containing the methods
+ specific to a given class:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp methodCount
+
+ \sa method(), methodOffset(), indexOfMethod()
+*/
+int QMetaObject::methodCount() const
+{
+ int n = priv(d.data)->methodCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->methodCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of enumerators in this class.
+
+ \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
+*/
+int QMetaObject::enumeratorCount() const
+{
+ int n = priv(d.data)->enumeratorCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->enumeratorCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of properties in this class, including the number of
+ properties provided by each base class.
+
+ Use code like the following to obtain a QStringList containing the properties
+ specific to a given class:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp propertyCount
+
+ \sa property(), propertyOffset(), indexOfProperty()
+*/
+int QMetaObject::propertyCount() const
+{
+ int n = priv(d.data)->propertyCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->propertyCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of items of class information in this class.
+
+ \sa classInfo(), classInfoOffset(), indexOfClassInfo()
+*/
+int QMetaObject::classInfoCount() const
+{
+ int n = priv(d.data)->classInfoCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->classInfoCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/** \internal
+* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
+* the baseObject
+* \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
+* \a normalizeStringData set to true if we should do a second pass for old moc generated files normalizing all the symbols.
+*/
+template<int MethodType>
+static inline int indexOfMethodRelative(const QMetaObject **baseObject,
+ const char *method,
+ bool normalizeStringData)
+{
+ for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
+ int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4)
+ ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
+ const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4)
+ ? (priv(m->d.data)->signalCount) : 0;
+ if (!normalizeStringData) {
+ for (; i >= end; --i) {
+ const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i];
+ if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {
+ *baseObject = m;
+ return i;
+ }
+ }
+ } else if (priv(m->d.data)->revision < 5) {
+ for (; i >= end; --i) {
+ const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]);
+ const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata);
+ if (normalizedSignature == method) {
+ *baseObject = m;
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+/*!
+ \since 4.5
+
+ Finds \a constructor and returns its index; otherwise returns -1.
+
+ Note that the \a constructor has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa constructor(), constructorCount(), normalizedSignature()
+*/
+int QMetaObject::indexOfConstructor(const char *constructor) const
+{
+ if (priv(d.data)->revision < 2)
+ return -1;
+ for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
+ const char *data = d.stringdata + d.data[priv(d.data)->constructorData + 5*i];
+ if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*!
+ Finds \a method and returns its index; otherwise returns -1.
+
+ Note that the \a method has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa method(), methodCount(), methodOffset(), normalizedSignature()
+*/
+int QMetaObject::indexOfMethod(const char *method) const
+{
+ const QMetaObject *m = this;
+ int i = indexOfMethodRelative<0>(&m, method, false);
+ if (i < 0) {
+ m = this;
+ i = indexOfMethodRelative<0>(&m, method, true);
+ }
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+/*!
+ Finds \a signal and returns its index; otherwise returns -1.
+
+ This is the same as indexOfMethod(), except that it will return
+ -1 if the method exists but isn't a signal.
+
+ Note that the \a signal has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
+*/
+int QMetaObject::indexOfSignal(const char *signal) const
+{
+ const QMetaObject *m = this;
+ int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false);
+ if (i < 0) {
+ m = this;
+ i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true);
+ }
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+/*! \internal
+ Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
+
+ \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
+*/
+int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
+ const char *signal,
+ bool normalizeStringData)
+{
+ int i = indexOfMethodRelative<MethodSignal>(baseObject, signal, normalizeStringData);
+#ifndef QT_NO_DEBUG
+ const QMetaObject *m = *baseObject;
+ if (i >= 0 && m && m->d.superdata) {
+ int conflict = m->d.superdata->indexOfMethod(signal);
+ if (conflict >= 0)
+ qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
+ signal, m->d.superdata->d.stringdata, m->d.stringdata);
+ }
+#endif
+ return i;
+}
+
+/*!
+ Finds \a slot and returns its index; otherwise returns -1.
+
+ This is the same as indexOfMethod(), except that it will return
+ -1 if the method exists but isn't a slot.
+
+ \sa indexOfMethod(), method(), methodCount(), methodOffset()
+*/
+int QMetaObject::indexOfSlot(const char *slot) const
+{
+ const QMetaObject *m = this;
+ int i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
+ if (i < 0)
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+// same as indexOfSignalRelative but for slots.
+int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
+ const char *slot,
+ bool normalizeStringData)
+{
+ return indexOfMethodRelative<MethodSlot>(m, slot, normalizeStringData);
+}
+
+static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
+{
+ while (self) {
+ if (strcmp(self->d.stringdata, name) == 0)
+ return self;
+ if (self->d.extradata) {
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *e;
+ Q_ASSERT(priv(self->d.data)->revision >= 2);
+#else
+ const QMetaObject **e;
+ if (priv(self->d.data)->revision < 2) {
+ e = (const QMetaObject**)(self->d.extradata);
+ } else
+#endif
+ {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata);
+ e = extra->objects;
+ }
+ if (e) {
+ while (*e) {
+#ifdef Q_NO_DATA_RELOCATION
+ if (const QMetaObject *m =QMetaObject_findMetaObject(&((*e)()), name))
+#else
+ if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
+#endif
+ return m;
+ ++e;
+ }
+ }
+ }
+ self = self->d.superdata;
+ }
+ return self;
+}
+
+/*!
+ Finds enumerator \a name and returns its index; otherwise returns
+ -1.
+
+ \sa enumerator(), enumeratorCount(), enumeratorOffset()
+*/
+int QMetaObject::indexOfEnumerator(const char *name) const
+{
+ const QMetaObject *m = this;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ for (int i = d->enumeratorCount - 1; i >= 0; --i) {
+ const char *prop = m->d.stringdata + m->d.data[d->enumeratorData + 4*i];
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->enumeratorOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+ return -1;
+}
+
+/*!
+ Finds property \a name and returns its index; otherwise returns
+ -1.
+
+ \sa property(), propertyCount(), propertyOffset()
+*/
+int QMetaObject::indexOfProperty(const char *name) const
+{
+ const QMetaObject *m = this;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ for (int i = d->propertyCount-1; i >= 0; --i) {
+ const char *prop = m->d.stringdata + m->d.data[d->propertyData + 3*i];
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->propertyOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+
+ if (priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)) {
+ QAbstractDynamicMetaObject *me =
+ const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
+
+ return me->createProperty(name, 0);
+ }
+
+ return -1;
+}
+
+/*!
+ Finds class information item \a name and returns its index;
+ otherwise returns -1.
+
+ \sa classInfo(), classInfoCount(), classInfoOffset()
+*/
+int QMetaObject::indexOfClassInfo(const char *name) const
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
+ if (strcmp(name, m->d.stringdata
+ + m->d.data[priv(m->d.data)->classInfoData + 2*i]) == 0) {
+ i += m->classInfoOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ return i;
+}
+
+/*!
+ \since 4.5
+
+ Returns the meta-data for the constructor with the given \a index.
+
+ \sa constructorCount(), newInstance()
+*/
+QMetaMethod QMetaObject::constructor(int index) const
+{
+ int i = index;
+ QMetaMethod result;
+ if (priv(d.data)->revision >= 2 && i >= 0 && i < priv(d.data)->constructorCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->constructorData + 5*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the method with the given \a index.
+
+ \sa methodCount(), methodOffset(), indexOfMethod()
+*/
+QMetaMethod QMetaObject::method(int index) const
+{
+ int i = index;
+ i -= methodOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->method(index);
+
+ QMetaMethod result;
+ if (i >= 0 && i < priv(d.data)->methodCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->methodData + 5*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the enumerator with the given \a index.
+
+ \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
+*/
+QMetaEnum QMetaObject::enumerator(int index) const
+{
+ int i = index;
+ i -= enumeratorOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->enumerator(index);
+
+ QMetaEnum result;
+ if (i >= 0 && i < priv(d.data)->enumeratorCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->enumeratorData + 4*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the property with the given \a index.
+ If no such property exists, a null QMetaProperty is returned.
+
+ \sa propertyCount(), propertyOffset(), indexOfProperty()
+*/
+QMetaProperty QMetaObject::property(int index) const
+{
+ int i = index;
+ i -= propertyOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->property(index);
+
+ QMetaProperty result;
+ if (i >= 0 && i < priv(d.data)->propertyCount) {
+ int handle = priv(d.data)->propertyData + 3*i;
+ int flags = d.data[handle + 2];
+ const char *type = d.stringdata + d.data[handle + 1];
+ result.mobj = this;
+ result.handle = handle;
+ result.idx = i;
+
+ if (flags & EnumOrFlag) {
+ result.menum = enumerator(indexOfEnumerator(type));
+ if (!result.menum.isValid()) {
+ QByteArray enum_name = type;
+ QByteArray scope_name = d.stringdata;
+ int s = enum_name.lastIndexOf("::");
+ if (s > 0) {
+ scope_name = enum_name.left(s);
+ enum_name = enum_name.mid(s + 2);
+ }
+ const QMetaObject *scope = 0;
+ if (scope_name == "Qt")
+ scope = &QObject::staticQtMetaObject;
+ else
+ scope = QMetaObject_findMetaObject(this, scope_name);
+ if (scope)
+ result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
+ }
+ }
+ }
+ return result;
+}
+
+/*!
+ \since 4.2
+
+ Returns the property that has the \c USER flag set to true.
+
+ \sa QMetaProperty::isUser()
+*/
+QMetaProperty QMetaObject::userProperty() const
+{
+ const int propCount = propertyCount();
+ for (int i = propCount - 1; i >= 0; --i) {
+ const QMetaProperty prop = property(i);
+ if (prop.isUser())
+ return prop;
+ }
+ return QMetaProperty();
+}
+
+/*!
+ Returns the meta-data for the item of class information with the
+ given \a index.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 0
+
+ \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
+ */
+QMetaClassInfo QMetaObject::classInfo(int index) const
+{
+ int i = index;
+ i -= classInfoOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->classInfo(index);
+
+ QMetaClassInfo result;
+ if (i >= 0 && i < priv(d.data)->classInfoCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->classInfoData + 2*i;
+ }
+ return result;
+}
+
+/*!
+ Returns true if the \a signal and \a method arguments are
+ compatible; otherwise returns false.
+
+ Both \a signal and \a method are expected to be normalized.
+
+ \sa normalizedSignature()
+*/
+bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
+{
+ const char *s1 = signal;
+ const char *s2 = method;
+ while (*s1++ != '(') { } // scan to first '('
+ 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);
+ if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
+ return true; // method has less args
+ return false;
+}
+
+static void qRemoveWhitespace(const char *s, char *d)
+{
+ char last = 0;
+ while (*s && is_space(*s))
+ s++;
+ while (*s) {
+ while (*s && !is_space(*s))
+ last = *d++ = *s++;
+ while (*s && is_space(*s))
+ s++;
+ if (*s && ((is_ident_char(*s) && is_ident_char(last))
+ || ((*s == ':') && (last == '<')))) {
+ last = *d++ = ' ';
+ }
+ }
+ *d = '\0';
+}
+
+static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
+{
+ const char *t = d;
+ while (*d && (templdepth
+ || (*d != ',' && *d != ')'))) {
+ if (*d == '<')
+ ++templdepth;
+ if (*d == '>')
+ --templdepth;
+ ++d;
+ }
+ if (strncmp("void", t, d - t) != 0)
+ result += normalizeTypeInternal(t, d);
+
+ return d;
+}
+
+
+/*!
+ \since 4.2
+
+ Normalizes a \a type.
+
+ See QMetaObject::normalizedSignature() for a description on how
+ Qt normalizes.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 1
+
+ \sa normalizedSignature()
+ */
+QByteArray QMetaObject::normalizedType(const char *type)
+{
+ QByteArray result;
+
+ if (!type || !*type)
+ return result;
+
+ QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
+ qRemoveWhitespace(type, stackbuf.data());
+ int templdepth = 0;
+ qNormalizeType(stackbuf.data(), templdepth, result);
+
+ return result;
+}
+
+/*!
+ Normalizes the signature of the given \a method.
+
+ Qt uses normalized signatures to decide whether two given signals
+ and slots are compatible. Normalization reduces whitespace to a
+ minimum, moves 'const' to the front where appropriate, removes
+ 'const' from value types and replaces const references with
+ values.
+
+ \sa checkConnectArgs(), normalizedType()
+ */
+QByteArray QMetaObject::normalizedSignature(const char *method)
+{
+ QByteArray result;
+ if (!method || !*method)
+ return result;
+ int len = int(strlen(method));
+ QVarLengthArray<char> stackbuf(len + 1);
+ char *d = stackbuf.data();
+ qRemoveWhitespace(method, d);
+
+ result.reserve(len);
+
+ int argdepth = 0;
+ int templdepth = 0;
+ while (*d) {
+ if (argdepth == 1) {
+ d = qNormalizeType(d, templdepth, result);
+ if (!*d) //most likely an invalid signature.
+ break;
+ }
+ if (*d == '(')
+ ++argdepth;
+ if (*d == ')')
+ --argdepth;
+ result += *d++;
+ }
+
+ return result;
+}
+
+enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
+
+/*!
+ Invokes the \a member (a signal or a slot name) on the object \a
+ obj. Returns true if the member could be invoked. Returns 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:
+
+ \list
+ \o If \a type is Qt::DirectConnection, the member will be invoked immediately.
+
+ \o 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.
+
+ \o 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.
+
+ \o 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.
+ \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{QPushButton::animateClick()}{animateClick()} slot on a
+ QPushButton, use the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 2
+
+ 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
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 3
+
+ 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 doc/src/snippets/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,
+ const char *member,
+ Qt::ConnectionType type,
+ QGenericReturnArgument ret,
+ QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9)
+{
+ 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()};
+
+ int paramCount;
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
+ len = qstrlen(typeNames[paramCount]);
+ if (len <= 0)
+ break;
+ sig.append(typeNames[paramCount], len);
+ sig.append(',');
+ }
+ if (paramCount == 1)
+ sig.append(')'); // no parameters
+ else
+ sig[sig.size() - 1] = ')';
+ sig.append('\0');
+
+ int idx = obj->metaObject()->indexOfMethod(sig.constData());
+ if (idx < 0) {
+ QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
+ idx = obj->metaObject()->indexOfMethod(norm.constData());
+ }
+
+ if (idx < 0 || idx >= obj->metaObject()->methodCount()) {
+ qWarning("QMetaObject::invokeMethod: No such method %s::%s",
+ obj->metaObject()->className(), sig.constData());
+ return false;
+ }
+ QMetaMethod method = obj->metaObject()->method(idx);
+ return method.invoke(obj, type, ret,
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+}
+
+/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument());
+ \overload invokeMethod()
+
+ This overload always invokes the member using the connection type Qt::AutoConnection.
+*/
+
+/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType type,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+
+ \overload invokeMethod()
+
+ This overload can be used if the return value of the member is of no interest.
+*/
+
+/*!
+ \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+
+ \overload invokeMethod()
+
+ This overload invokes the member using the connection type Qt::AutoConnection and
+ ignores return values.
+*/
+
+/*!
+ \class QMetaMethod
+
+ \brief The QMetaMethod class provides meta-data about a member
+ function.
+
+ \ingroup objectmodel
+
+ A QMetaMethod has a methodType(), a signature(), a list of
+ parameterTypes() and parameterNames(), a return typeName(), a
+ tag(), and an access() specifier. You can use invoke() to invoke
+ the method on an arbitrary QObject.
+
+ \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
+*/
+
+/*!
+ \enum QMetaMethod::Attributes
+
+ \internal
+
+ \value Compatibility
+ \value Cloned
+ \value Scriptable
+*/
+
+/*!
+ \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ \enum QMetaMethod::MethodType
+
+ \value Method The function is a plain member function.
+ \value Signal The function is a signal.
+ \value Slot The function is a slot.
+ \value Constructor The function is a constructor.
+*/
+
+/*!
+ \fn QMetaMethod::QMetaMethod()
+ \internal
+*/
+
+/*!
+ Returns the signature of this method (e.g.,
+ \c{setValue(double)}).
+
+ \sa parameterTypes(), parameterNames()
+*/
+const char *QMetaMethod::signature() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns a list of parameter types.
+
+ \sa parameterNames(), signature()
+*/
+QList<QByteArray> QMetaMethod::parameterTypes() const
+{
+ QList<QByteArray> list;
+ if (!mobj)
+ return list;
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ while (*signature && *signature != ')' && *++signature != ')') {
+ const char *begin = signature;
+ int level = 0;
+ while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
+ if (*signature == '<')
+ ++level;
+ else if (*signature == '>')
+ --level;
+ ++signature;
+ }
+ list += QByteArray(begin, signature - begin);
+ }
+ return list;
+}
+
+/*!
+ Returns a list of parameter names.
+
+ \sa parameterTypes(), signature()
+*/
+QList<QByteArray> QMetaMethod::parameterNames() const
+{
+ QList<QByteArray> list;
+ if (!mobj)
+ return list;
+ const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
+ if (*names == 0) {
+ // do we have one or zero arguments?
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ if (*++signature != ')')
+ list += QByteArray();
+ } else {
+ --names;
+ do {
+ const char *begin = ++names;
+ while (*names && *names != ',')
+ ++names;
+ list += QByteArray(begin, names - begin);
+ } while (*names);
+ }
+ return list;
+}
+
+
+/*!
+ Returns the return type of this method, or an empty string if the
+ return type is \e void.
+*/
+const char *QMetaMethod::typeName() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 2];
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ Tags are special macros recognized by \c moc that make it
+ possible to add extra information about a method. For the moment,
+ \c moc doesn't support any special tags.
+*/
+const char *QMetaMethod::tag() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 3];
+}
+
+
+/*! \internal */
+int QMetaMethod::attributes() const
+{
+ if (!mobj)
+ return false;
+ return ((mobj->d.data[handle + 4])>>4);
+}
+
+/*!
+ \since 4.6
+
+ Returns this method's index.
+*/
+int QMetaMethod::methodIndex() const
+{
+ if (!mobj)
+ return -1;
+ return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+}
+
+/*!
+ \internal
+
+ Returns the method revision if one was
+ specified by Q_REVISION, otherwise returns 0.
+ */
+int QMetaMethod::revision() const
+{
+ if (!mobj)
+ return 0;
+ if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) {
+ int offset = priv(mobj->d.data)->methodData
+ + priv(mobj->d.data)->methodCount * 5
+ + (handle - priv(mobj->d.data)->methodData) / 5;
+ return mobj->d.data[offset];
+ }
+ return 0;
+}
+
+/*!
+ Returns the access specification of this method (private,
+ protected, or public).
+
+ Signals are always protected, meaning that you can only emit them
+ from the class or from a subclass.
+
+ \sa methodType()
+*/
+QMetaMethod::Access QMetaMethod::access() const
+{
+ if (!mobj)
+ return Private;
+ return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
+}
+
+/*!
+ Returns the type of this method (signal, slot, or method).
+
+ \sa access()
+*/
+QMetaMethod::MethodType QMetaMethod::methodType() const
+{
+ if (!mobj)
+ return QMetaMethod::Method;
+ return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
+}
+
+/*!
+ Invokes this method on the object \a object. Returns true if the member could be invoked.
+ Returns 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:
+
+ \list
+ \o If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
+
+ \o 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.
+
+ \o 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
+
+ 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.
+
+ 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.
+
+ To asynchronously invoke the
+ \l{QPushButton::animateClick()}{animateClick()} slot on a
+ QPushButton:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 6
+
+ 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
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 7
+
+ 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 doc/src/snippets/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.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
+*/
+bool QMetaMethod::invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9) const
+{
+ 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
+ // the trick here is to make a function signature out of the return type
+ // so that we can call normalizedSignature() and avoid duplicating code
+ QByteArray unnormalized;
+ int len = qstrlen(returnValue.name());
+
+ unnormalized.reserve(len + 3);
+ unnormalized = "_("; // the function is called "_"
+ unnormalized.append(returnValue.name());
+ unnormalized.append(')');
+
+ QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData());
+ normalized.truncate(normalized.length() - 1); // drop the ending ')'
+
+ if (qstrcmp(normalized.constData() + 2, retType) != 0)
+ return false;
+ }
+ }
+
+ // check argument count (we don't allow invoking a method if given too few arguments)
+ const char *typeNames[] = {
+ returnValue.name(),
+ val0.name(),
+ val1.name(),
+ val2.name(),
+ val3.name(),
+ val4.name(),
+ val5.name(),
+ val6.name(),
+ val7.name(),
+ val8.name(),
+ val9.name()
+ };
+ int paramCount;
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
+ if (qstrlen(typeNames[paramCount]) <= 0)
+ break;
+ }
+ int metaMethodArgumentCount = 0;
+ {
+ // based on QMetaObject::parameterNames()
+ const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
+ if (*names == 0) {
+ // do we have one or zero arguments?
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ if (*++signature != ')')
+ ++metaMethodArgumentCount;
+ } else {
+ --names;
+ do {
+ ++names;
+ while (*names && *names != ',')
+ ++names;
+ ++metaMethodArgumentCount;
+ } while (*names);
+ }
+ }
+ if (paramCount <= metaMethodArgumentCount)
+ return false;
+
+ // check connection type
+ QThread *currentThread = QThread::currentThread();
+ QThread *objectThread = object->thread();
+ if (connectionType == Qt::AutoConnection) {
+ connectionType = currentThread == objectThread
+ ? Qt::DirectConnection
+ : Qt::QueuedConnection;
+ }
+
+#ifdef QT_NO_THREAD
+ if (connectionType == Qt::BlockingQueuedConnection) {
+ connectionType = Qt::DirectConnection;
+ }
+#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()
+ };
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
+ int idx_relative = ((handle - priv(mobj->d.data)->methodData) / 5);
+ int idx_offset = mobj->methodOffset();
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (QMetaObjectPrivate::get(mobj)->revision >= 6 && mobj->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(mobj->d.extradata)->static_metacall : 0;
+
+ if (connectionType == Qt::DirectConnection) {
+ 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 (connectionType == Qt::QueuedConnection) {
+ if (returnValue.data()) {
+ qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
+ "queued connections");
+ return false;
+ }
+
+ int nargs = 1; // include return type
+ void **args = (void **) qMalloc(paramCount * sizeof(void *));
+ Q_CHECK_PTR(args);
+ int *types = (int *) qMalloc(paramCount * sizeof(int));
+ Q_CHECK_PTR(types);
+ types[0] = 0; // return type
+ args[0] = 0;
+
+ for (int i = 1; i < paramCount; ++i) {
+ types[i] = QMetaType::type(typeNames[i]);
+ if (types[i]) {
+ args[i] = QMetaType::construct(types[i], param[i]);
+ ++nargs;
+ } else if (param[i]) {
+ qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
+ typeNames[i]);
+ for (int x = 1; x < i; ++x) {
+ if (types[x] && args[x])
+ QMetaType::destroy(types[x], args[x]);
+ }
+ qFree(types);
+ qFree(args);
+ return false;
+ }
+ }
+
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
+ 0, -1, nargs, types, args));
+ } else { // blocking queued connection
+#ifndef QT_NO_THREAD
+ if (currentThread == objectThread) {
+ qWarning("QMetaMethod::invoke: Dead lock detected in "
+ "BlockingQueuedConnection: Receiver is %s(%p)",
+ mobj->className(), object);
+ }
+
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
+ 0, -1, 0, 0, param, &semaphore));
+ semaphore.acquire();
+#endif // QT_NO_THREAD
+ }
+ return true;
+}
+
+/*! \fn bool QMetaMethod::invoke(QObject *object,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ \overload invoke()
+
+ This overload always invokes this method using the connection type Qt::AutoConnection.
+*/
+
+/*! \fn bool QMetaMethod::invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+
+ \overload invoke()
+
+ This overload can be used if the return value of the member is of no interest.
+*/
+
+/*!
+ \fn bool QMetaMethod::invoke(QObject *object,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+
+ \overload invoke()
+
+ This overload invokes this method using the
+ connection type Qt::AutoConnection and ignores return values.
+*/
+
+/*!
+ \class QMetaEnum
+ \brief The QMetaEnum class provides meta-data about an enumerator.
+
+ \ingroup objectmodel
+
+ Use name() for the enumerator's name. The enumerator's keys (names
+ of each enumerated item) are returned by key(); use keyCount() to find
+ the number of keys. isFlag() returns whether the enumerator is
+ meant to be used as a flag, meaning that its values can be combined
+ using the OR operator.
+
+ The conversion functions keyToValue(), valueToKey(), keysToValue(),
+ and valueToKeys() allow conversion between the integer
+ representation of an enumeration or set value and its literal
+ representation. The scope() function returns the class scope this
+ enumerator was declared in.
+
+ \sa QMetaObject, QMetaMethod, QMetaProperty
+*/
+
+/*!
+ \fn bool QMetaEnum::isValid() const
+
+ Returns true if this enum is valid (has a name); otherwise returns
+ false.
+
+ \sa name()
+*/
+
+/*!
+ \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
+ \internal
+*/
+
+
+/*!
+ \fn QMetaEnum::QMetaEnum()
+ \internal
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+
+ For example, the Qt::AlignmentFlag enumeration has \c
+ AlignmentFlag as the name and \l Qt as the scope.
+
+ \sa isValid(), scope()
+*/
+const char *QMetaEnum::name() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key()
+*/
+int QMetaEnum::keyCount() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.data[handle + 2];
+}
+
+
+/*!
+ Returns the key with the given \a index, or 0 if no such key exists.
+
+ \sa keyCount(), value(), valueToKey()
+*/
+const char *QMetaEnum::key(int index) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ if (index >= 0 && index < count)
+ return mobj->d.stringdata + mobj->d.data[data + 2*index];
+ return 0;
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), key(), keyToValue()
+*/
+int QMetaEnum::value(int index) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ if (index >= 0 && index < count)
+ return mobj->d.data[data + 2*index + 1];
+ return -1;
+}
+
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ When used as flags, enumerators can be combined using the OR
+ operator.
+
+ \sa keysToValue(), valueToKeys()
+*/
+bool QMetaEnum::isFlag() const
+{
+ return mobj && mobj->d.data[handle + 1];
+}
+
+
+/*!
+ Returns the scope this enumerator was declared in.
+
+ For example, the Qt::AlignmentFlag enumeration has \c Qt as
+ the scope and \c AlignmentFlag as the name.
+
+ \sa name()
+*/
+const char *QMetaEnum::scope() const
+{
+ return mobj?mobj->d.stringdata : 0;
+}
+
+/*!
+ Returns the integer value of the given enumeration \a key, or -1
+ if \a key is not defined.
+
+ For flag types, use keysToValue().
+
+ \sa valueToKey(), isFlag(), keysToValue()
+*/
+int QMetaEnum::keyToValue(const char *key) const
+{
+ 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;
+ }
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int i = 0; i < count; ++i)
+ if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key, mobj->d.stringdata, scope) == 0))
+ && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0)
+ return mobj->d.data[data + 2*i + 1];
+ return -1;
+}
+
+/*!
+ Returns the string that is used as the name of the given
+ enumeration \a value, or 0 if \a value is not defined.
+
+ For flag types, use valueToKeys().
+
+ \sa isFlag(), valueToKeys()
+*/
+const char* QMetaEnum::valueToKey(int value) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int i = 0; i < count; ++i)
+ if (value == (int)mobj->d.data[data + 2*i + 1])
+ return mobj->d.stringdata + mobj->d.data[data + 2*i];
+ return 0;
+}
+
+/*!
+ Returns the value derived from combining together the values of
+ the \a keys using the OR operator, or -1 if \a keys is not
+ defined. Note that the strings in \a keys must be '|'-separated.
+
+ \sa isFlag(), valueToKey(), valueToKeys()
+*/
+int QMetaEnum::keysToValue(const char *keys) const
+{
+ if (!mobj)
+ return -1;
+ QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
+ //#### TODO write proper code, do not use QStringList
+ int value = 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int li = 0; li < l.size(); ++li) {
+ QString trimmed = l.at(li).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 = count-1; i >= 0; --i)
+ if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key.constData(), mobj->d.stringdata, scope) == 0))
+ && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) {
+ value |= mobj->d.data[data + 2*i + 1];
+ break;
+ }
+ if (i < 0)
+ value |= -1;
+ }
+ return value;
+}
+
+/*!
+ Returns a byte array of '|'-separated keys that represents the
+ given \a value.
+
+ \sa isFlag(), valueToKey(), keysToValue()
+*/
+QByteArray QMetaEnum::valueToKeys(int value) const
+{
+ QByteArray keys;
+ if (!mobj)
+ return keys;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ int v = value;
+ for(int i = 0; i < count; i++) {
+ int k = mobj->d.data[data + 2*i + 1];
+ if ((k != 0 && (v & k) == k ) || (k == value)) {
+ v = v & ~k;
+ if (!keys.isEmpty())
+ keys += '|';
+ keys += mobj->d.stringdata + mobj->d.data[data + 2*i];
+ }
+ }
+ return keys;
+}
+
+static QByteArray qualifiedName(const QMetaEnum &e)
+{
+ return QByteArray(e.scope()) + "::" + e.name();
+}
+
+/*!
+ \class QMetaProperty
+ \brief The QMetaProperty class provides meta-data about a property.
+
+ \ingroup objectmodel
+
+ Property meta-data is obtained from an object's meta-object. See
+ QMetaObject::property() and QMetaObject::propertyCount() for
+ details.
+
+ \section1 Property Meta-Data
+
+ A property has a name() and a type(), as well as various
+ attributes that specify its behavior: isReadable(), isWritable(),
+ isDesignable(), isScriptable(), and isStored().
+
+ If the property is an enumeration, isEnumType() returns true; if the
+ property is an enumeration that is also a flag (i.e. its values
+ can be combined using the OR operator), isEnumType() and
+ isFlagType() both return true. The enumerator for these types is
+ available from enumerator().
+
+ The property's values are set and retrieved with read(), write(),
+ and reset(); they can also be changed through QObject's set and get
+ functions. See QObject::setProperty() and QObject::property() for
+ details.
+
+ \section1 Copying and Assignment
+
+ QMetaProperty objects can be copied by value. However, each copy will
+ refer to the same underlying property meta-data.
+
+ \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
+*/
+
+/*!
+ \fn bool QMetaProperty::isValid() const
+
+ Returns true if this property is valid (readable); otherwise
+ returns false.
+
+ \sa isReadable()
+*/
+
+/*!
+ \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QMetaProperty::QMetaProperty()
+ : mobj(0), handle(0), idx(0)
+{
+}
+
+
+/*!
+ Returns this property's name.
+
+ \sa type(), typeName()
+*/
+const char *QMetaProperty::name() const
+{
+ if (!mobj)
+ return 0;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the name of this property's type.
+
+ \sa type(), name()
+*/
+const char *QMetaProperty::typeName() const
+{
+ if (!mobj)
+ return 0;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ return mobj->d.stringdata + mobj->d.data[handle + 1];
+}
+
+/*!
+ Returns this property's type. The return value is one
+ of the values of the QVariant::Type enumeration.
+
+ \sa userType(), typeName(), name()
+*/
+QVariant::Type QMetaProperty::type() const
+{
+ if (!mobj)
+ return QVariant::Invalid;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+
+ uint type = flags >> 24;
+ if (type == 0xff) // special value for QVariant
+ type = QVariant::LastType;
+ if (type)
+ return QVariant::Type(type);
+ if (isEnumType()) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if (enumMetaTypeId == 0)
+ return QVariant::Int;
+ }
+#ifdef QT_COORD_TYPE
+ // qreal metatype must be resolved at runtime.
+ if (strcmp(typeName(), "qreal") == 0)
+ return QVariant::Type(qMetaTypeId<qreal>());
+#endif
+
+ return QVariant::UserType;
+}
+
+/*!
+ \since 4.2
+
+ Returns this property's user type. The return value is one
+ of the values that are registered with QMetaType, or 0 if
+ the type is not registered.
+
+ \sa type(), QMetaType, typeName()
+ */
+int QMetaProperty::userType() const
+{
+ QVariant::Type tp = type();
+ if (tp != QVariant::UserType)
+ return tp;
+ if (isEnumType()) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ return enumMetaTypeId;
+ }
+ return QMetaType::type(typeName());
+}
+
+/*!
+ \since 4.6
+
+ Returns this property's index.
+*/
+int QMetaProperty::propertyIndex() const
+{
+ if (!mobj)
+ return -1;
+ return idx + mobj->propertyOffset();
+}
+
+/*!
+ Returns true if the property's type is an enumeration value that
+ is used as a flag; otherwise returns false.
+
+ Flags can be combined using the OR operator. A flag type is
+ implicitly also an enum type.
+
+ \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
+*/
+
+bool QMetaProperty::isFlagType() const
+{
+ return isEnumType() && menum.isFlag();
+}
+
+/*!
+ Returns true if the property's type is an enumeration value;
+ otherwise returns false.
+
+ \sa enumerator(), isFlagType()
+*/
+bool QMetaProperty::isEnumType() const
+{
+ if (!mobj)
+ return false;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ int flags = mobj->d.data[handle + 2];
+ return (flags & EnumOrFlag) && menum.name();
+}
+
+/*!
+ \internal
+
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern.
+*/
+bool QMetaProperty::hasStdCppSet() const
+{
+ if (!mobj)
+ return false;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ int flags = mobj->d.data[handle + 2];
+ return (flags & StdCppSet);
+}
+
+/*!
+ Returns the enumerator if this property's type is an enumerator
+ type; otherwise the returned value is undefined.
+
+ \sa isEnumType(), isFlagType()
+*/
+QMetaEnum QMetaProperty::enumerator() const
+{
+ return menum;
+}
+
+/*!
+ Reads the property's value from the given \a object. Returns the value
+ if it was able to read it; otherwise returns an invalid variant.
+
+ \sa write(), reset(), isReadable()
+*/
+QVariant QMetaProperty::read(const QObject *object) const
+{
+ if (!object || !mobj)
+ return QVariant();
+
+ uint t = QVariant::Int;
+ if (isEnumType()) {
+ /*
+ try to create a QVariant that can be converted to this enum
+ type (only works if the enum has already been registered
+ with QMetaType)
+ */
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if (enumMetaTypeId != 0)
+ t = enumMetaTypeId;
+ } else {
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+ const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
+ t = (flags >> 24);
+ if (t == 0xff) // special value for QVariant
+ t = QVariant::LastType;
+ if (t == QVariant::Invalid)
+ t = QMetaType::type(typeName);
+ if (t == QVariant::Invalid)
+ t = QVariant::nameToType(typeName);
+ if (t == QVariant::Invalid || t == QVariant::UserType) {
+ if (t == QVariant::Invalid)
+ qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
+ return QVariant();
+ }
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value
+ int status = -1;
+ QVariant value;
+ void *argv[] = { 0, &value, &status };
+ if (t == QVariant::LastType) {
+ argv[0] = &value;
+ } else {
+ value = QVariant(t, (void*)0);
+ argv[0] = value.data();
+ }
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
+ idx + mobj->propertyOffset(), argv);
+
+ if (status != -1)
+ return value;
+ if (t != QVariant::LastType && argv[0] != value.data())
+ // pointer or reference
+ return QVariant((QVariant::Type)t, argv[0]);
+ return value;
+}
+
+/*!
+ Writes \a value as the property's value to the given \a object. Returns
+ true if the write succeeded; otherwise returns false.
+
+ \sa read(), reset(), isWritable()
+*/
+bool QMetaProperty::write(QObject *object, const QVariant &value) const
+{
+ if (!object || !isWritable())
+ return false;
+
+ QVariant v = value;
+ uint t = QVariant::Invalid;
+ if (isEnumType()) {
+ if (v.type() == QVariant::String
+#ifdef QT3_SUPPORT
+ || v.type() == QVariant::CString
+#endif
+ ) {
+ if (isFlagType())
+ v = QVariant(menum.keysToValue(value.toByteArray()));
+ else
+ v = QVariant(menum.keyToValue(value.toByteArray()));
+ } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ return false;
+ v = QVariant(*reinterpret_cast<const int *>(v.constData()));
+ }
+ v.convert(QVariant::Int);
+ } else {
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+ t = flags >> 24;
+ if (t == 0xff) // special value for QVariant
+ t = QVariant::LastType;
+ if (t == QVariant::Invalid) {
+ const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
+ const char *vtypeName = value.typeName();
+ if (vtypeName && strcmp(typeName, vtypeName) == 0)
+ t = value.userType();
+ else
+ t = QVariant::nameToType(typeName);
+ }
+ if (t == QVariant::Invalid)
+ return false;
+ if (t != QVariant::LastType && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
+ return false;
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value, return the value of status
+ int status = -1;
+ // the flags variable is used by the declarative module to implement
+ // interception of property writes.
+ int flags = 0;
+ void *argv[] = { 0, &v, &status, &flags };
+ if (t == QVariant::LastType)
+ argv[0] = &v;
+ else
+ argv[0] = v.data();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
+ return status;
+}
+
+/*!
+ Resets the property for the given \a object with a reset method.
+ Returns true if the reset worked; otherwise returns false.
+
+ Reset methods are optional; only a few properties support them.
+
+ \sa read(), write()
+*/
+bool QMetaProperty::reset(QObject *object) const
+{
+ if (!object || !mobj || !isResettable())
+ return false;
+ void *argv[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
+ return true;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false.
+
+ \sa reset()
+*/
+bool QMetaProperty::isResettable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Resettable;
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+
+ \sa isWritable(), read(), isValid()
+ */
+bool QMetaProperty::isReadable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Readable;
+}
+
+/*!
+ Returns true if this property has a corresponding change notify signal;
+ otherwise returns false.
+
+ \sa notifySignal()
+ */
+bool QMetaProperty::hasNotifySignal() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Notify;
+}
+
+/*!
+ \since 4.5
+
+ Returns the QMetaMethod instance of the property change notifying signal if
+ one was specified, otherwise returns an invalid QMetaMethod.
+
+ \sa hasNotifySignal()
+ */
+QMetaMethod QMetaProperty::notifySignal() const
+{
+ int id = notifySignalIndex();
+ if (id != -1)
+ return mobj->method(id);
+ else
+ return QMetaMethod();
+}
+
+/*!
+ \since 4.6
+
+ Returns the index of the property change notifying signal if one was
+ specified, otherwise returns -1.
+
+ \sa hasNotifySignal()
+ */
+int QMetaProperty::notifySignalIndex() const
+{
+ if (hasNotifySignal()) {
+ int offset = priv(mobj->d.data)->propertyData +
+ priv(mobj->d.data)->propertyCount * 3 + idx;
+ return mobj->d.data[offset] + mobj->methodOffset();
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ \internal
+
+ Returns the property revision if one was
+ specified by REVISION, otherwise returns 0.
+ */
+int QMetaProperty::revision() const
+{
+ if (!mobj)
+ return 0;
+ int flags = mobj->d.data[handle + 2];
+ if (flags & Revisioned) {
+ int offset = priv(mobj->d.data)->propertyData +
+ priv(mobj->d.data)->propertyCount * 3 + idx;
+ // Revision data is placed after NOTIFY data, if present.
+ // Iterate through properties to discover whether we have NOTIFY signals.
+ for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) {
+ int handle = priv(mobj->d.data)->propertyData + 3*i;
+ if (mobj->d.data[handle + 2] & Notify) {
+ offset += priv(mobj->d.data)->propertyCount;
+ break;
+ }
+ }
+ return mobj->d.data[offset];
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns
+ false.
+
+ \sa isReadable(), write()
+ */
+bool QMetaProperty::isWritable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Writable;
+}
+
+
+/*!
+ Returns true if this property is designable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
+ returns true (if the attribute is true or is a function or expression).
+
+ \sa isScriptable(), isStored()
+*/
+bool QMetaProperty::isDesignable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Designable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+
+
+}
+
+/*!
+ Returns true if the property is scriptable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isStored()
+*/
+bool QMetaProperty::isScriptable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Scriptable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ Returns true if the property is stored for \a object; otherwise returns
+ false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isScriptable()
+*/
+bool QMetaProperty::isStored(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Stored;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit for \a object 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 null, the function returns false if the \c
+ {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
+ true.
+
+ \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
+*/
+bool QMetaProperty::isUser(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & User;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ \since 4.6
+ Returns true if the property is constant; otherwise returns false.
+
+ A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
+ is set.
+*/
+bool QMetaProperty::isConstant() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Constant;
+}
+
+/*!
+ \since 4.6
+ Returns true if the property is final; otherwise returns false.
+
+ A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
+ is set.
+*/
+bool QMetaProperty::isFinal() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Final;
+}
+
+/*!
+ \obsolete
+
+ Returns true if the property is editable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c EDITABLE attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaProperty::isEditable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Editable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ \class QMetaClassInfo
+
+ \brief The QMetaClassInfo class provides additional information
+ about a class.
+
+ \ingroup objectmodel
+
+ Class information items are simple \e{name}--\e{value} pairs that
+ are specified using Q_CLASSINFO() in the source code. The
+ information can be retrieved using name() and value(). For example:
+
+ \snippet doc/src/snippets/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.
+
+ \sa QMetaObject
+*/
+
+
+/*!
+ \fn QMetaClassInfo::QMetaClassInfo()
+ \internal
+*/
+
+/*!
+ \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ Returns the name of this item.
+
+ \sa value()
+*/
+const char *QMetaClassInfo::name() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the value of this item.
+
+ \sa name()
+*/
+const char* QMetaClassInfo::value() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 1];
+}
+
+/*!
+ \macro QGenericArgument 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().
+
+ \sa Q_RETURN_ARG()
+*/
+
+/*!
+ \macro QGenericReturnArgument 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().
+
+ \sa Q_ARG()
+*/
+
+/*!
+ \class QGenericArgument
+
+ \brief The QGenericArgument class is an internal helper class for
+ marshalling arguments.
+
+ This class should never be used directly. Please use the \l Q_ARG()
+ macro instead.
+
+ \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
+*/
+
+/*!
+ \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
+
+ Constructs a QGenericArgument object with the given \a name and \a data.
+*/
+
+/*!
+ \fn QGenericArgument::data () const
+
+ Returns the data set in the constructor.
+*/
+
+/*!
+ \fn QGenericArgument::name () const
+
+ Returns the name set in the constructor.
+*/
+
+/*!
+ \class QGenericReturnArgument
+
+ \brief The QGenericReturnArgument class is an internal helper class for
+ marshalling arguments.
+
+ This class should never be used directly. Please use the
+ Q_RETURN_ARG() macro instead.
+
+ \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
+*/
+
+/*!
+ \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
+
+ Constructs a QGenericReturnArgument object with the given \a name
+ and \a data.
+*/
+
+/*! \internal
+ If the local_method_index is a cloned method, return the index of the original.
+
+ Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
+ */
+int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
+{
+ Q_ASSERT(local_method_index < get(mobj)->methodCount);
+ int handle = get(mobj)->methodData + 5 * local_method_index;
+ while (mobj->d.data[handle + 4] & MethodCloned) {
+ Q_ASSERT(local_method_index > 0);
+ handle -= 5;
+ local_method_index--;
+ }
+ return local_method_index;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
new file mode 100644
index 0000000000..e9bba45391
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.h
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECT_H
+#define QMETAOBJECT_H
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T> class QList;
+
+class Q_CORE_EXPORT QMetaMethod
+{
+public:
+ inline QMetaMethod() : mobj(0),handle(0) {}
+
+ const char *signature() const;
+ const char *typeName() const;
+ QList<QByteArray> parameterTypes() const;
+ QList<QByteArray> parameterNames() const;
+ const char *tag() const;
+ enum Access { Private, Protected, Public };
+ Access access() const;
+ enum MethodType { Method, Signal, Slot, Constructor };
+ MethodType methodType() const;
+ enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
+ int attributes() const;
+ int methodIndex() const;
+ int revision() const;
+
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+ bool invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const;
+ inline bool invoke(QObject *object,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, Qt::AutoConnection, returnValue,
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+ inline bool invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, connectionType, QGenericReturnArgument(),
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+ inline bool invoke(QObject *object,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, Qt::AutoConnection, QGenericReturnArgument(),
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+ friend struct QMetaObjectPrivate;
+ friend class QObject;
+};
+Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE);
+
+class Q_CORE_EXPORT QMetaEnum
+{
+public:
+ inline QMetaEnum() : mobj(0),handle(0) {}
+
+ const char *name() const;
+ bool isFlag() const;
+
+ int keyCount() const;
+ const char *key(int index) const;
+ int value(int index) const;
+
+ const char *scope() const;
+
+ int keyToValue(const char *key) const;
+ const char* valueToKey(int value) const;
+ int keysToValue(const char * keys) const;
+ QByteArray valueToKeys(int value) const;
+
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+ inline bool isValid() const { return name() != 0; }
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+};
+Q_DECLARE_TYPEINFO(QMetaEnum, Q_MOVABLE_TYPE);
+
+class Q_CORE_EXPORT QMetaProperty
+{
+public:
+ QMetaProperty();
+
+ const char *name() const;
+ const char *typeName() const;
+ QVariant::Type type() const;
+ int userType() const;
+ int propertyIndex() const;
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable(const QObject *obj = 0) const;
+ bool isScriptable(const QObject *obj = 0) const;
+ bool isStored(const QObject *obj = 0) const;
+ bool isEditable(const QObject *obj = 0) const;
+ bool isUser(const QObject *obj = 0) const;
+ bool isConstant() const;
+ bool isFinal() const;
+
+ bool isFlagType() const;
+ bool isEnumType() const;
+ QMetaEnum enumerator() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethod notifySignal() const;
+ int notifySignalIndex() const;
+
+ int revision() const;
+
+ QVariant read(const QObject *obj) const;
+ bool write(QObject *obj, const QVariant &value) const;
+ bool reset(QObject *obj) const;
+
+ bool hasStdCppSet() const;
+ inline bool isValid() const { return isReadable(); }
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ int idx;
+ QMetaEnum menum;
+ friend struct QMetaObject;
+};
+
+class Q_CORE_EXPORT QMetaClassInfo
+{
+public:
+ inline QMetaClassInfo() : mobj(0),handle(0) {}
+ const char *name() const;
+ const char *value() const;
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+};
+Q_DECLARE_TYPEINFO(QMetaClassInfo, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMETAOBJECT_H
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
new file mode 100644
index 0000000000..fdadf4ac9f
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECT_P_H
+#define QMETAOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of moc. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_NAMESPACE
+
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Constant = 0x00000400,
+ Final = 0x00000800,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Revisioned = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40,
+ MethodRevisioned = 0x80
+};
+
+enum MetaObjectFlags {
+ DynamicMetaObject = 0x01
+};
+
+class QMutex;
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData; //since revision 2
+ int flags; //since revision 3
+ int signalCount; //since revision 4
+ // revision 5 introduces changes in normalized signatures, no new members
+ // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
+
+ static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
+ { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
+
+ static int indexOfSignalRelative(const QMetaObject **baseObject,
+ const char* name,
+ bool normalizeStringData);
+ static int indexOfSlotRelative(const QMetaObject **m,
+ const char *slot,
+ bool normalizeStringData);
+ static int originalClone(const QMetaObject *obj, int local_method_index);
+
+#ifndef QT_NO_QOBJECT
+ //defined in qobject.cpp
+ enum DisconnectType { DisconnectAll, DisconnectOne };
+ static void memberIndexes(const QObject *obj, const QMetaMethod &member,
+ int *signalIndex, int *methodIndex);
+ static bool connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index_relative,
+ const QMetaObject *rmeta = 0,
+ int type = 0, int *types = 0);
+ static bool disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ DisconnectType = DisconnectAll);
+ static inline bool disconnectHelper(QObjectPrivate::Connection *c,
+ const QObject *receiver, int method_index,
+ QMutex *senderMutex, DisconnectType);
+#endif
+};
+
+#ifndef UTILS_H
+// 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 == '_'
+ );
+}
+
+static inline bool is_space(char s)
+{
+ return (s == ' ' || s == '\t');
+}
+#endif
+
+// This code is shared with moc.cpp
+static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
+{
+ int len = e - t;
+ /*
+ Convert 'char const *' into 'const char *'. Start at index 1,
+ not 0, because 'const char *' is already OK.
+ */
+ QByteArray constbuf;
+ for (int i = 1; i < len; i++) {
+ if ( t[i] == 'c'
+ && strncmp(t + i + 1, "onst", 4) == 0
+ && (i + 5 >= len || !is_ident_char(t[i + 5]))
+ && !is_ident_char(t[i-1])
+ ) {
+ constbuf = QByteArray(t, len);
+ if (is_space(t[i-1]))
+ constbuf.remove(i-1, 6);
+ else
+ constbuf.remove(i, 5);
+ constbuf.prepend("const ");
+ t = constbuf.data();
+ e = constbuf.data() + constbuf.length();
+ break;
+ }
+ /*
+ We musn't convert 'char * const *' into 'const char **'
+ and we must beware of 'Bar<const Bla>'.
+ */
+ if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
+ break;
+ }
+ if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) {
+ if (*(e-1) == '&') { // treat const reference as value
+ t += 6;
+ --e;
+ } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value
+ t += 6;
+ }
+ }
+ QByteArray result;
+ result.reserve(len);
+
+#if 1
+ // consume initial 'const '
+ if (strncmp("const ", t, 6) == 0) {
+ t+= 6;
+ result += "const ";
+ }
+#endif
+
+ // some type substitutions for 'unsigned x'
+ if (strncmp("unsigned", t, 8) == 0) {
+ // make sure "unsigned" is an isolated word before making substitutions
+ if (!t[8] || !is_ident_char(t[8])) {
+ if (strncmp(" int", t+8, 4) == 0) {
+ t += 8+4;
+ result += "uint";
+ } else if (strncmp(" long", t+8, 5) == 0) {
+ if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int'
+ && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long'
+ ) {
+ t += 8+5;
+ result += "ulong";
+ }
+ } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short
+ && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char
+ // treat rest (unsigned) as uint
+ t += 8;
+ result += "uint";
+ }
+ }
+ } else {
+ // discard 'struct', 'class', and 'enum'; they are optional
+ // and we don't want them in the normalized signature
+ struct {
+ const char *keyword;
+ int len;
+ } optional[] = {
+ { "struct ", 7 },
+ { "class ", 6 },
+ { "enum ", 5 },
+ { 0, 0 }
+ };
+ int i = 0;
+ do {
+ if (strncmp(optional[i].keyword, t, optional[i].len) == 0) {
+ t += optional[i].len;
+ break;
+ }
+ } while (optional[++i].keyword != 0);
+ }
+
+ bool star = false;
+ while (t != e) {
+ char c = *t++;
+ if (fixScope && c == ':' && *t == ':' ) {
+ ++t;
+ c = *t++;
+ int i = result.size() - 1;
+ while (i >= 0 && is_ident_char(result.at(i)))
+ --i;
+ result.resize(i + 1);
+ }
+ star = star || c == '*';
+ result += c;
+ if (c == '<') {
+ //template recursion
+ const char* tt = t;
+ int templdepth = 1;
+ while (t != e) {
+ c = *t++;
+ if (c == '<')
+ ++templdepth;
+ if (c == '>')
+ --templdepth;
+ if (templdepth == 0 || (templdepth == 1 && c == ',')) {
+ result += normalizeTypeInternal(tt, t-1, fixScope, false);
+ result += c;
+ if (templdepth == 0) {
+ if (*t == '>')
+ result += ' '; // avoid >>
+ break;
+ }
+ tt = t;
+ }
+ }
+ }
+
+ // cv qualifers can appear after the type as well
+ if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)
+ && (e - t == 5 || !is_ident_char(t[5]))) {
+ t += 5;
+ while (t != e && is_space(*t))
+ ++t;
+ if (adjustConst && t != e && *t == '&') {
+ // treat const ref as value
+ ++t;
+ } else if (adjustConst && !star) {
+ // treat const as value
+ } else if (!star) {
+ // move const to the front (but not if const comes after a *)
+ result.prepend("const ");
+ } else {
+ // keep const after a *
+ result += "const";
+ }
+ }
+ }
+
+ return result;
+}
+
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
new file mode 100644
index 0000000000..bdc96c638b
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -0,0 +1,1509 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetatype.h"
+#include "qobjectdefs.h"
+#include "qdatetime.h"
+#include "qbytearray.h"
+#include "qreadwritelock.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qvector.h"
+#include "qlocale.h"
+#include "qeasingcurve.h"
+
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include "qbitarray.h"
+# include "qurl.h"
+# include "qvariant.h"
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include "qsize.h"
+# include "qpoint.h"
+# include "qrect.h"
+# include "qline.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+/*!
+ \macro Q_DECLARE_METATYPE(Type)
+ \relates QMetaType
+
+ This macro makes the type \a Type known to QMetaType as long as it
+ provides a public default constructor, a public copy constructor and
+ a public destructor.
+ It is needed to use the type \a Type as a custom type in QVariant.
+
+ Ideally, this macro should be placed below the declaration of
+ the class or struct. If that is not possible, it can be put in
+ a private header file which has to be included every time that
+ type is used in a QVariant.
+
+ Adding a Q_DECLARE_METATYPE() makes the type known to all template
+ based functions, including QVariant. Note that if you intend to
+ use the type in \e queued signal and slot connections or in
+ QObject's property system, you also have to call
+ qRegisterMetaType() since the names are resolved at runtime.
+
+ This example shows a typical use case of Q_DECLARE_METATYPE():
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 0
+
+ If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
+ has to be outside the namespace:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 1
+
+ Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 2
+
+ \sa qRegisterMetaType()
+*/
+
+/*!
+ \enum QMetaType::Type
+
+ These are the built-in types supported by QMetaType:
+
+ \value Void \c void
+ \value Bool \c bool
+ \value Int \c int
+ \value UInt \c{unsigned int}
+ \value Double \c double
+ \value QChar QChar
+ \value QString QString
+ \value QByteArray QByteArray
+
+ \value VoidStar \c{void *}
+ \value Long \c{long}
+ \value LongLong LongLong
+ \value Short \c{short}
+ \value Char \c{char}
+ \value ULong \c{unsigned long}
+ \value ULongLong ULongLong
+ \value UShort \c{unsigned short}
+ \value UChar \c{unsigned char}
+ \value Float \c float
+ \value QObjectStar QObject *
+ \value QWidgetStar QWidget *
+ \value QVariant QVariant
+
+ \value QColorGroup QColorGroup
+ \value QCursor QCursor
+ \value QDate QDate
+ \value QSize QSize
+ \value QTime QTime
+ \value QVariantList QVariantList
+ \value QPolygon QPolygon
+ \value QColor QColor
+ \value QSizeF QSizeF
+ \value QRectF QRectF
+ \value QLine QLine
+ \value QTextLength QTextLength
+ \value QStringList QStringList
+ \value QVariantMap QVariantMap
+ \value QVariantHash QVariantHash
+ \value QIcon QIcon
+ \value QPen QPen
+ \value QLineF QLineF
+ \value QTextFormat QTextFormat
+ \value QRect QRect
+ \value QPoint QPoint
+ \value QUrl QUrl
+ \value QRegExp QRegExp
+ \value QDateTime QDateTime
+ \value QPointF QPointF
+ \value QPalette QPalette
+ \value QFont QFont
+ \value QBrush QBrush
+ \value QRegion QRegion
+ \value QBitArray QBitArray
+ \value QImage QImage
+ \value QKeySequence QKeySequence
+ \value QSizePolicy QSizePolicy
+ \value QPixmap QPixmap
+ \value QLocale QLocale
+ \value QBitmap QBitmap
+ \value QMatrix QMatrix
+ \value QTransform QTransform
+ \value QMatrix4x4 QMatrix4x4
+ \value QVector2D QVector2D
+ \value QVector3D QVector3D
+ \value QVector4D QVector4D
+ \value QQuaternion QQuaternion
+ \value QEasingCurve QEasingCurve
+
+ \value User Base value for user types
+
+ \omitvalue FirstCoreExtType
+ \omitvalue FirstGuiType
+ \omitvalue LastCoreExtType
+ \omitvalue LastCoreType
+ \omitvalue LastGuiType
+ \omitvalue QReal
+
+ Additional types can be registered using Q_DECLARE_METATYPE().
+
+ \sa type(), typeName()
+*/
+
+/*!
+ \class QMetaType
+ \brief The QMetaType class manages named types in the meta-object system.
+
+ \ingroup objectmodel
+ \threadsafe
+
+ 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 type available to non-template based
+ functions, such as the queued signal and slot connections.
+
+ Any class or struct that has a public default
+ constructor, a public copy constructor, and a public destructor
+ can be registered.
+
+ The following code allocates and destructs an instance of
+ \c{MyClass}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 3
+
+ If we want the stream operators \c operator<<() and \c
+ operator>>() to work on QVariant objects that store custom types,
+ the custom type must provide \c operator<<() and \c operator>>()
+ operators.
+
+ \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
+*/
+
+#define QT_ADD_STATIC_METATYPE(STR, TP) \
+ { STR, sizeof(STR) - 1, TP }
+
+/* Note: these MUST be in the order of the enums */
+static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
+
+ /* All Core types */
+ QT_ADD_STATIC_METATYPE("void", QMetaType::Void),
+ QT_ADD_STATIC_METATYPE("bool", QMetaType::Bool),
+ QT_ADD_STATIC_METATYPE("int", QMetaType::Int),
+ QT_ADD_STATIC_METATYPE("uint", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("qlonglong", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("qulonglong", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("double", QMetaType::Double),
+ QT_ADD_STATIC_METATYPE("QChar", QMetaType::QChar),
+ QT_ADD_STATIC_METATYPE("QVariantMap", QMetaType::QVariantMap),
+ QT_ADD_STATIC_METATYPE("QVariantList", QMetaType::QVariantList),
+ QT_ADD_STATIC_METATYPE("QString", QMetaType::QString),
+ QT_ADD_STATIC_METATYPE("QStringList", QMetaType::QStringList),
+ QT_ADD_STATIC_METATYPE("QByteArray", QMetaType::QByteArray),
+ QT_ADD_STATIC_METATYPE("QBitArray", QMetaType::QBitArray),
+ QT_ADD_STATIC_METATYPE("QDate", QMetaType::QDate),
+ QT_ADD_STATIC_METATYPE("QTime", QMetaType::QTime),
+ QT_ADD_STATIC_METATYPE("QDateTime", QMetaType::QDateTime),
+ QT_ADD_STATIC_METATYPE("QUrl", QMetaType::QUrl),
+ QT_ADD_STATIC_METATYPE("QLocale", QMetaType::QLocale),
+ QT_ADD_STATIC_METATYPE("QRect", QMetaType::QRect),
+ QT_ADD_STATIC_METATYPE("QRectF", QMetaType::QRectF),
+ QT_ADD_STATIC_METATYPE("QSize", QMetaType::QSize),
+ QT_ADD_STATIC_METATYPE("QSizeF", QMetaType::QSizeF),
+ QT_ADD_STATIC_METATYPE("QLine", QMetaType::QLine),
+ QT_ADD_STATIC_METATYPE("QLineF", QMetaType::QLineF),
+ QT_ADD_STATIC_METATYPE("QPoint", QMetaType::QPoint),
+ QT_ADD_STATIC_METATYPE("QPointF", QMetaType::QPointF),
+ QT_ADD_STATIC_METATYPE("QRegExp", QMetaType::QRegExp),
+ QT_ADD_STATIC_METATYPE("QVariantHash", QMetaType::QVariantHash),
+ QT_ADD_STATIC_METATYPE("QEasingCurve", QMetaType::QEasingCurve),
+
+ /* All GUI types */
+ QT_ADD_STATIC_METATYPE("QColorGroup", 63),
+ QT_ADD_STATIC_METATYPE("QFont", QMetaType::QFont),
+ QT_ADD_STATIC_METATYPE("QPixmap", QMetaType::QPixmap),
+ QT_ADD_STATIC_METATYPE("QBrush", QMetaType::QBrush),
+ QT_ADD_STATIC_METATYPE("QColor", QMetaType::QColor),
+ QT_ADD_STATIC_METATYPE("QPalette", QMetaType::QPalette),
+ QT_ADD_STATIC_METATYPE("QIcon", QMetaType::QIcon),
+ QT_ADD_STATIC_METATYPE("QImage", QMetaType::QImage),
+ QT_ADD_STATIC_METATYPE("QPolygon", QMetaType::QPolygon),
+ QT_ADD_STATIC_METATYPE("QRegion", QMetaType::QRegion),
+ QT_ADD_STATIC_METATYPE("QBitmap", QMetaType::QBitmap),
+ QT_ADD_STATIC_METATYPE("QCursor", QMetaType::QCursor),
+ QT_ADD_STATIC_METATYPE("QSizePolicy", QMetaType::QSizePolicy),
+ QT_ADD_STATIC_METATYPE("QKeySequence", QMetaType::QKeySequence),
+ QT_ADD_STATIC_METATYPE("QPen", QMetaType::QPen),
+ QT_ADD_STATIC_METATYPE("QTextLength", QMetaType::QTextLength),
+ QT_ADD_STATIC_METATYPE("QTextFormat", QMetaType::QTextFormat),
+ QT_ADD_STATIC_METATYPE("QMatrix", QMetaType::QMatrix),
+ QT_ADD_STATIC_METATYPE("QTransform", QMetaType::QTransform),
+ QT_ADD_STATIC_METATYPE("QMatrix4x4", QMetaType::QMatrix4x4),
+ QT_ADD_STATIC_METATYPE("QVector2D", QMetaType::QVector2D),
+ QT_ADD_STATIC_METATYPE("QVector3D", QMetaType::QVector3D),
+ QT_ADD_STATIC_METATYPE("QVector4D", QMetaType::QVector4D),
+ QT_ADD_STATIC_METATYPE("QQuaternion", QMetaType::QQuaternion),
+
+ /* All Metatype builtins */
+ QT_ADD_STATIC_METATYPE("void*", QMetaType::VoidStar),
+ QT_ADD_STATIC_METATYPE("long", QMetaType::Long),
+ QT_ADD_STATIC_METATYPE("short", QMetaType::Short),
+ QT_ADD_STATIC_METATYPE("char", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("ulong", QMetaType::ULong),
+ QT_ADD_STATIC_METATYPE("ushort", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("uchar", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("float", QMetaType::Float),
+ QT_ADD_STATIC_METATYPE("QObject*", QMetaType::QObjectStar),
+ QT_ADD_STATIC_METATYPE("QWidget*", QMetaType::QWidgetStar),
+ QT_ADD_STATIC_METATYPE("QVariant", QMetaType::QVariant),
+
+ /* Type aliases - order doesn't matter */
+ QT_ADD_STATIC_METATYPE("unsigned long", QMetaType::ULong),
+ QT_ADD_STATIC_METATYPE("unsigned int", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("unsigned short", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("unsigned char", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("signed char", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short),
+ QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("qint32", QMetaType::Int),
+ QT_ADD_STATIC_METATYPE("quint32", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("qint64", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("quint64", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("QList<QVariant>", QMetaType::QVariantList),
+ QT_ADD_STATIC_METATYPE("QMap<QString,QVariant>", QMetaType::QVariantMap),
+ QT_ADD_STATIC_METATYPE("QHash<QString,QVariant>", QMetaType::QVariantHash),
+ // let QMetaTypeId2 figure out the type at compile time
+ QT_ADD_STATIC_METATYPE("qreal", QMetaTypeId2<qreal>::MetaType),
+
+ {0, 0, QMetaType::Void}
+};
+
+struct QMetaTypeGuiHelper
+{
+ QMetaType::Constructor constr;
+ QMetaType::Destructor destr;
+#ifndef QT_NO_DATASTREAM
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+#endif
+};
+Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper = 0;
+
+class QCustomTypeInfo
+{
+public:
+ QCustomTypeInfo() : typeName(), constr(0), destr(0)
+#ifndef QT_NO_DATASTREAM
+ , saveOp(0), loadOp(0)
+#endif
+ {}
+
+ QByteArray typeName;
+ QMetaType::Constructor constr;
+ QMetaType::Destructor destr;
+#ifndef QT_NO_DATASTREAM
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+#endif
+ int alias;
+};
+
+Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
+Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
+Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
+
+#ifndef QT_NO_DATASTREAM
+/*! \internal
+*/
+void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
+ LoadOperator loadOp)
+{
+ int idx = type(typeName);
+ if (!idx)
+ return;
+ registerStreamOperators(idx, saveOp, loadOp);
+}
+
+/*! \internal
+*/
+void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
+ LoadOperator loadOp)
+{
+ if (idx < User)
+ return; //builtin types should not be registered;
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct)
+ return;
+ QWriteLocker locker(customTypesLock());
+ QCustomTypeInfo &inf = (*ct)[idx - User];
+ inf.saveOp = saveOp;
+ inf.loadOp = loadOp;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ Returns the type name associated with the given \a type, or 0 if no
+ matching type was found. The returned pointer must not be deleted.
+
+ \sa type(), isRegistered(), Type
+*/
+const char *QMetaType::typeName(int type)
+{
+ enum { GuiTypeCount = LastGuiType - FirstGuiType };
+
+ if (type >= 0 && type <= LastCoreType) {
+ return types[type].typeName;
+ } else if (type >= FirstGuiType && type <= LastGuiType) {
+ return types[type - FirstGuiType + LastCoreType + 1].typeName;
+ } else if (type >= FirstCoreExtType && type <= LastCoreExtType) {
+ return types[type - FirstCoreExtType + GuiTypeCount + LastCoreType + 2].typeName;
+ } else if (type >= User) {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ QReadLocker locker(customTypesLock());
+ return ct && ct->count() > type - User && !ct->at(type - User).typeName.isEmpty()
+ ? ct->at(type - User).typeName.constData()
+ : static_cast<const char *>(0);
+ }
+
+ return 0;
+}
+
+/*! \internal
+ Similar to QMetaType::type(), but only looks in the static set of types.
+*/
+static inline int qMetaTypeStaticType(const char *typeName, int length)
+{
+ int i = 0;
+ while (types[i].typeName && ((length != types[i].typeNameLength)
+ || strcmp(typeName, types[i].typeName))) {
+ ++i;
+ }
+ return types[i].type;
+}
+
+/*! \internal
+ Similar to QMetaType::type(), but only looks in the custom set of
+ types, and doesn't lock the mutex.
+*/
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
+{
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return 0;
+
+ for (int v = 0; v < ct->count(); ++v) {
+ const QCustomTypeInfo &customInfo = ct->at(v);
+ if ((length == customInfo.typeName.size())
+ && !strcmp(typeName, customInfo.typeName.constData())) {
+ if (customInfo.alias >= 0)
+ return customInfo.alias;
+ return v + QMetaType::User;
+ }
+ }
+ return 0;
+}
+
+/*! \internal
+
+ Registers a user type for marshalling, with \a typeName, a \a
+ destructor, and a \a constructor. Returns the type's handle,
+ or -1 if the type could not be registered.
+ */
+int QMetaType::registerType(const char *typeName, Destructor destructor,
+ Constructor constructor)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName || !destructor || !constructor)
+ return -1;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
+ int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (!idx) {
+ QWriteLocker locker(customTypesLock());
+ idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ if (!idx) {
+ QCustomTypeInfo inf;
+ inf.typeName = normalizedTypeName;
+ inf.constr = constructor;
+ inf.destr = destructor;
+ inf.alias = -1;
+ idx = ct->size() + User;
+ ct->append(inf);
+ }
+ }
+ return idx;
+}
+
+/*! \internal
+ \since 4.7
+
+ Registers a user type for marshalling, as an alias of another type (typedef)
+*/
+int QMetaType::registerTypedef(const char* typeName, int aliasId)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName)
+ return -1;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
+ int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (idx) {
+ Q_ASSERT(idx == aliasId);
+ return idx;
+ }
+
+ QWriteLocker locker(customTypesLock());
+ idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (idx)
+ return idx;
+
+ QCustomTypeInfo inf;
+ inf.typeName = normalizedTypeName;
+ inf.alias = aliasId;
+ inf.constr = 0;
+ inf.destr = 0;
+ ct->append(inf);
+ return aliasId;
+}
+
+/*!
+ \since 4.4
+
+ Unregisters a user type, with \a typeName.
+
+ \sa type(), typeName()
+ */
+void QMetaType::unregisterType(const char *typeName)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName)
+ return;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+ QWriteLocker locker(customTypesLock());
+ for (int v = 0; v < ct->count(); ++v) {
+ if (ct->at(v).typeName == typeName) {
+ QCustomTypeInfo &inf = (*ct)[v];
+ inf.typeName.clear();
+ inf.constr = 0;
+ inf.destr = 0;
+ inf.alias = -1;
+ }
+ }
+}
+
+/*!
+ Returns true if the datatype with ID \a type is registered;
+ otherwise returns false.
+
+ \sa type(), typeName(), Type
+*/
+bool QMetaType::isRegistered(int type)
+{
+ if (type >= 0 && type < User) {
+ // predefined type
+ return true;
+ }
+ QReadLocker locker(customTypesLock());
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
+}
+
+/*!
+ Returns a handle to the type called \a typeName, or 0 if there is
+ no such type.
+
+ \sa isRegistered(), typeName(), Type
+*/
+int QMetaType::type(const char *typeName)
+{
+ int length = qstrlen(typeName);
+ if (!length)
+ return 0;
+ int type = qMetaTypeStaticType(typeName, length);
+ if (!type) {
+ QReadLocker locker(customTypesLock());
+ type = qMetaTypeCustomType_unlocked(typeName, length);
+#ifndef QT_NO_QOBJECT
+ if (!type) {
+ const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+ type = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ if (!type) {
+ type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ }
+ }
+#endif
+ }
+ return type;
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ Writes the object pointed to by \a data with the ID \a type to
+ the given \a stream. Returns true if the object is saved
+ successfully; otherwise returns false.
+
+ The type must have been registered with qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() beforehand.
+
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator<<(), which relies on save()
+ to stream custom types.
+
+ \sa load(), qRegisterMetaTypeStreamOperators()
+*/
+bool QMetaType::save(QDataStream &stream, int type, const void *data)
+{
+ if (!data || !isRegistered(type))
+ return false;
+
+ switch(type) {
+ case QMetaType::Void:
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return false;
+ case QMetaType::Long:
+ stream << qlonglong(*static_cast<const long *>(data));
+ break;
+ case QMetaType::Int:
+ stream << *static_cast<const int *>(data);
+ break;
+ case QMetaType::Short:
+ stream << *static_cast<const short *>(data);
+ break;
+ case QMetaType::Char:
+ // force a char to be signed
+ stream << *static_cast<const signed char *>(data);
+ break;
+ case QMetaType::ULong:
+ stream << qulonglong(*static_cast<const ulong *>(data));
+ break;
+ case QMetaType::UInt:
+ stream << *static_cast<const uint *>(data);
+ break;
+ case QMetaType::LongLong:
+ stream << *static_cast<const qlonglong *>(data);
+ break;
+ case QMetaType::ULongLong:
+ stream << *static_cast<const qulonglong *>(data);
+ break;
+ case QMetaType::UShort:
+ stream << *static_cast<const ushort *>(data);
+ break;
+ case QMetaType::UChar:
+ stream << *static_cast<const uchar *>(data);
+ break;
+ case QMetaType::Bool:
+ stream << qint8(*static_cast<const bool *>(data));
+ break;
+ case QMetaType::Float:
+ stream << *static_cast<const float *>(data);
+ break;
+ case QMetaType::Double:
+ stream << *static_cast<const double *>(data);
+ break;
+ case QMetaType::QChar:
+ stream << *static_cast<const NS(QChar) *>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ stream << *static_cast<const NS(QVariantMap)*>(data);
+ break;
+ case QMetaType::QVariantHash:
+ stream << *static_cast<const NS(QVariantHash)*>(data);
+ break;
+ case QMetaType::QVariantList:
+ stream << *static_cast<const NS(QVariantList)*>(data);
+ break;
+ case QMetaType::QVariant:
+ stream << *static_cast<const NS(QVariant)*>(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ stream << *static_cast<const NS(QByteArray)*>(data);
+ break;
+ case QMetaType::QString:
+ stream << *static_cast<const NS(QString)*>(data);
+ break;
+ case QMetaType::QStringList:
+ stream << *static_cast<const NS(QStringList)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ stream << *static_cast<const NS(QBitArray)*>(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ stream << *static_cast<const NS(QDate)*>(data);
+ break;
+ case QMetaType::QTime:
+ stream << *static_cast<const NS(QTime)*>(data);
+ break;
+ case QMetaType::QDateTime:
+ stream << *static_cast<const NS(QDateTime)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ stream << *static_cast<const NS(QUrl)*>(data);
+ break;
+#endif
+ case QMetaType::QLocale:
+ stream << *static_cast<const NS(QLocale)*>(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ stream << *static_cast<const NS(QRect)*>(data);
+ break;
+ case QMetaType::QRectF:
+ stream << *static_cast<const NS(QRectF)*>(data);
+ break;
+ case QMetaType::QSize:
+ stream << *static_cast<const NS(QSize)*>(data);
+ break;
+ case QMetaType::QSizeF:
+ stream << *static_cast<const NS(QSizeF)*>(data);
+ break;
+ case QMetaType::QLine:
+ stream << *static_cast<const NS(QLine)*>(data);
+ break;
+ case QMetaType::QLineF:
+ stream << *static_cast<const NS(QLineF)*>(data);
+ break;
+ case QMetaType::QPoint:
+ stream << *static_cast<const NS(QPoint)*>(data);
+ break;
+ case QMetaType::QPointF:
+ stream << *static_cast<const NS(QPointF)*>(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ stream << *static_cast<const NS(QRegExp)*>(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ stream << *static_cast<const NS(QEasingCurve)*>(data);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+#endif
+ case QMetaType::QFont:
+ case QMetaType::QPixmap:
+ case QMetaType::QBrush:
+ case QMetaType::QColor:
+ case QMetaType::QPalette:
+ case QMetaType::QIcon:
+ case QMetaType::QImage:
+ case QMetaType::QPolygon:
+ case QMetaType::QRegion:
+ case QMetaType::QBitmap:
+ case QMetaType::QCursor:
+ case QMetaType::QSizePolicy:
+ case QMetaType::QKeySequence:
+ case QMetaType::QPen:
+ case QMetaType::QTextLength:
+ case QMetaType::QTextFormat:
+ case QMetaType::QMatrix:
+ case QMetaType::QTransform:
+ case QMetaType::QMatrix4x4:
+ case QMetaType::QVector2D:
+ case QMetaType::QVector3D:
+ case QMetaType::QVector4D:
+ case QMetaType::QQuaternion:
+ if (!qMetaTypeGuiHelper)
+ return false;
+ qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data);
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return false;
+
+ SaveOperator saveOp = 0;
+ {
+ QReadLocker locker(customTypesLock());
+ saveOp = ct->at(type - User).saveOp;
+ }
+
+ if (!saveOp)
+ return false;
+ saveOp(stream, data);
+ break; }
+ }
+
+ return true;
+}
+
+/*!
+ Reads the object of the specified \a type from the given \a
+ stream into \a data. Returns true if the object is loaded
+ successfully; otherwise returns false.
+
+ The type must have been registered with qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() beforehand.
+
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator>>(), which relies on load()
+ to stream custom types.
+
+ \sa save(), qRegisterMetaTypeStreamOperators()
+*/
+bool QMetaType::load(QDataStream &stream, int type, void *data)
+{
+ if (!data || !isRegistered(type))
+ return false;
+
+ switch(type) {
+ case QMetaType::Void:
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return false;
+ case QMetaType::Long: {
+ qlonglong l;
+ stream >> l;
+ *static_cast<long *>(data) = long(l);
+ break; }
+ case QMetaType::Int:
+ stream >> *static_cast<int *>(data);
+ break;
+ case QMetaType::Short:
+ stream >> *static_cast<short *>(data);
+ break;
+ case QMetaType::Char:
+ // force a char to be signed
+ stream >> *static_cast<signed char *>(data);
+ break;
+ case QMetaType::ULong: {
+ qulonglong ul;
+ stream >> ul;
+ *static_cast<ulong *>(data) = ulong(ul);
+ break; }
+ case QMetaType::UInt:
+ stream >> *static_cast<uint *>(data);
+ break;
+ case QMetaType::LongLong:
+ stream >> *static_cast<qlonglong *>(data);
+ break;
+ case QMetaType::ULongLong:
+ stream >> *static_cast<qulonglong *>(data);
+ break;
+ case QMetaType::UShort:
+ stream >> *static_cast<ushort *>(data);
+ break;
+ case QMetaType::UChar:
+ stream >> *static_cast<uchar *>(data);
+ break;
+ case QMetaType::Bool: {
+ qint8 b;
+ stream >> b;
+ *static_cast<bool *>(data) = b;
+ break; }
+ case QMetaType::Float:
+ stream >> *static_cast<float *>(data);
+ break;
+ case QMetaType::Double:
+ stream >> *static_cast<double *>(data);
+ break;
+ case QMetaType::QChar:
+ stream >> *static_cast< NS(QChar)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ stream >> *static_cast< NS(QVariantMap)*>(data);
+ break;
+ case QMetaType::QVariantHash:
+ stream >> *static_cast< NS(QVariantHash)*>(data);
+ break;
+ case QMetaType::QVariantList:
+ stream >> *static_cast< NS(QVariantList)*>(data);
+ break;
+ case QMetaType::QVariant:
+ stream >> *static_cast< NS(QVariant)*>(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ stream >> *static_cast< NS(QByteArray)*>(data);
+ break;
+ case QMetaType::QString:
+ stream >> *static_cast< NS(QString)*>(data);
+ break;
+ case QMetaType::QStringList:
+ stream >> *static_cast< NS(QStringList)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ stream >> *static_cast< NS(QBitArray)*>(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ stream >> *static_cast< NS(QDate)*>(data);
+ break;
+ case QMetaType::QTime:
+ stream >> *static_cast< NS(QTime)*>(data);
+ break;
+ case QMetaType::QDateTime:
+ stream >> *static_cast< NS(QDateTime)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ stream >> *static_cast< NS(QUrl)*>(data);
+ break;
+#endif
+ case QMetaType::QLocale:
+ stream >> *static_cast< NS(QLocale)*>(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ stream >> *static_cast< NS(QRect)*>(data);
+ break;
+ case QMetaType::QRectF:
+ stream >> *static_cast< NS(QRectF)*>(data);
+ break;
+ case QMetaType::QSize:
+ stream >> *static_cast< NS(QSize)*>(data);
+ break;
+ case QMetaType::QSizeF:
+ stream >> *static_cast< NS(QSizeF)*>(data);
+ break;
+ case QMetaType::QLine:
+ stream >> *static_cast< NS(QLine)*>(data);
+ break;
+ case QMetaType::QLineF:
+ stream >> *static_cast< NS(QLineF)*>(data);
+ break;
+ case QMetaType::QPoint:
+ stream >> *static_cast< NS(QPoint)*>(data);
+ break;
+ case QMetaType::QPointF:
+ stream >> *static_cast< NS(QPointF)*>(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ stream >> *static_cast< NS(QRegExp)*>(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ stream >> *static_cast< NS(QEasingCurve)*>(data);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+#endif
+ case QMetaType::QFont:
+ case QMetaType::QPixmap:
+ case QMetaType::QBrush:
+ case QMetaType::QColor:
+ case QMetaType::QPalette:
+ case QMetaType::QIcon:
+ case QMetaType::QImage:
+ case QMetaType::QPolygon:
+ case QMetaType::QRegion:
+ case QMetaType::QBitmap:
+ case QMetaType::QCursor:
+ case QMetaType::QSizePolicy:
+ case QMetaType::QKeySequence:
+ case QMetaType::QPen:
+ case QMetaType::QTextLength:
+ case QMetaType::QTextFormat:
+ case QMetaType::QMatrix:
+ case QMetaType::QTransform:
+ case QMetaType::QMatrix4x4:
+ case QMetaType::QVector2D:
+ case QMetaType::QVector3D:
+ case QMetaType::QVector4D:
+ case QMetaType::QQuaternion:
+ if (!qMetaTypeGuiHelper)
+ return false;
+ qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data);
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return false;
+
+ LoadOperator loadOp = 0;
+ {
+ QReadLocker locker(customTypesLock());
+ loadOp = ct->at(type - User).loadOp;
+ }
+
+ if (!loadOp)
+ return false;
+ loadOp(stream, data);
+ break; }
+ }
+ return true;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ Returns a copy of \a copy, assuming it is of type \a type. If \a
+ copy is zero, creates a default type.
+
+ \sa destroy(), isRegistered(), Type
+*/
+void *QMetaType::construct(int type, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return new void *(*static_cast<void* const *>(copy));
+ case QMetaType::Long:
+ return new long(*static_cast<const long*>(copy));
+ case QMetaType::Int:
+ return new int(*static_cast<const int*>(copy));
+ case QMetaType::Short:
+ return new short(*static_cast<const short*>(copy));
+ case QMetaType::Char:
+ return new char(*static_cast<const char*>(copy));
+ case QMetaType::ULong:
+ return new ulong(*static_cast<const ulong*>(copy));
+ case QMetaType::UInt:
+ return new uint(*static_cast<const uint*>(copy));
+ case QMetaType::LongLong:
+ return new qlonglong(*static_cast<const qlonglong*>(copy));
+ case QMetaType::ULongLong:
+ return new qulonglong(*static_cast<const qulonglong*>(copy));
+ case QMetaType::UShort:
+ return new ushort(*static_cast<const ushort*>(copy));
+ case QMetaType::UChar:
+ return new uchar(*static_cast<const uchar*>(copy));
+ case QMetaType::Bool:
+ return new bool(*static_cast<const bool*>(copy));
+ case QMetaType::Float:
+ return new float(*static_cast<const float*>(copy));
+ case QMetaType::Double:
+ return new double(*static_cast<const double*>(copy));
+ case QMetaType::QChar:
+ return new NS(QChar)(*static_cast<const NS(QChar)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ return new NS(QVariantMap)(*static_cast<const NS(QVariantMap)*>(copy));
+ case QMetaType::QVariantHash:
+ return new NS(QVariantHash)(*static_cast<const NS(QVariantHash)*>(copy));
+ case QMetaType::QVariantList:
+ return new NS(QVariantList)(*static_cast<const NS(QVariantList)*>(copy));
+ case QMetaType::QVariant:
+ return new NS(QVariant)(*static_cast<const NS(QVariant)*>(copy));
+#endif
+ case QMetaType::QByteArray:
+ return new NS(QByteArray)(*static_cast<const NS(QByteArray)*>(copy));
+ case QMetaType::QString:
+ return new NS(QString)(*static_cast<const NS(QString)*>(copy));
+ case QMetaType::QStringList:
+ return new NS(QStringList)(*static_cast<const NS(QStringList)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ return new NS(QBitArray)(*static_cast<const NS(QBitArray)*>(copy));
+#endif
+ case QMetaType::QDate:
+ return new NS(QDate)(*static_cast<const NS(QDate)*>(copy));
+ case QMetaType::QTime:
+ return new NS(QTime)(*static_cast<const NS(QTime)*>(copy));
+ case QMetaType::QDateTime:
+ return new NS(QDateTime)(*static_cast<const NS(QDateTime)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ return new NS(QUrl)(*static_cast<const NS(QUrl)*>(copy));
+#endif
+ case QMetaType::QLocale:
+ return new NS(QLocale)(*static_cast<const NS(QLocale)*>(copy));
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ return new NS(QRect)(*static_cast<const NS(QRect)*>(copy));
+ case QMetaType::QRectF:
+ return new NS(QRectF)(*static_cast<const NS(QRectF)*>(copy));
+ case QMetaType::QSize:
+ return new NS(QSize)(*static_cast<const NS(QSize)*>(copy));
+ case QMetaType::QSizeF:
+ return new NS(QSizeF)(*static_cast<const NS(QSizeF)*>(copy));
+ case QMetaType::QLine:
+ return new NS(QLine)(*static_cast<const NS(QLine)*>(copy));
+ case QMetaType::QLineF:
+ return new NS(QLineF)(*static_cast<const NS(QLineF)*>(copy));
+ case QMetaType::QPoint:
+ return new NS(QPoint)(*static_cast<const NS(QPoint)*>(copy));
+ case QMetaType::QPointF:
+ return new NS(QPointF)(*static_cast<const NS(QPointF)*>(copy));
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ return new NS(QRegExp)(*static_cast<const NS(QRegExp)*>(copy));
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ return new NS(QEasingCurve)(*static_cast<const NS(QEasingCurve)*>(copy));
+#endif
+ case QMetaType::Void:
+ return 0;
+ default:
+ ;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return new void *;
+ case QMetaType::Long:
+ return new long;
+ case QMetaType::Int:
+ return new int;
+ case QMetaType::Short:
+ return new short;
+ case QMetaType::Char:
+ return new char;
+ case QMetaType::ULong:
+ return new ulong;
+ case QMetaType::UInt:
+ return new uint;
+ case QMetaType::LongLong:
+ return new qlonglong;
+ case QMetaType::ULongLong:
+ return new qulonglong;
+ case QMetaType::UShort:
+ return new ushort;
+ case QMetaType::UChar:
+ return new uchar;
+ case QMetaType::Bool:
+ return new bool;
+ case QMetaType::Float:
+ return new float;
+ case QMetaType::Double:
+ return new double;
+ case QMetaType::QChar:
+ return new NS(QChar);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ return new NS(QVariantMap);
+ case QMetaType::QVariantHash:
+ return new NS(QVariantHash);
+ case QMetaType::QVariantList:
+ return new NS(QVariantList);
+ case QMetaType::QVariant:
+ return new NS(QVariant);
+#endif
+ case QMetaType::QByteArray:
+ return new NS(QByteArray);
+ case QMetaType::QString:
+ return new NS(QString);
+ case QMetaType::QStringList:
+ return new NS(QStringList);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ return new NS(QBitArray);
+#endif
+ case QMetaType::QDate:
+ return new NS(QDate);
+ case QMetaType::QTime:
+ return new NS(QTime);
+ case QMetaType::QDateTime:
+ return new NS(QDateTime);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ return new NS(QUrl);
+#endif
+ case QMetaType::QLocale:
+ return new NS(QLocale);
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ return new NS(QRect);
+ case QMetaType::QRectF:
+ return new NS(QRectF);
+ case QMetaType::QSize:
+ return new NS(QSize);
+ case QMetaType::QSizeF:
+ return new NS(QSizeF);
+ case QMetaType::QLine:
+ return new NS(QLine);
+ case QMetaType::QLineF:
+ return new NS(QLineF);
+ case QMetaType::QPoint:
+ return new NS(QPoint);
+ case QMetaType::QPointF:
+ return new NS(QPointF);
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ return new NS(QRegExp);
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ return new NS(QEasingCurve);
+#endif
+ case QMetaType::Void:
+ return 0;
+ default:
+ ;
+ }
+ }
+
+ Constructor constr = 0;
+ if (type >= FirstGuiType && type <= LastGuiType) {
+ if (!qMetaTypeGuiHelper)
+ return 0;
+ constr = qMetaTypeGuiHelper[type - FirstGuiType].constr;
+ } else {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ QReadLocker locker(customTypesLock());
+ if (type < User || !ct || ct->count() <= type - User)
+ return 0;
+ if (ct->at(type - User).typeName.isEmpty())
+ return 0;
+ constr = ct->at(type - User).constr;
+ }
+
+ return constr(copy);
+}
+
+/*!
+ Destroys the \a data, assuming it is of the \a type given.
+
+ \sa construct(), isRegistered(), Type
+*/
+void QMetaType::destroy(int type, void *data)
+{
+ if (!data)
+ return;
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ delete static_cast<void**>(data);
+ break;
+ case QMetaType::Long:
+ delete static_cast<long*>(data);
+ break;
+ case QMetaType::Int:
+ delete static_cast<int*>(data);
+ break;
+ case QMetaType::Short:
+ delete static_cast<short*>(data);
+ break;
+ case QMetaType::Char:
+ delete static_cast<char*>(data);
+ break;
+ case QMetaType::ULong:
+ delete static_cast<ulong*>(data);
+ break;
+ case QMetaType::LongLong:
+ delete static_cast<qlonglong*>(data);
+ break;
+ case QMetaType::ULongLong:
+ delete static_cast<qulonglong*>(data);
+ break;
+ case QMetaType::UInt:
+ delete static_cast<uint*>(data);
+ break;
+ case QMetaType::UShort:
+ delete static_cast<ushort*>(data);
+ break;
+ case QMetaType::UChar:
+ delete static_cast<uchar*>(data);
+ break;
+ case QMetaType::Bool:
+ delete static_cast<bool*>(data);
+ break;
+ case QMetaType::Float:
+ delete static_cast<float*>(data);
+ break;
+ case QMetaType::Double:
+ delete static_cast<double*>(data);
+ break;
+ case QMetaType::QChar:
+ delete static_cast< NS(QChar)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ delete static_cast< NS(QVariantMap)* >(data);
+ break;
+ case QMetaType::QVariantHash:
+ delete static_cast< NS(QVariantHash)* >(data);
+ break;
+ case QMetaType::QVariantList:
+ delete static_cast< NS(QVariantList)* >(data);
+ break;
+ case QMetaType::QVariant:
+ delete static_cast< NS(QVariant)* >(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ delete static_cast< NS(QByteArray)* >(data);
+ break;
+ case QMetaType::QString:
+ delete static_cast< NS(QString)* >(data);
+ break;
+ case QMetaType::QStringList:
+ delete static_cast< NS(QStringList)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ delete static_cast< NS(QBitArray)* >(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ delete static_cast< NS(QDate)* >(data);
+ break;
+ case QMetaType::QTime:
+ delete static_cast< NS(QTime)* >(data);
+ break;
+ case QMetaType::QDateTime:
+ delete static_cast< NS(QDateTime)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ delete static_cast< NS(QUrl)* >(data);
+#endif
+ break;
+ case QMetaType::QLocale:
+ delete static_cast< NS(QLocale)* >(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ delete static_cast< NS(QRect)* >(data);
+ break;
+ case QMetaType::QRectF:
+ delete static_cast< NS(QRectF)* >(data);
+ break;
+ case QMetaType::QSize:
+ delete static_cast< NS(QSize)* >(data);
+ break;
+ case QMetaType::QSizeF:
+ delete static_cast< NS(QSizeF)* >(data);
+ break;
+ case QMetaType::QLine:
+ delete static_cast< NS(QLine)* >(data);
+ break;
+ case QMetaType::QLineF:
+ delete static_cast< NS(QLineF)* >(data);
+ break;
+ case QMetaType::QPoint:
+ delete static_cast< NS(QPoint)* >(data);
+ break;
+ case QMetaType::QPointF:
+ delete static_cast< NS(QPointF)* >(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ delete static_cast< NS(QRegExp)* >(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ delete static_cast< NS(QEasingCurve)* >(data);
+ break;
+#endif
+ case QMetaType::Void:
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ Destructor destr = 0;
+ if (type >= FirstGuiType && type <= LastGuiType) {
+ Q_ASSERT(qMetaTypeGuiHelper);
+
+ if (!qMetaTypeGuiHelper)
+ return;
+ destr = qMetaTypeGuiHelper[type - FirstGuiType].destr;
+ } else {
+ QReadLocker locker(customTypesLock());
+ if (type < User || !ct || ct->count() <= type - User)
+ break;
+ if (ct->at(type - User).typeName.isEmpty())
+ break;
+ destr = ct->at(type - User).destr;
+ }
+ destr(data);
+ break; }
+ }
+}
+
+/*!
+ \fn int qRegisterMetaType(const char *typeName)
+ \relates QMetaType
+ \threadsafe
+
+ Registers the type name \a typeName for the type \c{T}. Returns
+ the internal ID used by QMetaType. Any class or struct that has a
+ public default constructor, a public copy constructor and a public
+ destructor can be registered.
+
+ After a type has been registered, you can create and destroy
+ objects of that type dynamically at run-time.
+
+ This example registers the class \c{MyClass}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 4
+
+ This function is useful to register typedefs so they can be used
+ by QMetaProperty, or in QueuedConnections
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 9
+
+ \sa qRegisterMetaTypeStreamOperators(), QMetaType::isRegistered(),
+ Q_DECLARE_METATYPE()
+*/
+
+/*!
+ \fn int qRegisterMetaTypeStreamOperators(const char *typeName)
+ \relates QMetaType
+ \threadsafe
+
+ Registers the stream operators for the type \c{T} called \a
+ typeName.
+
+ Afterward, the type can be streamed using QMetaType::load() and
+ QMetaType::save(). These functions are used when streaming a
+ QVariant.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 5
+
+ The stream operators should have the following signatures:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 6
+
+ \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
+*/
+
+/*! \typedef QMetaType::Destructor
+ \internal
+*/
+/*! \typedef QMetaType::Constructor
+ \internal
+*/
+/*! \typedef QMetaType::SaveOperator
+ \internal
+*/
+/*! \typedef QMetaType::LoadOperator
+ \internal
+*/
+
+/*!
+ \fn int qRegisterMetaType()
+ \relates QMetaType
+ \threadsafe
+ \since 4.2
+
+ 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 doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 7
+
+ 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.
+
+ 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.
+
+ \sa Q_DECLARE_METATYPE()
+ */
+
+/*! \fn int qMetaTypeId()
+ \relates QMetaType
+ \threadsafe
+ \since 4.1
+
+ Returns the meta type id of type \c T at compile time. If the
+ type was not declared with Q_DECLARE_METATYPE(), compilation will
+ fail.
+
+ Typical usage:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 8
+
+ QMetaType::type() returns the same ID as qMetaTypeId(), but does
+ a lookup at runtime based on the name of the type.
+ QMetaType::type() is a bit slower, but compilation succeeds if a
+ type is not registered.
+
+ \sa Q_DECLARE_METATYPE(), QMetaType::type()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
new file mode 100644
index 0000000000..a2bb7d1597
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.h
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETATYPE_H
+#define QMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+
+#ifndef QT_NO_DATASTREAM
+#include <QtCore/qdatastream.h>
+#endif
+
+#ifdef Bool
+#error qmetatype.h must be included before any header file that defines Bool
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QMetaType {
+public:
+ enum Type {
+ // these are merged with QVariant
+ Void = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
+ Double = 6, QChar = 7, QVariantMap = 8, QVariantList = 9,
+ QString = 10, QStringList = 11, QByteArray = 12,
+ QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
+ QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
+ QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27,
+ QVariantHash = 28, QEasingCurve = 29, LastCoreType = QEasingCurve,
+
+ FirstGuiType = 63 /* QColorGroup */,
+#ifdef QT3_SUPPORT
+ QColorGroup = 63,
+#endif
+ QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
+ QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
+ QCursor = 74, QSizePolicy = 75, QKeySequence = 76, QPen = 77,
+ QTextLength = 78, QTextFormat = 79, QMatrix = 80, QTransform = 81,
+ QMatrix4x4 = 82, QVector2D = 83, QVector3D = 84, QVector4D = 85,
+ QQuaternion = 86,
+ LastGuiType = QQuaternion,
+
+ FirstCoreExtType = 128 /* VoidStar */,
+ VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132,
+ UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137,
+ QVariant = 138,
+ LastCoreExtType = QVariant,
+
+// This logic must match the one in qglobal.h
+#if defined(QT_COORD_TYPE)
+ QReal = 0,
+#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
+ QReal = Float,
+#else
+ QReal = Double,
+#endif
+
+ User = 256
+ };
+
+ typedef void (*Destructor)(void *);
+ typedef void *(*Constructor)(const void *);
+
+#ifndef QT_NO_DATASTREAM
+ typedef void (*SaveOperator)(QDataStream &, const void *);
+ typedef void (*LoadOperator)(QDataStream &, void *);
+ static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
+ LoadOperator loadOp);
+ static void registerStreamOperators(int type, SaveOperator saveOp,
+ LoadOperator loadOp);
+#endif
+ static int registerType(const char *typeName, Destructor destructor,
+ Constructor constructor);
+ static int registerTypedef(const char *typeName, int aliasId);
+ static int type(const char *typeName);
+ static const char *typeName(int type);
+ static bool isRegistered(int type);
+ static void *construct(int type, const void *copy = 0);
+ static void destroy(int type, void *data);
+ static void unregisterType(const char *typeName);
+
+#ifndef QT_NO_DATASTREAM
+ static bool save(QDataStream &stream, int type, const void *data);
+ static bool load(QDataStream &stream, int type, void *data);
+#endif
+};
+
+template <typename T>
+void qMetaTypeDeleteHelper(T *t)
+{
+ delete t;
+}
+
+template <typename T>
+void *qMetaTypeConstructHelper(const T *t)
+{
+ if (!t)
+ return new T();
+ return new T(*static_cast<const T*>(t));
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+void qMetaTypeSaveHelper(QDataStream &stream, const T *t)
+{
+ stream << *t;
+}
+
+template <typename T>
+void qMetaTypeLoadHelper(QDataStream &stream, T *t)
+{
+ stream >> *t;
+}
+#endif // QT_NO_DATASTREAM
+
+template <typename T>
+struct QMetaTypeId
+{
+ enum { Defined = 0 };
+};
+
+template <typename T>
+struct QMetaTypeId2
+{
+ enum { Defined = QMetaTypeId<T>::Defined };
+ static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
+};
+
+namespace QtPrivate {
+ template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
+ struct QMetaTypeIdHelper {
+ static inline int qt_metatype_id()
+ { return QMetaTypeId2<T>::qt_metatype_id(); }
+ };
+ template <typename T> struct QMetaTypeIdHelper<T, false> {
+ static inline int qt_metatype_id()
+ { return -1; }
+ };
+}
+
+template <typename T>
+int qRegisterMetaType(const char *typeName
+#ifndef qdoc
+ , T * dummy = 0
+#endif
+)
+{
+ const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
+ if (typedefOf != -1)
+ return QMetaType::registerTypedef(typeName, typedefOf);
+
+ typedef void*(*ConstructPtr)(const T*);
+ ConstructPtr cptr = qMetaTypeConstructHelper<T>;
+ typedef void(*DeletePtr)(T*);
+ DeletePtr dptr = qMetaTypeDeleteHelper<T>;
+
+ return QMetaType::registerType(typeName, reinterpret_cast<QMetaType::Destructor>(dptr),
+ reinterpret_cast<QMetaType::Constructor>(cptr));
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+void qRegisterMetaTypeStreamOperators(const char *typeName
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+)
+{
+ typedef void(*SavePtr)(QDataStream &, const T *);
+ typedef void(*LoadPtr)(QDataStream &, T *);
+ SavePtr sptr = qMetaTypeSaveHelper<T>;
+ LoadPtr lptr = qMetaTypeLoadHelper<T>;
+
+ qRegisterMetaType<T>(typeName);
+ QMetaType::registerStreamOperators(typeName, reinterpret_cast<QMetaType::SaveOperator>(sptr),
+ reinterpret_cast<QMetaType::LoadOperator>(lptr));
+}
+#endif // QT_NO_DATASTREAM
+
+template <typename T>
+inline int qMetaTypeId(
+#ifndef qdoc
+ T * /* dummy */ = 0
+#endif
+)
+{
+ return QMetaTypeId2<T>::qt_metatype_id();
+}
+
+template <typename T>
+inline int qRegisterMetaType(
+#if !defined(qdoc) && !defined(Q_CC_SUN)
+ T * dummy = 0
+#endif
+)
+{
+#ifdef Q_CC_SUN
+ return qMetaTypeId(static_cast<T *>(0));
+#else
+ return qMetaTypeId(dummy);
+#endif
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+inline int qRegisterMetaTypeStreamOperators()
+{
+ typedef void(*SavePtr)(QDataStream &, const T *);
+ typedef void(*LoadPtr)(QDataStream &, T *);
+ SavePtr sptr = qMetaTypeSaveHelper<T>;
+ LoadPtr lptr = qMetaTypeLoadHelper<T>;
+
+ register int id = qMetaTypeId<T>();
+ QMetaType::registerStreamOperators(id,
+ reinterpret_cast<QMetaType::SaveOperator>(sptr),
+ reinterpret_cast<QMetaType::LoadOperator>(lptr));
+
+ return id;
+}
+#endif
+
+#define Q_DECLARE_METATYPE(TYPE) \
+ QT_BEGIN_NAMESPACE \
+ template <> \
+ struct QMetaTypeId< TYPE > \
+ { \
+ enum { Defined = 1 }; \
+ static int qt_metatype_id() \
+ { \
+ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ if (!metatype_id) \
+ metatype_id = qRegisterMetaType< TYPE >(#TYPE, \
+ reinterpret_cast< TYPE *>(quintptr(-1))); \
+ return metatype_id; \
+ } \
+ }; \
+ QT_END_NAMESPACE
+
+#define Q_DECLARE_BUILTIN_METATYPE(TYPE, NAME) \
+ QT_BEGIN_NAMESPACE \
+ template<> struct QMetaTypeId2<TYPE> \
+ { \
+ enum { Defined = 1, MetaType = QMetaType::NAME }; \
+ static inline int qt_metatype_id() { return QMetaType::NAME; } \
+ }; \
+ QT_END_NAMESPACE
+
+class QString;
+class QByteArray;
+class QChar;
+class QStringList;
+class QBitArray;
+class QDate;
+class QTime;
+class QDateTime;
+class QUrl;
+class QLocale;
+class QRect;
+class QRectF;
+class QSize;
+class QSizeF;
+class QLine;
+class QLineF;
+class QPoint;
+class QPointF;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+class QEasingCurve;
+class QWidget;
+class QObject;
+
+#ifdef QT3_SUPPORT
+class QColorGroup;
+#endif
+class QFont;
+class QPixmap;
+class QBrush;
+class QColor;
+class QPalette;
+class QIcon;
+class QImage;
+class QPolygon;
+class QRegion;
+class QBitmap;
+class QCursor;
+class QSizePolicy;
+class QKeySequence;
+class QPen;
+class QTextLength;
+class QTextFormat;
+class QMatrix;
+class QTransform;
+class QMatrix4x4;
+class QVector2D;
+class QVector3D;
+class QVector4D;
+class QQuaternion;
+class QVariant;
+
+QT_END_NAMESPACE
+
+Q_DECLARE_BUILTIN_METATYPE(QString, QString)
+Q_DECLARE_BUILTIN_METATYPE(int, Int)
+Q_DECLARE_BUILTIN_METATYPE(uint, UInt)
+Q_DECLARE_BUILTIN_METATYPE(bool, Bool)
+Q_DECLARE_BUILTIN_METATYPE(double, Double)
+Q_DECLARE_BUILTIN_METATYPE(QByteArray, QByteArray)
+Q_DECLARE_BUILTIN_METATYPE(QChar, QChar)
+Q_DECLARE_BUILTIN_METATYPE(long, Long)
+Q_DECLARE_BUILTIN_METATYPE(short, Short)
+Q_DECLARE_BUILTIN_METATYPE(char, Char)
+Q_DECLARE_BUILTIN_METATYPE(signed char, Char)
+Q_DECLARE_BUILTIN_METATYPE(ulong, ULong)
+Q_DECLARE_BUILTIN_METATYPE(ushort, UShort)
+Q_DECLARE_BUILTIN_METATYPE(uchar, UChar)
+Q_DECLARE_BUILTIN_METATYPE(float, Float)
+Q_DECLARE_BUILTIN_METATYPE(QObject *, QObjectStar)
+Q_DECLARE_BUILTIN_METATYPE(QWidget *, QWidgetStar)
+Q_DECLARE_BUILTIN_METATYPE(void *, VoidStar)
+Q_DECLARE_BUILTIN_METATYPE(qlonglong, LongLong)
+Q_DECLARE_BUILTIN_METATYPE(qulonglong, ULongLong)
+Q_DECLARE_BUILTIN_METATYPE(QStringList, QStringList)
+Q_DECLARE_BUILTIN_METATYPE(QBitArray, QBitArray)
+Q_DECLARE_BUILTIN_METATYPE(QDate, QDate)
+Q_DECLARE_BUILTIN_METATYPE(QTime, QTime)
+Q_DECLARE_BUILTIN_METATYPE(QDateTime, QDateTime)
+Q_DECLARE_BUILTIN_METATYPE(QUrl, QUrl)
+Q_DECLARE_BUILTIN_METATYPE(QLocale, QLocale)
+Q_DECLARE_BUILTIN_METATYPE(QRect, QRect)
+Q_DECLARE_BUILTIN_METATYPE(QRectF, QRectF)
+Q_DECLARE_BUILTIN_METATYPE(QSize, QSize)
+Q_DECLARE_BUILTIN_METATYPE(QSizeF, QSizeF)
+Q_DECLARE_BUILTIN_METATYPE(QLine, QLine)
+Q_DECLARE_BUILTIN_METATYPE(QLineF, QLineF)
+Q_DECLARE_BUILTIN_METATYPE(QPoint, QPoint)
+Q_DECLARE_BUILTIN_METATYPE(QPointF, QPointF)
+#ifndef QT_NO_REGEXP
+Q_DECLARE_BUILTIN_METATYPE(QRegExp, QRegExp)
+#endif
+Q_DECLARE_BUILTIN_METATYPE(QEasingCurve, QEasingCurve)
+
+#ifdef QT3_SUPPORT
+Q_DECLARE_BUILTIN_METATYPE(QColorGroup, QColorGroup)
+#endif
+Q_DECLARE_BUILTIN_METATYPE(QFont, QFont)
+Q_DECLARE_BUILTIN_METATYPE(QPixmap, QPixmap)
+Q_DECLARE_BUILTIN_METATYPE(QBrush, QBrush)
+Q_DECLARE_BUILTIN_METATYPE(QColor, QColor)
+Q_DECLARE_BUILTIN_METATYPE(QPalette, QPalette)
+Q_DECLARE_BUILTIN_METATYPE(QIcon, QIcon)
+Q_DECLARE_BUILTIN_METATYPE(QImage, QImage)
+Q_DECLARE_BUILTIN_METATYPE(QPolygon, QPolygon)
+Q_DECLARE_BUILTIN_METATYPE(QRegion, QRegion)
+Q_DECLARE_BUILTIN_METATYPE(QBitmap, QBitmap)
+Q_DECLARE_BUILTIN_METATYPE(QCursor, QCursor)
+Q_DECLARE_BUILTIN_METATYPE(QSizePolicy, QSizePolicy)
+Q_DECLARE_BUILTIN_METATYPE(QKeySequence, QKeySequence)
+Q_DECLARE_BUILTIN_METATYPE(QPen, QPen)
+Q_DECLARE_BUILTIN_METATYPE(QTextLength, QTextLength)
+Q_DECLARE_BUILTIN_METATYPE(QTextFormat, QTextFormat)
+Q_DECLARE_BUILTIN_METATYPE(QMatrix, QMatrix)
+Q_DECLARE_BUILTIN_METATYPE(QTransform, QTransform)
+Q_DECLARE_BUILTIN_METATYPE(QMatrix4x4, QMatrix4x4)
+Q_DECLARE_BUILTIN_METATYPE(QVector2D, QVector2D)
+Q_DECLARE_BUILTIN_METATYPE(QVector3D, QVector3D)
+Q_DECLARE_BUILTIN_METATYPE(QVector4D, QVector4D)
+Q_DECLARE_BUILTIN_METATYPE(QQuaternion, QQuaternion)
+Q_DECLARE_BUILTIN_METATYPE(QVariant, QVariant)
+
+QT_END_HEADER
+
+#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
new file mode 100644
index 0000000000..4e0f8aeb8e
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -0,0 +1,627 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmimedata.h"
+
+#include "private/qobject_p.h"
+#include "qurl.h"
+#include "qstringlist.h"
+#include "qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QMimeDataStruct
+{
+ QString format;
+ QVariant data;
+};
+
+class QMimeDataPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QMimeData)
+public:
+ void removeData(const QString &format);
+ void setData(const QString &format, const QVariant &data);
+ QVariant getData(const QString &format) const;
+
+ QVariant retrieveTypedData(const QString &format, QVariant::Type type) const;
+
+ QList<QMimeDataStruct> dataList;
+};
+
+void QMimeDataPrivate::removeData(const QString &format)
+{
+ for (int i=0; i<dataList.size(); i++) {
+ if (dataList.at(i).format == format) {
+ dataList.removeAt(i);
+ return;
+ }
+ }
+}
+
+void QMimeDataPrivate::setData(const QString &format, const QVariant &data)
+{
+ // remove it first if the format is already here.
+ removeData(format);
+ QMimeDataStruct mimeData;
+ mimeData.format = format;
+ mimeData.data = data;
+ dataList += mimeData;
+}
+
+
+QVariant QMimeDataPrivate::getData(const QString &format) const
+{
+ QVariant data;
+ for (int i=0; i<dataList.size(); i++) {
+ if (dataList.at(i).format == format) {
+ data = dataList.at(i).data;
+ break;
+ }
+ }
+ return data;
+}
+
+QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Type type) const
+{
+ Q_Q(const QMimeData);
+
+ QVariant data = q->retrieveData(format, type);
+ if (data.type() == type || !data.isValid())
+ return data;
+
+ // provide more conversion possiblities than just what QVariant provides
+
+ // URLs can be lists as well...
+ if ((type == QVariant::Url && data.type() == QVariant::List)
+ || (type == QVariant::List && data.type() == QVariant::Url))
+ return data;
+
+ // images and pixmaps are interchangeable
+ if ((type == QVariant::Pixmap && data.type() == QVariant::Image)
+ || (type == QVariant::Image && data.type() == QVariant::Pixmap))
+ return data;
+
+ if (data.type() == QVariant::ByteArray) {
+ // see if we can convert to the requested type
+ switch(type) {
+#ifndef QT_NO_TEXTCODEC
+ case QVariant::String: {
+ const QByteArray ba = data.toByteArray();
+ QTextCodec *codec = QTextCodec::codecForName("utf-8");
+ if (format == QLatin1String("text/html"))
+ codec = QTextCodec::codecForHtml(ba, codec);
+ return codec->toUnicode(ba);
+ }
+#endif // QT_NO_TEXTCODEC
+ case QVariant::Color: {
+ QVariant newData = data;
+ newData.convert(QVariant::Color);
+ return newData;
+ }
+ case QVariant::List: {
+ if (format != QLatin1String("text/uri-list"))
+ break;
+ // fall through
+ }
+ case QVariant::Url: {
+ QByteArray ba = data.toByteArray();
+ // 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;
+ }
+ default:
+ break;
+ }
+
+ } else if (type == QVariant::ByteArray) {
+
+ // try to convert to bytearray
+ switch(data.type()) {
+ case QVariant::ByteArray:
+ case QVariant::Color:
+ return data.toByteArray();
+ break;
+ case QVariant::String:
+ return data.toString().toUtf8();
+ break;
+ case QVariant::Url:
+ return data.toUrl().toEncoded();
+ break;
+ case QVariant::List: {
+ // 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).type() == QVariant::Url) {
+ result += list.at(i).toUrl().toEncoded();
+ result += "\r\n";
+ }
+ }
+ if (!result.isEmpty())
+ return result;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return data;
+}
+
+/*!
+ \class QMimeData
+ \brief The QMimeData class provides a container for data that records information
+ about its MIME type.
+
+ QMimeData is used to describe information that can be stored in
+ the \l{QClipboard}{clipboard}, and transferred via the \l{drag
+ and drop} mechanism. QMimeData objects associate the data that
+ they hold with the corresponding MIME types to ensure that
+ information can be safely transferred between applications, and
+ copied around within the same application.
+
+ QMimeData objects are usually created using \c new and supplied
+ to QDrag or QClipboard objects. This is to enable Qt to manage
+ the memory that they use.
+
+ A single QMimeData object can store the same data using several
+ different formats at the same time. The formats() function
+ returns a list of the available formats in order of preference.
+ The data() function returns the raw data associated with a MIME
+ type, and setData() allows you to set the data for a MIME type.
+
+ For the most common MIME types, QMimeData provides convenience
+ functions to access the data:
+
+ \table
+ \header \o Tester \o Getter \o Setter \o MIME Types
+ \row \o hasText() \o text() \o setText() \o \c text/plain
+ \row \o hasHtml() \o html() \o setHtml() \o \c text/html
+ \row \o hasUrls() \o urls() \o setUrls() \o \c text/uri-list
+ \row \o hasImage() \o imageData() \o setImageData() \o \c image/ *
+ \row \o hasColor() \o colorData() \o setColorData() \o \c application/x-color
+ \endtable
+
+ For example, if your write a widget that accepts URL drags, you
+ would end up writing code like this:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 0
+
+ There are three approaches for storing custom data in a QMimeData
+ object:
+
+ \list 1
+ \o Custom data can be stored directly in a QMimeData object as a
+ QByteArray using setData(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1
+
+ \o We can subclass QMimeData and reimplement hasFormat(),
+ formats(), and retrieveData().
+
+ \o If the drag and drop operation occurs within a single
+ application, we can subclass QMimeData and add extra data in
+ it, and use a qobject_cast() in the receiver's drop event
+ handler. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 2
+ \endlist
+
+ \section1 Platform-Specific MIME Types
+
+ On Windows, formats() will also return custom formats available
+ in the MIME data, using the \c{x-qt-windows-mime} subtype to
+ indicate that they represent data in non-standard formats.
+ The formats will take the following form:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 3
+
+ The following are examples of custom MIME types:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 4
+
+ The \c value declaration of each format describes the way in which the
+ data is encoded.
+
+ On Windows, the MIME format does not always map directly to the
+ clipboard formats. Qt provides QWindowsMime to map clipboard
+ formats to open-standard MIME formats. Similarly, the
+ QMacPasteboardMime maps MIME to Mac flavors.
+
+ \sa QClipboard, QDragEnterEvent, QDragMoveEvent, QDropEvent, QDrag,
+ QWindowsMime, QMacPasteboardMime, {Drag and Drop}
+*/
+
+/*!
+ Constructs a new MIME data object with no data in it.
+*/
+QMimeData::QMimeData()
+ : QObject(*new QMimeDataPrivate, 0)
+{
+}
+
+/*!
+ Destroys the MIME data object.
+*/
+QMimeData::~QMimeData()
+{
+}
+
+/*!
+ Returns a list of URLs contained within the MIME data object.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa hasUrls(), data()
+*/
+QList<QUrl> QMimeData::urls() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/uri-list"), QVariant::List);
+ QList<QUrl> urls;
+ if (data.type() == QVariant::Url)
+ urls.append(data.toUrl());
+ else if (data.type() == QVariant::List) {
+ QList<QVariant> list = data.toList();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).type() == QVariant::Url)
+ urls.append(list.at(i).toUrl());
+ }
+ }
+ return urls;
+}
+
+/*!
+ Sets the URLs stored in the MIME data object to those specified by \a urls.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa hasUrls(), setData()
+*/
+void QMimeData::setUrls(const QList<QUrl> &urls)
+{
+ Q_D(QMimeData);
+ QList<QVariant> list;
+ for (int i = 0; i < urls.size(); ++i)
+ list.append(urls.at(i));
+
+ d->setData(QLatin1String("text/uri-list"), list);
+}
+
+/*!
+ Returns true if the object can return a list of urls; otherwise
+ returns false.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa setUrls(), urls(), hasFormat()
+*/
+bool QMimeData::hasUrls() const
+{
+ return hasFormat(QLatin1String("text/uri-list"));
+}
+
+
+/*!
+ Returns a plain text (MIME type \c text/plain) representation of
+ the data.
+
+ \sa hasText(), html(), data()
+*/
+QString QMimeData::text() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/plain"), QVariant::String);
+ return data.toString();
+}
+
+/*!
+ Sets \a text as the plain text (MIME type \c text/plain) used to
+ represent the data.
+
+ \sa hasText(), setHtml(), setData()
+*/
+void QMimeData::setText(const QString &text)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("text/plain"), text);
+}
+
+/*!
+ Returns true if the object can return plain text (MIME type \c
+ text/plain); otherwise returns false.
+
+ \sa setText(), text(), hasHtml(), hasFormat()
+*/
+bool QMimeData::hasText() const
+{
+ return hasFormat(QLatin1String("text/plain"));
+}
+
+/*!
+ Returns a string if the data stored in the object is HTML (MIME
+ type \c text/html); otherwise returns an empty string.
+
+ \sa hasHtml(), setData()
+*/
+QString QMimeData::html() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/html"), QVariant::String);
+ return data.toString();
+}
+
+/*!
+ Sets \a html as the HTML (MIME type \c text/html) used to
+ represent the data.
+
+ \sa hasHtml(), setText(), setData()
+*/
+void QMimeData::setHtml(const QString &html)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("text/html"), html);
+}
+
+/*!
+ Returns true if the object can return HTML (MIME type \c
+ text/html); otherwise returns false.
+
+ \sa setHtml(), html(), hasFormat()
+*/
+bool QMimeData::hasHtml() const
+{
+ return hasFormat(QLatin1String("text/html"));
+}
+
+/*!
+ Returns a QVariant storing a QImage if the object can return an
+ image; otherwise returns a null variant.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QImage belongs to \l QtGui. To convert the
+ QVariant to a QImage, simply use qvariant_cast(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 5
+
+ \sa hasImage()
+*/
+QVariant QMimeData::imageData() const
+{
+ Q_D(const QMimeData);
+ return d->retrieveTypedData(QLatin1String("application/x-qt-image"), QVariant::Image);
+}
+
+/*!
+ Sets the data in the object to the given \a image.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QImage belongs to \l QtGui. The conversion
+ from QImage to QVariant is implicit. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 6
+
+ \sa hasImage(), setData()
+*/
+void QMimeData::setImageData(const QVariant &image)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("application/x-qt-image"), image);
+}
+
+/*!
+ Returns true if the object can return an image; otherwise returns
+ false.
+
+ \sa setImageData(), imageData(), hasFormat()
+*/
+bool QMimeData::hasImage() const
+{
+ return hasFormat(QLatin1String("application/x-qt-image"));
+}
+
+/*!
+ Returns a color if the data stored in the object represents a
+ color (MIME type \c application/x-color); otherwise returns a
+ null variant.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QColor belongs to \l QtGui. To convert the
+ QVariant to a QColor, simply use qvariant_cast(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 7
+
+ \sa hasColor(), setColorData(), data()
+*/
+QVariant QMimeData::colorData() const
+{
+ Q_D(const QMimeData);
+ return d->retrieveTypedData(QLatin1String("application/x-color"), QVariant::Color);
+}
+
+/*!
+ Sets the color data in the object to the given \a color.
+
+ Colors correspond to the MIME type \c application/x-color.
+
+ \sa hasColor(), setData()
+*/
+void QMimeData::setColorData(const QVariant &color)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("application/x-color"), color);
+}
+
+
+/*!
+ Returns true if the object can return a color (MIME type \c
+ application/x-color); otherwise returns false.
+
+ \sa setColorData(), colorData(), hasFormat()
+*/
+bool QMimeData::hasColor() const
+{
+ return hasFormat(QLatin1String("application/x-color"));
+}
+
+/*!
+ Returns the data stored in the object in the format described by
+ the MIME type specified by \a mimeType.
+*/
+QByteArray QMimeData::data(const QString &mimeType) const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(mimeType, QVariant::ByteArray);
+ return data.toByteArray();
+}
+
+/*!
+ Sets the data associated with the MIME type given by \a mimeType
+ to the specified \a data.
+
+ For the most common types of data, you can call the higher-level
+ functions setText(), setHtml(), setUrls(), setImageData(), and
+ setColorData() instead.
+
+ 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.
+
+ \sa hasFormat(), QMetaType, qRegisterMetaTypeStreamOperators()
+*/
+void QMimeData::setData(const QString &mimeType, const QByteArray &data)
+{
+ Q_D(QMimeData);
+ d->setData(mimeType, QVariant(data));
+}
+
+/*!
+ Returns true if the object can return data for the MIME type
+ specified by \a mimeType; otherwise returns false.
+
+ For the most common types of data, you can call the higher-level
+ functions hasText(), hasHtml(), hasUrls(), hasImage(), and
+ hasColor() instead.
+
+ \sa formats(), setData(), data()
+*/
+bool QMimeData::hasFormat(const QString &mimeType) const
+{
+ return formats().contains(mimeType);
+}
+
+/*!
+ Returns a list of formats supported by the object. This is a list
+ of MIME types for which the object can return suitable data. The
+ formats in the list are in a priority order.
+
+ For the most common types of data, you can call the higher-level
+ functions hasText(), hasHtml(), hasUrls(), hasImage(), and
+ hasColor() instead.
+
+ \sa hasFormat(), setData(), data()
+*/
+QStringList QMimeData::formats() const
+{
+ Q_D(const QMimeData);
+ QStringList list;
+ for (int i=0; i<d->dataList.size(); i++)
+ list += d->dataList.at(i).format;
+ return list;
+}
+
+/*!
+ Returns a variant with the given \a type containing data for the
+ MIME type specified by \a mimeType. If the object does not
+ support the MIME type or variant type given, a null variant is
+ returned instead.
+
+ This function is called by the general data() getter and by the
+ convenience getters (text(), html(), urls(), imageData(), and
+ colorData()). You can reimplement it if you want to store your
+ data using a custom data structure (instead of a QByteArray,
+ which is what setData() provides). You would then also need
+ to reimplement hasFormat() and formats().
+
+ \sa data()
+*/
+QVariant QMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+{
+ Q_UNUSED(type);
+ Q_D(const QMimeData);
+ return d->getData(mimeType);
+}
+
+/*!
+ Removes all the MIME type and data entries in the object.
+*/
+void QMimeData::clear()
+{
+ Q_D(QMimeData);
+ d->dataList.clear();
+}
+
+/*!
+ \since 4.4
+
+ Removes the data entry for \a mimeType in the object.
+*/
+void QMimeData::removeFormat(const QString &mimeType)
+{
+ Q_D(QMimeData);
+ d->removeData(mimeType);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmimedata.h b/src/corelib/kernel/qmimedata.h
new file mode 100644
index 0000000000..28b999c235
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEDATA_H
+#define QMIMEDATA_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QUrl;
+class QMimeDataPrivate;
+
+class Q_CORE_EXPORT QMimeData : public QObject
+{
+ Q_OBJECT
+public:
+ QMimeData();
+ ~QMimeData();
+
+ QList<QUrl> urls() const;
+ void setUrls(const QList<QUrl> &urls);
+ bool hasUrls() const;
+
+ QString text() const;
+ void setText(const QString &text);
+ bool hasText() const;
+
+ QString html() const;
+ void setHtml(const QString &html);
+ bool hasHtml() const;
+
+ QVariant imageData() const;
+ void setImageData(const QVariant &image);
+ bool hasImage() const;
+
+ QVariant colorData() const;
+ void setColorData(const QVariant &color);
+ bool hasColor() const;
+
+ QByteArray data(const QString &mimetype) const;
+ void setData(const QString &mimetype, const QByteArray &data);
+ void removeFormat(const QString &mimetype);
+
+ virtual bool hasFormat(const QString &mimetype) const;
+ virtual QStringList formats() const;
+
+ void clear();
+protected:
+ virtual QVariant retrieveData(const QString &mimetype,
+ QVariant::Type preferredType) const;
+private:
+ Q_DISABLE_COPY(QMimeData)
+ Q_DECLARE_PRIVATE(QMimeData)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMIMEDATA_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
new file mode 100644
index 0000000000..357cfd3f33
--- /dev/null
+++ b/src/corelib/kernel/qobject.cpp
@@ -0,0 +1,4310 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qobject.h"
+#include "qobject_p.h"
+#include "qmetaobject_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qvariant.h"
+#include "qmetaobject.h"
+#include <qregexp.h>
+#include <qthread.h>
+#include <private/qthread_p.h>
+#include <qdebug.h>
+#include <qhash.h>
+#include <qpair.h>
+#include <qvarlengtharray.h>
+#include <qset.h>
+#include <qsemaphore.h>
+#include <qsharedpointer.h>
+
+#include <private/qorderedmutexlocker_p.h>
+#include <private/qmutexpool_p.h>
+
+#include <new>
+
+#include <ctype.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+static int DIRECT_CONNECTION_ONLY = 0;
+
+static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
+{
+ 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;
+ 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;
+ return 0;
+ }
+ }
+ types[typeNames.count()] = 0;
+
+ return types;
+}
+
+static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
+static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+/** \internal
+ * mutex to be locked when accessing the connectionlists or the senders list
+ */
+static inline QMutex *signalSlotLock(const QObject *o)
+{
+ if (!signalSlotMutexes) {
+ QMutexPool *mp = new QMutexPool;
+ if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
+ delete mp;
+ }
+ }
+ return signalSlotMutexes->get(o);
+}
+
+extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
+{
+ objectCount.ref();
+}
+
+extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
+{
+ if(!objectCount.deref()) {
+ QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
+ delete old;
+ }
+}
+
+void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
+void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
+void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
+
+QObjectData::~QObjectData() {}
+
+QObjectPrivate::QObjectPrivate(int version)
+ : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
+{
+ if (version != QObjectPrivateVersion)
+ qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
+ version, QObjectPrivateVersion);
+
+ // QObjectData initialization
+ q_ptr = 0;
+ parent = 0; // no parent yet. It is set by setParent()
+ isWidget = false; // assume not a widget object
+ pendTimer = false; // no timers yet
+ blockSig = false; // not blocking signals
+ wasDeleted = false; // double-delete catcher
+ sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
+ receiveChildEvents = true;
+ postedEvents = 0;
+ extraData = 0;
+ connectedSignals[0] = connectedSignals[1] = 0;
+ inThreadChangeEvent = false;
+#ifdef QT_JAMBI_BUILD
+ inEventHandler = false;
+ deleteWatch = 0;
+#endif
+ metaObject = 0;
+ hasGuards = false;
+}
+
+QObjectPrivate::~QObjectPrivate()
+{
+ if (pendTimer) {
+ // unregister pending timers
+ if (threadData->eventDispatcher)
+ threadData->eventDispatcher->unregisterTimers(q_ptr);
+ }
+
+ if (postedEvents)
+ QCoreApplication::removePostedEvents(q_ptr, 0);
+
+ threadData->deref();
+
+ delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
+#ifdef QT_JAMBI_BUILD
+ if (deleteWatch)
+ *deleteWatch = 1;
+#endif
+#ifndef QT_NO_USERDATA
+ if (extraData)
+ qDeleteAll(extraData->userData);
+ delete extraData;
+#endif
+}
+
+
+#ifdef QT_JAMBI_BUILD
+int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) {
+ int *old = d->deleteWatch;
+ d->deleteWatch = w;
+ return old;
+}
+
+
+void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch) {
+ if (!deleteWatch)
+ d->deleteWatch = oldWatch;
+
+ if (oldWatch)
+ *oldWatch = deleteWatch;
+}
+#endif
+
+#ifdef QT3_SUPPORT
+void QObjectPrivate::sendPendingChildInsertedEvents()
+{
+ Q_Q(QObject);
+ for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
+ QObject *c = pendingChildInsertedEvents.at(i).data();
+ if (!c || c->parent() != q)
+ continue;
+ QChildEvent childEvent(QEvent::ChildInserted, c);
+ QCoreApplication::sendEvent(q, &childEvent);
+ }
+ pendingChildInsertedEvents.clear();
+}
+
+#endif
+
+
+/*!\internal
+ For a given metaobject, compute the signal offset, and the method offset (including signals)
+*/
+static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
+{
+ *signalOffset = *methodOffset = 0;
+ const QMetaObject *m = metaobject->d.superdata;
+ while (m) {
+ const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
+ *methodOffset += d->methodCount;
+ *signalOffset += (d->revision >= 4) ? d->signalCount : d->methodCount;
+ /*Before Qt 4.6 (revision 4), the signalCount information was not generated by moc.
+ so for compatibility we consider all the method as slot for old moc output*/
+ m = m->d.superdata;
+ }
+}
+
+/*
+ This vector contains the all connections from an object.
+
+ Each object may have one vector containing the lists of
+ connections for a given signal. The index in the vector correspond
+ to the signal index. The signal index is the one returned by
+ QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
+ Negative index means connections to all signals.
+
+ This vector is protected by the object mutex (signalSlotMutexes())
+
+ Each Connection is also part of a 'senders' linked list. The mutex
+ of the receiver must be locked when touching the pointers of this
+ linked list.
+*/
+class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
+{
+public:
+ bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
+ bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
+ int inUse; //number of functions that are currently accessing this object or its connections
+ QObjectPrivate::ConnectionList allsignals;
+
+ QObjectConnectionListVector()
+ : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
+ { }
+
+ QObjectPrivate::ConnectionList &operator[](int at)
+ {
+ if (at < 0)
+ return allsignals;
+ return QVector<QObjectPrivate::ConnectionList>::operator[](at);
+ }
+};
+
+// Used by QAccessibleWidget
+bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
+{
+ Q_Q(const QObject);
+ int signal_index = signalIndex(signal);
+ if (signal_index < 0)
+ return false;
+ QMutexLocker locker(signalSlotLock(q));
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const QObjectPrivate::Connection *c =
+ connectionLists->at(signal_index).first;
+
+ while (c) {
+ if (c->receiver == receiver)
+ return true;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ return false;
+}
+
+// Used by QAccessibleWidget
+QObjectList QObjectPrivate::receiverList(const char *signal) const
+{
+ Q_Q(const QObject);
+ QObjectList returnValue;
+ int signal_index = signalIndex(signal);
+ if (signal_index < 0)
+ return returnValue;
+ QMutexLocker locker(signalSlotLock(q));
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
+
+ while (c) {
+ if (c->receiver)
+ returnValue << c->receiver;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ return returnValue;
+}
+
+// Used by QAccessibleWidget
+QObjectList QObjectPrivate::senderList() const
+{
+ QObjectList returnValue;
+ QMutexLocker locker(signalSlotLock(q_func()));
+ for (Connection *c = senders; c; c = c->next)
+ returnValue << c->sender;
+ return returnValue;
+}
+
+void QObjectPrivate::addConnection(int signal, Connection *c)
+{
+ if (!connectionLists)
+ connectionLists = new QObjectConnectionListVector();
+ if (signal >= connectionLists->count())
+ connectionLists->resize(signal + 1);
+
+ ConnectionList &connectionList = (*connectionLists)[signal];
+ if (connectionList.last) {
+ connectionList.last->nextConnectionList = c;
+ } else {
+ connectionList.first = c;
+ }
+ connectionList.last = c;
+
+ cleanConnectionLists();
+}
+
+void QObjectPrivate::cleanConnectionLists()
+{
+ if (connectionLists->dirty && !connectionLists->inUse) {
+ // remove broken connections
+ for (int signal = -1; signal < connectionLists->count(); ++signal) {
+ QObjectPrivate::ConnectionList &connectionList =
+ (*connectionLists)[signal];
+
+ // Set to the last entry in the connection list that was *not*
+ // deleted. This is needed to update the list's last pointer
+ // at the end of the cleanup.
+ QObjectPrivate::Connection *last = 0;
+
+ QObjectPrivate::Connection **prev = &connectionList.first;
+ QObjectPrivate::Connection *c = *prev;
+ while (c) {
+ if (c->receiver) {
+ last = c;
+ prev = &c->nextConnectionList;
+ c = *prev;
+ } else {
+ QObjectPrivate::Connection *next = c->nextConnectionList;
+ *prev = next;
+ delete c;
+ c = next;
+ }
+ }
+
+ // Correct the connection list's last pointer.
+ // As conectionList.last could equal last, this could be a noop
+ connectionList.last = last;
+ }
+ connectionLists->dirty = false;
+ }
+}
+
+typedef QMultiHash<QObject *, QObject **> GuardHash;
+Q_GLOBAL_STATIC(GuardHash, guardHash)
+Q_GLOBAL_STATIC(QMutex, guardHashLock)
+
+/*!\internal
+ */
+void QMetaObject::addGuard(QObject **ptr)
+{
+ if (!*ptr)
+ return;
+ GuardHash *hash = guardHash();
+ if (!hash) {
+ *ptr = 0;
+ return;
+ }
+ QMutexLocker locker(guardHashLock());
+ QObjectPrivate::get(*ptr)->hasGuards = true;
+ hash->insert(*ptr, ptr);
+}
+
+/*!\internal
+ */
+void QMetaObject::removeGuard(QObject **ptr)
+{
+ if (!*ptr)
+ return;
+ GuardHash *hash = guardHash();
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (!hash || hash->isEmpty())
+ return;
+ QMutexLocker locker(guardHashLock());
+ if (!*ptr) //check again, under the lock
+ return;
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ bool more = false; //if the QObject has more pointer attached to it.
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
+ break;
+ }
+ more = true;
+ }
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
+}
+
+/*!\internal
+ */
+void QMetaObject::changeGuard(QObject **ptr, QObject *o)
+{
+ GuardHash *hash = guardHash();
+ if (!hash) {
+ *ptr = 0;
+ return;
+ }
+ QMutexLocker locker(guardHashLock());
+ if (o) {
+ hash->insert(o, ptr);
+ QObjectPrivate::get(o)->hasGuards = true;
+ }
+ if (*ptr) {
+ bool more = false; //if the QObject has more pointer attached to it.
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
+ break;
+ }
+ more = true;
+ }
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
+ }
+ *ptr = o;
+}
+
+/*! \internal
+ */
+void QObjectPrivate::clearGuards(QObject *object)
+{
+ GuardHash *hash = 0;
+ QMutex *mutex = 0;
+ QT_TRY {
+ hash = guardHash();
+ mutex = guardHashLock();
+ } QT_CATCH(const std::bad_alloc &) {
+ // do nothing in case of OOM - code below is safe
+ }
+
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (hash && !hash->isEmpty()) {
+ QMutexLocker locker(mutex);
+ GuardHash::iterator it = hash->find(object);
+ const GuardHash::iterator end = hash->end();
+ while (it.key() == object && it != end) {
+ *it.value() = 0;
+ it = hash->erase(it);
+ }
+ }
+}
+
+/*! \internal
+ */
+QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ int nargs, int *types, void **args, QSemaphore *semaphore)
+ : QEvent(MetaCall), sender_(sender), signalId_(signalId),
+ nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
+ callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
+{ }
+
+/*! \internal
+ */
+QMetaCallEvent::~QMetaCallEvent()
+{
+ if (types_) {
+ for (int i = 0; i < nargs_; ++i) {
+ if (types_[i] && args_[i])
+ QMetaType::destroy(types_[i], args_[i]);
+ }
+ qFree(types_);
+ qFree(args_);
+ }
+#ifndef QT_NO_THREAD
+ if (semaphore_)
+ semaphore_->release();
+#endif
+}
+
+/*! \internal
+ */
+void QMetaCallEvent::placeMetaCall(QObject *object)
+{
+ if (callFunction_) {
+ callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
+ } else {
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
+ }
+}
+
+/*!
+ \class QObject
+ \brief The QObject class is the base class of all Qt objects.
+
+ \ingroup objectmodel
+
+ \reentrant
+
+ QObject is the heart of the Qt \l{Object Model}. The central
+ feature in this model is a very powerful mechanism for seamless
+ object communication called \l{signals and slots}. You can
+ connect a signal to a slot with connect() and destroy the
+ connection with disconnect(). To avoid never ending notification
+ loops you can temporarily block signals with blockSignals(). The
+ protected functions connectNotify() and disconnectNotify() make
+ it possible to track connections.
+
+ QObjects organize themselves in \l {Object Trees & Ownership}
+ {object trees}. When you create a QObject with another object as
+ parent, the object will automatically add itself to the parent's
+ children() list. The parent takes ownership of the object; i.e.,
+ it will automatically delete its children in its destructor. You
+ can look for an object by name and optionally type using
+ findChild() or findChildren().
+
+ Every object has an objectName() and its class name can be found
+ via the corresponding metaObject() (see QMetaObject::className()).
+ You can determine whether the object's class inherits another
+ class in the QObject inheritance hierarchy by using the
+ inherits() function.
+
+ When an object is deleted, it emits a destroyed() signal. You can
+ catch this signal to avoid dangling references to QObjects.
+
+ QObjects can receive events through event() and filter the events
+ of other objects. See installEventFilter() and eventFilter() for
+ details. A convenience handler, childEvent(), can be reimplemented
+ to catch child events.
+
+ Events are delivered in the thread in which the object was
+ created; see \l{Thread Support in Qt} and thread() for details.
+ Note that event processing is not done at all for QObjects with no
+ thread affinity (thread() returns zero). Use the moveToThread()
+ function to change the thread affinity for an object and its
+ children (the object cannot be moved if it has a parent).
+
+ Last but not least, QObject provides the basic timer support in
+ Qt; see QTimer 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
+ \l{moc}{Meta Object Compiler} on the source file. We strongly
+ recommend the use of this macro in all subclasses of QObject
+ regardless of whether or not they actually use signals, slots and
+ properties, since failure to do so may lead certain functions to
+ exhibit strange behavior.
+
+ All Qt widgets inherit QObject. The convenience function
+ isWidgetType() returns whether an object is actually a widget. It
+ is much faster than
+ \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
+ \e{obj}->\l{inherits()}{inherits}("QWidget").
+
+ Some QObject functions, e.g. children(), return a QObjectList.
+ QObjectList is a typedef for QList<QObject *>.
+
+ \target No copy constructor
+ \section1 No copy constructor or assignment operator
+
+ QObject has neither a copy constructor nor an assignment operator.
+ This is by design. Actually, they are declared, but in a
+ \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
+ Qt classes derived from QObject (direct or indirect) use this
+ macro to declare their copy constructor and assignment operator to
+ be private. The reasoning is found in the discussion on
+ \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
+ Model} page.
+
+ The main consequence is that you should use pointers to QObject
+ (or to your QObject subclass) where you might otherwise be tempted
+ to use your QObject subclass as a value. For example, without a
+ copy constructor, you can't use a subclass of QObject as the value
+ to be stored in one of the container classes. You must store
+ pointers.
+
+ \section1 Auto-Connection
+
+ Qt's meta-object system provides a mechanism to automatically connect
+ signals and slots between QObject subclasses and their children. As long
+ as objects are defined with suitable object names, and slots follow a
+ simple naming convention, this connection can be performed at run-time
+ by the QMetaObject::connectSlotsByName() function.
+
+ \l uic generates code that invokes this function to enable
+ auto-connection to be performed between widgets on forms created
+ with \QD. More information about using auto-connection with \QD is
+ given in the \l{Using a Designer UI File in Your Application} section of
+ the \QD manual.
+
+ \section1 Dynamic Properties
+
+ From Qt 4.2, 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},
+ and both standard Qt widgets and user-created forms can be given dynamic
+ properties.
+
+ \section1 Internationalization (i18n)
+
+ All QObject subclasses support Qt's translation features, making it possible
+ to translate an application's user interface into different languages.
+
+ To make user-visible text translatable, it must be wrapped in calls to
+ the tr() function. This is explained in detail in the
+ \l{Writing Source Code for Translation} document.
+
+ \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
+ \sa {Object Trees & Ownership}
+*/
+
+/*!
+ \relates QObject
+
+ Returns a pointer to the object named \a name that inherits \a
+ type and with a given \a parent.
+
+ Returns 0 if there is no such child.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 0
+*/
+
+void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
+{
+ QObjectList list = parent->children();
+ if (list.size() == 0) return 0;
+ for (int i = 0; i < list.size(); ++i) {
+ QObject *obj = list.at(i);
+ if (name == obj->objectName() && obj->inherits(type))
+ return obj;
+ }
+ return 0;
+}
+
+
+/*****************************************************************************
+ QObject member functions
+ *****************************************************************************/
+
+// check the constructor's parent thread argument
+static bool check_parent_thread(QObject *parent,
+ QThreadData *parentThreadData,
+ QThreadData *currentThreadData)
+{
+ if (parent && parentThreadData != currentThreadData) {
+ QThread *parentThread = parentThreadData->thread;
+ QThread *currentThread = currentThreadData->thread;
+ qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
+ "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
+ parent->metaObject()->className(),
+ parent,
+ parentThread ? parentThread->metaObject()->className() : "QThread",
+ parentThread,
+ currentThread ? currentThread->metaObject()->className() : "QThread",
+ currentThread);
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Constructs an object with parent object \a parent.
+
+ The parent of an object may be viewed as the object's owner. For
+ instance, a \l{QDialog}{dialog box} is the parent of the \gui OK
+ and \gui Cancel buttons it contains.
+
+ The destructor of a parent object destroys all child objects.
+
+ Setting \a parent to 0 constructs an object with no parent. If the
+ object is a widget, it will become a top-level window.
+
+ \sa parent(), findChild(), findChildren()
+*/
+
+QObject::QObject(QObject *parent)
+ : d_ptr(new QObjectPrivate)
+{
+ Q_D(QObject);
+ d_ptr->q_ptr = this;
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ QT_TRY {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ setParent(parent);
+ } QT_CATCH(...) {
+ d->threadData->deref();
+ QT_RETHROW;
+ }
+ }
+ qt_addObject(this);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QObject()
+ \obsolete
+
+ Creates a new QObject with the given \a parent and object \a name.
+ */
+QObject::QObject(QObject *parent, const char *name)
+ : d_ptr(new QObjectPrivate)
+{
+ Q_D(QObject);
+ qt_addObject(d_ptr->q_ptr = this);
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ setParent(parent);
+ }
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*! \internal
+ */
+QObject::QObject(QObjectPrivate &dd, QObject *parent)
+ : d_ptr(&dd)
+{
+ Q_D(QObject);
+ d_ptr->q_ptr = this;
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ QT_TRY {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ if (d->isWidget) {
+ if (parent) {
+ d->parent = parent;
+ d->parent->d_func()->children.append(this);
+ }
+ // no events sent here, this is done at the end of the QWidget constructor
+ } else {
+ setParent(parent);
+ }
+ } QT_CATCH(...) {
+ d->threadData->deref();
+ QT_RETHROW;
+ }
+ }
+ qt_addObject(this);
+}
+
+/*!
+ Destroys the object, deleting all its child objects.
+
+ All signals to and from the object are automatically disconnected, and
+ any pending posted events for the object are removed from the event
+ queue. However, it is often safer to use deleteLater() rather than
+ deleting a QObject subclass directly.
+
+ \warning All child objects are deleted. If any of these objects
+ are on the stack or global, sooner or later your program will
+ crash. We do not recommend holding pointers to child objects from
+ 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
+ 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
+ delivered to it.
+
+ \sa deleteLater()
+*/
+
+QObject::~QObject()
+{
+ Q_D(QObject);
+ d->wasDeleted = true;
+ d->blockSig = 0; // unblock signals so we always emit destroyed()
+
+ if (d->hasGuards && !d->isWidget) {
+ // set all QPointers for this object to zero - note that
+ // ~QWidget() does this for us, so we don't have to do it twice
+ QObjectPrivate::clearGuards(this);
+ }
+
+ if (d->sharedRefcount) {
+ if (d->sharedRefcount->strongref > 0) {
+ qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
+ // but continue deleting, it's too late to stop anyway
+ }
+
+ // indicate to all QWeakPointers that this QObject has now been deleted
+ d->sharedRefcount->strongref = 0;
+ if (!d->sharedRefcount->weakref.deref())
+ delete d->sharedRefcount;
+ }
+
+
+ if (d->isSignalConnected(0)) {
+ QT_TRY {
+ emit destroyed(this);
+ } QT_CATCH(...) {
+ // all the signal/slots connections are still in place - if we don't
+ // quit now, we will crash pretty soon.
+ qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
+ QT_RETHROW;
+ }
+ }
+
+ if (d->declarativeData)
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
+
+ // set ref to zero to indicate that this object has been deleted
+ if (d->currentSender != 0)
+ d->currentSender->ref = 0;
+ d->currentSender = 0;
+
+ if (d->connectionLists || d->senders) {
+ QMutex *signalSlotMutex = signalSlotLock(this);
+ QMutexLocker locker(signalSlotMutex);
+
+ // disconnect all receivers
+ if (d->connectionLists) {
+ ++d->connectionLists->inUse;
+ int connectionListsCount = d->connectionLists->count();
+ for (int signal = -1; signal < connectionListsCount; ++signal) {
+ QObjectPrivate::ConnectionList &connectionList =
+ (*d->connectionLists)[signal];
+
+ while (QObjectPrivate::Connection *c = connectionList.first) {
+ if (!c->receiver) {
+ connectionList.first = c->nextConnectionList;
+ delete c;
+ continue;
+ }
+
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
+ if (needToUnlock)
+ m->unlockInline();
+
+ connectionList.first = c->nextConnectionList;
+ delete c;
+ }
+ }
+
+ if (!--d->connectionLists->inUse) {
+ delete d->connectionLists;
+ } else {
+ d->connectionLists->orphaned = true;
+ }
+ d->connectionLists = 0;
+ }
+
+ // disconnect all senders
+ QObjectPrivate::Connection *node = d->senders;
+ while (node) {
+ QObject *sender = node->sender;
+ QMutex *m = signalSlotLock(sender);
+ node->prev = &node;
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+ //the node has maybe been removed while the mutex was unlocked in relock?
+ if (!node || node->sender != sender) {
+ m->unlockInline();
+ continue;
+ }
+ node->receiver = 0;
+ QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
+ if (senderLists)
+ senderLists->dirty = true;
+
+ node = node->next;
+ if (needToUnlock)
+ m->unlockInline();
+ }
+ }
+
+ if (!d->children.isEmpty())
+ d->deleteChildren();
+
+ qt_removeObject(this);
+
+ if (d->parent) // remove it from parent object
+ d->setParent_helper(0);
+
+#ifdef QT_JAMBI_BUILD
+ if (d->inEventHandler) {
+ qWarning("QObject: Do not delete object, '%s', during its event handler!",
+ objectName().isNull() ? "unnamed" : qPrintable(objectName()));
+ }
+#endif
+}
+
+QObjectPrivate::Connection::~Connection()
+{
+ if (argumentTypes != &DIRECT_CONNECTION_ONLY)
+ delete [] static_cast<int *>(argumentTypes);
+}
+
+
+/*!
+ \fn QMetaObject *QObject::metaObject() const
+
+ Returns a pointer to the meta-object of this object.
+
+ A meta-object contains information about a class that inherits
+ QObject, e.g. class name, superclass name, properties, signals and
+ slots. Every QObject subclass that contains the Q_OBJECT macro will have a
+ meta-object.
+
+ The meta-object information is required by the signal/slot
+ connection mechanism and the property system. The inherits()
+ function also makes use of the meta-object.
+
+ If you have no pointer to an actual object instance but still
+ want to access the meta-object of a class, you can use \l
+ staticMetaObject.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 1
+
+ \sa staticMetaObject
+*/
+
+/*!
+ \variable QObject::staticMetaObject
+
+ This variable stores the meta-object for the class.
+
+ A meta-object contains information about a class that inherits
+ QObject, e.g. class name, superclass name, properties, signals and
+ slots. Every class that contains the Q_OBJECT macro will also have
+ a meta-object.
+
+ The meta-object information is required by the signal/slot
+ connection mechanism and the property system. The inherits()
+ function also makes use of the meta-object.
+
+ If you have a pointer to an object, you can use metaObject() to
+ retrieve the meta-object associated with that object.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 2
+
+ \sa metaObject()
+*/
+
+/*! \fn T *qobject_cast<T *>(QObject *object)
+ \relates QObject
+
+ Returns the given \a object cast to type T if the object is of type
+ T (or of a subclass); otherwise returns 0. If \a object is 0 then
+ it will also return 0.
+
+ The class T must inherit (directly or indirectly) QObject and be
+ declared with the \l Q_OBJECT macro.
+
+ A class is considered to inherit itself.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 3
+
+ The qobject_cast() function behaves similarly to the standard C++
+ \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}{Plug & Paint} example for details.
+
+ \warning If T isn't declared with the Q_OBJECT macro, this
+ function's return value is undefined.
+
+ \sa QObject::inherits()
+*/
+
+/*!
+ \fn bool QObject::inherits(const char *className) const
+
+ Returns true if this object is an instance of a class that
+ inherits \a className or a QObject subclass that inherits \a
+ className; otherwise returns false.
+
+ A class is considered to inherit itself.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4
+
+ If you need to determine whether an object is an instance of a particular
+ class for the purpose of casting it, consider using qobject_cast<Type *>(object)
+ instead.
+
+ \sa metaObject(), qobject_cast()
+*/
+
+/*!
+ \property QObject::objectName
+
+ \brief the name of this object
+
+ You can find an object by name (and type) using findChild(). You can
+ find a set of objects with findChildren().
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 5
+
+ By default, this property contains an empty string.
+
+ \sa metaObject(), QMetaObject::className()
+*/
+
+QString QObject::objectName() const
+{
+ Q_D(const QObject);
+ return d->objectName;
+}
+
+/*
+ Sets the object's name to \a name.
+*/
+void QObject::setObjectName(const QString &name)
+{
+ Q_D(QObject);
+ bool objectNameChanged = d->declarativeData && d->objectName != name;
+
+ d->objectName = name;
+
+ if (objectNameChanged)
+ d->declarativeData->objectNameChanged(d->declarativeData, this);
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \internal
+ QObject::child is compat but needs to call itself recursively,
+ that's why we need this helper.
+*/
+static QObject *qChildHelper(const char *objName, const char *inheritsClass,
+ bool recursiveSearch, const QObjectList &children)
+{
+ if (children.isEmpty())
+ return 0;
+
+ bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
+ const QLatin1String oName(objName);
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *obj = children.at(i);
+ if (onlyWidgets) {
+ if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
+ return obj;
+ } else if ((!inheritsClass || obj->inherits(inheritsClass))
+ && (!objName || obj->objectName() == oName))
+ return obj;
+ if (recursiveSearch && (obj = qChildHelper(objName, inheritsClass,
+ recursiveSearch, obj->children())))
+ return obj;
+ }
+ return 0;
+}
+
+
+/*!
+ Searches the children and optionally grandchildren of this object,
+ and returns a child that is called \a objName that inherits \a
+ inheritsClass. If \a inheritsClass is 0 (the default), any class
+ matches.
+
+ If \a recursiveSearch is true (the default), child() performs a
+ depth-first search of the object's children.
+
+ If there is no such object, this function returns 0. If there are
+ more than one, the first one found is returned.
+*/
+QObject* QObject::child(const char *objName, const char *inheritsClass,
+ bool recursiveSearch) const
+{
+ Q_D(const QObject);
+ return qChildHelper(objName, inheritsClass, recursiveSearch, d->children);
+}
+#endif
+
+/*!
+ \fn bool QObject::isWidgetType() const
+
+ Returns true if the object is a widget; otherwise returns false.
+
+ Calling this function is equivalent to calling
+ inherits("QWidget"), except that it is much faster.
+*/
+
+
+/*!
+ This virtual function receives events to an object and should
+ return true if the event \a e was recognized and processed.
+
+ The event() function can be reimplemented to customize the
+ behavior of an object.
+
+ \sa installEventFilter(), timerEvent(), QApplication::sendEvent(),
+ QApplication::postEvent(), QWidget::event()
+*/
+
+bool QObject::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::Timer:
+ timerEvent((QTimerEvent*)e);
+ break;
+
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ d_func()->sendPendingChildInsertedEvents();
+ break;
+#endif
+
+ case QEvent::ChildAdded:
+ case QEvent::ChildPolished:
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInserted:
+#endif
+ case QEvent::ChildRemoved:
+ childEvent((QChildEvent*)e);
+ break;
+
+ case QEvent::DeferredDelete:
+ qDeleteInEventHandler(this);
+ break;
+
+ case QEvent::MetaCall:
+ {
+#ifdef QT_JAMBI_BUILD
+ d_func()->inEventHandler = false;
+#endif
+ QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
+ QObjectPrivate::Sender currentSender;
+ currentSender.sender = const_cast<QObject*>(mce->sender());
+ currentSender.signal = mce->signalId();
+ currentSender.ref = 1;
+ QObjectPrivate::Sender * const previousSender =
+ QObjectPrivate::setCurrentSender(this, &currentSender);
+#if defined(QT_NO_EXCEPTIONS)
+ mce->placeMetaCall(this);
+#else
+ QT_TRY {
+ mce->placeMetaCall(this);
+ } QT_CATCH(...) {
+ QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
+ QT_RETHROW;
+ }
+#endif
+ QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
+ break;
+ }
+
+ case QEvent::ThreadChange: {
+ Q_D(QObject);
+ QThreadData *threadData = d->threadData;
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ if (eventDispatcher) {
+ QList<QPair<int, int> > timers = eventDispatcher->registeredTimers(this);
+ if (!timers.isEmpty()) {
+ // set inThreadChangeEvent to true to tell the dispatcher not to release out timer ids
+ // back to the pool (since the timer ids are moving to a new thread).
+ d->inThreadChangeEvent = true;
+ eventDispatcher->unregisterTimers(this);
+ d->inThreadChangeEvent = false;
+ QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
+ Q_ARG(void*, (new QList<QPair<int, int> >(timers))));
+ }
+ }
+ break;
+ }
+
+ default:
+ if (e->type() >= QEvent::User) {
+ customEvent(e);
+ break;
+ }
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \fn void QObject::timerEvent(QTimerEvent *event)
+
+ 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.
+
+ \sa startTimer(), killTimer(), event()
+*/
+
+void QObject::timerEvent(QTimerEvent *)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ child events. The event is passed in the \a event parameter.
+
+ QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
+ objects when children are added or removed. In both cases you can
+ only rely on the child being a QObject, or if isWidgetType()
+ returns true, a QWidget. (This is because, in the
+ \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
+ fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
+ case it might have been destructed already).
+
+ QEvent::ChildPolished events are sent to widgets when children
+ are polished, or when polished children are added. If you receive
+ a child polished event, the child's construction is usually
+ completed. However, this is not guaranteed, and multiple polish
+ events may be delivered during the execution of a widget's
+ constructor.
+
+ For every child widget, you receive one
+ \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
+ \l{QEvent::ChildPolished}{ChildPolished} events, and one
+ \l{QEvent::ChildRemoved}{ChildRemoved} event.
+
+ The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
+ a child is removed immediately after it is added. If a child is
+ polished several times during construction and destruction, you
+ may receive several child polished events for the same child,
+ each time with a different virtual table.
+
+ \sa event()
+*/
+
+void QObject::childEvent(QChildEvent * /* event */)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ custom events. Custom events are user-defined events with a type
+ value at least as large as the QEvent::User item of the
+ QEvent::Type enum, and is typically a QEvent subclass. The event
+ is passed in the \a event parameter.
+
+ \sa event(), QEvent
+*/
+void QObject::customEvent(QEvent * /* event */)
+{
+}
+
+
+
+/*!
+ Filters events if this object has been installed as an event
+ filter for the \a watched object.
+
+ In your reimplementation of this function, if you want to filter
+ the \a event out, i.e. stop it being handled further, return
+ true; otherwise return false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 6
+
+ Notice in the example above that unhandled events are passed to
+ the base class's eventFilter() function, since the base class
+ might have reimplemented eventFilter() for its own internal
+ purposes.
+
+ \warning If you delete the receiver object in this function, be
+ sure to return true. Otherwise, Qt will forward the event to the
+ deleted object and the program might crash.
+
+ \sa installEventFilter()
+*/
+
+bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
+{
+ return false;
+}
+
+/*!
+ \fn bool QObject::signalsBlocked() const
+
+ Returns true if signals are blocked; otherwise returns false.
+
+ Signals are not blocked by default.
+
+ \sa blockSignals()
+*/
+
+/*!
+ If \a block is true, signals emitted by this object are blocked
+ (i.e., emitting a signal will not invoke anything connected to it).
+ If \a block is false, no such blocking will occur.
+
+ The return value is the previous value of signalsBlocked().
+
+ Note that the destroyed() signal will be emitted even if the signals
+ for this object have been blocked.
+
+ \sa signalsBlocked()
+*/
+
+bool QObject::blockSignals(bool block)
+{
+ Q_D(QObject);
+ bool previous = d->blockSig;
+ d->blockSig = block;
+ return previous;
+}
+
+/*!
+ Returns the thread in which the object lives.
+
+ \sa moveToThread()
+*/
+QThread *QObject::thread() const
+{
+ return d_func()->threadData->thread;
+}
+
+/*!
+ 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.
+
+ To move an object to the main thread, use QApplication::instance()
+ to retrieve a pointer to the current application, and then use
+ QApplication::thread() to retrieve the thread in which the
+ application lives. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 7
+
+ If \a targetThread is zero, all event processing for this object
+ and its children stops.
+
+ Note that all active timers for the object will be reset. The
+ timers are first stopped in the current thread and restarted (with
+ the same interval) in the \a targetThread. As a result, constantly
+ moving an object between threads can postpone timer events
+ indefinitely.
+
+ A QEvent::ThreadChange event is sent to this object just before
+ the thread affinity is changed. You can handle this event to
+ perform any special processing. Note that any new events that are
+ posted to this object will be handled in the \a targetThread.
+
+ \warning This function is \e not thread-safe; the current thread
+ must be same as the current thread affinity. In other words, this
+ function can only "push" an object from the current thread to
+ another thread, it cannot "pull" an object from any arbitrary
+ thread to the current thread.
+
+ \sa thread()
+ */
+void QObject::moveToThread(QThread *targetThread)
+{
+ Q_D(QObject);
+
+ if (d->threadData->thread == targetThread) {
+ // object is already in this thread
+ return;
+ }
+
+ if (d->parent != 0) {
+ qWarning("QObject::moveToThread: Cannot move objects with a parent");
+ return;
+ }
+ if (d->isWidget) {
+ qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
+ return;
+ }
+
+ QThreadData *currentData = QThreadData::current();
+ QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);
+ if (d->threadData->thread == 0 && currentData == targetData) {
+ // one exception to the rule: we allow moving objects with no thread affinity to the current thread
+ currentData = d->threadData;
+ } else if (d->threadData != currentData) {
+ qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
+ "Cannot move to target thread (%p)\n",
+ currentData->thread, d->threadData->thread, targetData->thread);
+
+#ifdef Q_WS_MAC
+ qWarning("On Mac OS X, 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;
+ }
+
+ // prepare to move
+ d->moveToThread_helper();
+
+ QOrderedMutexLocker locker(&currentData->postEventList.mutex,
+ &targetData->postEventList.mutex);
+
+ // keep currentData alive (since we've got it locked)
+ currentData->ref();
+
+ // move the object
+ d_func()->setThreadData_helper(currentData, targetData);
+
+ locker.unlock();
+
+ // now currentData can commit suicide if it wants to
+ currentData->deref();
+}
+
+void QObjectPrivate::moveToThread_helper()
+{
+ Q_Q(QObject);
+ QEvent e(QEvent::ThreadChange);
+ QCoreApplication::sendEvent(q, &e);
+ 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)
+{
+ Q_Q(QObject);
+
+ // move posted events
+ int eventsMoved = 0;
+ for (int i = 0; i < currentData->postEventList.size(); ++i) {
+ const QPostEvent &pe = currentData->postEventList.at(i);
+ if (!pe.event)
+ continue;
+ if (pe.receiver == q) {
+ // move this post event to the targetList
+ targetData->postEventList.append(pe);
+ const_cast<QPostEvent &>(pe).event = 0;
+ ++eventsMoved;
+ }
+ }
+ if (eventsMoved > 0 && targetData->eventDispatcher) {
+ targetData->canWait = false;
+ targetData->eventDispatcher->wakeUp();
+ }
+
+ // the current emitting thread shouldn't restore currentSender after calling moveToThread()
+ if (currentSender)
+ currentSender->ref = 0;
+ currentSender = 0;
+
+#ifdef QT_JAMBI_BUILD
+ // the current event thread also shouldn't restore the delete watch
+ inEventHandler = false;
+
+ if (deleteWatch)
+ *deleteWatch = 1;
+ deleteWatch = 0;
+#endif
+
+ // set new thread data
+ targetData->ref();
+ threadData->deref();
+ threadData = targetData;
+
+ 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<QPair<int, int> > *timerList = reinterpret_cast<QList<QPair<int, int> > *>(pointer);
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ for (int i = 0; i < timerList->size(); ++i) {
+ const QPair<int, int> &pair = timerList->at(i);
+ eventDispatcher->registerTimer(pair.first, pair.second, q);
+ }
+ delete timerList;
+}
+
+
+//
+// The timer flag hasTimer is set when startTimer is called.
+// It is not reset when killing the timer because more than
+// one timer might be active.
+//
+
+/*!
+ 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.
+
+ 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 doc/src/snippets/code/src_corelib_kernel_qobject.cpp 8
+
+ Note that QTimer's accuracy depends on the underlying operating
+ system and hardware. 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()
+*/
+
+int QObject::startTimer(int interval)
+{
+ Q_D(QObject);
+
+ if (interval < 0) {
+ qWarning("QObject::startTimer: QTimer cannot have a negative interval");
+ return 0;
+ }
+
+ d->pendTimer = true; // set timer flag
+
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
+ return 0;
+ }
+ return d->threadData->eventDispatcher->registerTimer(interval, this);
+}
+
+/*!
+ Kills the timer with timer identifier, \a id.
+
+ The timer identifier is returned by startTimer() when a timer
+ event is started.
+
+ \sa timerEvent(), startTimer()
+*/
+
+void QObject::killTimer(int id)
+{
+ Q_D(QObject);
+ if (d->threadData->eventDispatcher)
+ d->threadData->eventDispatcher->unregisterTimer(id);
+}
+
+
+/*!
+ \fn QObject *QObject::parent() const
+
+ Returns a pointer to the parent object.
+
+ \sa children()
+*/
+
+/*!
+ \fn const QObjectList &QObject::children() const
+
+ Returns a list of child objects.
+ The QObjectList class is defined in the \c{<QObject>} header
+ file as the following:
+
+ \quotefromfile src/corelib/kernel/qobject.h
+ \skipto /typedef .*QObjectList/
+ \printuntil QObjectList
+
+ The first child added is the \l{QList::first()}{first} object in
+ the list and the last child added is the \l{QList::last()}{last}
+ object in the list, i.e. new children are appended at the end.
+
+ Note that the list order changes when QWidget children are
+ \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
+ widget that is raised becomes the last object in the list, and a
+ widget that is lowered becomes the first object in the list.
+
+ \sa findChild(), findChildren(), parent(), setParent()
+*/
+
+#ifdef QT3_SUPPORT
+static void objSearch(QObjectList &result,
+ const QObjectList &list,
+ const char *inheritsClass,
+ bool onlyWidgets,
+ const char *objName,
+ QRegExp *rx,
+ bool recurse)
+{
+ for (int i = 0; i < list.size(); ++i) {
+ QObject *obj = list.at(i);
+ if (!obj)
+ continue;
+ bool ok = true;
+ if (onlyWidgets)
+ ok = obj->isWidgetType();
+ else if (inheritsClass && !obj->inherits(inheritsClass))
+ ok = false;
+ if (ok) {
+ if (objName)
+ ok = (obj->objectName() == QLatin1String(objName));
+#ifndef QT_NO_REGEXP
+ else if (rx)
+ ok = (rx->indexIn(obj->objectName()) != -1);
+#endif
+ }
+ if (ok) // match!
+ result.append(obj);
+ if (recurse) {
+ QObjectList clist = obj->children();
+ if (!clist.isEmpty())
+ objSearch(result, clist, inheritsClass,
+ onlyWidgets, objName, rx, recurse);
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Searches the children and optionally grandchildren of this object,
+ and returns a list of those objects that are named or that match
+ \a objName and inherit \a inheritsClass. If \a inheritsClass is 0
+ (the default), all classes match. If \a objName is 0 (the
+ default), all object names match.
+
+ If \a regexpMatch is true (the default), \a objName is a regular
+ expression that the objects's names must match. The syntax is that
+ of a QRegExp. If \a regexpMatch is false, \a objName is a string
+ and object names must match it exactly.
+
+ Note that \a inheritsClass uses single inheritance from QObject,
+ the way inherits() does. According to inherits(), QWidget
+ inherits QObject but not QPaintDevice. This does not quite match
+ reality, but is the best that can be done on the wide variety of
+ compilers Qt supports.
+
+ Finally, if \a recursiveSearch is true (the default), queryList()
+ searches \e{n}th-generation as well as first-generation children.
+
+ If all this seems a bit complex for your needs, the simpler
+ child() function may be what you want.
+
+ This somewhat contrived example disables all the buttons in this
+ window:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 9
+
+ \warning Delete the list as soon you have finished using it. The
+ list contains pointers that may become invalid at almost any time
+ without notice (as soon as the user closes a window you may have
+ dangling pointers, for example).
+
+ \sa child() children(), parent(), inherits(), objectName(), QRegExp
+*/
+
+QObjectList QObject::queryList(const char *inheritsClass,
+ const char *objName,
+ bool regexpMatch,
+ bool recursiveSearch) const
+{
+ Q_D(const QObject);
+ QObjectList list;
+ bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
+#ifndef QT_NO_REGEXP
+ if (regexpMatch && objName) { // regexp matching
+ QRegExp rx(QString::fromLatin1(objName));
+ objSearch(list, d->children, inheritsClass, onlyWidgets, 0, &rx, recursiveSearch);
+ } else
+#endif
+ {
+ objSearch(list, d->children, inheritsClass, onlyWidgets, objName, 0, recursiveSearch);
+ }
+ return list;
+}
+#endif
+
+/*!
+ \fn T *QObject::findChild(const QString &name) const
+
+ Returns the child of this object that can be cast into type T and
+ that is called \a name, or 0 if there is no such object.
+ Omitting the \a name argument causes all object names to be matched.
+ The search is performed recursively.
+
+ 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.
+
+ This example returns a child \l{QPushButton} of \c{parentWidget}
+ named \c{"button1"}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 10
+
+ This example returns a \l{QListWidget} child of \c{parentWidget}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11
+
+ \sa findChildren()
+*/
+
+/*!
+ \fn QList<T> QObject::findChildren(const QString &name) 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.
+ The search is performed recursively.
+
+ The following example shows how to find a list of child \l{QWidget}s of
+ the specified \c{parentWidget} named \c{widgetname}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 12
+
+ This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13
+
+ \sa findChild()
+*/
+
+/*!
+ \fn QList<T> QObject::findChildren(const QRegExp &regExp) const
+ \overload findChildren()
+
+ Returns the children of this object that can be cast to type T
+ and that have names matching the regular expression \a regExp,
+ or an empty list if there are no such objects.
+ The search is performed recursively.
+*/
+
+/*!
+ \fn T qFindChild(const QObject *obj, const QString &name)
+ \relates QObject
+ \obsolete
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
+
+ \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.
+
+ \sa QObject::findChild()
+*/
+
+/*!
+ \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
+ \relates QObject
+ \obsolete
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
+
+ \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.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \fn QList<T> qFindChildren(const QObject *obj, const QRegExp &regExp)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
+
+ \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.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \internal
+ \fn T qFindChild(const QObject *obj, const QString &name = QString(), T dummy = 0)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
+
+ \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.
+
+ \sa QObject::findChild()
+*/
+
+/*!
+ \internal
+ \fn QList<T> qFindChildren(const QObject *obj, const QString &name = QString(), T dummy = 0)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
+
+ \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.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \internal
+*/
+void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
+ const QMetaObject &mo, QList<void*> *list)
+{
+ 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 (re) {
+ if (re->indexIn(obj->objectName()) != -1)
+ list->append(obj);
+ } else {
+ if (name.isNull() || obj->objectName() == name)
+ list->append(obj);
+ }
+ }
+ qt_qFindChildren_helper(obj, name, re, mo, list);
+ }
+}
+
+/*! \internal
+ */
+QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo)
+{
+ if (!parent)
+ return 0;
+ 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;
+ }
+ for (i = 0; i < children.size(); ++i) {
+ obj = qt_qFindChild_helper(children.at(i), name, mo);
+ if (obj)
+ return obj;
+ }
+ return 0;
+}
+
+/*!
+ Makes the object a child of \a parent.
+
+ \sa QWidget::setParent()
+*/
+
+void QObject::setParent(QObject *parent)
+{
+ Q_D(QObject);
+ Q_ASSERT(!d->isWidget);
+ d->setParent_helper(parent);
+}
+
+void QObjectPrivate::deleteChildren()
+{
+ const bool reallyWasDeleted = wasDeleted;
+ wasDeleted = true;
+ // delete children objects
+ // don't use qDeleteAll as the destructor of the child might
+ // delete siblings
+ for (int i = 0; i < children.count(); ++i) {
+ currentChildBeingDeleted = children.at(i);
+ children[i] = 0;
+ delete currentChildBeingDeleted;
+ }
+ children.clear();
+ currentChildBeingDeleted = 0;
+ wasDeleted = reallyWasDeleted;
+}
+
+void QObjectPrivate::setParent_helper(QObject *o)
+{
+ Q_Q(QObject);
+ if (o == parent)
+ return;
+ if (parent) {
+ QObjectPrivate *parentD = parent->d_func();
+ if (parentD->wasDeleted && wasDeleted
+ && parentD->currentChildBeingDeleted == q) {
+ // don't do anything since QObjectPrivate::deleteChildren() already
+ // cleared our entry in parentD->children.
+ } else {
+ const int index = parentD->children.indexOf(q);
+ if (parentD->wasDeleted) {
+ parentD->children[index] = 0;
+ } else {
+ parentD->children.removeAt(index);
+ if (sendChildEvents && parentD->receiveChildEvents) {
+ QChildEvent e(QEvent::ChildRemoved, q);
+ QCoreApplication::sendEvent(parent, &e);
+ }
+ }
+ }
+ }
+ parent = o;
+ if (parent) {
+ // object hierarchies are constrained to a single thread
+ if (threadData != parent->d_func()->threadData) {
+ qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
+ parent = 0;
+ return;
+ }
+ parent->d_func()->children.append(q);
+ if(sendChildEvents && parent->d_func()->receiveChildEvents) {
+ if (!isWidget) {
+ QChildEvent e(QEvent::ChildAdded, q);
+ QCoreApplication::sendEvent(parent, &e);
+#ifdef QT3_SUPPORT
+ if (QCoreApplicationPrivate::useQt3Support) {
+ if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
+ QCoreApplication::postEvent(parent,
+ new QEvent(QEvent::ChildInsertedRequest),
+ Qt::HighEventPriority);
+ }
+ parent->d_func()->pendingChildInsertedEvents.append(q);
+ }
+#endif
+ }
+ }
+ }
+ if (!wasDeleted && declarativeData)
+ QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
+}
+
+/*!
+ \fn void QObject::installEventFilter(QObject *filterObj)
+
+ Installs an event filter \a filterObj on this object. For example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 14
+
+ An event filter is an object that receives all events that are
+ sent to this object. The filter can either stop the event or
+ forward it to this object. The event filter \a filterObj receives
+ events via its eventFilter() function. The eventFilter() function
+ must return true if the event should be filtered, (i.e. stopped);
+ otherwise it must return false.
+
+ If multiple event filters are installed on a single object, the
+ filter that was installed last is activated first.
+
+ Here's a \c KeyPressEater class that eats the key presses of its
+ monitored objects:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 15
+
+ And here's how to install it on two widgets:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 16
+
+ The QShortcut class, for example, uses this technique to intercept
+ shortcut key presses.
+
+ \warning If you delete the receiver object in your eventFilter()
+ function, be sure to return true. If you return false, Qt sends
+ the event to the deleted object and the program will crash.
+
+ Note that the filtering object must be in the same thread as this
+ object. If \a filterObj is in a different thread, this function does
+ nothing. If either \a filterObj or this object are moved to a different
+ thread after calling this function, the event filter will not be
+ called until both objects have the same thread affinity again (it
+ is \e not removed).
+
+ \sa removeEventFilter(), eventFilter(), event()
+*/
+
+void QObject::installEventFilter(QObject *obj)
+{
+ Q_D(QObject);
+ if (!obj)
+ return;
+ if (d->threadData != obj->d_func()->threadData) {
+ qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
+ return;
+ }
+
+ // clean up unused items in the list
+ d->eventFilters.removeAll((QObject*)0);
+ d->eventFilters.removeAll(obj);
+ d->eventFilters.prepend(obj);
+}
+
+/*!
+ Removes an event filter object \a obj from this object. The
+ request is ignored if such an event filter has not been installed.
+
+ All event filters for this object are automatically removed when
+ this object is destroyed.
+
+ It is always safe to remove an event filter, even during event
+ filter activation (i.e. from the eventFilter() function).
+
+ \sa installEventFilter(), eventFilter(), event()
+*/
+
+void QObject::removeEventFilter(QObject *obj)
+{
+ Q_D(QObject);
+ for (int i = 0; i < d->eventFilters.count(); ++i) {
+ if (d->eventFilters.at(i) == obj)
+ d->eventFilters[i] = 0;
+ }
+}
+
+
+/*!
+ \fn QObject::destroyed(QObject *obj)
+
+ This signal is emitted immediately before the object \a obj is
+ destroyed, and can not be blocked.
+
+ All the objects's children are destroyed immediately after this
+ signal is emitted.
+
+ \sa deleteLater(), QPointer
+*/
+
+/*!
+ Schedules this object for deletion.
+
+ The object will be deleted when control returns to the event
+ loop. If the event loop is not running when this function is
+ called (e.g. deleteLater() is called on an object before
+ QCoreApplication::exec()), the object will be deleted once the
+ event loop is started.
+
+ Note that entering and leaving a new event loop (e.g., by opening a modal
+ dialog) will \e not perform the deferred deletion; for the object to be
+ deleted, the control must return to the event loop from which
+ deleteLater() was called.
+
+ \bold{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.
+
+ \sa destroyed(), QPointer
+*/
+void QObject::deleteLater()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
+}
+
+/*!
+ \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
+ \reentrant
+
+ Returns a translated version of \a sourceText, optionally based on a
+ \a disambiguation string and value of \a n for strings containing plurals;
+ otherwise returns \a sourceText itself if no appropriate translated string
+ is available.
+
+ Example:
+ \snippet mainwindows/sdi/mainwindow.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 (0 by default). In Qt 4.4 and earlier, this was
+ the preferred way to pass comments to translators.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17
+ \dots
+
+ 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.
+
+ \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 trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt}
+*/
+
+/*!
+ \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
+ \reentrant
+
+ 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).
+
+ Note that using the Utf8 variants of the translation functions
+ is not required if \c CODECFORTR is already set to UTF-8 in the
+ qmake project file and QTextCodec::setCodecForTr("UTF-8") is
+ used.
+
+ \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 doc/src/snippets/code/src_corelib_kernel_qobject.cpp 20
+
+ \sa tr(), QApplication::translate(), {Internationalization with Qt}
+*/
+
+
+
+
+/*****************************************************************************
+ Signals and slots
+ *****************************************************************************/
+
+
+const int flagged_locations_count = 2;
+static const char* flagged_locations[flagged_locations_count] = {0};
+
+const char *qFlagLocation(const char *method)
+{
+ static int idx = 0;
+ flagged_locations[idx] = method;
+ idx = (idx+1) % flagged_locations_count;
+ return method;
+}
+
+static int extract_code(const char *member)
+{
+ // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
+ return (((int)(*member) - '0') & 0x3);
+}
+
+static const char * extract_location(const char *member)
+{
+ for (int i = 0; i < flagged_locations_count; ++i) {
+ if (member == flagged_locations[i]) {
+ // signature includes location information after the first null-terminator
+ const char *location = member + qstrlen(member) + 1;
+ if (*location != '\0')
+ return location;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static bool check_signal_macro(const QObject *sender, const char *signal,
+ const char *func, const char *op)
+{
+ int sigcode = extract_code(signal);
+ if (sigcode != QSIGNAL_CODE) {
+ if (sigcode == QSLOT_CODE)
+ qWarning("Object::%s: Attempt to %s non-signal %s::%s",
+ func, op, sender->metaObject()->className(), signal+1);
+ else
+ qWarning("Object::%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)
+{
+ if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
+ qWarning("Object::%s: Use the SLOT or SIGNAL macro to "
+ "%s %s::%s", func, func, object->metaObject()->className(), method);
+ return false;
+ }
+ return true;
+}
+
+static void err_method_notfound(const QObject *object,
+ const char *method, const char *func)
+{
+ const char *type = "method";
+ switch (extract_code(method)) {
+ case QSLOT_CODE: type = "slot"; break;
+ case QSIGNAL_CODE: type = "signal"; break;
+ }
+ const char *loc = extract_location(method);
+ if (strchr(method,')') == 0) // common typing mistake
+ qWarning("Object::%s: Parentheses expected, %s %s::%s%s%s",
+ func, type, object->metaObject()->className(), method+1,
+ loc ? " in ": "", loc ? loc : "");
+ else
+ qWarning("Object::%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)
+{
+ QString a = sender ? sender->objectName() : QString();
+ QString b = receiver ? receiver->objectName() : QString();
+ if (!a.isEmpty())
+ qWarning("Object::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
+ if (!b.isEmpty())
+ qWarning("Object::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
+}
+
+/*!
+ Returns a pointer to the object that sent the signal, if called in
+ a slot activated by a signal; otherwise it returns 0. The pointer
+ is valid only during the execution of the slot that calls this
+ function from this object's thread context.
+
+ The pointer returned by this function becomes invalid if the
+ sender is destroyed, or if the slot is disconnected from the
+ sender's signal.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, getting access to the sender might be useful
+ when many signals are connected to a single slot.
+
+ \warning As mentioned above, the return value of this function is
+ not valid when the slot is called via a Qt::DirectConnection from
+ a thread different from this object's thread. Do not use this
+ function in this type of scenario.
+
+ \sa senderSignalIndex(), QSignalMapper
+*/
+
+QObject *QObject::sender() const
+{
+ Q_D(const QObject);
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (!d->currentSender)
+ return 0;
+
+ for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
+ if (c->sender == d->currentSender->sender)
+ return d->currentSender->sender;
+ }
+
+ return 0;
+}
+
+/*!
+ \since 4.8
+
+ Returns the meta-method index of the signal that called the currently
+ executing slot, which is a member of the class returned by sender().
+ If called outside of a slot activated by a signal, -1 is returned.
+
+ For signals with default parameters, this function will always return
+ the index with all parameters, regardless of which was used with
+ connect(). For example, the signal \c {destroyed(QObject *obj = 0)}
+ will have two different indexes (with and without the parameter), but
+ this function will always return the index with a parameter. This does
+ not apply when overloading signals with different parameters.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, getting access to the signal index might be useful
+ when many signals are connected to a single slot.
+
+ \warning The return value of this function is not valid when the slot
+ is called via a Qt::DirectConnection from a thread different from this
+ object's thread. Do not use this function in this type of scenario.
+
+ \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
+*/
+
+int QObject::senderSignalIndex() const
+{
+ Q_D(const QObject);
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (!d->currentSender)
+ return -1;
+
+ for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
+ if (c->sender == d->currentSender->sender)
+ return d->currentSender->signal;
+ }
+
+ return -1;
+}
+
+/*!
+ Returns the number of receivers connected to the \a signal.
+
+ Since both slots and signals can be used as receivers for signals,
+ and the same connections can be made many times, the number of
+ receivers is the same as the number of connections made from this
+ signal.
+
+ When calling this function, you can use the \c SIGNAL() macro to
+ pass a specific signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 21
+
+ As the code snippet above illustrates, you can use this function
+ to avoid emitting a signal that nobody listens to.
+
+ \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.
+*/
+
+int QObject::receivers(const char *signal) const
+{
+ Q_D(const QObject);
+ int receivers = 0;
+ if (signal) {
+ QByteArray signal_name = QMetaObject::normalizedSignature(signal);
+ signal = signal_name;
+#ifndef QT_NO_DEBUG
+ if (!check_signal_macro(this, signal, "receivers", "bind"))
+ return 0;
+#endif
+ signal++; // skip code
+ int signal_index = d->signalIndex(signal);
+ if (signal_index < 0) {
+#ifndef QT_NO_DEBUG
+ err_method_notfound(this, signal-1, "receivers");
+#endif
+ return false;
+ }
+
+ Q_D(const QObject);
+ QMutexLocker locker(signalSlotLock(this));
+ if (d->connectionLists) {
+ if (signal_index < d->connectionLists->count()) {
+ const QObjectPrivate::Connection *c =
+ d->connectionLists->at(signal_index).first;
+ while (c) {
+ receivers += c->receiver ? 1 : 0;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ }
+ return receivers;
+}
+
+/*!
+ \internal
+
+ This helper function calculates signal and method index for the given
+ member in the specified class.
+
+ \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
+
+ \li If specified member is not a member of obj instance class (or one of
+ its parent classes) then both signalIndex and methodIndex are set to -1.
+
+ This function is used by QObject::connect and QObject::disconnect which
+ are working with QMetaMethod.
+
+ \param[out] signalIndex is set to the signal index of member. If the member
+ specified is not signal this variable is set to -1.
+
+ \param[out] methodIndex is set to the method index of the member. If the
+ member is not a method of the object specified by obj param this variable
+ is set to -1.
+*/
+void QMetaObjectPrivate::memberIndexes(const QObject *obj,
+ const QMetaMethod &member,
+ int *signalIndex, int *methodIndex)
+{
+ *signalIndex = -1;
+ *methodIndex = -1;
+ if (!obj || !member.mobj)
+ return;
+ const QMetaObject *m = obj->metaObject();
+ // Check that member is member of obj class
+ while (m != 0 && m != member.mobj)
+ m = m->d.superdata;
+ if (!m)
+ return;
+ *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
+
+ int signalOffset;
+ int methodOffset;
+ computeOffsets(m, &signalOffset, &methodOffset);
+
+ *methodIndex += methodOffset;
+ if (member.methodType() == QMetaMethod::Signal) {
+ *signalIndex = originalClone(m, *signalIndex);
+ *signalIndex += signalOffset;
+ } else {
+ *signalIndex = -1;
+ }
+}
+
+static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
+ const QMetaObject *receiver, const QMetaMethod &method)
+{
+ if (signal.attributes() & QMetaMethod::Compatibility) {
+ if (!(method.attributes() & QMetaMethod::Compatibility))
+ qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
+ sender->className(), signal.signature());
+ } 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.signature(),
+ receiver->className(), method.signature());
+ }
+}
+
+/*!
+ \threadsafe
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a method in the \a receiver object.
+ Returns true if the connection succeeds; otherwise returns false.
+
+ You must use the \c SIGNAL() and \c SLOT() macros when specifying
+ the \a signal and the \a method, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
+
+ This example ensures that the label always displays the current
+ scroll bar value. Note that the signal and slots parameters must not
+ contain any variable names, only the type. E.g. the following would
+ not work and return false:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
+
+ A signal can also be connected to another signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
+
+ In this example, the \c MyWidget constructor relays a signal from
+ a private member variable, and makes it available under a name
+ that relates to \c MyWidget.
+
+ A signal can be connected to many slots and signals. Many signals
+ can be connected to one slot.
+
+ If a signal is connected to several slots, the slots are activated
+ in the same order as the order the connection was made, when the
+ signal is emitted.
+
+ The function returns true if it successfully connects the signal
+ to the slot. It will return false if it cannot create the
+ connection, for example, if QObject is unable to verify the
+ existence of either \a signal or \a method, or if their signatures
+ aren't compatible.
+
+ By default, a signal is emitted for every connection you make;
+ two signals are emitted for duplicate connections. You can break
+ all of these connections with a single disconnect() call.
+ If you pass the Qt::UniqueConnection \a type, the connection will only
+ be made if it is not a duplicate. If there is already a duplicate
+ (exact same signal to the exact same slot on the same objects),
+ the connection will fail and connect will return false.
+
+ The optional \a type parameter describes the type of connection
+ to establish. In particular, it determines whether a particular
+ signal is delivered to a slot immediately or queued for delivery
+ at a later time. If the signal is queued, 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
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
+
+ call qRegisterMetaType() to register the data type before you
+ establish the connection.
+
+ \sa disconnect(), sender(), qRegisterMetaType()
+*/
+
+bool QObject::connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+{
+ {
+ const void *cbdata[] = { sender, signal, receiver, method, &type };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ bool warnCompat = true;
+#endif
+ if (type == Qt::AutoCompatConnection) {
+ type = Qt::AutoConnection;
+#ifndef QT_NO_DEBUG
+ warnCompat = false;
+#endif
+ }
+
+ if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
+ qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(null)",
+ (signal && *signal) ? signal+1 : "(null)",
+ receiver ? receiver->metaObject()->className() : "(null)",
+ (method && *method) ? method+1 : "(null)");
+ return false;
+ }
+ QByteArray tmp_signal_name;
+
+ if (!check_signal_macro(sender, signal, "connect", "bind"))
+ return false;
+ const QMetaObject *smeta = sender->metaObject();
+ const char *signal_arg = signal;
+ ++signal; //skip code
+ int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0) {
+ // check for normalized signatures
+ tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
+ signal = tmp_signal_name.constData() + 1;
+
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ }
+ if (signal_index < 0) {
+ // re-use tmp_signal_name and signal from above
+
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ }
+ if (signal_index < 0) {
+ err_method_notfound(sender, signal_arg, "connect");
+ err_info_about_objects("connect", sender, receiver);
+ return false;
+ }
+ signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
+ int signalOffset, methodOffset;
+ computeOffsets(smeta, &signalOffset, &methodOffset);
+ int signal_absolute_index = signal_index + methodOffset;
+ signal_index += signalOffset;
+
+ QByteArray tmp_method_name;
+ int membcode = extract_code(method);
+
+ if (!check_method_code(membcode, receiver, method, "connect"))
+ return false;
+ const char *method_arg = method;
+ ++method; // skip code
+
+ const QMetaObject *rmeta = receiver->metaObject();
+ int method_index_relative = -1;
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ break;
+ }
+
+ if (method_index_relative < 0) {
+ // check for normalized methods
+ tmp_method_name = QMetaObject::normalizedSignature(method);
+ method = tmp_method_name.constData();
+
+ // rmeta may have been modified above
+ rmeta = receiver->metaObject();
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
+ break;
+ }
+ }
+
+ if (method_index_relative < 0) {
+ err_method_notfound(receiver, method_arg, "connect");
+ err_info_about_objects("connect", sender, receiver);
+ return false;
+ }
+
+ if (!QMetaObject::checkConnectArgs(signal, method)) {
+ qWarning("QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ sender->metaObject()->className(), signal,
+ receiver->metaObject()->className(), method);
+ return false;
+ }
+
+ int *types = 0;
+ if ((type == Qt::QueuedConnection)
+ && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
+ return false;
+
+#ifndef QT_NO_DEBUG
+ if (warnCompat) {
+ QMetaMethod smethod = smeta->method(signal_absolute_index);
+ QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
+ check_and_warn_compat(smeta, smethod, rmeta, rmethod);
+ }
+#endif
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
+ return false;
+ const_cast<QObject*>(sender)->connectNotify(signal - 1);
+ return true;
+}
+
+/*!
+ \since 4.8
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a method in the \a receiver object.
+ Returns true if the connection succeeds; otherwise returns false.
+
+ This function works in the same way as
+ connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+ but it uses QMetaMethod to specify signal and method.
+
+ \see connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+ */
+bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &method,
+ Qt::ConnectionType type)
+{
+#ifndef QT_NO_DEBUG
+ bool warnCompat = true;
+#endif
+ if (type == Qt::AutoCompatConnection) {
+ type = Qt::AutoConnection;
+#ifndef QT_NO_DEBUG
+ warnCompat = false;
+#endif
+ }
+
+ if (sender == 0
+ || receiver == 0
+ || signal.methodType() != QMetaMethod::Signal
+ || method.methodType() == QMetaMethod::Constructor) {
+ qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(null)",
+ signal.signature(),
+ receiver ? receiver->metaObject()->className() : "(null)",
+ method.signature() );
+ return false;
+ }
+
+ // Reconstructing SIGNAL() macro result for signal.signature() string
+ QByteArray signalSignature;
+ signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.append((char)(QSIGNAL_CODE + '0'));
+ signalSignature.append(signal.signature());
+
+ {
+ QByteArray methodSignature;
+ methodSignature.reserve(qstrlen(method.signature())+1);
+ methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
+ : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
+ methodSignature.append(method.signature());
+ const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+
+ int signal_index;
+ int method_index;
+ {
+ int dummy;
+ QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
+ QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
+ }
+
+ 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.signature(), smeta->className());
+ return false;
+ }
+ if (method_index == -1) {
+ qWarning("QObject::connect: Can't find method %s on instance of class %s",
+ method.signature(), rmeta->className());
+ return false;
+ }
+
+ if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
+ qWarning("QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ smeta->className(), signal.signature(),
+ rmeta->className(), method.signature());
+ return false;
+ }
+
+ int *types = 0;
+ if ((type == Qt::QueuedConnection)
+ && !(types = queuedConnectionTypes(signal.parameterTypes())))
+ return false;
+
+#ifndef QT_NO_DEBUG
+ if (warnCompat)
+ check_and_warn_compat(smeta, signal, rmeta, method);
+#endif
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
+ return false;
+
+ const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
+ return true;
+}
+
+/*!
+ \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
+ \overload connect()
+ \threadsafe
+
+ Connects \a signal from the \a sender object to this object's \a
+ method.
+
+ Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
+
+ Every connection you make emits a signal, so duplicate connections emit
+ two signals. You can break a connection using disconnect().
+
+ \sa disconnect()
+*/
+
+/*!
+ \threadsafe
+
+ Disconnects \a signal in object \a sender from \a method in object
+ \a receiver. Returns true if the connection is successfully broken;
+ otherwise returns false.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+
+ disconnect() is typically used in three ways, as the following
+ examples demonstrate.
+ \list 1
+ \i Disconnect everything connected to an object's signals:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27
+
+ \i Disconnect everything connected to a specific signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29
+
+ \i Disconnect a specific receiver:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 31
+
+ \endlist
+
+ 0 may be used as a wildcard, meaning "any signal", "any receiving
+ object", or "any slot in the receiving object", respectively.
+
+ The \a sender may never be 0. (You cannot disconnect signals from
+ more than one object in a single call.)
+
+ If \a signal is 0, it disconnects \a receiver and \a method from
+ any signal. If not, only the specified signal is disconnected.
+
+ If \a receiver is 0, it disconnects anything connected to \a
+ signal. If not, slots in objects other than \a receiver are not
+ disconnected.
+
+ If \a method is 0, it disconnects anything that is connected to \a
+ receiver. If not, only slots named \a method will be disconnected,
+ and all other slots are left alone. The \a method must be 0 if \a
+ receiver is left out, so you cannot disconnect a
+ specifically-named slot on all objects.
+
+ \sa connect()
+*/
+bool QObject::disconnect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method)
+{
+ if (sender == 0 || (receiver == 0 && method != 0)) {
+ qWarning("Object::disconnect: Unexpected null parameter");
+ return false;
+ }
+
+ {
+ const void *cbdata[] = { sender, signal, receiver, method };
+ if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
+ return true;
+ }
+
+ const char *signal_arg = signal;
+ QByteArray signal_name;
+ bool signal_found = false;
+ if (signal) {
+ QT_TRY {
+ signal_name = QMetaObject::normalizedSignature(signal);
+ signal = signal_name.constData();
+ } QT_CATCH (const std::bad_alloc &) {
+ // if the signal is already normalized, we can continue.
+ if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
+ QT_RETHROW;
+ }
+
+ if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
+ return false;
+ signal++; // skip code
+ }
+
+ QByteArray method_name;
+ const char *method_arg = method;
+ int membcode = -1;
+ bool method_found = false;
+ if (method) {
+ QT_TRY {
+ method_name = QMetaObject::normalizedSignature(method);
+ method = method_name.constData();
+ } QT_CATCH(const std::bad_alloc &) {
+ // if the method is already normalized, we can continue.
+ if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
+ QT_RETHROW;
+ }
+
+ membcode = extract_code(method);
+ if (!check_method_code(membcode, receiver, method, "disconnect"))
+ return false;
+ method++; // skip code
+ }
+
+ /* We now iterate through all the sender's and receiver's meta
+ * objects in order to also disconnect possibly shadowed signals
+ * and slots with the same signature.
+ */
+ bool res = false;
+ const QMetaObject *smeta = sender->metaObject();
+ do {
+ int signal_index = -1;
+ if (signal) {
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0)
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ if (signal_index < 0)
+ break;
+ signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
+ int signalOffset, methodOffset;
+ computeOffsets(smeta, &signalOffset, &methodOffset);
+ signal_index += signalOffset;
+ signal_found = true;
+ }
+
+ if (!method) {
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1);
+ } else {
+ const QMetaObject *rmeta = receiver->metaObject();
+ do {
+ int method_index = rmeta->indexOfMethod(method);
+ if (method_index >= 0)
+ while (method_index < rmeta->methodOffset())
+ rmeta = rmeta->superClass();
+ if (method_index < 0)
+ break;
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index);
+ method_found = true;
+ } while ((rmeta = rmeta->superClass()));
+ }
+ } while (signal && (smeta = smeta->superClass()));
+
+ if (signal && !signal_found) {
+ err_method_notfound(sender, signal_arg, "disconnect");
+ err_info_about_objects("disconnect", sender, receiver);
+ } else if (method && !method_found) {
+ err_method_notfound(receiver, method_arg, "disconnect");
+ err_info_about_objects("disconnect", sender, receiver);
+ }
+ if (res)
+ const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
+ return res;
+}
+
+/*!
+ \since 4.8
+
+ Disconnects \a signal in object \a sender from \a method in object
+ \a receiver. Returns true if the connection is successfully broken;
+ otherwise returns false.
+
+ This function provides the same posibilities like
+ disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
+ but uses QMetaMethod to represent the signal and the method to be disconnected.
+
+ Additionally this function returnsfalse and no signals and slots disconnected
+ if:
+ \list 1
+
+ \i \a signal is not a member of sender class or one of its parent classes.
+
+ \i \a method is not a member of receiver class or one of its parent classes.
+
+ \i \a signal instance represents not a signal.
+
+ \endlist
+
+ QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
+ In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
+ method shoud also be QMetaMethod(). \a sender parameter should be never 0.
+
+ \see 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 == 0 || (receiver == 0 && method.mobj != 0)) {
+ qWarning("Object::disconnect: Unexpected null parameter");
+ return false;
+ }
+ if (signal.mobj) {
+ if(signal.methodType() != QMetaMethod::Signal) {
+ qWarning("Object::%s: Attempt to %s non-signal %s::%s",
+ "disconnect","unbind",
+ sender->metaObject()->className(), signal.signature());
+ return false;
+ }
+ }
+ if (method.mobj) {
+ if(method.methodType() == QMetaMethod::Constructor) {
+ qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
+ receiver->metaObject()->className(), method.signature());
+ return false;
+ }
+ }
+
+ // Reconstructing SIGNAL() macro result for signal.signature() string
+ QByteArray signalSignature;
+ if (signal.mobj) {
+ signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.append((char)(QSIGNAL_CODE + '0'));
+ signalSignature.append(signal.signature());
+ }
+
+ {
+ QByteArray methodSignature;
+ if (method.mobj) {
+ methodSignature.reserve(qstrlen(method.signature())+1);
+ methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
+ : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
+ methodSignature.append(method.signature());
+ }
+ const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0,
+ receiver, method.mobj ? methodSignature.constData() : 0 };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+ int signal_index;
+ int method_index;
+ {
+ int dummy;
+ QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
+ QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
+ }
+ // If we are here sender is not null. If signal is not null while signal_index
+ // is -1 then this signal is not a member of sender.
+ if (signal.mobj && signal_index == -1) {
+ qWarning("QObject::disconect: signal %s not found on class %s",
+ signal.signature(), sender->metaObject()->className());
+ return false;
+ }
+ // If this condition is true then method is not a member of receeiver.
+ if (receiver && method.mobj && method_index == -1) {
+ qWarning("QObject::disconect: method %s not found on class %s",
+ method.signature(), receiver->metaObject()->className());
+ return false;
+ }
+
+ if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index))
+ return false;
+
+ const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
+ return true;
+}
+
+/*!
+ \threadsafe
+
+ \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method)
+ \overload disconnect()
+
+ Disconnects \a signal from \a method of \a receiver.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+*/
+
+/*!
+ \fn bool QObject::disconnect(const QObject *receiver, const char *method)
+ \overload disconnect()
+
+ Disconnects all signals in this object from \a receiver's \a
+ method.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+*/
+
+
+/*!
+ \fn void QObject::connectNotify(const char *signal)
+
+ This virtual function is called when something has been connected
+ to \a signal in this object.
+
+ If you want to compare \a signal with a specific signal, use
+ QLatin1String and the \c SIGNAL() macro as follows:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 32
+
+ If the signal contains multiple parameters or parameters that
+ contain spaces, call QMetaObject::normalizedSignature() on
+ the result of the \c SIGNAL() macro.
+
+ \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.
+
+ \sa connect(), disconnectNotify()
+*/
+
+void QObject::connectNotify(const char *)
+{
+}
+
+/*!
+ \fn void QObject::disconnectNotify(const char *signal)
+
+ This virtual function is called when something has been
+ disconnected from \a signal in this object.
+
+ See connectNotify() for an example of how to compare
+ \a signal with a specific signal.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, it might be useful for optimizing access to
+ expensive resources.
+
+ \sa disconnect(), connectNotify()
+*/
+
+void QObject::disconnectNotify(const char *)
+{
+}
+
+/* \internal
+ convert a signal index from the method range to the signal range
+ */
+static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
+{
+ if (signal_index < 0)
+ return signal_index;
+ while (metaObject && metaObject->methodOffset() > signal_index)
+ metaObject = metaObject->superClass();
+
+ if (metaObject) {
+ int signalOffset, methodOffset;
+ computeOffsets(metaObject, &signalOffset, &methodOffset);
+ if (signal_index < metaObject->methodCount())
+ signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
+ else
+ signal_index = signal_index - methodOffset + signalOffset;
+ }
+ return signal_index;
+}
+
+/*!\internal
+ \a types is a 0-terminated vector of meta types for queued
+ connections.
+
+ if \a signal_index is -1, then we effectively connect *all* signals
+ from the sender to the receiver's slot
+ */
+bool QMetaObject::connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index, int type, int *types)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::connect(sender, signal_index,
+ receiver, method_index,
+ 0, //FIXME, we could speed this connection up by computing the relative index
+ type, types);
+}
+
+/*! \internal
+ Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
+
+ method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
+ */
+bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ const QMetaObject *rmeta, int type, int *types)
+{
+ QObject *s = const_cast<QObject *>(sender);
+ QObject *r = const_cast<QObject *>(receiver);
+
+ int method_offset = rmeta ? rmeta->methodOffset() : 0;
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (rmeta && QMetaObjectPrivate::get(rmeta)->revision >= 6 && rmeta->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
+
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
+
+ if (type & Qt::UniqueConnection) {
+ QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
+ if (connectionLists && connectionLists->count() > signal_index) {
+ const QObjectPrivate::Connection *c2 =
+ (*connectionLists)[signal_index].first;
+
+ int method_index_absolute = method_index + method_offset;
+
+ while (c2) {
+ if (c2->receiver == receiver && c2->method() == method_index_absolute)
+ return false;
+ c2 = c2->nextConnectionList;
+ }
+ }
+ type &= Qt::UniqueConnection - 1;
+ }
+
+ QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ c->sender = s;
+ c->receiver = r;
+ c->method_relative = method_index;
+ c->method_offset = method_offset;
+ c->connectionType = type;
+ c->argumentTypes = types;
+ c->nextConnectionList = 0;
+ c->callFunction = callFunction;
+
+ QT_TRY {
+ QObjectPrivate::get(s)->addConnection(signal_index, c);
+ } QT_CATCH(...) {
+ delete c;
+ QT_RETHROW;
+ }
+
+ c->prev = &(QObjectPrivate::get(r)->senders);
+ c->next = *c->prev;
+ *c->prev = c;
+ if (c->next)
+ c->next->prev = &c->next;
+
+ QObjectPrivate *const sender_d = QObjectPrivate::get(s);
+ if (signal_index < 0) {
+ sender_d->connectedSignals[0] = sender_d->connectedSignals[1] = ~0;
+ } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) {
+ sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
+ }
+
+ return true;
+}
+
+/*!\internal
+ */
+bool QMetaObject::disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index,
+ receiver, method_index);
+}
+
+/*!\internal
+
+Disconnect a single signal connection. If QMetaObject::connect() has been called
+multiple times for the same sender, signal_index, receiver and method_index only
+one of these connections will be removed.
+ */
+bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index,
+ receiver, method_index,
+ QMetaObjectPrivate::DisconnectOne);
+}
+
+/*! \internal
+ Helper function to remove the connection from the senders list and setting the receivers to 0
+ */
+bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
+ const QObject *receiver, int method_index,
+ QMutex *senderMutex, DisconnectType disconnectType)
+{
+ bool success = false;
+ while (c) {
+ if (c->receiver
+ && (receiver == 0 || (c->receiver == receiver
+ && (method_index < 0 || c->method() == method_index)))) {
+ bool needToUnlock = false;
+ QMutex *receiverMutex = 0;
+ if (!receiver) {
+ receiverMutex = signalSlotLock(c->receiver);
+ // need to relock this receiver and sender in the correct order
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
+ }
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next)
+ c->next->prev = c->prev;
+ }
+
+ if (needToUnlock)
+ receiverMutex->unlockInline();
+
+ c->receiver = 0;
+
+ success = true;
+
+ if (disconnectType == DisconnectOne)
+ return success;
+ }
+ c = c->nextConnectionList;
+ }
+ return success;
+}
+
+/*! \internal
+ Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
+ */
+bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ DisconnectType disconnectType)
+{
+ if (!sender)
+ return false;
+
+ QObject *s = const_cast<QObject *>(sender);
+
+ QMutex *senderMutex = signalSlotLock(sender);
+ QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
+ QOrderedMutexLocker locker(senderMutex, receiverMutex);
+
+ QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
+ if (!connectionLists)
+ return false;
+
+ // prevent incoming connections changing the connectionLists while unlocked
+ ++connectionLists->inUse;
+
+ bool success = false;
+ if (signal_index < 0) {
+ // remove from all connection lists
+ for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
+ QObjectPrivate::Connection *c =
+ (*connectionLists)[signal_index].first;
+ if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ success = true;
+ connectionLists->dirty = true;
+ }
+ }
+ } else if (signal_index < connectionLists->count()) {
+ QObjectPrivate::Connection *c =
+ (*connectionLists)[signal_index].first;
+ if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ success = true;
+ connectionLists->dirty = true;
+ }
+ }
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+
+ return success;
+}
+
+/*!
+ \fn void QMetaObject::connectSlotsByName(QObject *object)
+
+ Searches recursively for all child objects of the given \a object, and connects
+ matching signals from them to slots of \a object that follow the following form:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 33
+
+ Let's assume our object has a child object of type QPushButton with
+ the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
+ button's \c{clicked()} signal would be:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 34
+
+ \sa QObject::setObjectName()
+ */
+void QMetaObject::connectSlotsByName(QObject *o)
+{
+ if (!o)
+ return;
+ const QMetaObject *mo = o->metaObject();
+ Q_ASSERT(mo);
+ const QObjectList list = o->findChildren<QObject *>(QString());
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const char *slot = mo->method(i).signature();
+ Q_ASSERT(slot);
+ if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
+ continue;
+ bool foundIt = false;
+ for(int j = 0; j < list.count(); ++j) {
+ const QObject *co = list.at(j);
+ QByteArray objName = co->objectName().toAscii();
+ int len = objName.length();
+ if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
+ continue;
+ int sigIndex = co->d_func()->signalIndex(slot + len + 4);
+ if (sigIndex < 0) { // search for compatible signals
+ const QMetaObject *smo = co->metaObject();
+ int slotlen = qstrlen(slot + len + 4) - 1;
+ for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
+ QMetaMethod method = smo->method(k);
+ if (method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
+ int signalOffset, methodOffset;
+ computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
+ sigIndex = k + - methodOffset + signalOffset;
+ break;
+ }
+ }
+ }
+ if (sigIndex < 0)
+ continue;
+ if (QMetaObjectPrivate::connect(co, sigIndex, o, i)) {
+ foundIt = true;
+ break;
+ }
+ }
+ if (foundIt) {
+ // we found our slot, now skip all overloads
+ while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
+ ++i;
+ } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
+ qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
+ }
+ }
+}
+
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
+{
+ if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ QMetaMethod m = sender->metaObject()->method(signal);
+ int *tmp = queuedConnectionTypes(m.parameterTypes());
+ if (!tmp) // cannot queue arguments
+ tmp = &DIRECT_CONNECTION_ONLY;
+ if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
+ if (tmp != &DIRECT_CONNECTION_ONLY)
+ delete [] tmp;
+ }
+ }
+ if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
+ return;
+ int nargs = 1; // include return type
+ while (c->argumentTypes[nargs-1])
+ ++nargs;
+ int *types = (int *) qMalloc(nargs*sizeof(int));
+ Q_CHECK_PTR(types);
+ void **args = (void **) qMalloc(nargs*sizeof(void *));
+ Q_CHECK_PTR(args);
+ types[0] = 0; // return type
+ args[0] = 0; // return value
+ for (int n = 1; n < nargs; ++n)
+ args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
+ c->method_relative,
+ c->callFunction,
+ sender, signal, nargs,
+ types, args));
+}
+
+
+/*!\internal
+ \obsolete.
+ Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) before Qt 4.6
+ */
+void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
+{
+ Q_UNUSED(to_signal_index);
+ activate(sender, from_signal_index, argv);
+}
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
+ void **argv)
+{
+ int signalOffset;
+ int methodOffset;
+ computeOffsets(m, &signalOffset, &methodOffset);
+
+ int signal_index = signalOffset + local_signal_index;
+
+ if (!sender->d_func()->isSignalConnected(signal_index))
+ return; // nothing connected to these signals, and no spy
+
+ if (sender->d_func()->blockSig)
+ return;
+
+ int signal_absolute_index = methodOffset + local_signal_index;
+
+ void *empty_argv[] = { 0 };
+ if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
+ qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
+ argv ? argv : empty_argv);
+ }
+
+ Qt::HANDLE currentThreadId = QThread::currentThreadId();
+
+ QMutexLocker locker(signalSlotLock(sender));
+ QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
+ if (!connectionLists) {
+ locker.unlock();
+ if (qt_signal_spy_callback_set.signal_end_callback != 0)
+ qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
+ return;
+ }
+ ++connectionLists->inUse;
+
+
+ const QObjectPrivate::ConnectionList *list;
+ if (signal_index < connectionLists->count())
+ list = &connectionLists->at(signal_index);
+ else
+ list = &connectionLists->allsignals;
+
+ do {
+ QObjectPrivate::Connection *c = list->first;
+ if (!c) continue;
+ // We need to check against last here to ensure that signals added
+ // during the signal emission are not emitted in this emission.
+ QObjectPrivate::Connection *last = list->last;
+
+ do {
+ if (!c->receiver)
+ continue;
+
+ QObject * const receiver = c->receiver;
+ const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
+
+ // determine if this connection should be sent immediately or
+ // put into the event queue
+ if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
+ || (c->connectionType == Qt::QueuedConnection)) {
+ queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
+ continue;
+#ifndef QT_NO_THREAD
+ } else if (c->connectionType == Qt::BlockingQueuedConnection) {
+ locker.unlock();
+ if (receiverInSameThread) {
+ qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
+ "Sender is %s(%p), receiver is %s(%p)",
+ sender->metaObject()->className(), sender,
+ receiver->metaObject()->className(), receiver);
+ }
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(receiver, new QMetaCallEvent(c->method_offset, c->method_relative,
+ c->callFunction,
+ sender, signal_absolute_index,
+ 0, 0,
+ argv ? argv : empty_argv,
+ &semaphore));
+ semaphore.acquire();
+ locker.relock();
+ continue;
+#endif
+ }
+
+ QObjectPrivate::Sender currentSender;
+ QObjectPrivate::Sender *previousSender = 0;
+ if (receiverInSameThread) {
+ currentSender.sender = sender;
+ currentSender.signal = signal_absolute_index;
+ currentSender.ref = 1;
+ previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ }
+ const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
+ const int method_relative = c->method_relative;
+ if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
+ //we compare the vtable to make sure we are not in the destructor of the object.
+ locker.unlock();
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0)
+ qt_signal_spy_callback_set.slot_begin_callback(receiver, c->method(), argv ? argv : empty_argv);
+
+ callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
+
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, c->method());
+ locker.relock();
+ } else {
+ const int method = method_relative + c->method_offset;
+ locker.unlock();
+
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
+ qt_signal_spy_callback_set.slot_begin_callback(receiver,
+ method,
+ argv ? argv : empty_argv);
+ }
+
+#if defined(QT_NO_EXCEPTIONS)
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+#else
+ QT_TRY {
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ } QT_CATCH(...) {
+ locker.relock();
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+ QT_RETHROW;
+ }
+#endif
+
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, method);
+
+ locker.relock();
+ }
+
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ if (connectionLists->orphaned)
+ break;
+ } while (c != last && (c = c->nextConnectionList) != 0);
+
+ if (connectionLists->orphaned)
+ break;
+ } while (list != &connectionLists->allsignals &&
+ //start over for all signals;
+ ((list = &connectionLists->allsignals), true));
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned) {
+ if (!connectionLists->inUse)
+ delete connectionLists;
+ } else if (connectionLists->dirty) {
+ sender->d_func()->cleanConnectionLists();
+ }
+
+ locker.unlock();
+
+ if (qt_signal_spy_callback_set.signal_end_callback != 0)
+ qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
+
+}
+
+/*!\internal
+ Obsolete. (signal_index comes from indexOfMethod())
+*/
+void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
+{
+ const QMetaObject *mo = sender->metaObject();
+ while (mo->methodOffset() > signal_index)
+ mo = mo->superClass();
+ activate(sender, mo, signal_index - mo->methodOffset(), argv);
+}
+
+/*!\internal
+ Obsolete, called by moc generated code before Qt 4.6 for cloned signals
+ But since Qt 4.6, all clones are connected to their original
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m,
+ int from_local_signal_index, int to_local_signal_index, void **argv)
+{
+ Q_UNUSED(to_local_signal_index);
+ Q_ASSERT(from_local_signal_index == QMetaObjectPrivate::originalClone(m, to_local_signal_index));
+ activate(sender, m, from_local_signal_index, argv);
+}
+
+/*! \internal
+ Returns the signal index used in the internal connectionLists vector.
+
+ It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
+ while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
+*/
+int QObjectPrivate::signalIndex(const char *signalName) const
+{
+ Q_Q(const QObject);
+ const QMetaObject *base = q->metaObject();
+ int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
+ if (relative_index < 0)
+ relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
+ if (relative_index < 0)
+ return relative_index;
+ relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
+ int signalOffset, methodOffset;
+ computeOffsets(base, &signalOffset, &methodOffset);
+ return relative_index + signalOffset;
+}
+
+/*****************************************************************************
+ Properties
+ *****************************************************************************/
+
+#ifndef QT_NO_PROPERTIES
+
+/*!
+ 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
+ true is returned on success and false otherwise. If the property
+ is not defined using Q_PROPERTY, and therefore not listed in the
+ meta-object, it is added as a dynamic property and false is returned.
+
+ Information about all available properties is provided through the
+ metaObject() and dynamicPropertyNames().
+
+ Dynamic properties can be queried again using property() and can be
+ removed by setting the property value to an invalid QVariant.
+ Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
+ to be sent to the object.
+
+ \bold{Note:} Dynamic properties starting with "_q_" are reserved for internal
+ purposes.
+
+ \sa property(), metaObject(), dynamicPropertyNames()
+*/
+bool QObject::setProperty(const char *name, const QVariant &value)
+{
+ Q_D(QObject);
+ 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;
+
+ const int idx = d->extraData->propertyNames.indexOf(name);
+
+ if (!value.isValid()) {
+ if (idx == -1)
+ return false;
+ d->extraData->propertyNames.removeAt(idx);
+ d->extraData->propertyValues.removeAt(idx);
+ } else {
+ if (idx == -1) {
+ d->extraData->propertyNames.append(name);
+ d->extraData->propertyValues.append(value);
+ } else {
+ d->extraData->propertyValues[idx] = value;
+ }
+ }
+
+ QDynamicPropertyChangeEvent ev(name);
+ QCoreApplication::sendEvent(this, &ev);
+
+ return false;
+ }
+ QMetaProperty p = meta->property(id);
+#ifndef QT_NO_DEBUG
+ if (!p.isWritable())
+ qWarning("%s::setProperty: Property \"%s\" invalid,"
+ " read-only or does not exist", metaObject()->className(), name);
+#endif
+ return p.write(this, value);
+}
+
+/*!
+ Returns the value of the object's \a name property.
+
+ If no such property exists, the returned variant is invalid.
+
+ Information about all available properties is provided through the
+ metaObject() and dynamicPropertyNames().
+
+ \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
+*/
+QVariant QObject::property(const char *name) const
+{
+ Q_D(const QObject);
+ const QMetaObject* meta = metaObject();
+ if (!name || !meta)
+ return QVariant();
+
+ int id = meta->indexOfProperty(name);
+ if (id < 0) {
+ if (!d->extraData)
+ return QVariant();
+ const int i = d->extraData->propertyNames.indexOf(name);
+ return d->extraData->propertyValues.value(i);
+ }
+ QMetaProperty p = meta->property(id);
+#ifndef QT_NO_DEBUG
+ if (!p.isReadable())
+ qWarning("%s::property: Property \"%s\" invalid or does not exist",
+ metaObject()->className(), name);
+#endif
+ return p.read(this);
+}
+
+/*!
+ \since 4.2
+
+ Returns the names of all properties that were dynamically added to
+ the object using setProperty().
+*/
+QList<QByteArray> QObject::dynamicPropertyNames() const
+{
+ Q_D(const QObject);
+ if (d->extraData)
+ return d->extraData->propertyNames;
+ return QList<QByteArray>();
+}
+
+#endif // QT_NO_PROPERTIES
+
+
+/*****************************************************************************
+ QObject debugging output routines.
+ *****************************************************************************/
+
+static void dumpRecursive(int level, QObject *object)
+{
+#if defined(QT_DEBUG)
+ 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));
+ }
+ }
+#else
+ Q_UNUSED(level)
+ Q_UNUSED(object)
+#endif
+}
+
+/*!
+ Dumps a tree of children to the debug output.
+
+ This function is useful for debugging, but does nothing if the
+ library has been compiled in release mode (i.e. without debugging
+ information).
+
+ \sa dumpObjectInfo()
+*/
+
+void QObject::dumpObjectTree()
+{
+ dumpRecursive(0, this);
+}
+
+/*!
+ Dumps information about signal connections, etc. for this object
+ to the debug output.
+
+ This function is useful for debugging, but does nothing if the
+ library has been compiled in release mode (i.e. without debugging
+ information).
+
+ \sa dumpObjectTree()
+*/
+
+void QObject::dumpObjectInfo()
+{
+#if defined(QT_DEBUG)
+ qDebug("OBJECT %s::%s", metaObject()->className(),
+ objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
+
+ Q_D(QObject);
+ QMutexLocker locker(signalSlotLock(this));
+
+ // first, look for connections where this object is the sender
+ qDebug(" SIGNALS OUT");
+
+ if (d->connectionLists) {
+ int offset = 0;
+ int offsetToNextMetaObject = 0;
+ for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
+ if (signal_index >= offsetToNextMetaObject) {
+ const QMetaObject *mo = metaObject();
+ int signalOffset, methodOffset;
+ computeOffsets(mo, &signalOffset, &methodOffset);
+ while (signalOffset > signal_index) {
+ mo = mo->superClass();
+ offsetToNextMetaObject = signalOffset;
+ computeOffsets(mo, &signalOffset, &methodOffset);
+ }
+ offset = methodOffset - signalOffset;
+ }
+ const QMetaMethod signal = metaObject()->method(signal_index + offset);
+ qDebug(" signal: %s", signal.signature());
+
+ // receivers
+ const QObjectPrivate::Connection *c =
+ d->connectionLists->at(signal_index).first;
+ while (c) {
+ if (!c->receiver) {
+ qDebug(" <Disconnected receiver>");
+ c = c->nextConnectionList;
+ continue;
+ }
+ const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaMethod method = receiverMetaObject->method(c->method());
+ qDebug(" --> %s::%s %s",
+ receiverMetaObject->className(),
+ c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
+ method.signature());
+ c = c->nextConnectionList;
+ }
+ }
+ } else {
+ qDebug( " <None>" );
+ }
+
+ // now look for connections where this object is the receiver
+ qDebug(" SIGNALS IN");
+
+ if (d->senders) {
+ for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
+ const QMetaMethod slot = metaObject()->method(s->method());
+ qDebug(" <-- %s::%s %s",
+ s->sender->metaObject()->className(),
+ s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
+ slot.signature());
+ }
+ } else {
+ qDebug(" <None>");
+ }
+#endif
+}
+
+#ifndef QT_NO_USERDATA
+/*!\internal
+ */
+uint QObject::registerUserData()
+{
+ static int user_data_registration = 0;
+ return user_data_registration++;
+}
+
+/*!\internal
+ */
+QObjectUserData::~QObjectUserData()
+{
+}
+
+/*!\internal
+ */
+void QObject::setUserData(uint id, QObjectUserData* data)
+{
+ Q_D(QObject);
+ if (!d->extraData)
+ d->extraData = new QObjectPrivate::ExtraData;
+
+ if (d->extraData->userData.size() <= (int) id)
+ d->extraData->userData.resize((int) id + 1);
+ d->extraData->userData[id] = data;
+}
+
+/*!\internal
+ */
+QObjectUserData* QObject::userData(uint id) const
+{
+ Q_D(const QObject);
+ if (!d->extraData)
+ return 0;
+ if ((int)id < d->extraData->userData.size())
+ return d->extraData->userData.at(id);
+ return 0;
+}
+
+#endif // QT_NO_USERDATA
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QObject *o) {
+#ifndef Q_BROKEN_DEBUG_STREAM
+ if (!o)
+ return dbg << "QObject(0x0) ";
+ dbg.nospace() << o->metaObject()->className() << '(' << (void *)o;
+ if (!o->objectName().isEmpty())
+ dbg << ", name = " << o->objectName();
+ dbg << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QObject to QDebug");
+ return dbg;
+ Q_UNUSED(o);
+#endif
+}
+#endif
+
+/*!
+ \fn void QObject::insertChild(QObject *object)
+
+ Use setParent() instead, i.e., call object->setParent(this).
+*/
+
+/*!
+ \fn void QObject::removeChild(QObject *object)
+
+ Use setParent() instead, i.e., call object->setParent(0).
+*/
+
+/*!
+ \fn bool QObject::isA(const char *className) const
+
+ Compare \a className with the object's metaObject()->className() instead.
+*/
+
+/*!
+ \fn const char *QObject::className() const
+
+ Use metaObject()->className() instead.
+*/
+
+/*!
+ \fn const char *QObject::name() const
+
+ Use objectName() instead.
+*/
+
+/*!
+ \fn const char *QObject::name(const char *defaultName) const
+
+ Use objectName() instead.
+*/
+
+/*!
+ \fn void QObject::setName(const char *name)
+
+ Use setObjectName() instead.
+*/
+
+/*!
+ \fn bool QObject::checkConnectArgs(const char *signal, const
+ QObject *object, const char *method)
+
+ Use QMetaObject::checkConnectArgs() instead.
+*/
+
+/*!
+ \fn QByteArray QObject::normalizeSignalSlot(const char *signalSlot)
+
+ Use QMetaObject::normalizedSignature() instead.
+*/
+
+/*!
+ \fn const char *QMetaObject::superClassName() const
+
+ \internal
+*/
+
+/*!
+ \macro Q_CLASSINFO(Name, Value)
+ \relates QObject
+
+ This macro associates extra information to the class, which is
+ available using QObject::metaObject(). Except for the ActiveQt
+ extension, Qt doesn't use this information.
+
+ The extra information takes the form of a \a Name string and a \a
+ Value literal string.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 35
+
+ \sa QMetaObject::classInfo()
+*/
+
+/*!
+ \macro Q_INTERFACES(...)
+ \relates QObject
+
+ This macro tells Qt which interfaces the class implements. This
+ is used when implementing plugins.
+
+ Example:
+
+ \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
+ \dots
+ \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
+
+ See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint
+ Basic Tools} example for details.
+
+ \sa Q_DECLARE_INTERFACE(), Q_EXPORT_PLUGIN2(), {How to Create Qt Plugins}
+*/
+
+/*!
+ \macro Q_PROPERTY(...)
+ \relates QObject
+
+ This macro is used for declaring properties in classes that
+ inherit QObject. Properties behave like class data members, but
+ they have additional features accessible through the \l
+ {Meta-Object System}.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 36
+
+ The property name and type and the \c READ function are required.
+ The type can be any type supported by QVariant, or it can be a
+ user-defined type. The other items are optional, but a \c WRITE
+ function is common. The attributes default to true except \c USER,
+ which defaults to false.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 37
+
+ For more details about how to use this macro, and a more detailed
+ example of its use, see the discussion on \l {Qt's Property System}.
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_ENUMS(...)
+ \relates QObject
+
+ This macro registers one or several enum types to the meta-object
+ system.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 38
+
+ If you want to register an enum that is declared in another class,
+ the enum must be fully qualified with the name of the class
+ defining it. In addition, the class \e defining the enum has to
+ inherit QObject as well as declare the enum using Q_ENUMS().
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_FLAGS(...)
+ \relates QObject
+
+ This macro registers one or several \l{QFlags}{flags types} to the
+ meta-object system. It is typically used in a class definition to declare
+ that values of a given enum can be used as flags and combined using the
+ bitwise OR operator.
+
+ For example, in QLibrary, the \l{QLibrary::LoadHints}{LoadHints} flag is
+ declared in the following way:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39a
+
+ The declaration of the flags themselves is performed in the public section
+ of the QLibrary class itself, using the \l Q_DECLARE_FLAGS() macro:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39b
+
+ \note This macro takes care of registering individual flag values
+ with the meta-object system, so it is unnecessary to use Q_ENUMS()
+ in addition to this macro.
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_OBJECT
+ \relates QObject
+
+ The Q_OBJECT macro must appear in the private section of a class
+ definition that declares its own signals and slots or that uses
+ other services provided by Qt's meta-object system.
+
+ For example:
+
+ \snippet doc/src/snippets/signalsandslots/signalsandslots.h 1
+ \codeline
+ \snippet doc/src/snippets/signalsandslots/signalsandslots.h 2
+ \snippet doc/src/snippets/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
+ for enums in a class that is not a QObject subclass. 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.
+ Q_GADGET is provided only for C++.
+
+ \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
+*/
+
+/*!
+ \macro Q_SIGNALS
+ \relates QObject
+
+ Use this macro to replace the \c signals keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SIGNAL
+ \relates QObject
+
+ This is an additional macro that allows you to mark a single
+ function as a signal. It can be quite useful, especially when you
+ use a 3rd-party source code parser which doesn't understand a \c
+ signals or \c Q_SIGNALS groups.
+
+ Use this macro to replace the \c signals keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SLOTS
+ \relates QObject
+
+ Use this macro to replace the \c slots keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SLOT
+ \relates QObject
+
+ This is an additional macro that allows you to mark a single
+ function as a slot. It can be quite useful, especially when you
+ use a 3rd-party source code parser which doesn't understand a \c
+ slots or \c Q_SLOTS groups.
+
+ Use this macro to replace the \c slots keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_EMIT
+ \relates QObject
+
+ Use this macro to replace the \c emit keyword for emitting
+ signals, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_INVOKABLE
+ \relates QObject
+
+ Apply this macro to definitions of member functions to allow them to
+ be invoked via the meta-object system. The macro is written before
+ the return type, as shown in the following example:
+
+ \snippet snippets/qmetaobject-invokable/window.h Window class with invokable method
+
+ The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
+ it to be registered with the meta-object system and enabling it to be
+ invoked using QMetaObject::invokeMethod().
+ Since \c normalMethod() function is not registered in this way, it cannot
+ be invoked using QMetaObject::invokeMethod().
+*/
+
+/*!
+ \typedef QObjectList
+ \relates QObject
+
+ Synonym for QList<QObject *>.
+*/
+
+void qDeleteInEventHandler(QObject *o)
+{
+#ifdef QT_JAMBI_BUILD
+ if (!o)
+ return;
+ QObjectPrivate::get(o)->inEventHandler = false;
+#endif
+ delete o;
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
new file mode 100644
index 0000000000..0ad73f5fe9
--- /dev/null
+++ b/src/corelib/kernel/qobject.h
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOBJECT_H
+#define QOBJECT_H
+
+#ifndef QT_NO_QOBJECT
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtCore/qcoreevent.h>
+#endif
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+class QTimerEvent;
+class QChildEvent;
+struct QMetaObject;
+class QVariant;
+class QObjectPrivate;
+class QObject;
+class QThread;
+class QWidget;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+#ifndef QT_NO_USERDATA
+class QObjectUserData;
+#endif
+
+typedef QList<QObject*> QObjectList;
+
+Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
+ const QMetaObject &mo, QList<void *> *list);
+Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo);
+
+class
+#if defined(__INTEL_COMPILER) && defined(Q_OS_WIN)
+Q_CORE_EXPORT
+#endif
+QObjectData {
+public:
+ virtual ~QObjectData() = 0;
+ QObject *q_ptr;
+ QObject *parent;
+ QObjectList children;
+
+ uint isWidget : 1;
+ uint pendTimer : 1;
+ uint blockSig : 1;
+ uint wasDeleted : 1;
+ uint ownObjectName : 1;
+ uint sendChildEvents : 1;
+ uint receiveChildEvents : 1;
+ uint inEventHandler : 1; //only used if QT_JAMBI_BUILD
+ uint inThreadChangeEvent : 1;
+ uint hasGuards : 1; //true iff there is one or more QPointer attached to this object
+ uint unused : 22;
+ int postedEvents;
+ QMetaObject *metaObject; // assert dynamic
+};
+
+
+class Q_CORE_EXPORT QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString objectName READ objectName WRITE setObjectName)
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ Q_INVOKABLE explicit QObject(QObject *parent=0);
+ virtual ~QObject();
+
+ virtual bool event(QEvent *);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+#ifdef qdoc
+ static QString tr(const char *sourceText, const char *comment = 0, int n = -1);
+ static QString trUtf8(const char *sourceText, const char *comment = 0, int n = -1);
+ virtual const QMetaObject *metaObject() const;
+ static const QMetaObject staticMetaObject;
+#endif
+#ifdef QT_NO_TRANSLATION
+ static QString tr(const char *sourceText, const char *, int)
+ { return QString::fromLatin1(sourceText); }
+ static QString tr(const char *sourceText, const char * = 0)
+ { return QString::fromLatin1(sourceText); }
+#ifndef QT_NO_TEXTCODEC
+ static QString trUtf8(const char *sourceText, const char *, int)
+ { return QString::fromUtf8(sourceText); }
+ static QString trUtf8(const char *sourceText, const char * = 0)
+ { return QString::fromUtf8(sourceText); }
+#endif
+#endif //QT_NO_TRANSLATION
+
+ QString objectName() const;
+ void setObjectName(const QString &name);
+
+ inline bool isWidgetType() const { return d_ptr->isWidget; }
+
+ inline bool signalsBlocked() const { return d_ptr->blockSig; }
+ bool blockSignals(bool b);
+
+ QThread *thread() const;
+ void moveToThread(QThread *thread);
+
+ int startTimer(int interval);
+ void killTimer(int id);
+
+ template<typename T>
+ inline T findChild(const QString &aName = QString()) const
+ { return static_cast<T>(qt_qFindChild_helper(this, aName, reinterpret_cast<T>(0)->staticMetaObject)); }
+
+ template<typename T>
+ inline QList<T> findChildren(const QString &aName = QString()) const
+ {
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(this, aName, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+ }
+
+#ifndef QT_NO_REGEXP
+ template<typename T>
+ inline QList<T> findChildren(const QRegExp &re) const
+ {
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(this, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+ }
+#endif
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QObject *child(const char *objName, const char *inheritsClass = 0,
+ bool recursiveSearch = true) const;
+ QT3_SUPPORT QObjectList queryList(const char *inheritsClass = 0,
+ const char *objName = 0,
+ bool regexpMatch = true,
+ bool recursiveSearch = true) const;
+#endif
+ inline const QObjectList &children() const { return d_ptr->children; }
+
+ void setParent(QObject *);
+ void installEventFilter(QObject *);
+ void removeEventFilter(QObject *);
+
+
+ static bool connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *member, Qt::ConnectionType =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ );
+
+ static bool connect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &method,
+ Qt::ConnectionType type =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ );
+
+ inline bool connect(const QObject *sender, const char *signal,
+ const char *member, Qt::ConnectionType type =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ ) const;
+
+ static bool disconnect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *member);
+ static bool disconnect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &member);
+ inline bool disconnect(const char *signal = 0,
+ const QObject *receiver = 0, const char *member = 0)
+ { return disconnect(this, signal, receiver, member); }
+ inline bool disconnect(const QObject *receiver, const char *member = 0)
+ { return disconnect(this, 0, receiver, member); }
+
+ void dumpObjectTree();
+ void dumpObjectInfo();
+
+#ifndef QT_NO_PROPERTIES
+ bool setProperty(const char *name, const QVariant &value);
+ QVariant property(const char *name) const;
+ QList<QByteArray> dynamicPropertyNames() const;
+#endif // QT_NO_PROPERTIES
+
+#ifndef QT_NO_USERDATA
+ static uint registerUserData();
+ void setUserData(uint id, QObjectUserData* data);
+ QObjectUserData* userData(uint id) const;
+#endif // QT_NO_USERDATA
+
+Q_SIGNALS:
+ void destroyed(QObject * = 0);
+
+public:
+ inline QObject *parent() const { return d_ptr->parent; }
+
+ inline bool inherits(const char *classname) const
+ { return const_cast<QObject *>(this)->qt_metacast(classname) != 0; }
+
+public Q_SLOTS:
+ void deleteLater();
+
+protected:
+ QObject *sender() const;
+ int senderSignalIndex() const;
+ int receivers(const char* signal) const;
+
+ virtual void timerEvent(QTimerEvent *);
+ virtual void childEvent(QChildEvent *);
+ virtual void customEvent(QEvent *);
+
+ virtual void connectNotify(const char *signal);
+ virtual void disconnectNotify(const char *signal);
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QObject(QObject *parent, const char *name);
+ inline QT3_SUPPORT void insertChild(QObject *o)
+ { if (o) o->setParent(this); }
+ inline QT3_SUPPORT void removeChild(QObject *o)
+ { if (o) o->setParent(0); }
+ inline QT3_SUPPORT bool isA(const char *classname) const
+ { return qstrcmp(classname, metaObject()->className()) == 0; }
+ inline QT3_SUPPORT const char *className() const { return metaObject()->className(); }
+ inline QT3_SUPPORT const char *name() const { return objectName().latin1_helper(); }
+ inline QT3_SUPPORT const char *name(const char *defaultName) const
+ { QString s = objectName(); return s.isEmpty()?defaultName:s.latin1_helper(); }
+ inline QT3_SUPPORT void setName(const char *aName) { setObjectName(QLatin1String(aName)); }
+protected:
+ inline QT3_SUPPORT bool checkConnectArgs(const char *signal,
+ const QObject *,
+ const char *member)
+ { return QMetaObject::checkConnectArgs(signal, member); }
+ static inline QT3_SUPPORT QByteArray normalizeSignalSlot(const char *signalSlot)
+ { return QMetaObject::normalizedSignature(signalSlot); }
+#endif
+
+protected:
+ QObject(QObjectPrivate &dd, QObject *parent = 0);
+
+protected:
+ QScopedPointer<QObjectData> d_ptr;
+
+ static const QMetaObject staticQtMetaObject;
+
+ friend struct QMetaObject;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QCoreApplication;
+ friend class QCoreApplicationPrivate;
+ friend class QWidget;
+ friend class QThreadData;
+
+private:
+ Q_DISABLE_COPY(QObject)
+ Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
+};
+
+inline bool QObject::connect(const QObject *asender, const char *asignal,
+ const char *amember, Qt::ConnectionType atype) const
+{ return connect(asender, asignal, this, amember, atype); }
+
+#ifndef QT_NO_USERDATA
+class Q_CORE_EXPORT QObjectUserData {
+public:
+ virtual ~QObjectUserData();
+};
+#endif
+
+#ifdef QT_DEPRECATED
+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())
+{
+ return o->findChildren<T>(name);
+}
+
+#ifndef QT_NO_REGEXP
+template<typename T>
+inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re)
+{
+ return o->findChildren<T>(re);
+}
+#endif
+
+#endif //QT_DEPRECATED
+
+template <class T>
+inline T qobject_cast(QObject *object)
+{
+#if !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object));
+#endif
+ return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
+}
+
+template <class T>
+inline T qobject_cast(const QObject *object)
+{
+#if !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
+#endif
+ return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
+}
+
+
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
+#ifndef Q_MOC_RUN
+# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline 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) : 0)); } \
+ template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
+ { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }
+#endif // Q_MOC_RUN
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
+#endif // QOBJECT_H
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
new file mode 100644
index 0000000000..2711a4b5f5
--- /dev/null
+++ b/src/corelib/kernel/qobject_p.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOBJECT_P_H
+#define QOBJECT_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/qobject.h"
+#include "QtCore/qpointer.h"
+#include "QtCore/qsharedpointer.h"
+#include "QtCore/qcoreevent.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qvector.h"
+#include "QtCore/qreadwritelock.h"
+#include "QtCore/qvariant.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVariant;
+class QThreadData;
+class QObjectConnectionListVector;
+namespace QtSharedPointer { struct ExternalRefCountData; }
+
+/* mirrored in QtTestLib, DON'T CHANGE without prior warning */
+struct QSignalSpyCallbackSet
+{
+ typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv);
+ typedef void (*EndCallback)(QObject *caller, int method_index);
+ BeginCallback signal_begin_callback,
+ slot_begin_callback;
+ EndCallback signal_end_callback,
+ slot_end_callback;
+};
+void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
+
+extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
+
+enum { QObjectPrivateVersion = QT_VERSION };
+
+class Q_CORE_EXPORT QAbstractDeclarativeData
+{
+public:
+ static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
+ static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
+ static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *);
+};
+
+class Q_CORE_EXPORT QObjectPrivate : public QObjectData
+{
+ Q_DECLARE_PUBLIC(QObject)
+
+public:
+ struct ExtraData
+ {
+ ExtraData() {}
+#ifndef QT_NO_USERDATA
+ QVector<QObjectUserData *> userData;
+#endif
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+ };
+
+ typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
+ struct Connection
+ {
+ QObject *sender;
+ QObject *receiver;
+ StaticMetaCallFunction callFunction;
+ // The next pointer for the singly-linked ConnectionList
+ Connection *nextConnectionList;
+ //senders linked list
+ Connection *next;
+ Connection **prev;
+ QBasicAtomicPointer<int> argumentTypes;
+ ushort method_offset;
+ ushort method_relative;
+ ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
+ ~Connection();
+ int method() const { return method_offset + method_relative; }
+ };
+ // ConnectionList is a singly-linked list
+ struct ConnectionList {
+ ConnectionList() : first(0), last(0) {}
+ Connection *first;
+ Connection *last;
+ };
+
+ struct Sender
+ {
+ QObject *sender;
+ int signal;
+ int ref;
+ };
+
+
+ QObjectPrivate(int version = QObjectPrivateVersion);
+ virtual ~QObjectPrivate();
+ void deleteChildren();
+
+ void setParent_helper(QObject *);
+ void moveToThread_helper();
+ void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
+ void _q_reregisterTimers(void *pointer);
+
+ bool isSender(const QObject *receiver, const char *signal) const;
+ QObjectList receiverList(const char *signal) const;
+ QObjectList senderList() const;
+
+ void addConnection(int signal, Connection *c);
+ void cleanConnectionLists();
+
+#ifdef QT3_SUPPORT
+ void sendPendingChildInsertedEvents();
+#endif
+
+ static inline Sender *setCurrentSender(QObject *receiver,
+ Sender *sender);
+ static inline void resetCurrentSender(QObject *receiver,
+ Sender *currentSender,
+ Sender *previousSender);
+#ifdef QT_JAMBI_BUILD
+ static int *setDeleteWatch(QObjectPrivate *d, int *newWatch);
+ static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch);
+#endif
+ static void clearGuards(QObject *);
+
+ static QObjectPrivate *get(QObject *o) {
+ return o->d_func();
+ }
+
+ int signalIndex(const char *signalName) const;
+ inline bool isSignalConnected(uint signalIdx) const;
+
+public:
+ QString objectName;
+ ExtraData *extraData; // extra data set by the user
+ QThreadData *threadData; // id of the thread that owns the object
+
+ QObjectConnectionListVector *connectionLists;
+
+ Connection *senders; // linked list of connections connected to this object
+ Sender *currentSender; // object currently activating the object
+ mutable quint32 connectedSignals[2];
+
+#ifdef QT3_SUPPORT
+ QVector< QWeakPointer<QObject> > pendingChildInsertedEvents;
+#else
+ // preserve binary compatibility with code compiled without Qt 3 support
+ // keeping the binary layout stable helps the Qt Creator debugger
+ void *unused;
+#endif
+
+ QList<QPointer<QObject> > eventFilters;
+ union {
+ QObject *currentChildBeingDeleted;
+ QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
+ };
+
+ // these objects are all used to indicate that a QObject was deleted
+ // plus QPointer, which keeps a separate list
+ QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
+#ifdef QT_JAMBI_BUILD
+ int *deleteWatch;
+#endif
+};
+
+
+/*! \internal
+
+ Returns true if the signal with index \a signal_index from object \a sender is connected.
+ Signals with indices above a certain range are always considered connected (see connectedSignals
+ in QObjectPrivate). If a signal spy is installed, all signals are considered connected.
+
+ \a signal_index must be the index returned by QObjectPrivate::signalIndex;
+*/
+inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
+{
+ return signal_index >= sizeof(connectedSignals) * 8
+ || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
+ || qt_signal_spy_callback_set.signal_begin_callback
+ || qt_signal_spy_callback_set.signal_end_callback);
+}
+
+inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
+ Sender *sender)
+{
+ Sender *previousSender = receiver->d_func()->currentSender;
+ receiver->d_func()->currentSender = sender;
+ return previousSender;
+}
+
+inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
+ Sender *currentSender,
+ Sender *previousSender)
+{
+ // ref is set to zero when this object is deleted during the metacall
+ if (currentSender->ref == 1)
+ receiver->d_func()->currentSender = previousSender;
+ // if we've recursed, we need to tell the caller about the objects deletion
+ if (previousSender)
+ previousSender->ref = currentSender->ref;
+}
+
+
+Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
+
+class QSemaphore;
+class Q_CORE_EXPORT QMetaCallEvent : public QEvent
+{
+public:
+ QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
+ int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
+ ~QMetaCallEvent();
+
+ inline int id() const { return method_offset_ + method_relative_; }
+ inline const QObject *sender() const { return sender_; }
+ inline int signalId() const { return signalId_; }
+ inline void **args() const { return args_; }
+
+ virtual void placeMetaCall(QObject *object);
+
+private:
+ const QObject *sender_;
+ int signalId_;
+ int nargs_;
+ int *types_;
+ void **args_;
+ QSemaphore *semaphore_;
+ QObjectPrivate::StaticMetaCallFunction callFunction_;
+ ushort method_offset_;
+ ushort method_relative_;
+};
+
+class QBoolBlocker
+{
+public:
+ inline 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 Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
+{
+ virtual ~QAbstractDynamicMetaObject() {}
+ virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
+ virtual int createProperty(const char *, const char *) { return -1; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QOBJECT_P_H
diff --git a/src/corelib/kernel/qobjectcleanuphandler.cpp b/src/corelib/kernel/qobjectcleanuphandler.cpp
new file mode 100644
index 0000000000..2355537a2a
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qobjectcleanuphandler.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QObjectCleanupHandler
+ \brief The QObjectCleanupHandler class watches the lifetime of multiple QObjects.
+
+ \ingroup objectmodel
+
+ A QObjectCleanupHandler is useful whenever you need to know when a
+ number of \l{QObject}s that are owned by someone else have been
+ deleted. This is important, for example, when referencing memory
+ in an application that has been allocated in a shared library.
+
+ To keep track of some \l{QObject}s, create a
+ QObjectCleanupHandler, and add() the objects you are interested
+ in. If you are no longer interested in tracking a particular
+ object, use remove() to remove it from the cleanup handler. If an
+ object being tracked by the cleanup handler gets deleted by
+ someone else it will automatically be removed from the cleanup
+ handler. You can delete all the objects in the cleanup handler
+ with clear(), or by destroying the cleanup handler. isEmpty()
+ returns true if the QObjectCleanupHandler has no objects to keep
+ track of.
+
+ \sa QPointer
+*/
+
+/*!
+ Constructs an empty QObjectCleanupHandler.
+*/
+QObjectCleanupHandler::QObjectCleanupHandler()
+{
+}
+
+/*!
+ Destroys the cleanup handler. All objects in this cleanup handler
+ will be deleted.
+
+ \sa clear()
+*/
+QObjectCleanupHandler::~QObjectCleanupHandler()
+{
+ clear();
+}
+
+/*!
+ Adds \a object to this cleanup handler and returns the pointer to
+ the object.
+
+ \sa remove()
+*/
+QObject *QObjectCleanupHandler::add(QObject* object)
+{
+ if (!object)
+ return 0;
+
+ connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ cleanupObjects.insert(0, object);
+ return object;
+}
+
+/*!
+ Removes the \a object from this cleanup handler. The object will
+ not be destroyed.
+
+ \sa add()
+*/
+void QObjectCleanupHandler::remove(QObject *object)
+{
+ int index;
+ if ((index = cleanupObjects.indexOf(object)) != -1) {
+ cleanupObjects.removeAt(index);
+ disconnect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ }
+}
+
+/*!
+ Returns true if this cleanup handler is empty or if all objects in
+ this cleanup handler have been destroyed; otherwise return false.
+
+ \sa add() remove() clear()
+*/
+bool QObjectCleanupHandler::isEmpty() const
+{
+ return cleanupObjects.isEmpty();
+}
+
+/*!
+ Deletes all objects in this cleanup handler. The cleanup handler
+ becomes empty.
+
+ \sa isEmpty()
+*/
+void QObjectCleanupHandler::clear()
+{
+ while (!cleanupObjects.isEmpty())
+ delete cleanupObjects.takeFirst();
+}
+
+void QObjectCleanupHandler::objectDestroyed(QObject *object)
+{
+ remove(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qobjectcleanuphandler.h b/src/corelib/kernel/qobjectcleanuphandler.h
new file mode 100644
index 0000000000..5004224e38
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOBJECTCLEANUPHANDLER_H
+#define QOBJECTCLEANUPHANDLER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QObjectCleanupHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ QObjectCleanupHandler();
+ ~QObjectCleanupHandler();
+
+ QObject* add(QObject* object);
+ void remove(QObject *object);
+ bool isEmpty() const;
+ void clear();
+
+private:
+ // ### move into d pointer
+ QObjectList cleanupObjects;
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOBJECTCLEANUPHANDLER_H
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
new file mode 100644
index 0000000000..4384837f63
--- /dev/null
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOBJECTDEFS_H
+#define QOBJECTDEFS_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArray;
+
+class QString;
+
+#ifndef Q_MOC_OUTPUT_REVISION
+#define Q_MOC_OUTPUT_REVISION 63
+#endif
+
+// The following macros are our "extensions" to C++
+// They are used, strictly speaking, only by the moc.
+
+#ifndef Q_MOC_RUN
+# if defined(QT_NO_KEYWORDS)
+# define QT_NO_EMIT
+# else
+# define slots
+# define signals protected
+# endif
+# define Q_SLOTS
+# define Q_SIGNALS protected
+# define Q_PRIVATE_SLOT(d, signature)
+# define Q_EMIT
+#ifndef QT_NO_EMIT
+# define emit
+#endif
+#define Q_CLASSINFO(name, value)
+#define Q_INTERFACES(x)
+#define Q_PROPERTY(text)
+#define Q_PRIVATE_PROPERTY(d, text)
+#define Q_REVISION(v)
+#define Q_OVERRIDE(text)
+#define Q_ENUMS(x)
+#define Q_FLAGS(x)
+#ifdef QT3_SUPPORT
+# define Q_SETS(x)
+#endif
+#define Q_SCRIPTABLE
+#define Q_INVOKABLE
+#define Q_SIGNAL
+#define Q_SLOT
+
+#ifndef QT_NO_TRANSLATION
+# ifndef QT_NO_TEXTCODEC
+// full set of tr functions
+// ### Qt 5: merge overloads
+# define QT_TR_FUNCTIONS \
+ static inline QString tr(const char *s, const char *c = 0) \
+ { return staticMetaObject.tr(s, c); } \
+ static inline QString trUtf8(const char *s, const char *c = 0) \
+ { return staticMetaObject.trUtf8(s, c); } \
+ static inline QString tr(const char *s, const char *c, int n) \
+ { return staticMetaObject.tr(s, c, n); } \
+ static inline QString trUtf8(const char *s, const char *c, int n) \
+ { return staticMetaObject.trUtf8(s, c, n); }
+# else
+// no QTextCodec, no utf8
+// ### Qt 5: merge overloads
+# define QT_TR_FUNCTIONS \
+ static inline QString tr(const char *s, const char *c = 0) \
+ { return staticMetaObject.tr(s, c); } \
+ static inline QString tr(const char *s, const char *c, int n) \
+ { return staticMetaObject.tr(s, c, n); }
+# endif
+#else
+// inherit the ones from QObject
+# define QT_TR_FUNCTIONS
+#endif
+
+#if defined(QT_NO_QOBJECT_CHECK)
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_CHECK
+#else
+
+/* This is a compile time check that ensures that any class cast with qobject_cast
+ actually contains a Q_OBJECT macro. Note: qobject_cast will fail if a QObject
+ subclass doesn't contain Q_OBJECT.
+
+ In qt_check_for_QOBJECT_macro, we call a dummy templated function with two
+ parameters, the first being "this" and the other the target of the qobject
+ cast. If the types are not identical, we know that a Q_OBJECT macro is missing.
+
+ If you get a compiler error here, make sure that the class you are casting
+ to contains a Q_OBJECT macro.
+*/
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_CHECK \
+ template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const \
+ { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
+
+template <typename T>
+inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
+
+template <typename T1, typename T2>
+inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
+#endif // QT_NO_QOBJECT_CHECK
+
+#ifdef Q_NO_DATA_RELOCATION
+#define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject();
+#else
+#define Q_OBJECT_GETSTATICMETAOBJECT
+#endif
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT \
+public: \
+ Q_OBJECT_CHECK \
+ static const QMetaObject staticMetaObject; \
+ Q_OBJECT_GETSTATICMETAOBJECT \
+ virtual const QMetaObject *metaObject() const; \
+ virtual void *qt_metacast(const char *); \
+ QT_TR_FUNCTIONS \
+ virtual int qt_metacall(QMetaObject::Call, int, void **); \
+private: \
+ Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
+ Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT
+/* tmake ignore Q_GADGET */
+#define Q_GADGET \
+public: \
+ static const QMetaObject staticMetaObject; \
+ Q_OBJECT_GETSTATICMETAOBJECT \
+private:
+#else // Q_MOC_RUN
+#define slots slots
+#define signals signals
+#define Q_SLOTS Q_SLOTS
+#define Q_SIGNALS Q_SIGNALS
+#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
+#define Q_INTERFACES(x) Q_INTERFACES(x)
+#define Q_PROPERTY(text) Q_PROPERTY(text)
+#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text)
+#define Q_REVISION(v) Q_REVISION(v)
+#define Q_OVERRIDE(text) Q_OVERRIDE(text)
+#define Q_ENUMS(x) Q_ENUMS(x)
+#define Q_FLAGS(x) Q_FLAGS(x)
+#ifdef QT3_SUPPORT
+# define Q_SETS(x) Q_SETS(x)
+#endif
+ /* tmake ignore Q_OBJECT */
+#define Q_OBJECT Q_OBJECT
+ /* tmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT_FAKE
+ /* tmake ignore Q_GADGET */
+#define Q_GADGET Q_GADGET
+#define Q_SCRIPTABLE Q_SCRIPTABLE
+#define Q_INVOKABLE Q_INVOKABLE
+#define Q_SIGNAL Q_SIGNAL
+#define Q_SLOT Q_SLOT
+#endif //Q_MOC_RUN
+
+// macro for onaming members
+#ifdef METHOD
+#undef METHOD
+#endif
+#ifdef SLOT
+#undef SLOT
+#endif
+#ifdef SIGNAL
+#undef SIGNAL
+#endif
+
+Q_CORE_EXPORT const char *qFlagLocation(const char *method);
+
+#define QTOSTRING_HELPER(s) #s
+#define QTOSTRING(s) QTOSTRING_HELPER(s)
+#ifndef QT_NO_DEBUG
+# define QLOCATION "\0"__FILE__":"QTOSTRING(__LINE__)
+# ifndef QT_NO_KEYWORDS
+# define METHOD(a) qFlagLocation("0"#a QLOCATION)
+# 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
+
+#ifdef QT3_SUPPORT
+#define METHOD_CODE 0 // member type codes
+#define SLOT_CODE 1
+#define SIGNAL_CODE 2
+#endif
+
+#define QMETHOD_CODE 0 // member type codes
+#define QSLOT_CODE 1
+#define QSIGNAL_CODE 2
+
+#define Q_ARG(type, data) QArgument<type >(#type, data)
+#define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
+
+class QObject;
+class QMetaMethod;
+class QMetaEnum;
+class QMetaProperty;
+class QMetaClassInfo;
+
+
+class Q_CORE_EXPORT QGenericArgument
+{
+public:
+ inline QGenericArgument(const char *aName = 0, const void *aData = 0)
+ : _data(aData), _name(aName) {}
+ inline void *data() const { return const_cast<void *>(_data); }
+ inline const char *name() const { return _name; }
+
+private:
+ const void *_data;
+ const char *_name;
+};
+
+class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument
+{
+public:
+ inline QGenericReturnArgument(const char *aName = 0, void *aData = 0)
+ : QGenericArgument(aName, aData)
+ {}
+};
+
+template <class T>
+class QArgument: public QGenericArgument
+{
+public:
+ inline QArgument(const char *aName, const T &aData)
+ : QGenericArgument(aName, static_cast<const void *>(&aData))
+ {}
+};
+template <class T>
+class QArgument<T &>: public QGenericArgument
+{
+public:
+ inline QArgument(const char *aName, T &aData)
+ : QGenericArgument(aName, static_cast<const void *>(&aData))
+ {}
+};
+
+
+template <typename T>
+class QReturnArgument: public QGenericReturnArgument
+{
+public:
+ inline QReturnArgument(const char *aName, T &aData)
+ : QGenericReturnArgument(aName, static_cast<void *>(&aData))
+ {}
+};
+
+struct Q_CORE_EXPORT QMetaObject
+{
+ const char *className() const;
+ const QMetaObject *superClass() const;
+
+ QObject *cast(QObject *obj) const;
+ const QObject *cast(const QObject *obj) const;
+
+#ifndef QT_NO_TRANSLATION
+ // ### Qt 4: Merge overloads
+ QString tr(const char *s, const char *c) const;
+ QString trUtf8(const char *s, const char *c) const;
+ QString tr(const char *s, const char *c, int n) const;
+ QString trUtf8(const char *s, const char *c, int n) const;
+#endif // QT_NO_TRANSLATION
+
+ int methodOffset() const;
+ int enumeratorOffset() const;
+ int propertyOffset() const;
+ int classInfoOffset() const;
+
+ int constructorCount() const;
+ int methodCount() const;
+ int enumeratorCount() const;
+ int propertyCount() const;
+ int classInfoCount() const;
+
+ int indexOfConstructor(const char *constructor) const;
+ int indexOfMethod(const char *method) const;
+ 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;
+
+ QMetaMethod constructor(int index) const;
+ QMetaMethod method(int index) const;
+ QMetaEnum enumerator(int index) const;
+ QMetaProperty property(int index) const;
+ QMetaClassInfo classInfo(int index) const;
+ QMetaProperty userProperty() const;
+
+ static bool checkConnectArgs(const char *signal, const char *method);
+ static QByteArray normalizedSignature(const char *method);
+ static QByteArray normalizedType(const char *type);
+
+ // internal index-based connect
+ static bool connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ int type = 0, int *types = 0);
+ // internal index-based disconnect
+ static bool disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index);
+ static bool disconnectOne(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index);
+ // internal slot-name based connect
+ static void connectSlotsByName(QObject *o);
+
+ // internal index-based signal activation
+ static void activate(QObject *sender, int signal_index, void **argv); //obsolete
+ static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); //obsolete
+ static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
+ static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); //obsolete
+
+ // internal guarded pointers
+ static void addGuard(QObject **ptr);
+ static void removeGuard(QObject **ptr);
+ static void changeGuard(QObject **ptr, QObject *o);
+
+ static bool invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument());
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
+ val4, val5, val6, val7, val8, val9);
+ }
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType type,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2,
+ val3, val4, val5, val6, val7, val8, val9);
+ }
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
+ val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+
+ QObject *newInstance(QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const;
+
+ enum Call {
+ InvokeMetaMethod,
+ ReadProperty,
+ WriteProperty,
+ ResetProperty,
+ QueryPropertyDesignable,
+ QueryPropertyScriptable,
+ QueryPropertyStored,
+ QueryPropertyEditable,
+ QueryPropertyUser,
+ CreateInstance
+ };
+
+ int static_metacall(Call, int, void **) const;
+ static int metacall(QObject *, Call, int, void **);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT const char *superClassName() const;
+#endif
+
+ struct { // private data
+ const QMetaObject *superdata;
+ const char *stringdata;
+ const uint *data;
+ const void *extradata;
+ } d;
+};
+
+typedef const QMetaObject& (*QMetaObjectAccessor)();
+
+struct QMetaObjectExtraData
+{
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *objects;
+#else
+ const QMetaObject **objects;
+#endif
+
+ typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); //from revision 6
+ //typedef int (*StaticMetaCall)(QMetaObject::Call, int, void **); //used from revison 2 until revison 5
+ StaticMetacallFunction static_metacall;
+};
+
+inline const char *QMetaObject::className() const
+{ return d.stringdata; }
+
+inline const QMetaObject *QMetaObject::superClass() const
+{ return d.superdata; }
+
+#ifdef QT3_SUPPORT
+inline const char *QMetaObject::superClassName() const
+{ return d.superdata ? d.superdata->className() : 0; }
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOBJECTDEFS_H
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp
new file mode 100644
index 0000000000..73f695b65a
--- /dev/null
+++ b/src/corelib/kernel/qpointer.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPointer
+ \brief The QPointer class is a template class that provides guarded pointers to QObject.
+
+ \ingroup objectmodel
+
+
+ A guarded pointer, QPointer<T>, behaves like a normal C++
+ pointer \c{T *}, except that it is automatically set to 0 when the
+ referenced object is destroyed (unlike normal C++ pointers, which
+ become "dangling pointers" in such cases). \c T must be a
+ subclass of QObject.
+
+ Guarded pointers are useful whenever you need to store a pointer
+ to a QObject that is owned by someone else, and therefore might be
+ destroyed while you still hold a reference to it. You can safely
+ test the pointer for validity.
+
+ Qt also provides QSharedPointer, an implementation of a reference-counted
+ shared pointer object, which can be used to maintain a collection of
+ references to an individual pointer.
+
+ Example:
+
+ \snippet doc/src/snippets/pointer/pointer.cpp 0
+ \dots
+ \snippet doc/src/snippets/pointer/pointer.cpp 1
+ \snippet doc/src/snippets/pointer/pointer.cpp 2
+
+ If the QLabel is deleted in the meantime, the \c label variable
+ will hold 0 instead of an invalid address, and the last line will
+ never be executed.
+
+ The functions and operators available with a QPointer are the
+ same as those available with a normal unguarded pointer, except
+ the pointer arithmetic operators (\c{+}, \c{-}, \c{++}, and
+ \c{--}), which are normally used only with arrays of objects.
+
+ Use QPointers like normal pointers and you will not need to read
+ this class documentation.
+
+ For creating guarded pointers, you can construct or assign to them
+ from a T* or from another guarded pointer of the same type. You
+ can compare them with each other using operator==() and
+ operator!=(), or test for 0 with isNull(). You can dereference
+ them using either the \c *x or the \c x->member notation.
+
+ A guarded pointer will automatically cast to a \c T *, so you can
+ freely mix guarded and unguarded pointers. This means that if you
+ have a QPointer<QWidget>, you can pass it to a function that
+ requires a QWidget *. For this reason, it is of little value to
+ declare functions to take a QPointer as a parameter; just use
+ normal pointers. Use a QPointer when you are storing a pointer
+ over time.
+
+ Note that class \c T must inherit QObject, or a compilation or
+ link error will result.
+
+ \sa QSharedPointer, QObject, QObjectCleanupHandler
+*/
+
+/*!
+ \fn QPointer::QPointer()
+
+ Constructs a 0 guarded pointer.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPointer::QPointer(T* p)
+
+ Constructs a guarded pointer that points to same object that \a p
+ points to.
+*/
+
+/*!
+ \fn QPointer::QPointer(const QPointer<T> &p)
+
+ Copies one guarded pointer from another. The constructed guarded
+ pointer points to the same object that \a p points to (which may
+ be 0).
+*/
+
+/*!
+ \fn QPointer::~QPointer()
+
+ Destroys the guarded pointer. Just like a normal pointer,
+ destroying a guarded pointer does \e not destroy the object being
+ pointed to.
+*/
+
+/*!
+ \fn QPointer<T>& QPointer::operator=(const QPointer<T> &p)
+
+ Assignment operator. This guarded pointer will now point to the
+ same object that \a p points to.
+*/
+
+/*!
+ \fn QPointer<T> & QPointer::operator=(T* p)
+
+ Assignment operator. This guarded pointer will now point to the
+ same object that \a p points to.
+*/
+
+/*!
+ \fn T* QPointer::data() const
+ \since 4.4
+
+ Returns the pointer to the object being guarded.
+*/
+
+/*!
+ \fn bool QPointer::isNull() const
+
+ Returns \c true if the referenced object has been destroyed or if
+ there is no referenced object; otherwise returns false.
+*/
+
+/*!
+ \fn T* QPointer::operator->() const
+
+ Overloaded arrow operator; implements pointer semantics. Just use
+ this operator as you would with a normal C++ pointer.
+*/
+
+/*!
+ \fn T& QPointer::operator*() const
+
+ Dereference operator; implements pointer semantics. Just use this
+ operator as you would with a normal C++ pointer.
+*/
+
+/*!
+ \fn QPointer::operator T*() const
+
+ Cast operator; implements pointer semantics. Because of this
+ function you can pass a QPointer\<T\> to a function where a T*
+ is required.
+*/
+
+/*!
+ \fn bool operator==(const T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p, const T *o)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p, T *o)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
+
+ Equality operator. Returns true if the guarded pointers \a p1 and \a p2
+ are pointing to the same object, otherwise
+ returns false.
+
+*/
+
+
+/*!
+ \fn bool operator!=(const T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p, const T *o)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p, T *o)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
+
+ Inequality operator. Returns true if the guarded pointers \a p1 and
+ \a p2 are not pointing to the same object, otherwise
+ returns false.
+*/
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h
new file mode 100644
index 0000000000..c2621cb8bd
--- /dev/null
+++ b/src/corelib/kernel/qpointer.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPOINTER_H
+#define QPOINTER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T>
+class QPointer
+{
+ QObject *o;
+public:
+ inline QPointer() : o(0) {}
+ inline QPointer(T *p) : o(p)
+ { QMetaObject::addGuard(&o); }
+ inline QPointer(const QPointer<T> &p) : o(p.o)
+ { QMetaObject::addGuard(&o); }
+ inline ~QPointer()
+ { QMetaObject::removeGuard(&o); }
+ inline QPointer<T> &operator=(const QPointer<T> &p)
+ { if (this != &p) QMetaObject::changeGuard(&o, p.o); return *this; }
+ inline QPointer<T> &operator=(T* p)
+ { if (o != p) QMetaObject::changeGuard(&o, p); return *this; }
+
+ inline bool isNull() const
+ { return !o; }
+
+ inline T* operator->() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T& operator*() const
+ { return *static_cast<T*>(const_cast<QObject*>(o)); }
+ inline operator T*() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T* data() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+};
+
+
+#if (!defined(Q_CC_SUN) || (__SUNPRO_CC >= 0x580)) // ambiguity between const T * and T *
+
+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; }
+
+#else
+
+template<class T>
+inline bool operator==(const void *o, const QPointer<T> &p)
+{ return o == p.operator->(); }
+
+template<class T>
+inline bool operator==(const QPointer<T> &p, const void *o)
+{ return p.operator->() == o; }
+
+#endif
+
+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->(); }
+
+
+#if (!defined(Q_CC_SUN) || (__SUNPRO_CC >= 0x580)) // ambiguity between const T * and T *
+
+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; }
+
+#else
+
+template<class T>
+inline bool operator!= (const void *o, const QPointer<T> &p)
+{ return o != p.operator->(); }
+
+template<class T>
+inline bool operator!= (const QPointer<T> &p, const void *o)
+{ return p.operator->() != o; }
+
+#endif
+
+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->() ; }
+
+// Make MSVC < 1400 (2005) handle "if (NULL == p)" syntax
+#if defined(Q_CC_MSVC) && (_MSC_VER < 1400)
+template<class T>
+inline bool operator== (int i, const QPointer<T> &p)
+{ Q_ASSERT(i == 0); return !i && p.isNull(); }
+
+template<class T>
+inline bool operator!= (int i, const QPointer<T> &p)
+{ Q_ASSERT(i == 0); return !i && !p.isNull(); }
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPOINTER_H
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
new file mode 100644
index 0000000000..78715a1966
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qcryptographichash.h>
+#ifdef Q_OS_SYMBIAN
+#include <e32const.h>
+#endif
+#include <qdebug.h>
+
+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
+ On Symbian key will be truncated to 80 characters
+ */
+QString
+QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
+ const QString &prefix)
+{
+ if (key.isEmpty())
+ return QString();
+
+ QString result = prefix;
+
+ QString part1 = key;
+ part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString());
+ result.append(part1);
+
+ QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
+ result.append(QLatin1String(hex));
+#ifdef Q_OS_WIN
+ return result;
+#elif defined(Q_OS_SYMBIAN)
+ return result.left(KMaxKernelName);
+#else
+ return QDir::tempPath() + QLatin1Char('/') + result;
+#endif
+}
+#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY
+
+#ifndef QT_NO_SHAREDMEMORY
+
+/*!
+ \class QSharedMemory
+ \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
+
+ \o 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.
+
+ \o 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.
+
+ \o 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.
+
+ \o Symbian: 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 Symbian kernel
+ releases the shared memory segment automatically.
+ Also, access to a shared memory segment cannot be limited to read-only
+ in Symbian.
+
+ \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.
+
+ Unlike QtSharedMemory, 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. Do not mix using QtSharedMemory and QSharedMemory. Port
+ everything to QSharedMemory.
+
+ \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 (e.g. unable to lock()) and a user-defined mechanism
+ should be used to achieve a 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()
+ */
+QSharedMemory::QSharedMemory(QObject *parent)
+ : QObject(*new QSharedMemoryPrivate, parent)
+{
+}
+
+/*!
+ 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()
+ */
+QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
+ : QObject(*new QSharedMemoryPrivate, parent)
+{
+ setKey(key);
+}
+
+/*!
+ 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.
+
+ \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 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 true if this process is attached to the shared memory
+ segment.
+
+ \sa attach(), detach()
+ */
+bool QSharedMemory::isAttached() const
+{
+ Q_D(const QSharedMemory);
+ return (0 != 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 true if it detaches the shared
+ memory segment. If it returns 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 true. If another process has locked the
+ segment, this function blocks until the lock is released. Then it
+ acquires the lock and returns true. If this function returns 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 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
diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h
new file mode 100644
index 0000000000..4a610033a1
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHAREDMEMORY_H
+#define QSHAREDMEMORY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SHAREDMEMORY
+
+class QSharedMemoryPrivate;
+
+class Q_CORE_EXPORT QSharedMemory : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSharedMemory)
+
+public:
+ enum AccessMode
+ {
+ ReadOnly,
+ ReadWrite
+ };
+
+ enum SharedMemoryError
+ {
+ NoError,
+ PermissionDenied,
+ InvalidSize,
+ KeyError,
+ AlreadyExists,
+ NotFound,
+ LockError,
+ OutOfResources,
+ UnknownError
+ };
+
+ QSharedMemory(QObject *parent = 0);
+ QSharedMemory(const QString &key, QObject *parent = 0);
+ ~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)
+};
+
+#endif // QT_NO_SHAREDMEMORY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSHAREDMEMORY_H
+
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
new file mode 100644
index 0000000000..72eda372ae
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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"
+
+#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"
+#include "private/qobject_p.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#elif defined(Q_OS_SYMBIAN)
+#include <e32std.h>
+#include <sys/types.h>
+#else
+#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 = 0;
+ return false;
+ }
+
+private:
+ QSharedMemory *q_sm;
+};
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSharedMemory)
+
+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
+ HANDLE handle();
+#else
+ key_t handle();
+#endif
+ bool initKey();
+ bool cleanHandle();
+ bool create(int size);
+ bool attach(QSharedMemory::AccessMode mode);
+ bool detach();
+
+#ifdef Q_OS_SYMBIAN
+ void setErrorString(const QString &function, TInt errorCode);
+#else
+ void setErrorString(const QString &function);
+#endif
+
+#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
+ HANDLE hand;
+#elif defined(Q_OS_SYMBIAN)
+ RChunk chunk;
+#else
+ key_t unix_key;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
+
+#endif // QSHAREDMEMORY_P_H
+
diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp
new file mode 100644
index 0000000000..3565e264db
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_symbian.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include "qcore_symbian_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+#define QSHAREDMEMORY_DEBUG
+
+QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+ memory(0), size(0), error(QSharedMemory::NoError),
+ systemSemaphore(QString()), lockedByMe(false)
+{
+}
+
+void QSharedMemoryPrivate::setErrorString(const QString &function, TInt errorCode)
+{
+ if (errorCode == KErrNone)
+ return;
+ switch (errorCode) {
+ case KErrAlreadyExists:
+ error = QSharedMemory::AlreadyExists;
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ break;
+ case KErrNotFound:
+ error = QSharedMemory::NotFound;
+ errorString = QSharedMemory::tr("%1: doesn't exists").arg(function);
+ break;
+ case KErrArgument:
+ error = QSharedMemory::InvalidSize;
+ errorString = QSharedMemory::tr("%1: invalid size").arg(function);
+ break;
+ case KErrNoMemory:
+ error = QSharedMemory::OutOfResources;
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ break;
+ case KErrPermissionDenied:
+ error = QSharedMemory::PermissionDenied;
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errorCode);
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+key_t QSharedMemoryPrivate::handle()
+{
+ // Not really cost effective to check here if shared memory is attachable, as it requires
+ // exactly the same call as attaching, so always assume handle is valid and return failure
+ // from attach.
+ return 1;
+}
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ chunk.Close();
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ QString function = QLatin1String("QSharedMemory::create");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: key error").arg(function);
+ return false;
+ }
+
+ TPtrC ptr(qt_QString2TPtrC(nativeKey));
+
+ TInt err = chunk.CreateGlobal(ptr, size, size);
+
+ setErrorString(function, err);
+
+ if (err != KErrNone)
+ return false;
+
+ // Zero out the created chunk
+ Mem::FillZ(chunk.Base(), chunk.Size());
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */)
+{
+ // Grab a pointer to the memory block
+ if (!chunk.Handle()) {
+ QString function = QLatin1String("QSharedMemory::handle");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ return false;
+ }
+
+ TPtrC ptr(qt_QString2TPtrC(nativeKey));
+
+ TInt err = KErrNoMemory;
+
+ err = chunk.OpenGlobal(ptr, false);
+
+ if (err != KErrNone) {
+ setErrorString(function, err);
+ return false;
+ }
+ }
+
+ size = chunk.Size();
+ memory = chunk.Base();
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ chunk.Close();
+
+ memory = 0;
+ size = 0;
+
+ return true;
+}
+
+#endif //QT_NO_SHAREDMEMORY
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
new file mode 100644
index 0000000000..b30117f6c1
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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_NO_SHAREDMEMORY
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.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
+
+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(const QString &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
+ }
+}
+
+/*!
+ \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 true if the unix file was created.
+
+ -1 error
+ 0 already existed
+ 1 created
+ */
+int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
+{
+ if (QFile::exists(fileName))
+ return 0;
+
+ 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, 0666 | IPC_CREAT | IPC_EXCL)) {
+ QString function = QLatin1String("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 ? 0444 : 0660));
+ if (-1 == id) {
+ setErrorString(QLatin1String("QSharedMemory::attach (shmget)"));
+ return false;
+ }
+
+ // grab the memory
+ memory = shmat(id, 0, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
+ if ((void*) - 1 == memory) {
+ memory = 0;
+ 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)) {
+ QString function = QLatin1String("QSharedMemory::detach");
+ switch (errno) {
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: not attached").arg(function);
+ error = QSharedMemory::NotFound;
+ break;
+ default:
+ setErrorString(function);
+ }
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+ // Get the number of current attachments
+ int id = shmget(unix_key, 0, 0444);
+ 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
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
new file mode 100644
index 0000000000..bc13e338bd
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+ memory(0), size(0), error(QSharedMemory::NoError),
+ systemSemaphore(QString()), lockedByMe(false), hand(0)
+{
+}
+
+void QSharedMemoryPrivate::setErrorString(const QString &function)
+{
+ BOOL 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:
+#ifdef Q_OS_WINCE
+ // This happens on CE only if no file is present as CreateFileMappingW
+ // bails out with this error code
+ case ERROR_INVALID_PARAMETER:
+#endif
+ 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) {
+ QString function = QLatin1String("QSharedMemory::handle");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ return false;
+ }
+#ifndef Q_OS_WINCE
+ hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16());
+#else
+ // This works for opening a mapping too, but always opens it with read/write access in
+ // attach as it seems.
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16());
+#endif
+ if (!hand) {
+ setErrorString(function);
+ return false;
+ }
+ }
+ 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)
+{
+ QString function = QLatin1String("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, (wchar_t*)nativeKey.utf16());
+ setErrorString(function);
+
+ // hand is valid when it already exists unlike unix so explicitly check
+ if (error == QSharedMemory::AlreadyExists || !hand)
+ return false;
+
+ return true;
+}
+
+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
new file mode 100644
index 0000000000..017aa72376
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsignalmapper.h"
+#ifndef QT_NO_SIGNALMAPPER
+#include "qhash.h"
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSignalMapperPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSignalMapper)
+public:
+ void _q_senderDestroyed() {
+ Q_Q(QSignalMapper);
+ q->removeMappings(q->sender());
+ }
+ QHash<QObject *, int> intHash;
+ QHash<QObject *, QString> stringHash;
+ QHash<QObject *, QWidget*> widgetHash;
+ QHash<QObject *, QObject*> objectHash;
+
+};
+
+
+/*!
+ \class QSignalMapper
+ \brief The QSignalMapper class bundles signals from identifiable senders.
+
+ \ingroup objectmodel
+
+
+ This class collects a set of parameterless signals, and re-emits
+ them with integer, string or widget parameters corresponding to
+ the object that sent the signal.
+
+ The class supports the mapping of particular strings or integers
+ with particular objects using setMapping(). The objects' signals
+ can then be connected to the map() slot which will emit the
+ mapped() signal with the string or integer associated with the
+ original signalling object. Mappings can be removed later using
+ removeMappings().
+
+ Example: Suppose we want to create a custom widget that contains
+ a group of buttons (like a tool palette). One approach is to
+ connect each button's \c clicked() signal to its own custom slot;
+ but in this example we want to connect all the buttons to a
+ single slot and parameterize the slot by the button that was
+ clicked.
+
+ Here's the definition of a simple custom widget that has a single
+ signal, \c clicked(), which is emitted with the text of the button
+ that was clicked:
+
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 0
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 1
+
+ The only function that we need to implement is the constructor:
+
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 0
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 1
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 2
+
+ A list of texts is passed to the constructor. A signal mapper is
+ constructed and for each text in the list a QPushButton is
+ created. We connect each button's \c clicked() signal to the
+ signal mapper's map() slot, and create a mapping in the signal
+ mapper from each button to the button's text. Finally we connect
+ the signal mapper's mapped() signal to the custom widget's \c
+ clicked() signal. When the user clicks a button, the custom
+ widget will emit a single \c clicked() signal whose argument is
+ the text of the button the user clicked.
+
+ \sa QObject, QButtonGroup, QActionGroup
+*/
+
+/*!
+ Constructs a QSignalMapper with parent \a parent.
+*/
+QSignalMapper::QSignalMapper(QObject* parent)
+ : QObject(*new QSignalMapperPrivate, parent)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QSignalMapper()
+ \obsolete
+ */
+QSignalMapper::QSignalMapper(QObject *parent, const char *name)
+ : QObject(*new QSignalMapperPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the QSignalMapper.
+*/
+QSignalMapper::~QSignalMapper()
+{
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the given \a
+ sender, the signal mapped(\a id) is emitted.
+
+ There may be at most one integer ID for each sender.
+
+ \sa mapping()
+*/
+void QSignalMapper::setMapping(QObject *sender, int id)
+{
+ Q_D(QSignalMapper);
+ d->intHash.insert(sender, id);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a text ) is emitted.
+
+ There may be at most one text for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, const QString &text)
+{
+ Q_D(QSignalMapper);
+ d->stringHash.insert(sender, text);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a widget ) is emitted.
+
+ There may be at most one widget for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, QWidget *widget)
+{
+ Q_D(QSignalMapper);
+ d->widgetHash.insert(sender, widget);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a object ) is emitted.
+
+ There may be at most one object for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, QObject *object)
+{
+ Q_D(QSignalMapper);
+ d->objectHash.insert(sender, object);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Returns the sender QObject that is associated with the \a id.
+
+ \sa setMapping()
+*/
+QObject *QSignalMapper::mapping(int id) const
+{
+ Q_D(const QSignalMapper);
+ return d->intHash.key(id);
+}
+
+/*!
+ \overload mapping()
+*/
+QObject *QSignalMapper::mapping(const QString &id) const
+{
+ Q_D(const QSignalMapper);
+ return d->stringHash.key(id);
+}
+
+/*!
+ \overload mapping()
+
+ Returns the sender QObject that is associated with the \a widget.
+*/
+QObject *QSignalMapper::mapping(QWidget *widget) const
+{
+ Q_D(const QSignalMapper);
+ return d->widgetHash.key(widget);
+}
+
+/*!
+ \overload mapping()
+
+ Returns the sender QObject that is associated with the \a object.
+*/
+QObject *QSignalMapper::mapping(QObject *object) const
+{
+ Q_D(const QSignalMapper);
+ return d->objectHash.key(object);
+}
+
+/*!
+ Removes all mappings for \a sender.
+
+ This is done automatically when mapped objects are destroyed.
+*/
+void QSignalMapper::removeMappings(QObject *sender)
+{
+ Q_D(QSignalMapper);
+
+ d->intHash.remove(sender);
+ d->stringHash.remove(sender);
+ d->widgetHash.remove(sender);
+ d->objectHash.remove(sender);
+}
+
+/*!
+ This slot emits signals based on which object sends signals to it.
+*/
+void QSignalMapper::map() { map(sender()); }
+
+/*!
+ This slot emits signals based on the \a sender object.
+*/
+void QSignalMapper::map(QObject *sender)
+{
+ Q_D(QSignalMapper);
+ if (d->intHash.contains(sender))
+ emit mapped(d->intHash.value(sender));
+ if (d->stringHash.contains(sender))
+ emit mapped(d->stringHash.value(sender));
+ if (d->widgetHash.contains(sender))
+ emit mapped(d->widgetHash.value(sender));
+ if (d->objectHash.contains(sender))
+ emit mapped(d->objectHash.value(sender));
+}
+
+
+/*!
+ \fn void QSignalMapper::mapped(int i)
+
+ This signal is emitted when map() is signalled from an object that
+ has an integer mapping set. The object's mapped integer is passed
+ in \a i.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(const QString &text)
+
+ This signal is emitted when map() is signalled from an object that
+ has a string mapping set. The object's mapped string is passed in
+ \a text.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(QWidget *widget)
+
+ This signal is emitted when map() is signalled from an object that
+ has a widget mapping set. The object's mapped widget is passed in
+ \a widget.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(QObject *object)
+
+ This signal is emitted when map() is signalled from an object that
+ has an object mapping set. The object provided by the map is passed in
+ \a object.
+
+ \sa setMapping()
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qsignalmapper.cpp"
+
+#endif // QT_NO_SIGNALMAPPER
+
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
new file mode 100644
index 0000000000..ddf5c34e47
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALMAPPER_H
+#define QSIGNALMAPPER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SIGNALMAPPER
+class QSignalMapperPrivate;
+
+class Q_CORE_EXPORT QSignalMapper : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSignalMapper)
+public:
+ explicit QSignalMapper(QObject *parent = 0);
+ ~QSignalMapper();
+
+ void setMapping(QObject *sender, int id);
+ void setMapping(QObject *sender, const QString &text);
+ void setMapping(QObject *sender, QWidget *widget);
+ void setMapping(QObject *sender, QObject *object);
+ void removeMappings(QObject *sender);
+
+ QObject *mapping(int id) const;
+ QObject *mapping(const QString &text) const;
+ QObject *mapping(QWidget *widget) const;
+ QObject *mapping(QObject *object) const;
+
+Q_SIGNALS:
+ void mapped(int);
+ void mapped(const QString &);
+ void mapped(QWidget *);
+ void mapped(QObject *);
+
+public Q_SLOTS:
+ void map();
+ void map(QObject *sender);
+
+private:
+ Q_DISABLE_COPY(QSignalMapper)
+ Q_PRIVATE_SLOT(d_func(), void _q_senderDestroyed())
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QSignalMapper(QObject *parent, const char *name);
+#endif
+};
+#endif // QT_NO_SIGNALMAPPER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIGNALMAPPER_H
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
new file mode 100644
index 0000000000..360bc372f0
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsocketnotifier.h"
+
+#include "qplatformdefs.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+
+#include "qobject_p.h"
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSocketNotifier
+ \brief The QSocketNotifier class provides support for monitoring
+ activity on a file descriptor.
+
+ \ingroup network
+ \ingroup io
+
+ The QSocketNotifier makes it possible to integrate Qt's event
+ loop with other event loops based on file descriptors. For
+ example, the \l{CORBA Framework} uses it to process CORBA
+ events. File descriptor action is detected in Qt's main event
+ loop (QCoreApplication::exec()).
+
+ \target write notifiers
+
+ 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.
+
+ There are three types of socket notifiers: read, write, and
+ exception. The type is described by the \l Type enum, and must be
+ specified when constructing the socket notifier. After
+ construction it can be determined using the type() function. Note
+ that if you need to monitor both reads and writes for the same
+ file descriptor, you must create two socket notifiers. Note also
+ that it is not possible to install two socket notifiers of the
+ same type (\l Read, \l Write, \l Exception) on the same socket.
+
+ The setEnabled() function allows you to disable as well as enable
+ the socket notifier. It is generally advisable to explicitly
+ enable or disable the socket notifier, especially for write
+ notifiers. A disabled notifier ignores socket events (the same
+ effect as not creating the socket notifier). Use the isEnabled()
+ function to determine the notifier's current status.
+
+ Finally, you can use the socket() function to retrieve the
+ socket identifier. Although the class is called QSocketNotifier,
+ it is normally used for other types of devices than sockets.
+ QTcpSocket and QUdpSocket provide notification through signals, so
+ there is normally no need to use a QSocketNotifier on them.
+
+ \section1 Notes for Windows Users
+
+ The socket passed to QSocketNotifier will become non-blocking, even if
+ it was created as a blocking socket.
+ The activated() signal is sometimes triggered by high general activity
+ on the host, even if there is nothing to read. A subsequent read from
+ the socket can then fail, the error indicating that there is no data
+ available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
+ limitation, and not a bug in QSocketNotifier.
+
+ To ensure that the socket notifier handles read notifications correctly,
+ follow these steps when you receive a notification:
+
+ \list 1
+ \o Disable the notifier.
+ \o Read data from the socket.
+ \o Re-enable the notifier if you are interested in more data (such as after
+ having written a new command to a remote server).
+ \endlist
+
+ To ensure that the socket notifier handles write notifications correctly,
+ follow these steps when you receive a notification:
+
+ \list 1
+ \o Disable the notifier.
+ \o Write as much data as you can (before \c EWOULDBLOCK is returned).
+ \o Re-enable notifier if you have more data to write.
+ \endlist
+
+ \bold{Further information:}
+ On Windows, Qt always disables the notifier after getting a notification,
+ and only re-enables it if more data is expected. For example, if data is
+ read from the socket and it can be used to read more, or if reading or
+ writing is not possible because the socket would block, in which case
+ it is necessary to wait before attempting to read or write again.
+
+ \sa QFile, QProcess, QTcpSocket, QUdpSocket
+*/
+
+/*!
+ \enum QSocketNotifier::Type
+
+ This enum describes the various types of events that a socket
+ notifier can recognize. The type must be specified when
+ constructing the socket notifier.
+
+ Note that if you need to monitor both reads and writes for the
+ same file descriptor, you must create two socket notifiers. Note
+ also that it is not possible to install two socket notifiers of
+ the same type (Read, Write, Exception) on the same socket.
+
+ \value Read There is data to be read.
+ \value Write Data can be written.
+ \value Exception An exception has occurred. We recommend against using this.
+
+ \sa QSocketNotifier(), type()
+*/
+
+/*!
+ Constructs a socket notifier with the given \a parent. It enables
+ the \a socket, and watches for events of the given \a type.
+
+ It is generally advisable to explicitly enable or disable the
+ socket notifier, especially for write notifiers.
+
+ \bold{Note for Windows users:} The socket passed to QSocketNotifier
+ will become non-blocking, even if it was created as a blocking socket.
+
+ \sa setEnabled(), isEnabled()
+*/
+
+QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent)
+ : QObject(parent)
+{
+ if (socket < 0)
+ qWarning("QSocketNotifier: Invalid socket specified");
+ sockfd = socket;
+ sntype = type;
+ snenabled = true;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QSocketNotifier: Can only be used with threads started with QThread");
+ } else {
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+
+ Use the QSocketNotifier() constructor combined with the
+ QObject::setObjectName() function instead.
+
+ \oldcode
+ QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent, name);
+ \newcode
+ QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent);
+ notifier->setObjectName(name);
+ \endcode
+*/
+
+QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent,
+ const char *name)
+ : QObject(parent)
+{
+ setObjectName(QString::fromAscii(name));
+ if (socket < 0)
+ qWarning("QSocketNotifier: Invalid socket specified");
+ sockfd = socket;
+ sntype = type;
+ snenabled = true;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QSocketNotifier: Can only be used with threads started with QThread");
+ } else {
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ }
+}
+#endif
+/*!
+ Destroys this socket notifier.
+*/
+
+QSocketNotifier::~QSocketNotifier()
+{
+ setEnabled(false);
+}
+
+
+/*!
+ \fn void QSocketNotifier::activated(int socket)
+
+ This signal is emitted whenever the socket notifier is enabled and
+ a socket event corresponding to its \l {Type}{type} occurs.
+
+ The socket identifier is passed in the \a socket parameter.
+
+ \sa type(), socket()
+*/
+
+
+/*!
+ \fn int QSocketNotifier::socket() const
+
+ Returns the socket identifier specified to the constructor.
+
+ \sa type()
+*/
+
+/*!
+ \fn Type QSocketNotifier::type() const
+
+ Returns the socket event type specified to the constructor.
+
+ \sa socket()
+*/
+
+
+/*!
+ \fn bool QSocketNotifier::isEnabled() const
+
+ Returns true if the notifier is enabled; otherwise returns false.
+
+ \sa setEnabled()
+*/
+
+/*!
+ 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).
+
+ Write notifiers should normally be disabled immediately after the
+ activated() signal has been emitted
+
+ \sa isEnabled(), activated()
+*/
+
+void QSocketNotifier::setEnabled(bool enable)
+{
+ if (sockfd < 0)
+ return;
+ if (snenabled == enable) // no change
+ return;
+ snenabled = enable;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down
+ return;
+ if (snenabled)
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ else
+ d->threadData->eventDispatcher->unregisterSocketNotifier(this);
+}
+
+
+/*!\reimp
+*/
+bool QSocketNotifier::event(QEvent *e)
+{
+ // Emits the activated() signal when a QEvent::SockAct is
+ // received.
+ if (e->type() == QEvent::ThreadChange) {
+ if (snenabled) {
+ QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
+ Q_ARG(bool, snenabled));
+ setEnabled(false);
+ }
+ }
+ QObject::event(e); // will activate filters
+ if (e->type() == QEvent::SockAct) {
+ emit activated(sockfd);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h
new file mode 100644
index 0000000000..13a5160e3c
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOCKETNOTIFIER_H
+#define QSOCKETNOTIFIER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QSocketNotifier : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ enum Type { Read, Write, Exception };
+
+ QSocketNotifier(int socket, Type, QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QSocketNotifier(int socket, Type, QObject *parent, const char *name);
+#endif
+ ~QSocketNotifier();
+
+ inline int socket() const { return sockfd; }
+ inline Type type() const { return sntype; }
+
+ inline bool isEnabled() const { return snenabled; }
+
+public Q_SLOTS:
+ void setEnabled(bool);
+
+Q_SIGNALS:
+ void activated(int socket);
+
+protected:
+ bool event(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QSocketNotifier)
+
+ int sockfd;
+ Type sntype;
+ bool snenabled;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOCKETNOTIFIER_H
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
new file mode 100644
index 0000000000..18622c7a08
--- /dev/null
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#include "qsystemerror_p.h"
+#if !defined(Q_OS_WINCE)
+# include <errno.h>
+# if defined(Q_CC_MSVC)
+# include <crtdbg.h>
+# endif
+#endif
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
+ defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
+namespace {
+ // There are two incompatible versions of strerror_r:
+ // a) the XSI/POSIX.1 version, which returns an int,
+ // indicating success or not
+ // b) the GNU version, which returns a char*, which may or may not
+ // be the beginning of the buffer we used
+ // The GNU libc manpage for strerror_r says you should use the the XSI
+ // 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 QString fromstrerror_helper(int, const QByteArray &buf)
+ {
+ return QString::fromLocal8Bit(buf);
+ }
+ static inline QString fromstrerror_helper(const char *str, const QByteArray &)
+ {
+ return QString::fromLocal8Bit(str);
+ }
+}
+#endif
+
+static QString standardLibraryErrorString(int errorCode)
+{
+ const char *s = 0;
+ QString ret;
+ switch (errorCode) {
+ case 0:
+ break;
+ case EACCES:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
+ break;
+ case EMFILE:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
+ break;
+ case ENOENT:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
+ break;
+ case ENOSPC:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
+ break;
+ default: {
+ #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
+ QByteArray buf(1024, '\0');
+ ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
+ #else
+ ret = QString::fromLocal8Bit(strerror(errorCode));
+ #endif
+ break; }
+ }
+ if (s) {
+ // ######## this breaks moc build currently
+ // ret = QCoreApplication::translate("QIODevice", s);
+ ret = QString::fromLatin1(s);
+ }
+ return ret.trimmed();
+}
+
+#ifdef Q_OS_WIN
+static QString windowsErrorString(int errorCode)
+{
+ QString ret;
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string,
+ 0,
+ NULL);
+ ret = QString::fromWCharArray(string);
+ LocalFree((HLOCAL)string);
+
+ if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
+ ret = QString::fromLatin1("The specified module could not be found.");
+ return ret;
+}
+#endif
+
+#ifdef Q_OS_SYMBIAN
+static QString symbianErrorString(int errorCode)
+{
+ switch (errorCode) {
+ case KErrNotFound:
+ return QLatin1String("not found");
+ case KErrCancel:
+ return QLatin1String("cancelled");
+ case KErrNoMemory:
+ return QLatin1String("out of memory");
+ case KErrNotSupported:
+ return QLatin1String("not supported");
+ case KErrBadHandle:
+ return QLatin1String("bad handle"); //KERN-EXEC 0 panic is more likely
+ case KErrAlreadyExists:
+ return QLatin1String("already exists");
+ case KErrPathNotFound:
+ return QLatin1String("path not found");
+ case KErrInUse:
+ return QLatin1String("in use");
+ case KErrNotReady:
+ return QLatin1String("not ready (e.g. FS dismounted, network down)");
+ case KErrCorrupt:
+ return QLatin1String("corrupt");
+ case KErrAccessDenied:
+ return QLatin1String("access denied");
+ case KErrLocked:
+ return QLatin1String("locked");
+ case KErrWrite:
+ return QLatin1String("incomplete write error");
+ case KErrDisMounted:
+ return QLatin1String("file system dismounted during operation"); //i.e. a forcible dismount was done while we had files open
+ case KErrEof:
+ return QLatin1String("end of file");
+ case KErrDiskFull:
+ return QLatin1String("no space in file system");
+ case KErrBadName:
+ return QLatin1String("invalid filename");
+ case KErrTimedOut:
+ return QLatin1String("timed out");
+ case KErrBadDescriptor:
+ return QLatin1String("bad descriptor (passed address on stack to async call?)");
+ case KErrAbort:
+ return QLatin1String("aborted");
+ case KErrTooBig:
+ return QLatin1String("too big"); //e.g. trying to open a >2GB file with 32 bit API
+ case KErrBadPower:
+ return QLatin1String("insufficient power");
+ case KErrDirFull:
+ return QLatin1String("no space in directory table");
+ case KErrHardwareNotAvailable:
+ return QLatin1String("hardware not available");
+ case KErrSessionClosed:
+ return QLatin1String("session closed");
+ case KErrPermissionDenied:
+ return QLatin1String("permission denied");
+ default:
+ return QString(QLatin1String("symbian error %1")).arg(errorCode);
+ }
+}
+#endif
+
+QString QSystemError::toString()
+{
+ switch(errorScope) {
+ case NativeError:
+#if defined (Q_OS_WIN)
+ return windowsErrorString(errorCode);
+#elif defined (Q_OS_SYMBIAN)
+ return symbianErrorString(errorCode);
+#else
+ //unix: fall through as native and standard library are the same
+#endif
+ case StandardLibraryError:
+ return standardLibraryErrorString(errorCode);
+ default:
+ qWarning("invalid error scope");
+ //fall through
+ case NoError:
+ return QLatin1String("No error");
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h
new file mode 100644
index 0000000000..e96e85a7ad
--- /dev/null
+++ b/src/corelib/kernel/qsystemerror_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSYSTEMERROR_P_H
+#define QSYSTEMERROR_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 <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QSystemError
+{
+public:
+ enum ErrorScope
+ {
+ NoError,
+ StandardLibraryError,
+ NativeError
+ };
+
+ inline QSystemError(int error, ErrorScope scope);
+ inline QSystemError();
+
+ QString toString();
+ inline ErrorScope scope();
+ inline int error();
+
+ //data members
+ int errorCode;
+ ErrorScope errorScope;
+};
+
+QSystemError::QSystemError(int error, QSystemError::ErrorScope scope)
+: errorCode(error), errorScope(scope)
+{
+
+}
+
+QSystemError::QSystemError()
+: errorCode(0), errorScope(NoError)
+{
+
+}
+
+QSystemError::ErrorScope QSystemError::scope()
+{
+ return errorScope;
+}
+
+int QSystemError::error()
+{
+ return errorCode;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QSYSTEMERROR_P_H
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
new file mode 100644
index 0000000000..80dccc2184
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+/*!
+ \class QSystemSemaphore
+ \since 4.4
+
+ \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.
+
+ Like its lighter counterpart QSemaphore, 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
+ if your application doesn't need to access your semaphores across
+ multiple processes, you will probably want to use QSemaphore.
+
+ Semaphores support two fundamental operations, acquire() and release():
+
+ acquire() tries to acquire one resource. If there isn't a resource
+ available, the call blocks until a resource becomes available. Then
+ the resource is acquired and the call returns.
+
+ release() releases one resource so it can be acquired by another
+ 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.
+
+ Example: Create a system semaphore
+ \snippet doc/src/snippets/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:
+
+ \bold{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.
+
+ \bold{Unix:}
+
+ \list
+ \o 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.
+
+ \o 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.
+
+ \o Symbian: QSystemSemaphore behaves the same as Windows semaphores.
+ In other words, the operating system owns the semaphore and ignores
+ QSystemSemaphore::AccessMode.
+
+ \endlist
+
+ \sa QSharedMemory, QSemaphore
+ */
+
+/*!
+ 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.
+
+ In Unix, if the \a mode is \l {QSystemSemaphore::} {Open} and the
+ system already has a semaphore identified by \a key, that semaphore
+ is used, and the semaphore's resource count is not changed, i.e., \a
+ initialValue is ignored. But if the system does not already have a
+ semaphore identified by \a key, it creates a new semaphore for that
+ key and sets its resource count to \a initialValue.
+
+ In Unix, if the \a mode is \l {QSystemSemaphore::} {Create} and the
+ system already has a semaphore identified by \a key, that semaphore
+ is used, and its resource count is set to \a initialValue. If the
+ system does not already have a semaphore identified by \a key, it
+ creates a new semaphore for that key and sets its resource count to
+ \a initialValue.
+
+ In Windows and in Symbian, \a mode is ignored, and the system always tries to
+ create a semaphore for the specified \a key. If the system does not
+ already have a semaphore identified as \a key, it creates the
+ semaphore and sets its resource count to \a initialValue. But if the
+ system already has a semaphore identified as \a key it uses that
+ semaphore and ignores \a initialValue.
+
+ The \l {QSystemSemaphore::AccessMode} {mode} parameter is only used
+ in Unix systems to handle the case where a semaphore survives a
+ process crash. In that case, the next process to allocate a
+ semaphore with the same \a key will get the semaphore that survived
+ the crash, and unless \a mode is \l {QSystemSemaphore::} {Create},
+ the resource count will not be reset to \a initialValue but will
+ retain the initial value it had been given by the crashed process.
+
+ \sa acquire(), key()
+ */
+QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
+ : d(new QSystemSemaphorePrivate)
+{
+ setKey(key, initialValue, mode);
+}
+
+/*!
+ The destructor destroys the QSystemSemaphore object, but the
+ underlying system semaphore is not removed from the system unless
+ this instance of QSystemSemaphore is the last one existing for that
+ system semaphore.
+
+ Two important side effects of the destructor depend on the system.
+ In Windows, if acquire() has been called for this semaphore but not
+ release(), release() will not be called by the destructor, nor will
+ the resource be released when the process exits normally. This would
+ be a program bug which could be the cause of a deadlock in another
+ process trying to acquire the same resource. In Unix, acquired
+ resources that are not released before the destructor is called are
+ automatically released when the process exits.
+*/
+QSystemSemaphore::~QSystemSemaphore()
+{
+ d->cleanHandle();
+}
+
+/*!
+ \enum QSystemSemaphore::AccessMode
+
+ This enum is used by the constructor and setKey(). Its purpose is to
+ enable handling the problem in Unix implementations of semaphores
+ that survive a crash. In Unix, when a semaphore survives a crash, we
+ need a way to force it to reset its resource count, when the system
+ reuses the semaphore. In Windows and in Symbian, where semaphores can't survive a
+ crash, this enum has no effect.
+
+ \value Open If the semaphore already exists, its initial resource
+ count is not reset. If the semaphore does not already exist, it is
+ created and its initial resource count set.
+
+ \value Create QSystemSemaphore takes ownership of the semaphore and
+ sets its resource count to the requested value, regardless of
+ whether the semaphore already exists by having survived a crash.
+ This value should be passed to the constructor, when the first
+ semaphore for a particular key is constructed and you know that if
+ the semaphore already exists it could only be because of a crash. In
+ Windows and in Symbian, where a semaphore can't survive a crash, Create and Open
+ have the same behavior.
+*/
+
+/*!
+ 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)
+{
+ if (key == d->key && mode == Open)
+ return;
+ d->error = NoError;
+ d->errorString = QString();
+#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
+ // 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);
+ return;
+ }
+#endif
+ d->cleanHandle();
+ d->key = key;
+ 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);
+}
+
+/*!
+ Returns the 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;
+}
+
+/*!
+ Acquires one of the resources guarded by this semaphore, if there is
+ one available, and returns true. If all the resources guarded by this
+ semaphore have already been acquired, the call blocks until one of
+ them is released by another process or thread having a semaphore
+ with the same key.
+
+ If false is returned, a system error has occurred. Call error()
+ to get a value of QSystemSemaphore::SystemSemaphoreError that
+ indicates which error occurred.
+
+ \sa release()
+ */
+bool QSystemSemaphore::acquire()
+{
+ return d->modifySemaphore(-1);
+}
+
+/*!
+ Releases \a n resources guarded by the semaphore. Returns true
+ unless there is a system error.
+
+ Example: Create a system semaphore having five resources; acquire
+ them all and then release them all.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 1
+
+ This function can also "create" resources. For example, immediately
+ following the sequence of statements above, suppose we add the
+ statement:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 2
+
+ Ten new resources are now guarded by the semaphore, in addition to
+ the five that already existed. You would not normally use this
+ function to create more resources.
+
+ \sa acquire()
+ */
+bool QSystemSemaphore::release(int n)
+{
+ if (n == 0)
+ return true;
+ if (n < 0) {
+ qWarning("QSystemSemaphore::release: n is negative.");
+ return false;
+ }
+ return d->modifySemaphore(n);
+}
+
+/*!
+ Returns a value indicating whether an error occurred, and, if so,
+ which error it was.
+
+ \sa errorString()
+ */
+QSystemSemaphore::SystemSemaphoreError QSystemSemaphore::error() const
+{
+ return d->error;
+}
+
+/*!
+ \enum QSystemSemaphore::SystemSemaphoreError
+
+ \value NoError No error occurred.
+
+ \value PermissionDenied The operation failed because the caller
+ didn't have the required permissions.
+
+ \value KeyError The operation failed because of an invalid key.
+
+ \value AlreadyExists The operation failed because a system
+ semaphore with the specified key already existed.
+
+ \value NotFound The operation failed because a system semaphore
+ with the specified key could not be found.
+
+ \value OutOfResources The operation failed because there was
+ not enough memory available to fill the request.
+
+ \value UnknownError Something else happened and it was bad.
+*/
+
+/*!
+ Returns a text description of the last error that occurred. If
+ error() returns an \l {QSystemSemaphore::SystemSemaphoreError} {error
+ value}, call this function to get a text string that describes the
+ error.
+
+ \sa error()
+ */
+QString QSystemSemaphore::errorString() const
+{
+ return d->errorString;
+}
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsystemsemaphore.h b/src/corelib/kernel/qsystemsemaphore.h
new file mode 100644
index 0000000000..305d311fda
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSYSTEMSEMAPHORE_H
+#define QSYSTEMSEMAPHORE_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#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
+
+QT_END_HEADER
+
+#endif // QSYSTEMSEMAPHORE_H
+
diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h
new file mode 100644
index 0000000000..f8f5043e23
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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"
+#ifndef Q_OS_WINCE
+# include <sys/types.h>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+class RSemaphore;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSystemSemaphorePrivate
+{
+
+public:
+ QSystemSemaphorePrivate();
+
+ QString makeKeyFileName()
+ {
+ return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemsem_"));
+ }
+
+#ifdef Q_OS_WIN
+ HANDLE handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function);
+#elif defined(Q_OS_SYMBIAN)
+ int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function,int err = 0);
+#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
+ HANDLE semaphore;
+ HANDLE semaphoreLock;
+#elif defined(Q_OS_SYMBIAN)
+ RSemaphore semaphore;
+#else
+ int semaphore;
+ bool createdFile;
+ bool createdSemaphore;
+ key_t unix_key;
+#endif
+ QString errorString;
+ QSystemSemaphore::SystemSemaphoreError error;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+#endif // QSYSTEMSEMAPHORE_P_H
+
diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
new file mode 100644
index 0000000000..0d257b8f5e
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include "qcoreapplication.h"
+#include <qdebug.h>
+
+#include "qcore_symbian_p.h"
+#include <e32cmn.h>
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+ error(QSystemSemaphore::NoError)
+{
+}
+
+void QSystemSemaphorePrivate::setErrorString(const QString &function, int err)
+{
+ if (err == KErrNone){
+ return;
+ }
+ switch(err){
+ case KErrAlreadyExists:
+ errorString = QCoreApplication::tr("%1: already exists", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::AlreadyExists;
+ break;
+ case KErrNotFound:
+ errorString = QCoreApplication::tr("%1: does not exist", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::NotFound;
+ break;
+ case KErrNoMemory:
+ case KErrInUse:
+ errorString = QCoreApplication::tr("%1: out of resources", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::OutOfResources;
+ break;
+ case KErrPermissionDenied:
+ errorString = QCoreApplication::tr("%1: permission denied", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::PermissionDenied;
+ break;
+default:
+ errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err);
+ error = QSystemSemaphore::UnknownError;
+ }
+
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+}
+
+int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
+{
+ if (semaphore.Handle()) {
+ return semaphore.Handle();
+ }
+
+ // don't allow making handles on empty keys
+ if (key.isEmpty())
+ return 0;
+
+ TPtrC name(qt_QString2TPtrC(fileName));
+ int err = KErrAlreadyExists;
+ int tryCount = 10;
+ // Sort out race conditions by retrying several times until existing handle is acquired.
+ // Sometimes opening can fail inexplicably with KErrPermissionDenied many times in a row.
+ while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) {
+ err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess);
+ if (err != KErrNoMemory && err != KErrNone)
+ err = semaphore.OpenGlobal(name,EOwnerProcess);
+ }
+ if (err){
+ setErrorString(QLatin1String("QSystemSemaphore::handle"),err);
+ return 0;
+ }
+ return semaphore.Handle();
+}
+
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ semaphore.Close();
+}
+
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (0 == handle())
+ return false;
+
+ if (count > 0) {
+ semaphore.Signal(count);
+ } else {
+ semaphore.Wait();
+ }
+ return true;
+}
+
+#endif //QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
new file mode 100644
index 0000000000..55b65b75de
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#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
+
+QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+ semaphore(-1), createdFile(false),
+ createdSemaphore(false), unix_key(-1), 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
+ }
+}
+
+/*!
+ \internal
+
+ Setup unix_key
+ */
+key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
+{
+ if (key.isEmpty()){
+ errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").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 = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+ createdFile = (1 == built);
+
+ // Get the unix key for the created file
+ unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
+ if (-1 == unix_key) {
+ errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+
+ // Get semaphore
+ semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL);
+ if (-1 == semaphore) {
+ if (errno == EEXIST)
+ semaphore = semget(unix_key, 1, 0666 | 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() << QLatin1String("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;
+
+ register 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() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
+#endif
+ return false;
+ }
+
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
new file mode 100644
index 0000000000..fad50f2ffb
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include "qcoreapplication.h"
+#include <qdebug.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, (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() << QLatin1String("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() << QLatin1String("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
+#endif
+ return false;
+ }
+ } else {
+ if (WAIT_OBJECT_0 != WaitForSingleObject(semaphore, INFINITE)) {
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
+#endif
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#endif //QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
new file mode 100644
index 0000000000..79e4cca3e8
--- /dev/null
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -0,0 +1,571 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcoreevent.h>
+#include <qdatetime.h>
+#include <qlibraryinfo.h>
+#include <qobject.h>
+#include <qcoreapplication.h>
+
+#include "stdio.h"
+#include "stdlib.h"
+
+QT_BEGIN_NAMESPACE
+
+#include "qconfig_eval.cpp"
+
+static const char boilerplate_unsuported[] =
+ "\nQt %1 Evaluation License\n"
+ "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
+ "All rights reserved.\n\n"
+ "This trial version may only be used for evaluation purposes\n"
+ "and will shut down after 120 minutes.\n"
+ "Registered to:\n"
+ " Licensee: %2\n\n"
+ "The evaluation expires in %4 days\n\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char boilerplate_supported[] =
+ "\nQt %1 Evaluation License\n"
+ "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
+ "All rights reserved.\n\n"
+ "This trial version may only be used for evaluation purposes\n"
+ "Registered to:\n"
+ " Licensee: %2\n\n"
+ "The evaluation expires in %4 days\n\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char boilerplate_expired[] =
+ "This software is using the trial version of the Qt GUI toolkit.\n"
+ "The trial period has expired. If you need more time to\n"
+ "evaluate Qt, or if you have any questions about Qt, contact us\n"
+ "at: http://qt.nokia.com/about/contact-us.\n\n";
+
+static const char will_shutdown_1min[] =
+ "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char will_shutdown_now[] =
+ "\nThe evaluation of Qt has now reached its automatic\n"
+ "timeout and will shut down.\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static int qt_eval_is_supported()
+{
+ const volatile char *const license_key = qt_eval_key_data + 12;
+
+ // fast fail
+ if (!qt_eval_key_data[0] || !*license_key)
+ return -1;
+
+ // is this an unsupported evaluation?
+ const volatile char *typecode = license_key;
+ int field = 2;
+ for ( ; field && *typecode; ++typecode)
+ if (*typecode == '-')
+ --field;
+
+ if (!field && typecode[1] == '4' && typecode[2] == 'M') {
+ if (typecode[0] == 'Q')
+ return 0;
+ else if (typecode[0] == 'R' || typecode[0] == 'Z')
+ return 1;
+ }
+ return -1;
+}
+
+static int qt_eval_days_left()
+{
+ if (qt_eval_is_supported() < 0)
+ return -2;
+
+ QDate today = QDate::currentDate();
+ QDate build = QLibraryInfo::buildDate();
+ return qMax(-1, today.daysTo(build) + 30);
+}
+
+static QString qt_eval_string()
+{
+ const char *msg;
+ switch (qt_eval_is_supported()) {
+ case 0:
+ msg = boilerplate_unsuported;
+ break;
+ case 1:
+ msg = boilerplate_supported;
+ break;
+ default:
+ return QString();
+ msg = 0;
+ }
+
+ return QString::fromLatin1(msg)
+ .arg(QLatin1String(QT_VERSION_STR))
+ .arg(QLibraryInfo::licensee())
+ .arg(qt_eval_days_left());
+}
+
+#define WARN_TIMEOUT 60 * 1000 * 119
+#define KILL_DELAY 60 * 1000 * 1
+
+class QCoreFuriCuri : public QObject
+{
+public:
+
+ int warn;
+ int kill;
+
+ QCoreFuriCuri() : QObject(), warn(-1), kill(-1)
+ {
+ if (!qt_eval_is_supported()) {
+ warn = startTimer(WARN_TIMEOUT);
+ kill = 0;
+ }
+ }
+
+ void timerEvent(QTimerEvent *e) {
+ if (e->timerId() == warn) {
+ killTimer(warn);
+ fprintf(stderr, "%s\n", will_shutdown_1min);
+ kill = startTimer(KILL_DELAY);
+ } else if (e->timerId() == kill) {
+ fprintf(stderr, "%s\n", will_shutdown_now);
+ QCoreApplication::instance()->quit();
+ }
+ }
+};
+
+#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED)
+
+void qt_core_eval_init(uint type)
+{
+ if (!type)
+ return; // GUI app
+
+ switch (qt_eval_days_left()) {
+ case -2:
+ return;
+
+ case -1:
+ fprintf(stderr, "%s\n", boilerplate_expired);
+ if (type == 0) {
+ // if we're a console app only.
+ exit(0);
+ }
+
+ default:
+ fprintf(stderr, "%s\n", qPrintable(qt_eval_string()));
+ if (type == 0) {
+ Q_UNUSED(new QCoreFuriCuri());
+ }
+ }
+}
+#endif
+
+#ifdef QT_BUILD_GUI_LIB
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qapplication.h>
+QT_END_INCLUDE_NAMESPACE
+
+
+static const char * const qtlogo_eval_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"46 55 174 2",
+" c #002E02",
+". c #00370D",
+"X c #003A0E",
+"o c #003710",
+"O c #013C13",
+"+ c #043E1A",
+"@ c #084F0A",
+"# c #0B520C",
+"$ c #054413",
+"% c #0C4C17",
+"& c #07421D",
+"* c #09451D",
+"= c #0D491E",
+"- c #125515",
+"; c #13541A",
+": c #17591B",
+"> c #1B5C1D",
+", c #1F611F",
+"< c #20621E",
+"1 c #337B1E",
+"2 c #0B4521",
+"3 c #0F4923",
+"4 c #114B24",
+"5 c #154D2A",
+"6 c #175323",
+"7 c #1C5924",
+"8 c #1C532F",
+"9 c #1E5432",
+"0 c #245936",
+"q c #265938",
+"w c #295C3B",
+"e c #246324",
+"r c #266823",
+"t c #2A6C24",
+"y c #276628",
+"u c #2D7026",
+"i c #327427",
+"p c #367927",
+"a c #37782A",
+"s c #397C2A",
+"d c #2E613E",
+"f c #336C37",
+"g c #2F6040",
+"h c #356545",
+"j c #3C6B4E",
+"k c #3F6C51",
+"l c #406E4F",
+"z c #406D52",
+"x c #477457",
+"c c #497557",
+"v c #4B7857",
+"b c #517B5E",
+"n c #3C8423",
+"m c #3E812C",
+"M c #53A61D",
+"N c #41862C",
+"B c #458A2D",
+"V c #498F2D",
+"C c #479324",
+"Z c #489226",
+"A c #4D952C",
+"S c #478B30",
+"D c #488C30",
+"F c #4D9232",
+"G c #509632",
+"H c #549A33",
+"J c #589F35",
+"K c #56A526",
+"L c #57A821",
+"P c #5BAA27",
+"I c #57A32A",
+"U c #5CA72E",
+"Y c #5DAB2A",
+"T c #5CA336",
+"R c #60AD2E",
+"E c #63B12D",
+"W c #65AF35",
+"Q c #62A53F",
+"! c #65AE39",
+"~ c #66B036",
+"^ c #6AB437",
+"/ c #67B138",
+"( c #6AB339",
+") c #6DB838",
+"_ c #70BA3C",
+"` c #4D8545",
+"' c #4E8942",
+"] c #548851",
+"[ c #6FAF4A",
+"{ c #6DB243",
+"} c #71B546",
+"| c #70B840",
+" . c #73B648",
+".. c #79BA4E",
+"X. c #7CBB53",
+"o. c #598266",
+"O. c #62886D",
+"+. c #6A8F75",
+"@. c #6B9173",
+"#. c #70937A",
+"$. c #799F79",
+"%. c #7BAF66",
+"&. c #81BD5B",
+"*. c #85BF60",
+"=. c #85AC7F",
+"-. c #8DBA7B",
+";. c #87C061",
+":. c #8AC364",
+">. c #8DC46A",
+",. c #90C56E",
+"<. c #93C771",
+"1. c #96CA73",
+"2. c #9ACB7C",
+"3. c #9FD07D",
+"4. c #779981",
+"5. c #7F9F89",
+"6. c #809F88",
+"7. c #82A18B",
+"8. c #86A192",
+"9. c #8DA994",
+"0. c #8FA998",
+"q. c #94AF9B",
+"w. c #97B991",
+"e. c #97B19E",
+"r. c #9DB6A3",
+"t. c #A3BCA7",
+"y. c #A6BCAB",
+"u. c #A9BEB1",
+"i. c #9ECD81",
+"p. c #A2CF85",
+"a. c #A5D284",
+"s. c #A6D189",
+"d. c #A9D28E",
+"f. c #ABD491",
+"g. c #B1D797",
+"h. c #B1D699",
+"j. c #B5D89E",
+"k. c #ADC5AC",
+"l. c #B1CAAE",
+"z. c #B9DAA3",
+"x. c #BDDDA8",
+"c. c #ADC1B4",
+"v. c #B2C6B6",
+"b. c #B5C6BC",
+"n. c #B6C9BA",
+"m. c #BCD1BA",
+"M. c #C6E1B4",
+"N. c #CDE5BD",
+"B. c #C2D2C6",
+"V. c #CADEC2",
+"C. c #C6D3CC",
+"Z. c #C8D7CB",
+"A. c #CEDAD2",
+"S. c #D2DDD4",
+"D. c #D3E9C6",
+"F. c #D7EBC9",
+"G. c #D9EBCD",
+"H. c #DEEED4",
+"J. c #D6E0D9",
+"K. c #DAE4DC",
+"L. c #E0EFD7",
+"P. c #E5F2DD",
+"I. c #DFE8E0",
+"U. c #E4EBE5",
+"Y. c #E9EFEA",
+"T. c #EDF4EB",
+"R. c #F0FAE6",
+"E. c #F1F8EC",
+"W. c #EDF0F0",
+"Q. c #F4F7F3",
+"!. c #F6F9F4",
+"~. c #F8FAF7",
+"^. c #FEFEFE",
+"/. c None",
+/* pixels */
+"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.",
+"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.",
+"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.",
+"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.",
+"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.",
+"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ",
+"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ",
+"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ",
+"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ",
+"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
+"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
+"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ",
+"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ",
+"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ",
+"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ",
+"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ",
+"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ",
+"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ",
+"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ",
+"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ",
+"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ",
+"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ",
+"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .",
+"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.",
+"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.",
+"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.",
+"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.",
+"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.",
+"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.",
+"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.",
+"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.",
+"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.",
+"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.",
+"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././."
+};
+
+class EvalMessageBox : public QDialog
+{
+public:
+ EvalMessageBox(bool expired)
+ {
+ setWindowTitle(QLatin1String(" "));
+
+ QString str = qt_eval_string();
+ if (expired) {
+ str = QLatin1String(boilerplate_expired);
+ } else {
+ str = qt_eval_string();
+ }
+ str = str.trimmed();
+
+ QFrame *border = new QFrame(this);
+
+ QLabel *pixmap_label = new QLabel(border);
+ pixmap_label->setPixmap(qtlogo_eval_xpm);
+ pixmap_label->setAlignment(Qt::AlignTop);
+
+ QLabel *text_label = new QLabel(str, border);
+
+ QHBoxLayout *pm_and_text_layout = new QHBoxLayout();
+ pm_and_text_layout->addWidget(pixmap_label);
+ pm_and_text_layout->addWidget(text_label);
+
+ QVBoxLayout *master_layout = new QVBoxLayout(border);
+ master_layout->addLayout(pm_and_text_layout);
+
+ QVBoxLayout *border_layout = new QVBoxLayout(this);
+ border_layout->setMargin(0);
+ border_layout->addWidget(border);
+
+ if (expired) {
+ QPushButton *cmd = new QPushButton(QLatin1String("OK"), border);
+ cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ cmd->setDefault(true);
+
+ QHBoxLayout *button_layout = new QHBoxLayout();
+ master_layout->addLayout(button_layout);
+ button_layout->addWidget(cmd);
+
+ connect(cmd, SIGNAL(clicked()), this, SLOT(close()));
+ } else {
+ border->setFrameShape(QFrame::WinPanel);
+ border->setFrameShadow(QFrame::Raised);
+ setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ QTimer::singleShot(7000, this, SLOT(close()));
+ setAttribute(Qt::WA_DeleteOnClose);
+ }
+
+ setFixedSize(sizeHint());
+ }
+};
+
+class QGuiFuriCuri : public QCoreFuriCuri
+{
+public:
+ void timerEvent(QTimerEvent *e) {
+ if (e->timerId() == warn) {
+ killTimer(warn);
+ QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min));
+ kill = startTimer(KILL_DELAY);
+ } else if (e->timerId() == kill) {
+ killTimer(kill);
+ QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now));
+ qApp->quit();
+ }
+ }
+};
+
+
+void qt_gui_eval_init(uint)
+{
+ switch (qt_eval_days_left()) {
+ case -2:
+ return;
+
+ case -1: {
+ EvalMessageBox box(true);
+ box.exec();
+ ::exit(0);
+ }
+
+ default: {
+ EvalMessageBox *box = new EvalMessageBox(false);
+ box->show();
+ Q_UNUSED(new QGuiFuriCuri());
+ }
+ }
+}
+
+static QString qt_eval_title_prefix()
+{
+ return QLatin1String("[Qt Evaluation] ");
+}
+
+QString qt_eval_adapt_window_title(const QString &title)
+{
+ if (qt_eval_days_left() == -2)
+ return title;
+ return qt_eval_title_prefix() + title;
+}
+
+void qt_eval_init_widget(QWidget *w)
+{
+ if (qt_eval_days_left() == -2)
+ return;
+ if (w->isTopLevel()) {
+ QString windowTitle = w->windowTitle();
+ if (windowTitle.isEmpty()) {
+ w->setWindowTitle(QLatin1String(" "));
+ } else if (!windowTitle.startsWith(qt_eval_title_prefix())) {
+ qt_eval_adapt_window_title(windowTitle);
+ }
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
new file mode 100644
index 0000000000..3efeda229d
--- /dev/null
+++ b/src/corelib/kernel/qtimer.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtimer.h"
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QTimer
+ \brief The QTimer class provides repetitive and single-shot timers.
+
+ \ingroup events
+
+
+ The QTimer class provides a high-level programming interface for
+ timers. To use it, create a QTimer, connect its timeout() signal
+ to the appropriate slots, and call start(). From then on it will
+ emit the timeout() signal at constant intervals.
+
+ Example for a one second (1000 millisecond) timer (from the
+ \l{widgets/analogclock}{Analog Clock} example):
+
+ \snippet examples/widgets/analogclock/analogclock.cpp 4
+ \snippet examples/widgets/analogclock/analogclock.cpp 5
+ \snippet examples/widgets/analogclock/analogclock.cpp 6
+
+ From then on, the \c update() slot is called every second.
+
+ You can set a timer to time out only once by calling
+ setSingleShot(true). You can also use the static
+ QTimer::singleShot() function to call a slot after a specified
+ interval:
+
+ \snippet doc/src/snippets/timers/timers.cpp 3
+
+ 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.
+
+ As a special case, a QTimer with a timeout of 0 will time out as
+ soon as all the events in the window system's event queue have
+ been processed. This can be used to do heavy work while providing
+ a snappy user interface:
+
+ \snippet doc/src/snippets/timers/timers.cpp 4
+ \snippet doc/src/snippets/timers/timers.cpp 5
+ \snippet doc/src/snippets/timers/timers.cpp 6
+
+ \c processOneThing() will from then on be called repeatedly. It
+ should be written in such a way that it always returns quickly
+ (typically after processing one data item) so that Qt can deliver
+ events to widgets 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; multithreading is now becoming available on
+ more and more platforms, and we expect that zero-millisecond
+ QTimers will gradually be replaced by \l{QThread}s.
+
+ \section1 Accuracy and Timer Resolution
+
+ Timers will never time out earlier than the specified timeout value
+ and they are not guaranteed to time out at the exact value specified.
+ In many situations, they may time out late by a period of time that
+ depends on the accuracy of the system timers.
+
+ The accuracy of timers depends on the underlying operating system
+ and hardware. Most platforms support a resolution of 1 millisecond,
+ though the accuracy of the timer will not equal this resolution
+ in many real-world situations.
+
+ If Qt is unable to deliver the requested number of timer clicks,
+ it will silently discard some.
+
+ \section1 Alternatives to QTimer
+
+ An alternative to using QTimer is to call QObject::startTimer()
+ for your object and reimplement the QObject::timerEvent() event
+ handler in your class (which must inherit QObject). The
+ disadvantage is that timerEvent() does not support such
+ high-level features as single-shot timers or signals.
+
+ Another alternative to using QTimer is to use 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 tries to work around these limitations.
+
+ \sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers,
+ {Analog Clock Example}, {Wiggly Example}
+*/
+
+
+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)
+{
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a timer called \a name, with a \a parent.
+*/
+
+QTimer::QTimer(QObject *parent, const char *name)
+ : QObject(parent), id(INV_TIMER), single(0), nulltimer(0)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the timer.
+*/
+
+QTimer::~QTimer()
+{
+ if (id != INV_TIMER) // stop running timer
+ stop();
+}
+
+
+/*!
+ \fn void QTimer::timeout()
+
+ This signal is emitted when the timer times out.
+
+ \sa interval, start(), stop()
+*/
+
+/*!
+ \property QTimer::active
+ \since 4.3
+
+ This boolean property is true if the timer is running; otherwise
+ false.
+*/
+
+/*!
+ \fn bool QTimer::isActive() const
+
+ Returns true if the timer is running (pending); otherwise returns
+ false.
+*/
+
+/*!
+ \fn int QTimer::timerId() const
+
+ Returns the ID of the timer if the timer is running; otherwise returns
+ -1.
+*/
+
+
+/*! \overload start()
+
+ Starts or restarts the timer with the timeout specified in \l interval.
+
+ If \l singleShot is true, the timer will be activated only once.
+*/
+void QTimer::start()
+{
+ if (id != INV_TIMER) // stop running timer
+ stop();
+ nulltimer = (!inter && single);
+ id = QObject::startTimer(inter);
+}
+
+/*!
+ Starts or restarts the timer with a timeout interval of \a msec
+ milliseconds.
+*/
+void QTimer::start(int msec)
+{
+ inter = msec;
+ start();
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \overload start()
+
+ Call setSingleShot(\a sshot) and start(\a msec) instead.
+*/
+
+int QTimer::start(int msec, bool sshot)
+{
+ if (id >=0 && nulltimer && !msec && sshot)
+ return id;
+ stop();
+ setInterval(msec);
+ setSingleShot(sshot);
+ start();
+ return timerId();
+}
+#endif
+
+
+/*!
+ Stops the timer.
+
+ \sa start()
+*/
+
+void QTimer::stop()
+{
+ if (id != INV_TIMER) {
+ QObject::killTimer(id);
+ id = INV_TIMER;
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void QTimer::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == id) {
+ if (single)
+ stop();
+ emit timeout();
+ }
+}
+
+class QSingleShotTimer : public QObject
+{
+ Q_OBJECT
+ int timerId;
+public:
+ ~QSingleShotTimer();
+ QSingleShotTimer(int msec, QObject *r, const char * m);
+Q_SIGNALS:
+ void timeout();
+protected:
+ void timerEvent(QTimerEvent *);
+};
+
+QSingleShotTimer::QSingleShotTimer(int msec, QObject *receiver, const char *member)
+ : QObject(QAbstractEventDispatcher::instance())
+{
+ connect(this, SIGNAL(timeout()), receiver, member);
+ timerId = startTimer(msec);
+}
+
+QSingleShotTimer::~QSingleShotTimer()
+{
+ if (timerId > 0)
+ killTimer(timerId);
+}
+
+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;
+ 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);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qtimer.moc"
+QT_END_INCLUDE_NAMESPACE
+
+/*!
+ \reentrant
+ This static function calls a slot after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \link QObject::timerEvent() timerEvent\endlink or
+ create a local QTimer object.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qtimer.cpp 0
+
+ This sample program automatically terminates after 10 minutes
+ (600,000 milliseconds).
+
+ The \a receiver is the receiving object and the \a member is the
+ slot. The time interval is \a msec milliseconds.
+
+ \sa start()
+*/
+
+void QTimer::singleShot(int msec, QObject *receiver, const char *member)
+{
+ if (receiver && member) {
+ if (msec == 0) {
+ // special code shortpath for 0-timers
+ const char* bracketPosition = strchr(member, '(');
+ if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) {
+ qWarning("QTimer::singleShot: Invalid slot specification");
+ return;
+ }
+ QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
+ QMetaObject::invokeMethod(receiver, methodName.constData(), Qt::QueuedConnection);
+ return;
+ }
+ (void) new QSingleShotTimer(msec, receiver, member);
+ }
+}
+
+/*!
+ \property QTimer::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 milliseconds.
+
+ \sa interval, singleShot()
+*/
+
+/*!
+ \property QTimer::interval
+ \brief the timeout interval in milliseconds
+
+ The default value for this property is 0. A QTimer with a timeout
+ interval of 0 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 its timerId().
+
+ \sa singleShot
+*/
+void QTimer::setInterval(int msec)
+{
+ inter = msec;
+ if (id != INV_TIMER) { // create new timer
+ QObject::killTimer(id); // restart timer
+ id = QObject::startTimer(msec);
+ }
+}
+
+/*! \fn void QTimer::changeInterval(int msec)
+
+ Use setInterval(msec) or start(msec) instead.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
new file mode 100644
index 0000000000..a7470848ee
--- /dev/null
+++ b/src/corelib/kernel/qtimer.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTIMER_H
+#define QTIMER_H
+
+#ifndef QT_NO_QOBJECT
+
+#include <QtCore/qbasictimer.h> // conceptual inheritance
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+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 active READ isActive)
+public:
+ explicit QTimer(QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QTimer(QObject *parent, const char *name);
+#endif
+ ~QTimer();
+
+ inline bool isActive() const { return id >= 0; }
+ int timerId() const { return id; }
+
+ void setInterval(int msec);
+ int interval() const { return inter; }
+
+ inline void setSingleShot(bool singleShot);
+ inline bool isSingleShot() const { return single; }
+
+ static void singleShot(int msec, QObject *receiver, const char *member);
+
+public Q_SLOTS:
+ void start(int msec);
+
+ void start();
+ void stop();
+
+#ifdef QT3_SUPPORT
+ inline QT_MOC_COMPAT void changeInterval(int msec) { start(msec); }
+ QT_MOC_COMPAT int start(int msec, bool sshot);
+#endif
+
+Q_SIGNALS:
+ void timeout();
+
+protected:
+ void timerEvent(QTimerEvent *);
+
+private:
+ Q_DISABLE_COPY(QTimer)
+
+ inline int startTimer(int){ return -1;}
+ inline void killTimer(int){}
+
+ int id, inter, del;
+ uint single : 1;
+ uint nulltimer : 1;
+};
+
+inline void QTimer::setSingleShot(bool asingleShot) { single = asingleShot; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QOBJECT
+
+#endif // QTIMER_H
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
new file mode 100644
index 0000000000..22b06a56a6
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -0,0 +1,979 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qtranslator.h"
+
+#ifndef QT_NO_TRANSLATION
+
+#include "qfileinfo.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qdatastream.h"
+#include "qfile.h"
+#include "qmap.h"
+#include "qalgorithms.h"
+#include "qhash.h"
+#include "qtranslator_p.h"
+#include "qlocale.h"
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
+#define QT_USE_MMAP
+#include "private/qcore_unix_p.h"
+#endif
+
+// most of the headers below are already included in qplatformdefs.h
+// also this lacks Large File support but that's probably irrelevant
+#if defined(QT_USE_MMAP)
+// for mmap
+#include <sys/mman.h>
+#include <errno.h>
+#endif
+
+#include <stdlib.h>
+
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Obsolete1,
+ Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete2 };
+/*
+$ mcookie
+3cb86418caef9c95cd211cbf60a1bddd
+$
+*/
+
+// magic number for the file
+static const int MagicLength = 16;
+static const uchar magic[MagicLength] = {
+ 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
+ 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
+};
+
+static bool match(const uchar* found, const char* target, uint len)
+{
+ // catch the case if \a found has a zero-terminating symbol and \a len includes it.
+ // (normalize it to be without the zero-terminating symbol)
+ if (len > 0 && found[len-1] == '\0')
+ --len;
+ return (memcmp(found, target, len) == 0 && target[len] == '\0');
+}
+
+static uint elfHash(const char *name)
+{
+ const uchar *k;
+ uint h = 0;
+ uint g;
+
+ if (name) {
+ k = (const uchar *) name;
+ while (*k) {
+ h = (h << 4) + *k++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ if (!h)
+ h = 1;
+ return h;
+}
+
+static int numerusHelper(int n, const uchar *rules, int rulesSize)
+{
+#define CHECK_RANGE \
+ do { \
+ if (i >= rulesSize) \
+ return -1; \
+ } while (0)
+
+ int result = 0;
+ int i = 0;
+
+ if (rulesSize == 0)
+ return 0;
+
+ for (;;) {
+ bool orExprTruthValue = false;
+
+ for (;;) {
+ bool andExprTruthValue = true;
+
+ for (;;) {
+ bool truthValue = true;
+
+ CHECK_RANGE;
+ int opcode = rules[i++];
+
+ int leftOperand = n;
+ if (opcode & Q_MOD_10) {
+ leftOperand %= 10;
+ } else if (opcode & Q_MOD_100) {
+ leftOperand %= 100;
+ } else if (opcode & Q_LEAD_1000) {
+ while (leftOperand >= 1000)
+ leftOperand /= 1000;
+ }
+
+ int op = opcode & Q_OP_MASK;
+
+ CHECK_RANGE;
+ int rightOperand = rules[i++];
+
+ switch (op) {
+ default:
+ return -1;
+ case Q_EQ:
+ truthValue = (leftOperand == rightOperand);
+ break;
+ case Q_LT:
+ truthValue = (leftOperand < rightOperand);
+ break;
+ case Q_LEQ:
+ truthValue = (leftOperand <= rightOperand);
+ break;
+ case Q_BETWEEN:
+ int bottom = rightOperand;
+ CHECK_RANGE;
+ int top = rules[i++];
+ truthValue = (leftOperand >= bottom && leftOperand <= top);
+ }
+
+ if (opcode & Q_NOT)
+ truthValue = !truthValue;
+
+ andExprTruthValue = andExprTruthValue && truthValue;
+
+ if (i == rulesSize || rules[i] != Q_AND)
+ break;
+ ++i;
+ }
+
+ orExprTruthValue = orExprTruthValue || andExprTruthValue;
+
+ if (i == rulesSize || rules[i] != Q_OR)
+ break;
+ ++i;
+ }
+
+ if (orExprTruthValue)
+ return result;
+
+ ++result;
+
+ if (i == rulesSize)
+ return result;
+
+ if (rules[i++] != Q_NEWRULE)
+ break;
+ }
+ return -1;
+}
+
+class QTranslatorPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QTranslator)
+public:
+ enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88 };
+
+ QTranslatorPrivate()
+ : used_mmap(0), unmapPointer(0), unmapLength(0),
+ messageArray(0), offsetArray(0), contextArray(0), numerusRulesArray(0),
+ messageLength(0), offsetLength(0), contextLength(0), numerusRulesLength(0) {}
+
+ // for mmap'ed files, this is what needs to be unmapped.
+ bool used_mmap : 1;
+ char *unmapPointer;
+ unsigned int unmapLength;
+
+ // for squeezed but non-file data, this is what needs to be deleted
+ const uchar *messageArray;
+ const uchar *offsetArray;
+ const uchar *contextArray;
+ const uchar *numerusRulesArray;
+ uint messageLength;
+ uint offsetLength;
+ uint contextLength;
+ uint numerusRulesLength;
+
+ bool do_load(const QString &filename);
+ bool do_load(const uchar *data, int len);
+ QString do_translate(const char *context, const char *sourceText, const char *comment,
+ int n) const;
+ void clear();
+};
+
+/*!
+ \class QTranslator
+
+ \brief The QTranslator class provides internationalization support for text
+ output.
+
+ \ingroup i18n
+
+ An object of this class contains a set of translations from a
+ source language to a target language. QTranslator provides
+ functions to look up translations in a translation file.
+ Translation files are created using \l{Qt Linguist}.
+
+ The most common use of QTranslator is to: load a translation
+ file, install it using QApplication::installTranslator(), and use
+ it via QObject::tr(). Here's the \c main() function from the
+ \l{linguist/hellotr}{Hello tr()} example:
+
+ \snippet examples/linguist/hellotr/main.cpp 2
+
+ Note that the translator must be created \e before the
+ application's widgets.
+
+ Most applications will never need to do anything else with this
+ class. The other functions provided by this class are useful for
+ applications that work on translator files.
+
+ \section1 Looking up Translations
+
+ It is possible to look up a translation using translate() (as tr()
+ and QApplication::translate() do). The translate() function takes
+ up to three parameters:
+
+ \list
+ \o The \e context - usually the class name for the tr() caller.
+ \o The \e {source text} - usually the argument to tr().
+ \o The \e disambiguation - an optional string that helps disambiguate
+ different uses of the same text in the same context.
+ \endlist
+
+ For example, the "Cancel" in a dialog might have "Anuluj" when the
+ program runs in Polish (in this case the source text would be
+ "Cancel"). The context would (normally) be the dialog's class
+ name; there would normally be no comment, and the translated text
+ would be "Anuluj".
+
+ But it's not always so simple. The Spanish version of a printer
+ dialog with settings for two-sided printing and binding would
+ probably require both "Activado" and "Activada" as translations
+ for "Enabled". In this case the source text would be "Enabled" in
+ both cases, and the context would be the dialog's class name, but
+ the two items would have disambiguations such as "two-sided printing"
+ for one and "binding" for the other. The disambiguation enables the
+ translator to choose the appropriate gender for the Spanish version,
+ and enables Qt to distinguish between translations.
+
+ \section1 Using Multiple Translations
+
+ Multiple translation files can be installed in an application.
+ Translations are searched for in the reverse order in which they were
+ installed, so the most recently installed translation file is searched
+ for translations first and the earliest translation file is searched
+ last. The search stops as soon as a translation containing a matching
+ string is found.
+
+ This mechanism makes it possible for a specific translation to be
+ "selected" or given priority over the others; simply uninstall the
+ translator from the application by passing it to the
+ QApplication::removeTranslator() function and reinstall it with
+ QApplication::installTranslator(). It will then be the first
+ translation to be searched for matching strings.
+
+ \sa QApplication::installTranslator(), QApplication::removeTranslator(),
+ QObject::tr(), QApplication::translate(), {I18N Example},
+ {Hello tr() Example}, {Arrow Pad Example}, {Troll Print Example}
+*/
+
+/*!
+ Constructs an empty message file object with parent \a parent that
+ is not connected to any file.
+*/
+
+QTranslator::QTranslator(QObject * parent)
+ : QObject(*new QTranslatorPrivate, parent)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QTranslator()
+ \obsolete
+ */
+QTranslator::QTranslator(QObject * parent, const char * name)
+ : QObject(*new QTranslatorPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+QTranslator::~QTranslator()
+{
+ if (QCoreApplication::instance())
+ QCoreApplication::removeTranslator(this);
+ Q_D(QTranslator);
+ d->clear();
+}
+
+/*!
+
+ Loads \a filename + \a suffix (".qm" if the \a suffix is not
+ specified), which may be an absolute file name or relative to \a
+ directory. Returns true if the translation is successfully loaded;
+ otherwise returns false.
+
+ If \a directory is not specified, the directory of the
+ application's executable is used (i.e., as
+ \l{QCoreApplication::}{applicationDirPath()}).
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with text after a character in \a search_delimiters
+ stripped ("_." is the default for \a search_delimiters if it is
+ an empty string) and \a suffix.
+ \o File name stripped without \a suffix appended.
+ \o File name stripped further, etc.
+ \endlist
+
+ For example, an application running in the fr_CA locale
+ (French-speaking Canada) might call load("foo.fr_ca",
+ "/opt/foolib"). load() would then try to open the first existing
+ readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.fr_ca.qm
+ \o \c /opt/foolib/foo.fr_ca
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo
+ \endlist
+*/
+
+bool QTranslator::load(const QString & filename, const QString & directory,
+ const QString & search_delimiters,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+
+ QString prefix;
+ if (QFileInfo(filename).isRelative()) {
+ prefix = directory;
+ if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
+ prefix += QLatin1Char('/');
+ }
+
+ QString fname = filename;
+ QString realname;
+ QString delims;
+ delims = search_delimiters.isNull() ? QString::fromLatin1("_.") : search_delimiters;
+
+ for (;;) {
+ QFileInfo fi;
+
+ realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ break;
+
+ realname = prefix + fname;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ break;
+
+ int rightmost = 0;
+ for (int i = 0; i < (int)delims.length(); i++) {
+ int k = fname.lastIndexOf(delims[i]);
+ if (k > rightmost)
+ rightmost = k;
+ }
+
+ // no truncations? fail
+ if (rightmost == 0)
+ return false;
+
+ fname.truncate(rightmost);
+ }
+
+ // realname is now the fully qualified name of a readable file.
+ return d->do_load(realname);
+}
+
+bool QTranslatorPrivate::do_load(const QString &realname)
+{
+ QTranslatorPrivate *d = this;
+ bool ok = false;
+
+#ifdef QT_USE_MMAP
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef MAP_FAILED
+#define MAP_FAILED -1
+#endif
+
+ int fd = -1;
+ if (!realname.startsWith(QLatin1Char(':')))
+ fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
+#if defined(Q_OS_WIN)
+ _S_IREAD | _S_IWRITE
+#else
+ 0666
+#endif
+ );
+ if (fd >= 0) {
+ QT_STATBUF st;
+ if (!QT_FSTAT(fd, &st)) {
+ char *ptr;
+ ptr = reinterpret_cast<char *>(
+ mmap(0, st.st_size, // any address, whole file
+ PROT_READ, // read-only memory
+ MAP_FILE | MAP_PRIVATE, // swap-backed map from file
+ fd, 0)); // from offset 0 of fd
+ if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
+ d->used_mmap = true;
+ d->unmapPointer = ptr;
+ d->unmapLength = st.st_size;
+ ok = true;
+ }
+ }
+ ::close(fd);
+ }
+#endif // QT_USE_MMAP
+
+ if (!ok) {
+ QFile file(realname);
+ d->unmapLength = file.size();
+ if (!d->unmapLength)
+ return false;
+ d->unmapPointer = new char[d->unmapLength];
+
+ if (file.open(QIODevice::ReadOnly))
+ ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));
+
+ if (!ok) {
+ delete [] d->unmapPointer;
+ d->unmapPointer = 0;
+ d->unmapLength = 0;
+ return false;
+ }
+ }
+
+ return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
+}
+
+static QString find_translation(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ QString path;
+ if (QFileInfo(filename).isRelative()) {
+ path = directory;
+ if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ }
+
+ QFileInfo fi;
+ QString realname;
+ QStringList fuzzyLocales;
+
+ // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
+
+ QStringList languages = locale.uiLanguages();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ 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);
+ }
+#endif
+
+ // try explicit locales names first
+ foreach (QString localeName, languages) {
+ localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ fuzzyLocales.append(localeName);
+ }
+
+ // start guessing
+ foreach (QString localeName, fuzzyLocales) {
+ for (;;) {
+ int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
+ // no truncations? fail
+ if (rightmost <= 0)
+ break;
+ localeName.truncate(rightmost);
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+ }
+
+ if (!suffix.isNull()) {
+ realname = path + filename + suffix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+
+ realname = path + filename + prefix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ return QString();
+}
+
+/*!
+ \since 4.8
+
+ Loads \a filename + \a prefix + \a \l{QLocale::uiLanguages()}{ui language
+ name} + \a suffix (".qm" if the \a suffix is not specified), which may be
+ an absolute file name or relative to \a directory. Returns true if the
+ translation is successfully loaded; otherwise returns false.
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with ui language part after a "_" character stripped and \a suffix.
+ \o File name with ui language part stripped without \a suffix appended.
+ \o File name with ui language part stripped further, etc.
+ \endlist
+
+ For example, an application running in the locale with the following
+ l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
+ load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would
+ replace '-' (dash) with '_' (underscore) in the ui language and then try to
+ open the first existing readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.es.qm
+ \o \c /opt/foolib/foo.es
+ \o \c /opt/foolib/foo.fr_CA.qm
+ \o \c /opt/foolib/foo.fr_CA
+ \o \c /opt/foolib/foo.de.qm
+ \o \c /opt/foolib/foo.de
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo.
+ \o \c /opt/foolib/foo
+ \endlist
+
+ For OSs where file system is case sensitive, QTranslator also tries to load
+ a lower-cased version of the locale name.
+*/
+bool QTranslator::load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+ QString fname = find_translation(locale, filename, prefix, directory, suffix);
+ return !fname.isEmpty() && d->do_load(fname);
+}
+
+/*!
+ \overload load()
+ \fn bool QTranslator::load(const uchar *data, int len)
+
+ Loads the QM file data \a data of length \a len into the
+ translator.
+
+ The data is not copied. The caller must be able to guarantee that \a data
+ will not be deleted or modified.
+*/
+bool QTranslator::load(const uchar *data, int len)
+{
+ Q_D(QTranslator);
+ d->clear();
+ return d->do_load(data, len);
+}
+
+static quint8 read8(const uchar *data)
+{
+ return *data;
+}
+
+static quint16 read16(const uchar *data)
+{
+ return (data[0] << 8) | (data[1]);
+}
+
+static quint32 read32(const uchar *data)
+{
+ return (data[0] << 24)
+ | (data[1] << 16)
+ | (data[2] << 8)
+ | (data[3]);
+}
+
+bool QTranslatorPrivate::do_load(const uchar *data, int len)
+{
+ if (!data || len < MagicLength || memcmp(data, magic, MagicLength))
+ return false;
+
+ bool ok = true;
+ const uchar *end = data + len;
+
+ data += MagicLength;
+
+ while (data < end - 4) {
+ quint8 tag = read8(data++);
+ quint32 blockLen = read32(data);
+ data += 4;
+ if (!tag || !blockLen)
+ break;
+ if (data + blockLen > end) {
+ ok = false;
+ break;
+ }
+
+ if (tag == QTranslatorPrivate::Contexts) {
+ contextArray = data;
+ contextLength = blockLen;
+ } else if (tag == QTranslatorPrivate::Hashes) {
+ offsetArray = data;
+ offsetLength = blockLen;
+ } else if (tag == QTranslatorPrivate::Messages) {
+ messageArray = data;
+ messageLength = blockLen;
+ } else if (tag == QTranslatorPrivate::NumerusRules) {
+ numerusRulesArray = data;
+ numerusRulesLength = blockLen;
+ }
+
+ data += blockLen;
+ }
+
+ return ok;
+}
+
+static QString getMessage(const uchar *m, const uchar *end, const char *context,
+ const char *sourceText, const char *comment, int numerus)
+{
+ const uchar *tn = 0;
+ uint tn_length = 0;
+ int currentNumerus = -1;
+
+ for (;;) {
+ uchar tag = 0;
+ if (m < end)
+ tag = read8(m++);
+ switch((Tag)tag) {
+ case Tag_End:
+ goto end;
+ case Tag_Translation: {
+ int len = read32(m);
+ if (len % 1)
+ return QString();
+ m += 4;
+ if (++currentNumerus == numerus) {
+ tn_length = len;
+ tn = m;
+ }
+ m += len;
+ break;
+ }
+ case Tag_Obsolete1:
+ m += 4;
+ break;
+ case Tag_SourceText: {
+ quint32 len = read32(m);
+ m += 4;
+ if (!match(m, sourceText, len))
+ return QString();
+ m += len;
+ }
+ break;
+ case Tag_Context: {
+ quint32 len = read32(m);
+ m += 4;
+ if (!match(m, context, len))
+ return QString();
+ m += len;
+ }
+ break;
+ case Tag_Comment: {
+ quint32 len = read32(m);
+ m += 4;
+ if (*m && !match(m, comment, len))
+ return QString();
+ m += len;
+ }
+ break;
+ default:
+ return QString();
+ }
+ }
+end:
+ if (!tn)
+ return QString();
+ QString str = QString((const QChar *)tn, tn_length/2);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ for (int i = 0; i < str.length(); ++i)
+ str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));
+ }
+ return str;
+}
+
+QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,
+ const char *comment, int n) const
+{
+ if (context == 0)
+ context = "";
+ if (sourceText == 0)
+ sourceText = "";
+ if (comment == 0)
+ comment = "";
+
+ if (!offsetLength)
+ return QString();
+
+ /*
+ Check if the context belongs to this QTranslator. If many
+ translators are installed, this step is necessary.
+ */
+ if (contextLength) {
+ quint16 hTableSize = read16(contextArray);
+ uint g = elfHash(context) % hTableSize;
+ const uchar *c = contextArray + 2 + (g << 1);
+ quint16 off = read16(c);
+ c += 2;
+ if (off == 0)
+ return QString();
+ c = contextArray + (2 + (hTableSize << 1) + (off << 1));
+
+ for (;;) {
+ quint8 len = read8(c++);
+ if (len == 0)
+ return QString();
+ if (match(c, context, len))
+ break;
+ c += len;
+ }
+ }
+
+ size_t numItems = offsetLength / (2 * sizeof(quint32));
+ if (!numItems)
+ return QString();
+
+ int numerus = 0;
+ if (n >= 0)
+ numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
+
+ for (;;) {
+ quint32 h = elfHash(QByteArray(QByteArray(sourceText) + comment).constData());
+
+ const uchar *start = offsetArray;
+ const uchar *end = start + ((numItems-1) << 3);
+ while (start <= end) {
+ const uchar *middle = start + (((end - start) >> 4) << 3);
+ uint hash = read32(middle);
+ if (h == hash) {
+ start = middle;
+ break;
+ } else if (hash < h) {
+ start = middle + 8;
+ } else {
+ end = middle - 8;
+ }
+ }
+
+ if (start <= end) {
+ // go back on equal key
+ while (start != offsetArray && read32(start) == read32(start-8))
+ start -= 8;
+
+ while (start < offsetArray + offsetLength) {
+ quint32 rh = read32(start);
+ start += 4;
+ if (rh != h)
+ break;
+ quint32 ro = read32(start);
+ start += 4;
+ QString tn = getMessage(messageArray + ro, messageArray + messageLength, context,
+ sourceText, comment, numerus);
+ if (!tn.isNull())
+ return tn;
+ }
+ }
+ if (!comment[0])
+ break;
+ comment = "";
+ }
+ return QString();
+}
+
+/*!
+ Empties this translator of all contents.
+
+ This function works with stripped translator files.
+*/
+
+void QTranslatorPrivate::clear()
+{
+ Q_Q(QTranslator);
+ if (unmapPointer && unmapLength) {
+#if defined(QT_USE_MMAP)
+ if (used_mmap)
+ munmap(unmapPointer, unmapLength);
+ else
+#endif
+ delete [] unmapPointer;
+ }
+
+ unmapPointer = 0;
+ unmapLength = 0;
+ messageArray = 0;
+ contextArray = 0;
+ offsetArray = 0;
+ numerusRulesArray = 0;
+ messageLength = 0;
+ contextLength = 0;
+ offsetLength = 0;
+ numerusRulesLength = 0;
+
+ if (QCoreApplicationPrivate::isTranslatorInstalled(q))
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::LanguageChange));
+}
+
+/*!
+ Returns the translation for the key (\a context, \a sourceText,
+ \a disambiguation). If none is found, also tries (\a context, \a
+ sourceText, ""). If that still fails, returns an empty string.
+
+ If you need to programatically insert translations in to a
+ QTranslator, this function can be reimplemented.
+
+ \sa load()
+*/
+QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation) const
+{
+ Q_D(const QTranslator);
+ return d->do_translate(context, sourceText, disambiguation, -1);
+}
+
+
+/*!
+ \overload translate()
+
+ Returns the translation for the key (\a context, \a sourceText,
+ \a disambiguation). If none is found, also tries (\a context, \a
+ sourceText, ""). If that still fails, returns an empty string.
+
+ If \a n is not -1, it is used to choose an appropriate form for
+ the translation (e.g. "%n file found" vs. "%n files found").
+
+ \sa load()
+*/
+QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation,
+ int n) const
+{
+ Q_D(const QTranslator);
+ // this step is necessary because the 3-parameter translate() overload is virtual
+ if (n == -1)
+ return translate(context, sourceText, disambiguation);
+ return d->do_translate(context, sourceText, disambiguation, n);
+}
+
+/*!
+ Returns true if this translator is empty, otherwise returns false.
+ This function works with stripped and unstripped translation files.
+*/
+bool QTranslator::isEmpty() const
+{
+ Q_D(const QTranslator);
+ return !d->unmapPointer && !d->unmapLength && !d->messageArray &&
+ !d->offsetArray && !d->contextArray;
+}
+
+/*!
+ \fn QString QTranslator::find(const char *context, const char *sourceText, const char * comment = 0) const
+
+ Use translate(\a context, \a sourceText, \a comment) instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TRANSLATION
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
new file mode 100644
index 0000000000..7a4fa00369
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSLATOR_H
+#define QTRANSLATOR_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_TRANSLATION
+
+class QLocale;
+class QTranslatorPrivate;
+
+class Q_CORE_EXPORT QTranslator : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QTranslator(QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QTranslator(QObject * parent, const char * name);
+#endif
+ ~QTranslator();
+
+ // ### Qt 5: Merge (with "int n = -1")
+ virtual QString translate(const char *context, const char *sourceText,
+ const char *disambiguation = 0) const;
+ QString translate(const char *context, const char *sourceText, const char *disambiguation,
+ int n) const;
+
+ virtual bool isEmpty() 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);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QString find(const char *context, const char *sourceText, const char * comment = 0) const
+ { return translate(context, sourceText, comment); }
+#endif
+
+private:
+ Q_DISABLE_COPY(QTranslator)
+ Q_DECLARE_PRIVATE(QTranslator)
+};
+
+#endif // QT_NO_TRANSLATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTRANSLATOR_H
diff --git a/src/corelib/kernel/qtranslator_p.h b/src/corelib/kernel/qtranslator_p.h
new file mode 100644
index 0000000000..fd29592ded
--- /dev/null
+++ b/src/corelib/kernel/qtranslator_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSLATOR_P_H
+#define QTRANSLATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qfontencodings_x11.cpp and qfont_x11.cpp. This header file may
+// change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+enum {
+ Q_EQ = 0x01,
+ Q_LT = 0x02,
+ Q_LEQ = 0x03,
+ Q_BETWEEN = 0x04,
+
+ Q_NOT = 0x08,
+ Q_MOD_10 = 0x10,
+ Q_MOD_100 = 0x20,
+ Q_LEAD_1000 = 0x40,
+
+ Q_AND = 0xFD,
+ Q_OR = 0xFE,
+ Q_NEWRULE = 0xFF,
+
+ Q_OP_MASK = 0x07,
+
+ Q_NEQ = Q_NOT | Q_EQ,
+ Q_GT = Q_NOT | Q_LEQ,
+ Q_GEQ = Q_NOT | Q_LT,
+ Q_NOT_BETWEEN = Q_NOT | Q_BETWEEN
+};
+
+#endif
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
new file mode 100644
index 0000000000..f0652386c2
--- /dev/null
+++ b/src/corelib/kernel/qvariant.cpp
@@ -0,0 +1,3237 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvariant.h"
+#include "qbitarray.h"
+#include "qbytearray.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qmap.h"
+#include "qdatetime.h"
+#include "qeasingcurve.h"
+#include "qlist.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qurl.h"
+#include "qlocale.h"
+#include "private/qvariant_p.h"
+
+#ifndef QT_NO_GEOM_VARIANT
+#include "qsize.h"
+#include "qpoint.h"
+#include "qrect.h"
+#include "qline.h"
+#endif
+
+#include <float.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef DBL_DIG
+# define DBL_DIG 10
+#endif
+#ifndef FLT_DIG
+# define FLT_DIG 6
+#endif
+
+static void construct(QVariant::Private *x, const void *copy)
+{
+ x->is_shared = false;
+
+ switch (x->type) {
+ case QVariant::String:
+ v_construct<QString>(x, copy);
+ break;
+ case QVariant::Char:
+ v_construct<QChar>(x, copy);
+ break;
+ case QVariant::StringList:
+ v_construct<QStringList>(x, copy);
+ break;
+ case QVariant::Map:
+ v_construct<QVariantMap>(x, copy);
+ break;
+ case QVariant::Hash:
+ v_construct<QVariantHash>(x, copy);
+ break;
+ case QVariant::List:
+ v_construct<QVariantList>(x, copy);
+ break;
+ case QVariant::Date:
+ v_construct<QDate>(x, copy);
+ break;
+ case QVariant::Time:
+ v_construct<QTime>(x, copy);
+ break;
+ case QVariant::DateTime:
+ v_construct<QDateTime>(x, copy);
+ break;
+ case QVariant::ByteArray:
+ v_construct<QByteArray>(x, copy);
+ break;
+ case QVariant::BitArray:
+ v_construct<QBitArray>(x, copy);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ v_construct<QSize>(x, copy);
+ break;
+ case QVariant::SizeF:
+ v_construct<QSizeF>(x, copy);
+ break;
+ case QVariant::Rect:
+ v_construct<QRect>(x, copy);
+ break;
+ case QVariant::LineF:
+ v_construct<QLineF>(x, copy);
+ break;
+ case QVariant::Line:
+ v_construct<QLine>(x, copy);
+ break;
+ case QVariant::RectF:
+ v_construct<QRectF>(x, copy);
+ break;
+ case QVariant::Point:
+ v_construct<QPoint>(x, copy);
+ break;
+ case QVariant::PointF:
+ v_construct<QPointF>(x, copy);
+ break;
+#endif
+ case QVariant::Url:
+ v_construct<QUrl>(x, copy);
+ break;
+ case QVariant::Locale:
+ v_construct<QLocale>(x, copy);
+ break;
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ v_construct<QRegExp>(x, copy);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ v_construct<QEasingCurve>(x, copy);
+ break;
+#endif
+ case QVariant::Int:
+ x->data.i = copy ? *static_cast<const int *>(copy) : 0;
+ break;
+ case QVariant::UInt:
+ x->data.u = copy ? *static_cast<const uint *>(copy) : 0u;
+ break;
+ case QVariant::Bool:
+ x->data.b = copy ? *static_cast<const bool *>(copy) : false;
+ break;
+ case QVariant::Double:
+ x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
+ break;
+ case QMetaType::Float:
+ x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
+ break;
+ case QMetaType::QObjectStar:
+ x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0;
+ break;
+ case QVariant::LongLong:
+ x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
+ break;
+ case QVariant::ULongLong:
+ x->data.ull = copy ? *static_cast<const qulonglong *>(copy) : Q_UINT64_C(0);
+ break;
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ break;
+ default:
+ void *ptr = QMetaType::construct(x->type, copy);
+ if (!ptr) {
+ x->type = QVariant::Invalid;
+ } else {
+ x->is_shared = true;
+ x->data.shared = new QVariant::PrivateShared(ptr);
+ }
+ break;
+ }
+ x->is_null = !copy;
+}
+
+static void clear(QVariant::Private *d)
+{
+ switch (d->type) {
+ case QVariant::String:
+ v_clear<QString>(d);
+ break;
+ case QVariant::Char:
+ v_clear<QChar>(d);
+ break;
+ case QVariant::StringList:
+ v_clear<QStringList>(d);
+ break;
+ case QVariant::Map:
+ v_clear<QVariantMap>(d);
+ break;
+ case QVariant::Hash:
+ v_clear<QVariantHash>(d);
+ break;
+ case QVariant::List:
+ v_clear<QVariantList>(d);
+ break;
+ case QVariant::Date:
+ v_clear<QDate>(d);
+ break;
+ case QVariant::Time:
+ v_clear<QTime>(d);
+ break;
+ case QVariant::DateTime:
+ v_clear<QDateTime>(d);
+ break;
+ case QVariant::ByteArray:
+ v_clear<QByteArray>(d);
+ break;
+ case QVariant::BitArray:
+ v_clear<QBitArray>(d);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Point:
+ v_clear<QPoint>(d);
+ break;
+ case QVariant::PointF:
+ v_clear<QPointF>(d);
+ break;
+ case QVariant::Size:
+ v_clear<QSize>(d);
+ break;
+ case QVariant::SizeF:
+ v_clear<QSizeF>(d);
+ break;
+ case QVariant::Rect:
+ v_clear<QRect>(d);
+ break;
+ case QVariant::LineF:
+ v_clear<QLineF>(d);
+ break;
+ case QVariant::Line:
+ v_clear<QLine>(d);
+ break;
+ case QVariant::RectF:
+ v_clear<QRectF>(d);
+ break;
+#endif
+ case QVariant::Url:
+ v_clear<QUrl>(d);
+ break;
+ case QVariant::Locale:
+ v_clear<QLocale>(d);
+ break;
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ v_clear<QRegExp>(d);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ v_clear<QEasingCurve>(d);
+ break;
+#endif
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QMetaType::QObjectStar:
+ break;
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Bool:
+ break;
+ default:
+ QMetaType::destroy(d->type, d->data.shared->ptr);
+ delete d->data.shared;
+ break;
+ }
+
+ d->type = QVariant::Invalid;
+ d->is_null = true;
+ d->is_shared = false;
+}
+
+static bool isNull(const QVariant::Private *d)
+{
+ switch(d->type) {
+ case QVariant::String:
+ return v_cast<QString>(d)->isNull();
+ case QVariant::Char:
+ return v_cast<QChar>(d)->isNull();
+ case QVariant::Date:
+ return v_cast<QDate>(d)->isNull();
+ case QVariant::Time:
+ return v_cast<QTime>(d)->isNull();
+ case QVariant::DateTime:
+ return v_cast<QDateTime>(d)->isNull();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->isNull();
+ case QVariant::BitArray:
+ return v_cast<QBitArray>(d)->isNull();
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ return v_cast<QSize>(d)->isNull();
+ case QVariant::SizeF:
+ return v_cast<QSizeF>(d)->isNull();
+ case QVariant::Rect:
+ return v_cast<QRect>(d)->isNull();
+ case QVariant::Line:
+ return v_cast<QLine>(d)->isNull();
+ case QVariant::LineF:
+ return v_cast<QLineF>(d)->isNull();
+ case QVariant::RectF:
+ return v_cast<QRectF>(d)->isNull();
+ case QVariant::Point:
+ return v_cast<QPoint>(d)->isNull();
+ case QVariant::PointF:
+ return v_cast<QPointF>(d)->isNull();
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+#endif
+ case QVariant::Url:
+ case QVariant::Locale:
+ case QVariant::RegExp:
+ case QVariant::StringList:
+ case QVariant::Map:
+ case QVariant::Hash:
+ case QVariant::List:
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Bool:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QMetaType::QObjectStar:
+ break;
+ }
+ return d->is_null;
+}
+
+/*
+ \internal
+ \since 4.4
+
+ We cannot use v_cast() for QMetaType's numeric types because they're smaller than QVariant::Private::Data,
+ which in turns makes v_cast() believe the value is stored in d->data.c. But
+ it's not, since we're a QMetaType type.
+ */
+template<typename T>
+inline bool compareNumericMetaType(const QVariant::Private *const a, const QVariant::Private *const b)
+{
+ return *static_cast<const T *>(a->data.shared->ptr) == *static_cast<const T *>(b->data.shared->ptr);
+}
+
+/*!
+ \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)
+{
+ switch(a->type) {
+ case QVariant::List:
+ return *v_cast<QVariantList>(a) == *v_cast<QVariantList>(b);
+ case QVariant::Map: {
+ const QVariantMap *m1 = v_cast<QVariantMap>(a);
+ const QVariantMap *m2 = v_cast<QVariantMap>(b);
+ if (m1->count() != m2->count())
+ return false;
+ QVariantMap::ConstIterator it = m1->constBegin();
+ QVariantMap::ConstIterator it2 = m2->constBegin();
+ while (it != m1->constEnd()) {
+ if (*it != *it2 || it.key() != it2.key())
+ return false;
+ ++it;
+ ++it2;
+ }
+ return true;
+ }
+ case QVariant::Hash:
+ return *v_cast<QVariantHash>(a) == *v_cast<QVariantHash>(b);
+ case QVariant::String:
+ return *v_cast<QString>(a) == *v_cast<QString>(b);
+ case QVariant::Char:
+ return *v_cast<QChar>(a) == *v_cast<QChar>(b);
+ case QVariant::StringList:
+ return *v_cast<QStringList>(a) == *v_cast<QStringList>(b);
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ return *v_cast<QSize>(a) == *v_cast<QSize>(b);
+ case QVariant::SizeF:
+ return *v_cast<QSizeF>(a) == *v_cast<QSizeF>(b);
+ case QVariant::Rect:
+ return *v_cast<QRect>(a) == *v_cast<QRect>(b);
+ case QVariant::Line:
+ return *v_cast<QLine>(a) == *v_cast<QLine>(b);
+ case QVariant::LineF:
+ return *v_cast<QLineF>(a) == *v_cast<QLineF>(b);
+ case QVariant::RectF:
+ return *v_cast<QRectF>(a) == *v_cast<QRectF>(b);
+ case QVariant::Point:
+ return *v_cast<QPoint>(a) == *v_cast<QPoint>(b);
+ case QVariant::PointF:
+ return *v_cast<QPointF>(a) == *v_cast<QPointF>(b);
+#endif
+ case QVariant::Url:
+ return *v_cast<QUrl>(a) == *v_cast<QUrl>(b);
+ case QVariant::Locale:
+ return *v_cast<QLocale>(a) == *v_cast<QLocale>(b);
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ return *v_cast<QRegExp>(a) == *v_cast<QRegExp>(b);
+#endif
+ case QVariant::Int:
+ return a->data.i == b->data.i;
+ case QVariant::UInt:
+ return a->data.u == b->data.u;
+ case QVariant::LongLong:
+ return a->data.ll == b->data.ll;
+ case QVariant::ULongLong:
+ return a->data.ull == b->data.ull;
+ case QVariant::Bool:
+ return a->data.b == b->data.b;
+ case QVariant::Double:
+ return a->data.d == b->data.d;
+ case QMetaType::Float:
+ return a->data.f == b->data.f;
+ case QMetaType::QObjectStar:
+ return a->data.o == b->data.o;
+ case QVariant::Date:
+ return *v_cast<QDate>(a) == *v_cast<QDate>(b);
+ case QVariant::Time:
+ return *v_cast<QTime>(a) == *v_cast<QTime>(b);
+ case QVariant::DateTime:
+ return *v_cast<QDateTime>(a) == *v_cast<QDateTime>(b);
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ return *v_cast<QEasingCurve>(a) == *v_cast<QEasingCurve>(b);
+#endif
+ case QVariant::ByteArray:
+ return *v_cast<QByteArray>(a) == *v_cast<QByteArray>(b);
+ case QVariant::BitArray:
+ return *v_cast<QBitArray>(a) == *v_cast<QBitArray>(b);
+ case QVariant::Invalid:
+ return true;
+ case QMetaType::Long:
+ return compareNumericMetaType<long>(a, b);
+ case QMetaType::ULong:
+ return compareNumericMetaType<ulong>(a, b);
+ case QMetaType::Short:
+ return compareNumericMetaType<short>(a, b);
+ case QMetaType::UShort:
+ return compareNumericMetaType<ushort>(a, b);
+ case QMetaType::UChar:
+ return compareNumericMetaType<uchar>(a, b);
+ case QMetaType::Char:
+ return compareNumericMetaType<char>(a, b);
+ default:
+ break;
+ }
+ if (!QMetaType::isRegistered(a->type))
+ qFatal("QVariant::compare: type %d unknown to QVariant.", a->type);
+
+ const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
+ const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
+
+ /* The reason we cannot place this test in a case branch above for the types
+ * QMetaType::VoidStar, QMetaType::QObjectStar and so forth, is that it wouldn't include
+ * user defined pointer types. */
+ const char *const typeName = QMetaType::typeName(a->type);
+ uint typeNameLen = qstrlen(typeName);
+ if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
+ return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
+
+ if (a->is_null && b->is_null)
+ return true;
+
+ return a_ptr == b_ptr;
+}
+
+/*!
+ \internal
+ */
+static qlonglong qMetaTypeNumber(const QVariant::Private *d)
+{
+ switch (d->type) {
+ case QMetaType::Int:
+ return d->data.i;
+ case QMetaType::LongLong:
+ return d->data.ll;
+ case QMetaType::Char:
+ return qlonglong(*static_cast<signed char *>(d->data.shared->ptr));
+ case QMetaType::Short:
+ return qlonglong(*static_cast<short *>(d->data.shared->ptr));
+ case QMetaType::Long:
+ return qlonglong(*static_cast<long *>(d->data.shared->ptr));
+ case QMetaType::Float:
+ return qRound64(d->data.f);
+ case QVariant::Double:
+ return qRound64(d->data.d);
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
+{
+ switch (d->type) {
+ case QVariant::UInt:
+ return d->data.u;
+ case QVariant::ULongLong:
+ return d->data.ull;
+ case QMetaType::UChar:
+ return qulonglong(*static_cast<unsigned char *>(d->data.shared->ptr));
+ case QMetaType::UShort:
+ return qulonglong(*static_cast<ushort *>(d->data.shared->ptr));
+ case QMetaType::ULong:
+ return qulonglong(*static_cast<ulong *>(d->data.shared->ptr));
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
+{
+ *ok = true;
+
+ switch (uint(d->type)) {
+ case QVariant::String:
+ return v_cast<QString>(d)->toLongLong(ok);
+ case QVariant::Char:
+ return v_cast<QChar>(d)->unicode();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->toLongLong(ok);
+ case QVariant::Bool:
+ return qlonglong(d->data.b);
+ case QVariant::Double:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ case QMetaType::LongLong:
+ return qMetaTypeNumber(d);
+ case QVariant::ULongLong:
+ case QVariant::UInt:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ return qlonglong(qMetaTypeUNumber(d));
+ }
+
+ *ok = false;
+ return Q_INT64_C(0);
+}
+
+static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
+{
+ *ok = true;
+
+ switch (uint(d->type)) {
+ case QVariant::String:
+ return v_cast<QString>(d)->toULongLong(ok);
+ case QVariant::Char:
+ return v_cast<QChar>(d)->unicode();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->toULongLong(ok);
+ case QVariant::Bool:
+ return qulonglong(d->data.b);
+ case QVariant::Double:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ case QMetaType::LongLong:
+ return qulonglong(qMetaTypeNumber(d));
+ case QVariant::ULongLong:
+ case QVariant::UInt:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ return qMetaTypeUNumber(d);
+ }
+
+ *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 == LiteralWrapper("0") || str == LiteralWrapper("false") || str.isEmpty());
+}
+
+/*!
+ \internal
+
+ Converts \a d to type \a t, which is placed in \a result.
+ */
+static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, bool *ok)
+{
+ Q_ASSERT(d->type != uint(t));
+ Q_ASSERT(result);
+
+ bool dummy;
+ if (!ok)
+ ok = &dummy;
+
+ switch (uint(t)) {
+ case QVariant::Url:
+ switch (d->type) {
+ case QVariant::String:
+ *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QVariant::String: {
+ QString *str = static_cast<QString *>(result);
+ switch (d->type) {
+ case QVariant::Char:
+ *str = QString(*v_cast<QChar>(d));
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *str = QChar::fromAscii(*static_cast<char *>(d->data.shared->ptr));
+ break;
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ *str = QString::number(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *str = QString::number(qMetaTypeUNumber(d));
+ break;
+ case QMetaType::Float:
+ *str = QString::number(d->data.f, 'g', FLT_DIG);
+ break;
+ case QVariant::Double:
+ *str = QString::number(d->data.d, 'g', DBL_DIG);
+ break;
+#if !defined(QT_NO_DATESTRING)
+ case QVariant::Date:
+ *str = v_cast<QDate>(d)->toString(Qt::ISODate);
+ break;
+ case QVariant::Time:
+ *str = v_cast<QTime>(d)->toString(Qt::ISODate);
+ break;
+ case QVariant::DateTime:
+ *str = v_cast<QDateTime>(d)->toString(Qt::ISODate);
+ break;
+#endif
+ case QVariant::Bool:
+ *str = QLatin1String(d->data.b ? "true" : "false");
+ break;
+ case QVariant::ByteArray:
+ *str = QString::fromAscii(v_cast<QByteArray>(d)->constData());
+ break;
+ case QVariant::StringList:
+ if (v_cast<QStringList>(d)->count() == 1)
+ *str = v_cast<QStringList>(d)->at(0);
+ break;
+ case QVariant::Url:
+ *str = v_cast<QUrl>(d)->toString();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ case QVariant::Char: {
+ QChar *c = static_cast<QChar *>(result);
+ switch (d->type) {
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ *c = QChar(ushort(qMetaTypeNumber(d)));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *c = QChar(ushort(qMetaTypeUNumber(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size: {
+ QSize *s = static_cast<QSize *>(result);
+ switch (d->type) {
+ case QVariant::SizeF:
+ *s = v_cast<QSizeF>(d)->toSize();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::SizeF: {
+ QSizeF *s = static_cast<QSizeF *>(result);
+ switch (d->type) {
+ case QVariant::Size:
+ *s = QSizeF(*(v_cast<QSize>(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::Line: {
+ QLine *s = static_cast<QLine *>(result);
+ switch (d->type) {
+ case QVariant::LineF:
+ *s = v_cast<QLineF>(d)->toLine();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::LineF: {
+ QLineF *s = static_cast<QLineF *>(result);
+ switch (d->type) {
+ case QVariant::Line:
+ *s = QLineF(*(v_cast<QLine>(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+#endif
+ case QVariant::StringList:
+ if (d->type == QVariant::List) {
+ QStringList *slst = static_cast<QStringList *>(result);
+ const QVariantList *list = v_cast<QVariantList >(d);
+ for (int i = 0; i < list->size(); ++i)
+ slst->append(list->at(i).toString());
+ } else if (d->type == QVariant::String) {
+ QStringList *slst = static_cast<QStringList *>(result);
+ *slst = QStringList(*v_cast<QString>(d));
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Date: {
+ QDate *dt = static_cast<QDate *>(result);
+ if (d->type == QVariant::DateTime)
+ *dt = v_cast<QDateTime>(d)->date();
+#ifndef QT_NO_DATESTRING
+ else if (d->type == QVariant::String)
+ *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate);
+#endif
+ else
+ return false;
+
+ return dt->isValid();
+ }
+ case QVariant::Time: {
+ QTime *t = static_cast<QTime *>(result);
+ switch (d->type) {
+ case QVariant::DateTime:
+ *t = v_cast<QDateTime>(d)->time();
+ break;
+#ifndef QT_NO_DATESTRING
+ case QVariant::String:
+ *t = QTime::fromString(*v_cast<QString>(d), Qt::ISODate);
+ break;
+#endif
+ default:
+ return false;
+ }
+ return t->isValid();
+ }
+ case QVariant::DateTime: {
+ QDateTime *dt = static_cast<QDateTime *>(result);
+ switch (d->type) {
+#ifndef QT_NO_DATESTRING
+ case QVariant::String:
+ *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
+ break;
+#endif
+ case QVariant::Date:
+ *dt = QDateTime(*v_cast<QDate>(d));
+ break;
+ default:
+ return false;
+ }
+ return dt->isValid();
+ }
+ case QVariant::ByteArray: {
+ QByteArray *ba = static_cast<QByteArray *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *ba = v_cast<QString>(d)->toAscii();
+ break;
+ case QVariant::Double:
+ *ba = QByteArray::number(d->data.d, 'g', DBL_DIG);
+ break;
+ case QMetaType::Float:
+ *ba = QByteArray::number(d->data.f, 'g', FLT_DIG);
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *ba = QByteArray(1, *static_cast<char *>(d->data.shared->ptr));
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *ba = QByteArray::number(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *ba = QByteArray::number(qMetaTypeUNumber(d));
+ break;
+ case QVariant::Bool:
+ *ba = QByteArray(d->data.b ? "true" : "false");
+ break;
+ default:
+ 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 QVariant::Int:
+ *static_cast<int *>(result) = int(qConvertToNumber(d, ok));
+ return *ok;
+ case QVariant::UInt:
+ *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok));
+ return *ok;
+ case QVariant::LongLong:
+ *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok);
+ return *ok;
+ case QVariant::ULongLong: {
+ *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok);
+ return *ok;
+ }
+ case QMetaType::UChar: {
+ *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok);
+ return *ok;
+ }
+ case QVariant::Bool: {
+ bool *b = static_cast<bool *>(result);
+ switch(d->type) {
+ case QVariant::ByteArray:
+ *b = qt_convertToBool<QByteArray, QByteArray>(d);
+ break;
+ case QVariant::String:
+ *b = qt_convertToBool<QString, QLatin1String>(d);
+ break;
+ case QVariant::Char:
+ *b = !v_cast<QChar>(d)->isNull();
+ break;
+ case QVariant::Double:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ *b = qMetaTypeNumber(d) != Q_INT64_C(0);
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
+ break;
+ default:
+ *b = false;
+ return false;
+ }
+ break;
+ }
+ case QVariant::Double: {
+ double *f = static_cast<double *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *f = v_cast<QString>(d)->toDouble(ok);
+ break;
+ case QVariant::ByteArray:
+ *f = v_cast<QByteArray>(d)->toDouble(ok);
+ break;
+ case QVariant::Bool:
+ *f = double(d->data.b);
+ break;
+ case QMetaType::Float:
+ *f = double(d->data.f);
+ break;
+ case QVariant::LongLong:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *f = double(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *f = double(qMetaTypeUNumber(d));
+ break;
+ default:
+ *f = 0.0;
+ return false;
+ }
+ break;
+ }
+ case QMetaType::Float: {
+ float *f = static_cast<float *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *f = v_cast<QString>(d)->toFloat(ok);
+ break;
+ case QVariant::ByteArray:
+ *f = v_cast<QByteArray>(d)->toFloat(ok);
+ break;
+ case QVariant::Bool:
+ *f = float(d->data.b);
+ break;
+ case QVariant::Double:
+ *f = float(d->data.d);
+ break;
+ case QVariant::LongLong:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *f = float(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *f = float(qMetaTypeUNumber(d));
+ break;
+ default:
+ *f = 0.0f;
+ return false;
+ }
+ break;
+ }
+ case QVariant::List:
+ if (d->type == QVariant::StringList) {
+ QVariantList *lst = static_cast<QVariantList *>(result);
+ const QStringList *slist = v_cast<QStringList>(d);
+ for (int i = 0; i < slist->size(); ++i)
+ lst->append(QVariant(slist->at(i)));
+ } else if (qstrcmp(QMetaType::typeName(d->type), "QList<QVariant>") == 0) {
+ *static_cast<QVariantList *>(result) =
+ *static_cast<QList<QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Map:
+ if (qstrcmp(QMetaType::typeName(d->type), "QMap<QString, QVariant>") == 0) {
+ *static_cast<QVariantMap *>(result) =
+ *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Hash:
+ if (qstrcmp(QMetaType::typeName(d->type), "QHash<QString, QVariant>") == 0) {
+ *static_cast<QVariantHash *>(result) =
+ *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Rect:
+ if (d->type == QVariant::RectF)
+ *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect();
+ else
+ return false;
+ break;
+ case QVariant::RectF:
+ if (d->type == QVariant::Rect)
+ *static_cast<QRectF *>(result) = *v_cast<QRect>(d);
+ else
+ return false;
+ break;
+ case QVariant::PointF:
+ if (d->type == QVariant::Point)
+ *static_cast<QPointF *>(result) = *v_cast<QPoint>(d);
+ else
+ return false;
+ break;
+ case QVariant::Point:
+ if (d->type == QVariant::PointF)
+ *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
+ default:
+ return false;
+ }
+ return true;
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+static void streamDebug(QDebug dbg, const QVariant &v)
+{
+ switch (v.userType()) {
+ case QVariant::Int:
+ dbg.nospace() << v.toInt();
+ break;
+ case QVariant::UInt:
+ dbg.nospace() << v.toUInt();
+ break;
+ case QVariant::LongLong:
+ dbg.nospace() << v.toLongLong();
+ break;
+ case QVariant::ULongLong:
+ dbg.nospace() << v.toULongLong();
+ break;
+ case QMetaType::Float:
+ dbg.nospace() << v.toFloat();
+ break;
+ case QMetaType::QObjectStar:
+ dbg.nospace() << qvariant_cast<QObject *>(v);
+ break;
+ case QVariant::Double:
+ dbg.nospace() << v.toDouble();
+ break;
+ case QVariant::Bool:
+ dbg.nospace() << v.toBool();
+ break;
+ case QVariant::String:
+ dbg.nospace() << v.toString();
+ break;
+ case QVariant::Char:
+ dbg.nospace() << v.toChar();
+ break;
+ case QVariant::StringList:
+ dbg.nospace() << v.toStringList();
+ break;
+ case QVariant::Map:
+ dbg.nospace() << v.toMap();
+ break;
+ case QVariant::Hash:
+ dbg.nospace() << v.toHash();
+ break;
+ case QVariant::List:
+ dbg.nospace() << v.toList();
+ break;
+ case QVariant::Date:
+ dbg.nospace() << v.toDate();
+ break;
+ case QVariant::Time:
+ dbg.nospace() << v.toTime();
+ break;
+ case QVariant::DateTime:
+ dbg.nospace() << v.toDateTime();
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ dbg.nospace() << v.toEasingCurve();
+ break;
+#endif
+ case QVariant::ByteArray:
+ dbg.nospace() << v.toByteArray();
+ break;
+ case QVariant::Url:
+ dbg.nospace() << v.toUrl();
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Point:
+ dbg.nospace() << v.toPoint();
+ break;
+ case QVariant::PointF:
+ dbg.nospace() << v.toPointF();
+ break;
+ case QVariant::Rect:
+ dbg.nospace() << v.toRect();
+ break;
+ case QVariant::Size:
+ dbg.nospace() << v.toSize();
+ break;
+ case QVariant::SizeF:
+ dbg.nospace() << v.toSizeF();
+ break;
+ case QVariant::Line:
+ dbg.nospace() << v.toLine();
+ break;
+ case QVariant::LineF:
+ dbg.nospace() << v.toLineF();
+ break;
+ case QVariant::RectF:
+ dbg.nospace() << v.toRectF();
+ break;
+#endif
+ case QVariant::BitArray:
+ //dbg.nospace() << v.toBitArray();
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+const QVariant::Handler qt_kernel_variant_handler = {
+ construct,
+ clear,
+ isNull,
+#ifndef QT_NO_DATASTREAM
+ 0,
+ 0,
+#endif
+ compare,
+ convert,
+ 0,
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+ streamDebug
+#else
+ 0
+#endif
+};
+
+Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
+{
+ return &qt_kernel_variant_handler;
+}
+
+
+const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
+
+/*!
+ \class QVariant
+ \brief The QVariant class acts like a union for the most common Qt data types.
+
+ \ingroup objectmodel
+ \ingroup shared
+
+
+ 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.)
+ 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
+ be converted to a particular type using canConvert().
+
+ The methods named toT() (e.g., toInt(), toString()) are const. If
+ you ask for the stored type, they return a copy of the stored
+ object. If you ask for a type that can be generated from the
+ stored type, toT() copies and converts and leaves the object
+ itself unchanged. If you ask for a type that cannot be generated
+ from the stored type, the result depends on the type; see the
+ function documentation for details.
+
+ Here is some example code to demonstrate the use of QVariant:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 0
+
+ You can even store QList<QVariant> and QMap<QString, QVariant>
+ values in a variant, so you can easily construct arbitrarily
+ complex data structures of arbitrary types. This is very powerful
+ 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.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1
+
+ QVariant can be extended to support other types than those
+ mentioned in the \l Type enum. See the \l QMetaType documentation
+ for details.
+
+ \section1 A Note on GUI Types
+
+ Because QVariant is part of the QtCore library, it cannot provide
+ conversion functions to data types defined in QtGui, such as
+ QColor, QImage, and QPixmap. In other words, there is no \c
+ toColor() function. Instead, you can use the QVariant::value() or
+ the qvariant_cast() template function. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2
+
+ The inverse conversion (e.g., from QColor to QVariant) is
+ automatic for all data types supported by QVariant, including
+ GUI-related types:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 3
+
+ \section1 Using canConvert() and convert() Consecutively
+
+ When using canConvert() and convert() consecutively, it is possible for
+ canConvert() to return true, but convert() to return false. This
+ is typically because canConvert() only reports the general ability of
+ QVariant to convert between types given suitable data; it is still
+ possible to supply data which cannot actually be converted.
+
+ For example, canConvert() 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
+ successful conversion.
+
+ \sa QMetaType
+*/
+
+/*!
+ \enum QVariant::Type
+
+ This enum type defines the types of variable that a QVariant can
+ contain.
+
+ \value Invalid no type
+ \value BitArray a QBitArray
+ \value Bitmap a QBitmap
+ \value Bool a bool
+ \value Brush a QBrush
+ \value ByteArray a QByteArray
+ \value Char a QChar
+ \value Color a QColor
+ \value Cursor a QCursor
+ \value Date a QDate
+ \value DateTime a QDateTime
+ \value Double a double
+ \value EasingCurve a QEasingCurve
+ \value Font a QFont
+ \value Hash a QVariantHash
+ \value Icon a QIcon
+ \value Image a QImage
+ \value Int an int
+ \value KeySequence a QKeySequence
+ \value Line a QLine
+ \value LineF a QLineF
+ \value List a QVariantList
+ \value Locale a QLocale
+ \value LongLong a \l qlonglong
+ \value Map a QVariantMap
+ \value Matrix a QMatrix
+ \value Transform a QTransform
+ \value Matrix4x4 a QMatrix4x4
+ \value Palette a QPalette
+ \value Pen a QPen
+ \value Pixmap a QPixmap
+ \value Point a QPoint
+ \value PointArray a QPointArray
+ \value PointF a QPointF
+ \value Polygon a QPolygon
+ \value Quaternion a QQuaternion
+ \value Rect a QRect
+ \value RectF a QRectF
+ \value RegExp a QRegExp
+ \value Region a QRegion
+ \value Size a QSize
+ \value SizeF a QSizeF
+ \value SizePolicy a QSizePolicy
+ \value String a QString
+ \value StringList a QStringList
+ \value TextFormat a QTextFormat
+ \value TextLength a QTextLength
+ \value Time a QTime
+ \value UInt a \l uint
+ \value ULongLong a \l qulonglong
+ \value Url a QUrl
+ \value Vector2D a QVector2D
+ \value Vector3D a QVector3D
+ \value Vector4D a QVector4D
+
+ \value UserType Base value for user-defined types.
+
+ \omitvalue CString
+ \omitvalue ColorGroup
+ \omitvalue IconSet
+ \omitvalue LastGuiType
+ \omitvalue LastCoreType
+ \omitvalue LastType
+*/
+
+/*!
+ \fn QVariant::QVariant()
+
+ Constructs an invalid variant.
+*/
+
+
+/*!
+ \fn QVariant::QVariant(int typeOrUserType, const void *copy)
+
+ Constructs variant of type \a typeOrUserType, and initializes with
+ \a copy if \a copy is not 0.
+
+ 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, \c QMetaType::QObjectStar and
+ \c QMetaType::QWidgetStar.
+
+ \sa QVariant::fromValue(), Type
+*/
+
+/*!
+ \fn QVariant::QVariant(Type type)
+
+ Constructs a null variant of type \a type.
+*/
+
+
+
+/*!
+ \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 0.
+*/
+
+void QVariant::create(int type, const void *copy)
+{
+ d.type = type;
+ handler->construct(&d, 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 && d.type > Char && d.type < UserType))
+ handler->clear(&d);
+}
+
+/*!
+ \fn QVariant::QVariant(const QVariant &p)
+
+ Constructs a copy of the variant, \a p, passed as the argument to
+ this constructor.
+*/
+
+QVariant::QVariant(const QVariant &p)
+ : d(p.d)
+{
+ if (d.is_shared) {
+ d.data.shared->ref.ref();
+ } else if (p.d.type > Char && p.d.type < QVariant::UserType) {
+ handler->construct(&d, p.constData());
+ d.is_null = p.d.is_null;
+ }
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ Reads the variant from the data stream, \a s.
+*/
+QVariant::QVariant(QDataStream &s)
+{
+ d.is_null = true;
+ s >> *this;
+}
+#endif //QT_NO_DATASTREAM
+
+/*!
+ \fn QVariant::QVariant(const QString &val)
+
+ Constructs a new variant with a string value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QLatin1String &val)
+
+ Constructs a new variant with a string value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const char *val)
+
+ Constructs a new variant with a string value of \a val.
+ The variant creates a deep copy of \a val, using the encoding
+ set by QTextCodec::setCodecForCStrings().
+
+ Note that \a val is converted to a QString for storing in the
+ variant and QVariant::type() will return QMetaType::QString for
+ the variant.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications.
+
+ \sa QTextCodec::setCodecForCStrings()
+*/
+
+#ifndef QT_NO_CAST_FROM_ASCII
+QVariant::QVariant(const char *val)
+{
+ QString s = QString::fromAscii(val);
+ create(String, &s);
+}
+#endif
+
+/*!
+ \fn QVariant::QVariant(const QStringList &val)
+
+ Constructs a new variant with a string list value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QMap<QString, QVariant> &val)
+
+ Constructs a new variant with a map of QVariants, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QHash<QString, QVariant> &val)
+
+ Constructs a new variant with a hash of QVariants, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QDate &val)
+
+ Constructs a new variant with a date value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QTime &val)
+
+ Constructs a new variant with a time value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QDateTime &val)
+
+ Constructs a new variant with a date/time value, \a val.
+*/
+
+/*!
+ \since 4.7
+ \fn QVariant::QVariant(const QEasingCurve &val)
+
+ Constructs a new variant with an easing curve value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QByteArray &val)
+
+ Constructs a new variant with a bytearray value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QBitArray &val)
+
+ Constructs a new variant with a bitarray value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QPoint &val)
+
+ Constructs a new variant with a point value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QPointF &val)
+
+ Constructs a new variant with a point value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QRectF &val)
+
+ Constructs a new variant with a rect value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QLineF &val)
+
+ Constructs a new variant with a line value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QLine &val)
+
+ Constructs a new variant with a line value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QRect &val)
+
+ Constructs a new variant with a rect value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QSize &val)
+
+ Constructs a new variant with a size value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QSizeF &val)
+
+ Constructs a new variant with a size value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QUrl &val)
+
+ Constructs a new variant with a url value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(int val)
+
+ Constructs a new variant with an integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(uint val)
+
+ Constructs a new variant with an unsigned integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(qlonglong val)
+
+ Constructs a new variant with a long long integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(qulonglong val)
+
+ Constructs a new variant with an unsigned long long integer value, \a val.
+*/
+
+
+/*!
+ \fn QVariant::QVariant(bool val)
+
+ Constructs a new variant with a boolean value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(double val)
+
+ Constructs a new variant with a floating point value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(float val)
+
+ Constructs a new variant with a floating point value, \a val.
+ \since 4.6
+*/
+
+/*!
+ \fn QVariant::QVariant(const QList<QVariant> &val)
+
+ Constructs a new variant with a list value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QChar &c)
+
+ Constructs a new variant with a char value, \a c.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QLocale &l)
+
+ Constructs a new variant with a locale value, \a l.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QRegExp &regExp)
+
+ Constructs a new variant with the regexp value \a regExp.
+*/
+
+/*! \since 4.2
+ \fn QVariant::QVariant(Qt::GlobalColor color)
+
+ Constructs a new variant of type QVariant::Color and initializes
+ it with \a color.
+
+ This is a convenience constructor that allows \c{QVariant(Qt::blue);}
+ to create a valid QVariant storing a QColor.
+
+ Note: This constructor will assert if the application does not link
+ to the Qt GUI library.
+ */
+
+QVariant::QVariant(Type type)
+{ create(type, 0); }
+QVariant::QVariant(int typeOrUserType, const void *copy)
+{ create(typeOrUserType, copy); d.is_null = false; }
+
+/*! \internal
+ flags is true if it is a pointer type
+ */
+QVariant::QVariant(int typeOrUserType, const void *copy, uint flags)
+{
+ if (flags) { //type is a pointer type
+ d.type = typeOrUserType;
+ d.data.ptr = *reinterpret_cast<void *const*>(copy);
+ d.is_null = false;
+ } else {
+ create(typeOrUserType, copy);
+ d.is_null = false;
+ }
+}
+
+QVariant::QVariant(int val)
+{ d.is_null = false; d.type = Int; d.data.i = val; }
+QVariant::QVariant(uint val)
+{ d.is_null = false; d.type = UInt; d.data.u = val; }
+QVariant::QVariant(qlonglong val)
+{ d.is_null = false; d.type = LongLong; d.data.ll = val; }
+QVariant::QVariant(qulonglong val)
+{ d.is_null = false; d.type = ULongLong; d.data.ull = val; }
+QVariant::QVariant(bool val)
+{ d.is_null = false; d.type = Bool; d.data.b = val; }
+QVariant::QVariant(double val)
+{ d.is_null = false; d.type = Double; d.data.d = val; }
+
+QVariant::QVariant(const QByteArray &val)
+{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); }
+QVariant::QVariant(const QBitArray &val)
+{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); }
+QVariant::QVariant(const QString &val)
+{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); }
+QVariant::QVariant(const QChar &val)
+{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); }
+QVariant::QVariant(const QLatin1String &val)
+{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
+QVariant::QVariant(const QStringList &val)
+{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); }
+
+QVariant::QVariant(const QDate &val)
+{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); }
+QVariant::QVariant(const QTime &val)
+{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); }
+QVariant::QVariant(const QDateTime &val)
+{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); }
+#ifndef QT_BOOTSTRAPPED
+QVariant::QVariant(const QEasingCurve &val)
+{ d.is_null = false; d.type = EasingCurve; v_construct<QEasingCurve>(&d, val); }
+#endif
+QVariant::QVariant(const QList<QVariant> &list)
+{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); }
+QVariant::QVariant(const QMap<QString, QVariant> &map)
+{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); }
+QVariant::QVariant(const QHash<QString, QVariant> &hash)
+{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, hash); }
+#ifndef QT_NO_GEOM_VARIANT
+QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); }
+QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); }
+QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); }
+QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); }
+QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); }
+QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); }
+QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); }
+QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); }
+#endif
+QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
+#ifndef QT_NO_REGEXP
+QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
+#endif
+QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
+
+/*!
+ 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
+ particular, QVariant::UserType is returned here only if the value
+ is equal or greater than QMetaType::User.
+
+ Note that return values in the ranges QVariant::Char through
+ QVariant::RegExp and QVariant::Font through QVariant::Transform
+ correspond to the values in the ranges QMetaType::QChar through
+ QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion.
+
+ Pay particular attention when working with char and QChar
+ variants. Note that there is no QVariant constructor specifically
+ for type char, but there is one for QChar. For a variant of type
+ QChar, this function returns QVariant::Char, which is the same as
+ QMetaType::QChar, but for a variant of type \c char, this function
+ returns QMetaType::Char, which is \e not the same as
+ QVariant::Char.
+
+ Also note that the types \c void*, \c long, \c short, \c unsigned
+ \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c
+ QObject*, and \c QWidget* are represented in QMetaType::Type but
+ not in QVariant::Type, and they can be returned by this function.
+ However, they are considered to be user defined types when tested
+ against QVariant::Type.
+
+ To test whether an instance of QVariant contains a data type that
+ is compatible with the data type you are interested in, use
+ canConvert().
+*/
+
+QVariant::Type QVariant::type() const
+{
+ return d.type >= QMetaType::User ? UserType : static_cast<Type>(d.type);
+}
+
+/*!
+ Returns the storage type of the value stored in the variant. For
+ non-user types, this is the same as type().
+
+ \sa type()
+*/
+
+int QVariant::userType() const
+{
+ return d.type;
+}
+
+/*!
+ Assigns the value of the variant \a variant to this 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 if (variant.d.type > Char && variant.d.type < UserType) {
+ d.type = variant.d.type;
+ handler->construct(&d, variant.constData());
+ d.is_null = variant.d.is_null;
+ } else {
+ d = variant.d;
+ }
+
+ return *this;
+}
+
+/*!
+ \fn void QVariant::swap(QVariant &other)
+ \since 4.8
+
+ Swaps variant \a other with this variant. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ \fn void QVariant::detach()
+
+ \internal
+*/
+
+void QVariant::detach()
+{
+ if (!d.is_shared || d.data.shared->ref == 1)
+ return;
+
+ Private dd;
+ dd.type = d.type;
+ handler->construct(&dd, constData());
+ if (!d.data.shared->ref.deref())
+ handler->clear(&d);
+ d.data.shared = dd.data.shared;
+}
+
+/*!
+ \fn bool QVariant::isDetached() const
+
+ \internal
+*/
+
+// ### Qt 5: change typeName()(and froends= to return a QString. Suggestion from Harald.
+/*!
+ Returns the name of the type stored in the variant. The returned
+ strings describe the C++ datatype used to store the data: for
+ example, "QFont", "QString", or "QVariantList". An Invalid
+ variant returns 0.
+*/
+const char *QVariant::typeName() const
+{
+ return typeToName(Type(d.type));
+}
+
+/*!
+ Convert this variant to type Invalid and free up any resources
+ used.
+*/
+void QVariant::clear()
+{
+ if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type < UserType && d.type > Char))
+ handler->clear(&d);
+ d.type = Invalid;
+ d.is_null = true;
+ d.is_shared = false;
+}
+
+/*!
+ Converts the enum representation of the storage type, \a typ, to
+ its string representation.
+
+ Returns a null pointer if the type is QVariant::Invalid or doesn't exist.
+*/
+const char *QVariant::typeToName(Type typ)
+{
+ if (typ == Invalid)
+ return 0;
+ if (typ == UserType)
+ return "UserType";
+
+ return QMetaType::typeName(typ);
+}
+
+
+/*!
+ 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)
+{
+ if (!name || !*name)
+ return Invalid;
+ if (strcmp(name, "Q3CString") == 0)
+ return ByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return Icon;
+ if (strcmp(name, "UserType") == 0)
+ return UserType;
+
+ int metaType = QMetaType::type(name);
+ return metaType <= int(LastGuiType) ? QVariant::Type(metaType) : UserType;
+}
+
+#ifndef QT_NO_DATASTREAM
+enum { MapFromThreeCount = 36 };
+static const ushort map_from_three[MapFromThreeCount] =
+{
+ QVariant::Invalid,
+ QVariant::Map,
+ QVariant::List,
+ QVariant::String,
+ QVariant::StringList,
+ QVariant::Font,
+ QVariant::Pixmap,
+ QVariant::Brush,
+ QVariant::Rect,
+ QVariant::Size,
+ QVariant::Color,
+ QVariant::Palette,
+ 63, // ColorGroup
+ QVariant::Icon,
+ QVariant::Point,
+ QVariant::Image,
+ QVariant::Int,
+ QVariant::UInt,
+ QVariant::Bool,
+ QVariant::Double,
+ QVariant::ByteArray,
+ QVariant::Polygon,
+ QVariant::Region,
+ QVariant::Bitmap,
+ QVariant::Cursor,
+ QVariant::SizePolicy,
+ QVariant::Date,
+ QVariant::Time,
+ QVariant::DateTime,
+ QVariant::ByteArray,
+ QVariant::BitArray,
+ QVariant::KeySequence,
+ QVariant::Pen,
+ QVariant::LongLong,
+ QVariant::ULongLong,
+ QVariant::EasingCurve
+};
+
+/*!
+ Internal function for loading a variant from stream \a s. Use the
+ stream operators instead.
+
+ \internal
+*/
+void QVariant::load(QDataStream &s)
+{
+ clear();
+
+ quint32 u;
+ s >> u;
+ if (s.version() < QDataStream::Qt_4_0) {
+ if (u >= MapFromThreeCount)
+ return;
+ u = map_from_three[u];
+ }
+ qint8 is_null = false;
+ if (s.version() >= QDataStream::Qt_4_2)
+ s >> is_null;
+ if (u == QVariant::UserType) {
+ QByteArray name;
+ s >> name;
+ u = QMetaType::type(name);
+ if (!u) {
+ s.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+ create(static_cast<int>(u), 0);
+ d.is_null = is_null;
+
+ if (!isValid()) {
+ // Since we wrote something, we should read something
+ QString x;
+ s >> x;
+ d.is_null = true;
+ return;
+ }
+
+ // const cast is safe since we operate on a newly constructed variant
+ if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) {
+ s.setStatus(QDataStream::ReadCorruptData);
+ qWarning("QVariant::load: unable to load type %d.", d.type);
+ }
+}
+
+/*!
+ Internal function for saving a variant to the stream \a s. Use the
+ stream operators instead.
+
+ \internal
+*/
+void QVariant::save(QDataStream &s) const
+{
+ quint32 tp = type();
+ if (s.version() < QDataStream::Qt_4_0) {
+ int i;
+ for (i = MapFromThreeCount - 1; i >= 0; i--) {
+ if (map_from_three[i] == tp) {
+ tp = i;
+ break;
+ }
+ }
+ if (i == -1) {
+ s << QVariant();
+ return;
+ }
+ }
+ s << tp;
+ if (s.version() >= QDataStream::Qt_4_2)
+ s << qint8(d.is_null);
+ if (tp == QVariant::UserType) {
+ s << QMetaType::typeName(userType());
+ }
+
+ if (!isValid()) {
+ s << QString();
+ return;
+ }
+
+ if (!QMetaType::save(s, d.type, constData())) {
+ Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
+ qWarning("QVariant::save: unable to save type %d.", d.type);
+ }
+}
+
+/*!
+ \since 4.4
+
+ Reads a variant \a p from the stream \a s.
+
+ \sa \link datastreamformat.html Format of the QDataStream
+ operators \endlink
+*/
+QDataStream& operator>>(QDataStream &s, QVariant &p)
+{
+ p.load(s);
+ return s;
+}
+
+/*!
+ Writes a variant \a p to the stream \a s.
+
+ \sa \link datastreamformat.html Format of the QDataStream
+ operators \endlink
+*/
+QDataStream& operator<<(QDataStream &s, const QVariant &p)
+{
+ p.save(s);
+ return s;
+}
+
+/*!
+ 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;
+}
+
+/*!
+ 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
+
+/*!
+ \fn bool QVariant::isValid() const
+
+ Returns true if the storage type of this variant is not
+ QVariant::Invalid; otherwise returns false.
+*/
+
+template <typename T>
+inline T qVariantToHelper(const QVariant::Private &d, QVariant::Type t,
+ const QVariant::Handler *handler, T * = 0)
+{
+ if (d.type == t)
+ return *v_cast<T>(&d);
+
+ T ret;
+ handler->convert(&d, t, &ret, 0);
+ return ret;
+}
+
+/*!
+ \fn QStringList QVariant::toStringList() const
+
+ Returns the variant as a QStringList if the variant has type()
+ StringList, \l String, or \l List of a type that can be converted
+ to QString; otherwise returns an empty list.
+
+ \sa canConvert(), convert()
+*/
+QStringList QVariant::toStringList() const
+{
+ return qVariantToHelper<QStringList>(d, StringList, handler);
+}
+
+/*!
+ Returns the variant as a QString if the variant has type() \l
+ String, \l Bool, \l ByteArray, \l Char, \l Date, \l DateTime, \l
+ Double, \l Int, \l LongLong, \l StringList, \l Time, \l UInt, or
+ \l ULongLong; otherwise returns an empty string.
+
+ \sa canConvert(), convert()
+*/
+QString QVariant::toString() const
+{
+ return qVariantToHelper<QString>(d, String, handler);
+}
+
+/*!
+ Returns the variant as a QMap<QString, QVariant> if the variant
+ has type() \l Map; otherwise returns an empty map.
+
+ \sa canConvert(), convert()
+*/
+QVariantMap QVariant::toMap() const
+{
+ return qVariantToHelper<QVariantMap>(d, Map, handler);
+}
+
+/*!
+ Returns the variant as a QHash<QString, QVariant> if the variant
+ has type() \l Hash; otherwise returns an empty map.
+
+ \sa canConvert(), convert()
+*/
+QVariantHash QVariant::toHash() const
+{
+ return qVariantToHelper<QVariantHash>(d, Hash, handler);
+}
+
+/*!
+ \fn QDate QVariant::toDate() const
+
+ Returns the variant as a QDate if the variant has type() \l Date,
+ \l DateTime, or \l String; otherwise returns an invalid date.
+
+ If the type() is \l String, an invalid date will be returned if the
+ string cannot be parsed as a Qt::ISODate format date.
+
+ \sa canConvert(), convert()
+*/
+QDate QVariant::toDate() const
+{
+ return qVariantToHelper<QDate>(d, Date, handler);
+}
+
+/*!
+ \fn QTime QVariant::toTime() const
+
+ Returns the variant as a QTime if the variant has type() \l Time,
+ \l DateTime, or \l String; otherwise returns an invalid time.
+
+ If the type() is \l String, an invalid time will be returned if
+ the string cannot be parsed as a Qt::ISODate format time.
+
+ \sa canConvert(), convert()
+*/
+QTime QVariant::toTime() const
+{
+ return qVariantToHelper<QTime>(d, Time, handler);
+}
+
+/*!
+ \fn QDateTime QVariant::toDateTime() const
+
+ Returns the variant as a QDateTime if the variant has type() \l
+ DateTime, \l Date, or \l String; otherwise returns an invalid
+ date/time.
+
+ If the type() is \l String, an invalid date/time will be returned
+ if the string cannot be parsed as a Qt::ISODate format date/time.
+
+ \sa canConvert(), convert()
+*/
+QDateTime QVariant::toDateTime() const
+{
+ return qVariantToHelper<QDateTime>(d, DateTime, handler);
+}
+
+/*!
+ \since 4.7
+ \fn QEasingCurve QVariant::toEasingCurve() const
+
+ Returns the variant as a QEasingCurve if the variant has type() \l
+ EasingCurve; otherwise returns a default easing curve.
+
+ \sa canConvert(), convert()
+*/
+#ifndef QT_BOOTSTRAPPED
+QEasingCurve QVariant::toEasingCurve() const
+{
+ return qVariantToHelper<QEasingCurve>(d, EasingCurve, handler);
+}
+#endif
+
+/*!
+ \fn QByteArray QVariant::toByteArray() const
+
+ Returns the variant as a QByteArray if the variant has type() \l
+ ByteArray or \l String (converted using QString::fromAscii());
+ otherwise returns an empty byte array.
+
+ \sa canConvert(), convert()
+*/
+QByteArray QVariant::toByteArray() const
+{
+ return qVariantToHelper<QByteArray>(d, ByteArray, handler);
+}
+
+#ifndef QT_NO_GEOM_VARIANT
+/*!
+ \fn QPoint QVariant::toPoint() const
+
+ Returns the variant as a QPoint if the variant has type()
+ \l Point or \l PointF; otherwise returns a null QPoint.
+
+ \sa canConvert(), convert()
+*/
+QPoint QVariant::toPoint() const
+{
+ return qVariantToHelper<QPoint>(d, Point, handler);
+}
+
+/*!
+ \fn QRect QVariant::toRect() const
+
+ Returns the variant as a QRect if the variant has type() \l Rect;
+ otherwise returns an invalid QRect.
+
+ \sa canConvert(), convert()
+*/
+QRect QVariant::toRect() const
+{
+ return qVariantToHelper<QRect>(d, Rect, handler);
+}
+
+/*!
+ \fn QSize QVariant::toSize() const
+
+ Returns the variant as a QSize if the variant has type() \l Size;
+ otherwise returns an invalid QSize.
+
+ \sa canConvert(), convert()
+*/
+QSize QVariant::toSize() const
+{
+ return qVariantToHelper<QSize>(d, Size, handler);
+}
+
+/*!
+ \fn QSizeF QVariant::toSizeF() const
+
+ Returns the variant as a QSizeF if the variant has type() \l
+ SizeF; otherwise returns an invalid QSizeF.
+
+ \sa canConvert(), convert()
+*/
+QSizeF QVariant::toSizeF() const
+{
+ return qVariantToHelper<QSizeF>(d, SizeF, handler);
+}
+
+/*!
+ \fn QRectF QVariant::toRectF() const
+
+ Returns the variant as a QRectF if the variant has type() \l Rect
+ or \l RectF; otherwise returns an invalid QRectF.
+
+ \sa canConvert(), convert()
+*/
+QRectF QVariant::toRectF() const
+{
+ return qVariantToHelper<QRectF>(d, RectF, handler);
+}
+
+/*!
+ \fn QLineF QVariant::toLineF() const
+
+ Returns the variant as a QLineF if the variant has type() \l
+ LineF; otherwise returns an invalid QLineF.
+
+ \sa canConvert(), convert()
+*/
+QLineF QVariant::toLineF() const
+{
+ return qVariantToHelper<QLineF>(d, LineF, handler);
+}
+
+/*!
+ \fn QLine QVariant::toLine() const
+
+ Returns the variant as a QLine if the variant has type() \l Line;
+ otherwise returns an invalid QLine.
+
+ \sa canConvert(), convert()
+*/
+QLine QVariant::toLine() const
+{
+ return qVariantToHelper<QLine>(d, Line, handler);
+}
+
+/*!
+ \fn QPointF QVariant::toPointF() const
+
+ Returns the variant as a QPointF if the variant has type() \l
+ Point or \l PointF; otherwise returns a null QPointF.
+
+ \sa canConvert(), convert()
+*/
+QPointF QVariant::toPointF() const
+{
+ return qVariantToHelper<QPointF>(d, PointF, handler);
+}
+
+#endif // QT_NO_GEOM_VARIANT
+
+/*!
+ \fn QUrl QVariant::toUrl() const
+
+ Returns the variant as a QUrl if the variant has type()
+ \l Url; otherwise returns an invalid QUrl.
+
+ \sa canConvert(), convert()
+*/
+QUrl QVariant::toUrl() const
+{
+ return qVariantToHelper<QUrl>(d, Url, handler);
+}
+
+/*!
+ \fn QLocale QVariant::toLocale() const
+
+ Returns the variant as a QLocale if the variant has type()
+ \l Locale; otherwise returns an invalid QLocale.
+
+ \sa canConvert(), convert()
+*/
+QLocale QVariant::toLocale() const
+{
+ return qVariantToHelper<QLocale>(d, Locale, handler);
+}
+
+/*!
+ \fn QRegExp QVariant::toRegExp() const
+ \since 4.1
+
+ Returns the variant as a QRegExp if the variant has type() \l
+ RegExp; otherwise returns an empty QRegExp.
+
+ \sa canConvert(), convert()
+*/
+#ifndef QT_NO_REGEXP
+QRegExp QVariant::toRegExp() const
+{
+ return qVariantToHelper<QRegExp>(d, RegExp, handler);
+}
+#endif
+
+/*!
+ \fn QChar QVariant::toChar() const
+
+ Returns the variant as a QChar if the variant has type() \l Char,
+ \l Int, or \l UInt; otherwise returns an invalid QChar.
+
+ \sa canConvert(), convert()
+*/
+QChar QVariant::toChar() const
+{
+ return qVariantToHelper<QChar>(d, Char, handler);
+}
+
+/*!
+ Returns the variant as a QBitArray if the variant has type()
+ \l BitArray; otherwise returns an empty bit array.
+
+ \sa canConvert(), convert()
+*/
+QBitArray QVariant::toBitArray() const
+{
+ return qVariantToHelper<QBitArray>(d, BitArray, handler);
+}
+
+template <typename T>
+inline T qNumVariantToHelper(const QVariant::Private &d,
+ const QVariant::Handler *handler, bool *ok, const T& val)
+{
+ uint t = qMetaTypeId<T>();
+ if (ok)
+ *ok = true;
+ if (d.type == t)
+ return val;
+
+ T ret;
+ if (!handler->convert(&d, QVariant::Type(t), &ret, ok) && ok)
+ *ok = false;
+ return ret;
+}
+
+/*!
+ Returns the variant as an int if the variant has type() \l Int,
+ \l Bool, \l ByteArray, \l Char, \l Double, \l LongLong, \l
+ String, \l UInt, or \l ULongLong; otherwise returns 0.
+
+ 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.
+
+ \bold{Warning:} If the value is convertible to a \l LongLong but is too
+ large to be represented in an int, the resulting arithmetic overflow will
+ not be reflected in \a ok. A simple workaround is to use QString::toInt().
+ Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code.
+
+ \sa canConvert(), convert()
+*/
+int QVariant::toInt(bool *ok) const
+{
+ return qNumVariantToHelper<int>(d, handler, ok, d.data.i);
+}
+
+/*!
+ Returns the variant as an unsigned int if the variant has type()
+ \l UInt, \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l
+ LongLong, \l String, or \l ULongLong; otherwise returns 0.
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to an unsigned int; otherwise \c{*}\a{ok} is set to false.
+
+ \bold{Warning:} If the value is convertible to a \l ULongLong but is too
+ large to be represented in an unsigned int, the resulting arithmetic overflow will
+ not be reflected in \a ok. A simple workaround is to use QString::toUInt().
+ Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code.
+
+ \sa canConvert(), convert()
+*/
+uint QVariant::toUInt(bool *ok) const
+{
+ return qNumVariantToHelper<uint>(d, handler, ok, d.data.u);
+}
+
+/*!
+ Returns the variant as a long long int if the variant has type()
+ \l LongLong, \l Bool, \l ByteArray, \l Char, \l Double, \l Int,
+ \l String, \l UInt, or \l ULongLong; otherwise returns 0.
+
+ 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(), convert()
+*/
+qlonglong QVariant::toLongLong(bool *ok) const
+{
+ return qNumVariantToHelper<qlonglong>(d, handler, ok, d.data.ll);
+}
+
+/*!
+ Returns the variant as as an unsigned long long int if the
+ variant has type() \l ULongLong, \l Bool, \l ByteArray, \l Char,
+ \l Double, \l Int, \l LongLong, \l String, or \l UInt; otherwise
+ returns 0.
+
+ 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(), convert()
+*/
+qulonglong QVariant::toULongLong(bool *ok) const
+{
+ return qNumVariantToHelper<qulonglong>(d, handler, ok, d.data.ull);
+}
+
+/*!
+ Returns the variant as a bool if the variant has type() Bool.
+
+ Returns true if the variant has type() \l Bool, \l Char, \l Double,
+ \l Int, \l LongLong, \l UInt, or \l ULongLong and the value is
+ non-zero, or if the variant has type \l String or \l ByteArray and
+ its lower-case content is not empty, "0" or "false"; otherwise
+ returns false.
+
+ \sa canConvert(), convert()
+*/
+bool QVariant::toBool() const
+{
+ if (d.type == Bool)
+ return d.data.b;
+
+ bool res = false;
+ handler->convert(&d, Bool, &res, 0);
+
+ return res;
+}
+
+/*!
+ Returns the variant as a double if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ 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(), convert()
+*/
+double QVariant::toDouble(bool *ok) const
+{
+ return qNumVariantToHelper<double>(d, handler, ok, d.data.d);
+}
+
+/*!
+ Returns the variant as a float if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ \since 4.6
+
+ 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(), convert()
+*/
+float QVariant::toFloat(bool *ok) const
+{
+ return qNumVariantToHelper<float>(d, handler, ok, d.data.f);
+}
+
+/*!
+ Returns the variant as a qreal if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ \since 4.6
+
+ 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(), convert()
+*/
+qreal QVariant::toReal(bool *ok) const
+{
+ return qNumVariantToHelper<qreal>(d, handler, ok, d.data.real);
+}
+
+/*!
+ Returns the variant as a QVariantList if the variant has type()
+ \l List or \l StringList; otherwise returns an empty list.
+
+ \sa canConvert(), convert()
+*/
+QVariantList QVariant::toList() const
+{
+ return qVariantToHelper<QVariantList>(d, List, handler);
+}
+
+/*! \fn QVariant::canCast(Type t) const
+ Use canConvert() instead.
+*/
+
+/*! \fn QVariant::cast(Type t)
+ Use convert() instead.
+*/
+
+
+static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
+{
+/*Invalid*/ 0,
+
+/*Bool*/ 1 << QVariant::Double | 1 << QVariant::Int | 1 << QVariant::UInt
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::ByteArray
+ | 1 << QVariant::String | 1 << QVariant::Char,
+
+/*Int*/ 1 << QVariant::UInt | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*UInt*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*LLong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*ULlong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*double*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::ULongLong
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::ByteArray,
+
+/*QChar*/ 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::ULongLong,
+
+/*QMap*/ 0,
+
+/*QList*/ 1 << QVariant::StringList,
+
+/*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int
+ | 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double
+ | 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char
+ | 1 << QVariant::Url,
+
+/*QStringList*/ 1 << QVariant::List | 1 << QVariant::String,
+
+/*QByteArray*/ 1 << QVariant::String | 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::Bool
+ | 1 << QVariant::Double | 1 << QVariant::LongLong | 1 << QVariant::ULongLong,
+
+/*QBitArray*/ 0,
+
+/*QDate*/ 1 << QVariant::String | 1 << QVariant::DateTime,
+
+/*QTime*/ 1 << QVariant::String | 1 << QVariant::DateTime,
+
+/*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date,
+
+/*QUrl*/ 1 << QVariant::String,
+
+/*QLocale*/ 0,
+
+/*QRect*/ 1 << QVariant::RectF,
+
+/*QRectF*/ 1 << QVariant::Rect,
+
+/*QSize*/ 1 << QVariant::SizeF,
+
+/*QSizeF*/ 1 << QVariant::Size,
+
+/*QLine*/ 1 << QVariant::LineF,
+
+/*QLineF*/ 1 << QVariant::Line,
+
+/*QPoint*/ 1 << QVariant::PointF,
+
+/*QPointF*/ 1 << QVariant::Point,
+
+/*QRegExp*/ 0,
+
+/*QHash*/ 0,
+
+/*QEasingCurve*/ 0
+};
+
+/*!
+ Returns true if the variant's type can be cast to the requested
+ type, \a t. Such casting is done automatically when calling the
+ toInt(), toBool(), ... methods.
+
+ The following casts are done automatically:
+
+ \table
+ \header \o Type \o Automatically Cast To
+ \row \o \l Bool \o \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l ByteArray \o \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l Char \o \l Bool, \l Int, \l UInt, \l LongLong, \l ULongLong
+ \row \o \l Color \o \l String
+ \row \o \l Date \o \l DateTime, \l String
+ \row \o \l DateTime \o \l Date, \l String, \l Time
+ \row \o \l Double \o \l Bool, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l Font \o \l String
+ \row \o \l Int \o \l Bool, \l Char, \l Double, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l KeySequence \o \l Int, \l String
+ \row \o \l List \o \l StringList (if the list's items can be converted to strings)
+ \row \o \l LongLong \o \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l String, \l UInt, \l ULongLong
+ \row \o \l Point \o PointF
+ \row \o \l Rect \o RectF
+ \row \o \l String \o \l Bool, \l ByteArray, \l Char, \l Color, \l Date, \l DateTime, \l Double,
+ \l Font, \l Int, \l KeySequence, \l LongLong, \l StringList, \l Time, \l UInt,
+ \l ULongLong
+ \row \o \l StringList \o \l List, \l String (if the list contains exactly one item)
+ \row \o \l Time \o \l String
+ \row \o \l UInt \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l ULongLong
+ \row \o \l ULongLong \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt
+ \endtable
+
+ \sa convert()
+*/
+bool QVariant::canConvert(Type t) const
+{
+ //we can treat floats as double
+ //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
+ //which can't be handled by qCanConvertMatrix
+ //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
+ if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+
+ if (currentType == uint(t))
+ return true;
+
+ if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ switch (uint(t)) {
+ case QVariant::Int:
+ return currentType == QVariant::KeySequence
+ || currentType == QMetaType::ULong
+ || currentType == QMetaType::Long
+ || currentType == QMetaType::UShort
+ || currentType == QMetaType::UChar
+ || currentType == QMetaType::Char
+ || currentType == QMetaType::Short;
+ 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;
+ case QVariant::String:
+ return currentType == QVariant::KeySequence || currentType == QVariant::Font
+ || currentType == QVariant::Color;
+ case QVariant::KeySequence:
+ return currentType == QVariant::String || currentType == QVariant::Int;
+ 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::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
+ default:
+ return false;
+ }
+ }
+
+ if(t == String && currentType == StringList)
+ return v_cast<QStringList>(&d)->count() == 1;
+ else
+ return qCanConvertMatrix[t] & (1 << currentType);
+}
+
+/*!
+ Casts the variant to the requested type, \a t. If the cast cannot be
+ done, the variant is cleared. Returns true if the current type of
+ the variant was successfully cast; otherwise returns false.
+
+ \warning For historical reasons, converting a null QVariant results
+ in a null value of the desired type (e.g., an empty string for
+ QString) and a result of false.
+
+ \sa canConvert(), clear()
+*/
+
+bool QVariant::convert(Type t)
+{
+ if (d.type == uint(t))
+ return true;
+
+ QVariant oldValue = *this;
+
+ clear();
+ if (!oldValue.canConvert(t))
+ return false;
+
+ create(t, 0);
+ if (oldValue.isNull())
+ return false;
+
+ bool isOk = true;
+ if (!handler->convert(&oldValue.d, t, data(), &isOk))
+ isOk = false;
+ d.is_null = !isOk;
+ return isOk;
+}
+
+/*!
+ \fn bool operator==(const QVariant &v1, const QVariant &v2)
+
+ \relates QVariant
+
+ Returns true if \a v1 and \a v2 are equal; otherwise returns false.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+/*!
+ \fn bool operator!=(const QVariant &v1, const QVariant &v2)
+
+ \relates QVariant
+
+ Returns false if \a v1 and \a v2 are equal; otherwise returns true.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+
+/*! \fn bool QVariant::operator==(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if they are
+ equal; otherwise returns false.
+
+ In the case of custom types, their equalness operators are not called.
+ Instead the values' addresses are compared.
+*/
+
+/*!
+ \fn bool QVariant::operator!=(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if they are not
+ equal; otherwise returns false.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+
+static bool qIsNumericType(uint tp)
+{
+ return (tp >= QVariant::Bool && tp <= QVariant::Double)
+ || (tp >= QMetaType::Long && tp <= QMetaType::Float);
+}
+
+static bool qIsFloatingPoint(uint tp)
+{
+ return tp == QVariant::Double || tp == QMetaType::Float;
+}
+
+/*! \internal
+ */
+bool QVariant::cmp(const QVariant &v) const
+{
+ QVariant v2 = v;
+ if (d.type != v2.d.type) {
+ if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) {
+ if (qIsFloatingPoint(d.type) || qIsFloatingPoint(v.d.type))
+ return qFuzzyCompare(toReal(), v.toReal());
+ else
+ return toLongLong() == v.toLongLong();
+ }
+ if (!v2.canConvert(Type(d.type)) || !v2.convert(Type(d.type)))
+ return false;
+ }
+ return handler->compare(&d, &v2.d);
+}
+
+/*! \internal
+ */
+
+const void *QVariant::constData() const
+{
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
+}
+
+/*!
+ \fn const void* QVariant::data() const
+
+ \internal
+*/
+
+/*! \internal */
+void* QVariant::data()
+{
+ detach();
+ return const_cast<void *>(constData());
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \internal
+ */
+void *QVariant::castOrDetach(Type t)
+{
+ if (d.type != uint(t)) {
+ if (!convert(t))
+ create(t, 0);
+ } else {
+ detach();
+ }
+ return data();
+}
+#endif
+
+/*!
+ Returns true if this is a NULL variant, false otherwise.
+*/
+bool QVariant::isNull() const
+{
+ return handler->isNull(&d);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QVariant &v)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QVariant(" << v.typeName() << ", ";
+ QVariant::handler->debugStream(dbg, v);
+ dbg.nospace() << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QVariant to QDebug");
+ return dbg;
+ Q_UNUSED(v);
+#endif
+}
+
+QDebug operator<<(QDebug dbg, const QVariant::Type p)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QVariant::" << QVariant::typeToName(p);
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QVariant::Type to QDebug");
+ return dbg;
+ Q_UNUSED(p);
+#endif
+}
+#endif
+
+/*!
+ \fn int &QVariant::asInt()
+
+ Use toInt() instead.
+*/
+
+/*!
+ \fn uint &QVariant::asUInt()
+
+ Use toUInt() instead.
+*/
+
+/*!
+ \fn qlonglong &QVariant::asLongLong()
+
+ Use toLongLong() instead.
+*/
+
+/*!
+ \fn qulonglong &QVariant::asULongLong()
+
+ Use toULongLong() instead.
+*/
+
+/*!
+ \fn bool &QVariant::asBool()
+
+ Use toBool() instead.
+*/
+
+/*!
+ \fn double &QVariant::asDouble()
+
+ Use toDouble() instead.
+*/
+
+/*!
+ \fn QByteArray &QVariant::asByteArray()
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QBitArray &QVariant::asBitArray()
+
+ Use toBitArray() instead.
+*/
+
+/*!
+ \fn QString &QVariant::asString()
+
+ Use toString() instead.
+*/
+
+/*!
+ \fn QStringList &QVariant::asStringList()
+
+ Use toStringList() instead.
+*/
+
+/*!
+ \fn QDate &QVariant::asDate()
+
+ Use toDate() instead.
+*/
+
+/*!
+ \fn QTime &QVariant::asTime()
+
+ Use toTime() instead.
+*/
+
+/*!
+ \fn QDateTime &QVariant::asDateTime()
+
+ Use toDateTime() instead.
+*/
+
+/*!
+ \fn QList<QVariant> &QVariant::asList()
+
+ Use toList() instead.
+*/
+
+/*!
+ \fn QMap<QString, QVariant> &QVariant::asMap()
+
+ Use toMap() instead.
+*/
+
+/*!
+ \fn QVariant::QVariant(bool b, int dummy)
+
+ Use the QVariant(bool) constructor instead.
+
+*/
+
+/*!
+ \fn const QByteArray QVariant::toCString() const
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QByteArray &QVariant::asCString()
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QPoint &QVariant::asPoint()
+
+ Use toPoint() instead.
+ */
+
+/*!
+ \fn QRect &QVariant::asRect()
+
+ Use toRect() instead.
+ */
+
+/*!
+ \fn QSize &QVariant::asSize()
+
+ Use toSize() instead.
+ */
+
+/*! \fn void QVariant::setValue(const 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
+ error will occur if QMetaType doesn't handle the type.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4
+
+ \sa value(), fromValue(), canConvert()
+ */
+
+/*! \fn 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.
+ If the value cannot be converted, \l{default-constructed value}
+ will be returned.
+
+ If the type \c{T} is supported by QVariant, this function behaves
+ exactly as toString(), toInt() etc.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5
+
+ \sa setValue(), fromValue(), canConvert()
+*/
+
+/*! \fn bool QVariant::canConvert() const
+
+ Returns true if the variant can be converted to the template type \c{T},
+ otherwise false.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6
+
+ \sa convert()
+*/
+
+/*! \fn static QVariant QVariant::fromValue(const T &value)
+
+ Returns a QVariant containing a copy of \a value. Behaves
+ exactly like setValue() otherwise.
+
+ Example:
+
+ \snippet doc/src/snippets/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 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.
+
+ For example, a QObject pointer can be stored in a variant with the
+ following code:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 8
+
+ \sa QVariant::fromValue()
+*/
+
+/*! \fn void qVariantSetValue(QVariant &variant, const T &value)
+ \relates QVariant
+ \obsolete
+
+ Sets the contents of the given \a variant to a copy of the
+ \a value with the specified template type \c{T}.
+
+ This function is equivalent to QVariant::setValue(\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.
+
+ \sa QVariant::setValue()
+*/
+
+/*!
+ \fn T qvariant_cast(const QVariant &value)
+ \relates QVariant
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ This function is equivalent to QVariant::value().
+
+ \sa QVariant::value()
+*/
+
+/*! \fn T qVariantValue(const QVariant &value)
+ \relates QVariant
+ \obsolete
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ This function is equivalent to
+ \l{QVariant::value()}{QVariant::value}<T>(\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.
+
+ \sa QVariant::value(), qvariant_cast()
+*/
+
+/*! \fn bool qVariantCanConvert(const QVariant &value)
+ \relates QVariant
+ \obsolete
+
+ Returns true if the given \a value can be converted to the
+ template type specified; otherwise returns false.
+
+ This function is equivalent to QVariant::canConvert(\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.
+
+ \sa QVariant::canConvert()
+*/
+
+/*!
+ \typedef QVariantList
+ \relates QVariant
+
+ Synonym for QList<QVariant>.
+*/
+
+/*!
+ \typedef QVariantMap
+ \relates QVariant
+
+ Synonym for QMap<QString, QVariant>.
+*/
+
+/*!
+ \typedef QVariantHash
+ \relates QVariant
+ \since 4.5
+
+ Synonym for QHash<QString, QVariant>.
+*/
+
+/*!
+ \typedef QVariant::DataPtr
+ \internal
+*/
+
+/*!
+ \fn DataPtr &QVariant::data_ptr()
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
new file mode 100644
index 0000000000..1b8cb7fd0b
--- /dev/null
+++ b/src/corelib/kernel/qvariant.h
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVARIANT_H
+#define QVARIANT_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QBitArray;
+class QDataStream;
+class QDate;
+class QDateTime;
+class QEasingCurve;
+class QLine;
+class QLineF;
+class QLocale;
+class QMatrix;
+class QTransform;
+class QStringList;
+class QTime;
+class QPoint;
+class QPointF;
+class QSize;
+class QSizeF;
+class QRect;
+class QRectF;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+class QTextFormat;
+class QTextLength;
+class QUrl;
+class QVariant;
+class QVariantComparisonHelper;
+
+template <typename T>
+inline QVariant qVariantFromValue(const T &);
+
+template<typename T>
+inline T qvariant_cast(const QVariant &);
+
+class Q_CORE_EXPORT QVariant
+{
+ public:
+ enum Type {
+ Invalid = 0,
+
+ Bool = 1,
+ Int = 2,
+ UInt = 3,
+ LongLong = 4,
+ ULongLong = 5,
+ Double = 6,
+ Char = 7,
+ Map = 8,
+ List = 9,
+ String = 10,
+ StringList = 11,
+ ByteArray = 12,
+ BitArray = 13,
+ Date = 14,
+ Time = 15,
+ DateTime = 16,
+ Url = 17,
+ Locale = 18,
+ Rect = 19,
+ RectF = 20,
+ Size = 21,
+ SizeF = 22,
+ Line = 23,
+ LineF = 24,
+ Point = 25,
+ PointF = 26,
+ RegExp = 27,
+ Hash = 28,
+ EasingCurve = 29,
+ LastCoreType = EasingCurve,
+
+ // value 62 is internally reserved
+#ifdef QT3_SUPPORT
+ ColorGroup = 63,
+#endif
+ Font = 64,
+ Pixmap = 65,
+ Brush = 66,
+ Color = 67,
+ Palette = 68,
+ Icon = 69,
+ Image = 70,
+ Polygon = 71,
+ Region = 72,
+ Bitmap = 73,
+ Cursor = 74,
+ SizePolicy = 75,
+ KeySequence = 76,
+ Pen = 77,
+ TextLength = 78,
+ TextFormat = 79,
+ Matrix = 80,
+ Transform = 81,
+ Matrix4x4 = 82,
+ Vector2D = 83,
+ Vector3D = 84,
+ Vector4D = 85,
+ Quaternion = 86,
+ LastGuiType = Quaternion,
+
+ UserType = 127,
+#ifdef QT3_SUPPORT
+ IconSet = Icon,
+ CString = ByteArray,
+ PointArray = Polygon,
+#endif
+ LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
+ };
+
+ inline QVariant();
+ ~QVariant();
+ QVariant(Type type);
+ QVariant(int typeOrUserType, const void *copy);
+ QVariant(int typeOrUserType, const void *copy, uint flags);
+ QVariant(const QVariant &other);
+
+#ifndef QT_NO_DATASTREAM
+ QVariant(QDataStream &s);
+#endif
+
+ QVariant(int i);
+ QVariant(uint ui);
+ QVariant(qlonglong ll);
+ QVariant(qulonglong ull);
+ QVariant(bool b);
+ QVariant(double d);
+ QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
+#endif
+
+ QVariant(const QByteArray &bytearray);
+ QVariant(const QBitArray &bitarray);
+ QVariant(const QString &string);
+ QVariant(const QLatin1String &string);
+ QVariant(const QStringList &stringlist);
+ QVariant(const QChar &qchar);
+ QVariant(const QDate &date);
+ QVariant(const 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
+ QVariant(const QSize &size);
+ QVariant(const QSizeF &size);
+ QVariant(const QPoint &pt);
+ QVariant(const QPointF &pt);
+ QVariant(const QLine &line);
+ QVariant(const QLineF &line);
+ QVariant(const QRect &rect);
+ QVariant(const QRectF &rect);
+#endif
+ QVariant(const QUrl &url);
+ QVariant(const QLocale &locale);
+#ifndef QT_NO_REGEXP
+ QVariant(const QRegExp &regExp);
+#endif
+#ifndef QT_BOOTSTRAPPED
+ QVariant(const QEasingCurve &easing);
+#endif
+ QVariant(Qt::GlobalColor color);
+
+ QVariant& operator=(const QVariant &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QVariant &operator=(QVariant &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QVariant &other) { qSwap(d, other.d); }
+
+ Type type() const;
+ int userType() const;
+ const char *typeName() const;
+
+ bool canConvert(Type t) const;
+ bool convert(Type t);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool canCast(Type t) const
+ { return canConvert(t); }
+ inline QT3_SUPPORT bool cast(Type t)
+ { return convert(t); }
+#endif
+
+ inline bool isValid() const;
+ bool isNull() const;
+
+ void clear();
+
+ void detach();
+ inline bool isDetached() const;
+
+ int toInt(bool *ok = 0) const;
+ uint toUInt(bool *ok = 0) const;
+ qlonglong toLongLong(bool *ok = 0) const;
+ qulonglong toULongLong(bool *ok = 0) const;
+ bool toBool() const;
+ double toDouble(bool *ok = 0) const;
+ float toFloat(bool *ok = 0) const;
+ qreal toReal(bool *ok = 0) const;
+ QByteArray toByteArray() const;
+ QBitArray toBitArray() const;
+ QString toString() const;
+ QStringList toStringList() const;
+ QChar toChar() const;
+ QDate toDate() const;
+ QTime toTime() const;
+ QDateTime toDateTime() const;
+ QList<QVariant> toList() const;
+ QMap<QString, QVariant> toMap() const;
+ QHash<QString, QVariant> toHash() const;
+
+#ifndef QT_NO_GEOM_VARIANT
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+ QRect toRect() const;
+ QSize toSize() const;
+ QSizeF toSizeF() const;
+ QLine toLine() const;
+ QLineF toLineF() const;
+ QRectF toRectF() const;
+#endif
+ QUrl toUrl() const;
+ QLocale toLocale() const;
+#ifndef QT_NO_REGEXP
+ QRegExp toRegExp() const;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ QEasingCurve toEasingCurve() const;
+#endif
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT int &asInt();
+ inline QT3_SUPPORT uint &asUInt();
+ inline QT3_SUPPORT qlonglong &asLongLong();
+ inline QT3_SUPPORT qulonglong &asULongLong();
+ inline QT3_SUPPORT bool &asBool();
+ inline QT3_SUPPORT double &asDouble();
+ inline QT3_SUPPORT QByteArray &asByteArray();
+ inline QT3_SUPPORT QBitArray &asBitArray();
+ inline QT3_SUPPORT QString &asString();
+ inline QT3_SUPPORT QStringList &asStringList();
+ inline QT3_SUPPORT QDate &asDate();
+ inline QT3_SUPPORT QTime &asTime();
+ inline QT3_SUPPORT QDateTime &asDateTime();
+ inline QT3_SUPPORT QList<QVariant> &asList();
+ inline QT3_SUPPORT QMap<QString,QVariant> &asMap();
+ inline QT3_SUPPORT QPoint &asPoint();
+ inline QT3_SUPPORT QRect &asRect();
+ inline QT3_SUPPORT QSize &asSize();
+#endif //QT3_SUPPORT
+
+#ifndef QT_NO_DATASTREAM
+ void load(QDataStream &ds);
+ void save(QDataStream &ds) const;
+#endif
+ static const char *typeToName(Type type);
+ static Type nameToType(const char *name);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QVariant(bool val, int) { create(Bool, &val); }
+ inline QT3_SUPPORT const QByteArray toCString() const { return toByteArray(); }
+ inline QT3_SUPPORT QByteArray &asCString() { return *reinterpret_cast<QByteArray *>(castOrDetach(ByteArray)); }
+#endif
+
+ void *data();
+ const void *constData() const;
+ inline const void *data() const { return constData(); }
+
+ template<typename T>
+ inline void setValue(const T &value);
+
+ template<typename T>
+ inline T value() const
+ { return qvariant_cast<T>(*this); }
+
+ template<typename T>
+ static inline QVariant fromValue(const T &value)
+ { return qVariantFromValue(value); }
+
+ template<typename T>
+ bool canConvert() const
+ { return canConvert(Type(qMetaTypeId<T>())); }
+
+ public:
+#ifndef qdoc
+ struct PrivateShared
+ {
+ inline PrivateShared(void *v) : ptr(v), ref(1) { }
+ void *ptr;
+ QAtomicInt ref;
+ };
+ struct Private
+ {
+ inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; }
+ inline Private(const Private &other)
+ : data(other.data), type(other.type),
+ is_shared(other.is_shared), is_null(other.is_null)
+ {}
+ union Data
+ {
+ char c;
+ int i;
+ uint u;
+ bool b;
+ double d;
+ float f;
+ qreal real;
+ qlonglong ll;
+ qulonglong ull;
+ QObject *o;
+ void *ptr;
+ PrivateShared *shared;
+ } data;
+ uint type : 30;
+ uint is_shared : 1;
+ uint is_null : 1;
+ };
+ public:
+ typedef void (*f_construct)(Private *, const void *);
+ typedef void (*f_clear)(Private *);
+ typedef bool (*f_null)(const Private *);
+#ifndef QT_NO_DATASTREAM
+ typedef void (*f_load)(Private *, QDataStream &);
+ typedef void (*f_save)(const Private *, QDataStream &);
+#endif
+ typedef bool (*f_compare)(const Private *, const Private *);
+ typedef bool (*f_convert)(const QVariant::Private *d, Type t, void *, bool *);
+ typedef bool (*f_canConvert)(const QVariant::Private *d, Type t);
+ typedef void (*f_debugStream)(QDebug, const QVariant &);
+ struct Handler {
+ f_construct construct;
+ f_clear clear;
+ f_null isNull;
+#ifndef QT_NO_DATASTREAM
+ f_load load;
+ f_save save;
+#endif
+ f_compare compare;
+ f_convert convert;
+ f_canConvert canConvert;
+ f_debugStream debugStream;
+ };
+#endif
+
+ inline bool operator==(const QVariant &v) const
+ { return cmp(v); }
+ inline bool operator!=(const QVariant &v) const
+ { return !cmp(v); }
+
+protected:
+ friend inline bool qvariant_cast_helper(const QVariant &, QVariant::Type, void *);
+ friend int qRegisterGuiVariant();
+ friend int qUnregisterGuiVariant();
+ friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
+#endif
+ Private d;
+
+ static const Handler *handler;
+
+ void create(int type, const void *copy);
+#ifdef QT3_SUPPORT
+ void *castOrDetach(Type t);
+#endif
+ bool cmp(const QVariant &other) const;
+
+private:
+ // force compile error, prevent QVariant(bool) to be called
+ inline QVariant(void *) { Q_ASSERT(false); }
+#ifdef QT_NO_CAST_FROM_ASCII
+ // force compile error when implicit conversion is not wanted
+ inline QVariant(const char *) { Q_ASSERT(false); }
+#endif
+#ifndef QT3_SUPPORT
+ // force compile error, prevent QVariant(QVariant::Type, int) to be called
+ inline QVariant(bool, int) { Q_ASSERT(false); }
+#endif
+public:
+ typedef Private DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+typedef QList<QVariant> QVariantList;
+typedef QMap<QString, QVariant> QVariantMap;
+typedef QHash<QString, QVariant> QVariantHash;
+
+inline bool qvariant_cast_helper(const QVariant &v, QVariant::Type tp, void *ptr)
+{ return QVariant::handler->convert(&v.d, tp, ptr, 0); }
+
+template <typename T>
+inline QVariant qVariantFromValue(const T &t)
+{
+ return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer);
+}
+
+template <>
+inline QVariant qVariantFromValue(const QVariant &t) { return t; }
+
+template <typename T>
+inline void qVariantSetValue(QVariant &v, const T &t)
+{
+ //if possible we reuse the current QVariant private
+ const uint type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
+ QVariant::Private &d = v.data_ptr();
+ if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
+ d.type = type;
+ d.is_null = false;
+ T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
+ if (QTypeInfo<T>::isComplex)
+ old->~T();
+ new (old) T(t); //call the copy constructor
+ } else {
+ v = QVariant(type, &t, QTypeInfo<T>::isPointer);
+ }
+}
+
+template <>
+inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t)
+{
+ v = t;
+}
+
+
+inline QVariant::QVariant() {}
+inline bool QVariant::isValid() const { return d.type != Invalid; }
+
+#ifdef QT3_SUPPORT
+inline int &QVariant::asInt()
+{ return *reinterpret_cast<int *>(castOrDetach(Int)); }
+inline uint &QVariant::asUInt()
+{ return *reinterpret_cast<uint *>(castOrDetach(UInt)); }
+inline qlonglong &QVariant::asLongLong()
+{ return *reinterpret_cast<qlonglong *>(castOrDetach(LongLong)); }
+inline qulonglong &QVariant::asULongLong()
+{ return *reinterpret_cast<qulonglong *>(castOrDetach(ULongLong)); }
+inline bool &QVariant::asBool()
+{ return *reinterpret_cast<bool *>(castOrDetach(Bool)); }
+inline double &QVariant::asDouble()
+{ return *reinterpret_cast<double *>(castOrDetach(Double)); }
+inline QByteArray& QVariant::asByteArray()
+{ return *reinterpret_cast<QByteArray *>(castOrDetach(ByteArray)); }
+inline QBitArray& QVariant::asBitArray()
+{ return *reinterpret_cast<QBitArray *>(castOrDetach(BitArray)); }
+inline QString& QVariant::asString()
+{ return *reinterpret_cast<QString *>(castOrDetach(String)); }
+inline QStringList& QVariant::asStringList()
+{ return *reinterpret_cast<QStringList *>(castOrDetach(StringList)); }
+inline QDate& QVariant::asDate()
+{ return *reinterpret_cast<QDate *>(castOrDetach(Date)); }
+inline QTime& QVariant::asTime()
+{ return *reinterpret_cast<QTime *>(castOrDetach(Time)); }
+inline QDateTime& QVariant::asDateTime()
+{ return *reinterpret_cast<QDateTime *>(castOrDetach(DateTime)); }
+inline QList<QVariant>& QVariant::asList()
+{ return *reinterpret_cast<QList<QVariant> *>(castOrDetach(List)); }
+inline QMap<QString, QVariant>& QVariant::asMap()
+{ return *reinterpret_cast<QMap<QString, QVariant> *>(castOrDetach(Map)); }
+inline QPoint &QVariant::asPoint()
+{ return *reinterpret_cast<QPoint *>(castOrDetach(Point)); }
+inline QRect &QVariant::asRect()
+{ return *reinterpret_cast<QRect *>(castOrDetach(Rect)); }
+inline QSize &QVariant::asSize()
+{ return *reinterpret_cast<QSize *>(castOrDetach(Size)); }
+#endif //QT3_SUPPORT
+
+template<typename T>
+inline void QVariant::setValue(const T &avalue)
+{ qVariantSetValue(*this, avalue); }
+
+#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 == 1; }
+
+
+#ifdef qdoc
+ inline bool operator==(const QVariant &v1, const QVariant &v2);
+ inline bool operator!=(const QVariant &v1, const QVariant &v2);
+#else
+
+/* Helper class to add one more level of indirection to prevent
+ implicit casts.
+*/
+class QVariantComparisonHelper
+{
+public:
+ inline QVariantComparisonHelper(const QVariant &var)
+ : v(&var) {}
+private:
+ friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
+ const QVariant *v;
+};
+
+inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
+{
+ return v1.cmp(*v2.v);
+}
+
+inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
+{
+ return !operator==(v1, v2);
+}
+#endif
+
+#ifndef QT_MOC
+template<typename T> inline T qvariant_cast(const QVariant &v)
+{
+ const int vid = qMetaTypeId<T>(static_cast<T *>(0));
+ if (vid == v.userType())
+ return *reinterpret_cast<const T *>(v.constData());
+ if (vid < int(QMetaType::User)) {
+ T t;
+ if (qvariant_cast_helper(v, QVariant::Type(vid), &t))
+ return t;
+ }
+ return T();
+}
+
+template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
+{
+ if (v.userType() == QMetaType::QVariant)
+ return *reinterpret_cast<const QVariant *>(v.constData());
+ return v;
+}
+
+#ifdef QT_DEPRECATED
+template<typename T>
+inline QT_DEPRECATED T qVariantValue(const QVariant &variant)
+{ return qvariant_cast<T>(variant); }
+
+template<typename T>
+inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant)
+{ return variant.template canConvert<T>(); }
+#endif
+
+#endif
+Q_DECLARE_SHARED(QVariant)
+Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_BUILTIN_METATYPE(QVariantList, QVariantList)
+Q_DECLARE_BUILTIN_METATYPE(QVariantMap, QVariantMap)
+Q_DECLARE_BUILTIN_METATYPE(QVariantHash, QVariantHash)
+
+QT_END_HEADER
+
+#endif // QVARIANT_H
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
new file mode 100644
index 0000000000..a30d2df5f7
--- /dev/null
+++ b/src/corelib/kernel/qvariant_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVARIANT_P_H
+#define QVARIANT_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.
+//
+
+// takes a type, returns the internal void* pointer cast
+// to a pointer of the input type
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack
+
+template <typename T>
+inline T *v_cast(const QVariant::Private *nd, T * = 0)
+{
+ QVariant::Private *d = const_cast<QVariant::Private *>(nd);
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<T *>(d->data.shared->ptr)
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
+}
+
+#else // every other compiler in this world
+
+template <typename T>
+inline const T *v_cast(const QVariant::Private *d, T * = 0)
+{
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<const T *>(d->data.shared->ptr)
+ : static_cast<const T *>(static_cast<const void *>(&d->data.c)));
+}
+
+template <typename T>
+inline T *v_cast(QVariant::Private *d, T * = 0)
+{
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<T *>(d->data.shared->ptr)
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
+}
+
+#endif
+
+
+//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) { }
+ QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
+
+private:
+ T m_t;
+};
+
+// 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 * = 0)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
+ : new QVariantPrivateSharedEx<T>;
+ x->is_shared = true;
+ } else {
+ if (copy)
+ new (&x->data.ptr) T(*static_cast<const T *>(copy));
+ else
+ new (&x->data.ptr) T;
+ }
+}
+
+template <class T>
+inline void v_construct(QVariant::Private *x, const T &t)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = new QVariantPrivateSharedEx<T>(t);
+ x->is_shared = true;
+ } else {
+ new (&x->data.ptr) T(t);
+ }
+}
+
+// deletes the internal structures
+template <class T>
+inline void v_clear(QVariant::Private *d, T* = 0)
+{
+
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ //now we need to cast
+ //because QVariant::PrivateShared doesn't have a virtual destructor
+ delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
+ } else {
+ v_cast<T>(d)->~T();
+ }
+
+}
+
+Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
+
+QT_END_NAMESPACE
+
+#endif // QVARIANT_P_H
diff --git a/src/corelib/kernel/qwineventnotifier_p.cpp b/src/corelib/kernel/qwineventnotifier_p.cpp
new file mode 100644
index 0000000000..afdc26502e
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwineventnotifier_p.h"
+
+#include "qeventdispatcher_win_p.h"
+#include "qcoreapplication.h"
+
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ \class QWinEventNotifier
+ \brief The QWinEventNotifier class provides support for the Windows Wait functions.
+
+ The QWinEventNotifier class makes it possible to use the wait
+ functions on windows in a asynchronous manner. With this class
+ you can register a HANDLE to an event and get notification when
+ that event becomes signalled. The state of the event is not modified
+ in the process so if it is a manual reset event you will need to
+ reset it after the notification.
+*/
+
+
+QWinEventNotifier::QWinEventNotifier(QObject *parent)
+ : QObject(parent), handleToEvent(0), enabled(false)
+{}
+
+QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
+ : QObject(parent), handleToEvent(hEvent), enabled(false)
+{
+ Q_D(QObject);
+ QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher);
+ Q_ASSERT_X(eventDispatcher, "QWinEventNotifier::QWinEventNotifier()",
+ "Cannot create a win event notifier without a QEventDispatcherWin32");
+ eventDispatcher->registerEventNotifier(this);
+ enabled = true;
+}
+
+QWinEventNotifier::~QWinEventNotifier()
+{
+ setEnabled(false);
+}
+
+void QWinEventNotifier::setHandle(HANDLE hEvent)
+{
+ setEnabled(false);
+ handleToEvent = hEvent;
+}
+
+HANDLE QWinEventNotifier::handle() const
+{
+ return handleToEvent;
+}
+
+bool QWinEventNotifier::isEnabled() const
+{
+ return enabled;
+}
+
+void QWinEventNotifier::setEnabled(bool enable)
+{
+ if (enabled == enable) // no change
+ return;
+ enabled = enable;
+
+ Q_D(QObject);
+ QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher);
+ if (!eventDispatcher) // perhaps application is shutting down
+ return;
+
+ if (enabled)
+ eventDispatcher->registerEventNotifier(this);
+ else
+ eventDispatcher->unregisterEventNotifier(this);
+}
+
+bool QWinEventNotifier::event(QEvent * e)
+{
+ if (e->type() == QEvent::ThreadChange) {
+ if (enabled) {
+ QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
+ Q_ARG(bool, enabled));
+ setEnabled(false);
+ }
+ }
+ QObject::event(e); // will activate filters
+ if (e->type() == QEvent::WinEventAct) {
+ emit activated(handleToEvent);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h
new file mode 100644
index 0000000000..9d7ab6a1c8
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINEVENTNOTIFIER_P_H
+#define QWINEVENTNOTIFIER_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/qobject.h"
+#include "QtCore/qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QWinEventNotifier : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ explicit QWinEventNotifier(QObject *parent = 0);
+ explicit QWinEventNotifier(HANDLE hEvent, QObject *parent = 0);
+ ~QWinEventNotifier();
+
+ void setHandle(HANDLE hEvent);
+ HANDLE handle() const;
+
+ bool isEnabled() const;
+
+public Q_SLOTS:
+ void setEnabled(bool enable);
+
+Q_SIGNALS:
+ void activated(HANDLE hEvent);
+
+protected:
+ bool event(QEvent * e);
+
+private:
+ Q_DISABLE_COPY(QWinEventNotifier)
+
+ HANDLE handleToEvent;
+ bool enabled;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINEVENTNOTIFIER_P_H
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
new file mode 100644
index 0000000000..eb7a7f7fa8
--- /dev/null
+++ b/src/corelib/plugin/plugin.pri
@@ -0,0 +1,35 @@
+# Qt core library plugin module
+
+HEADERS += \
+ plugin/qfactoryinterface.h \
+ plugin/qpluginloader.h \
+ plugin/qlibrary.h \
+ plugin/qlibrary_p.h \
+ plugin/qplugin.h \
+ plugin/quuid.h \
+ plugin/qfactoryloader_p.h \
+ plugin/qsystemlibrary_p.h \
+ plugin/qelfparser_p.h
+
+SOURCES += \
+ plugin/qpluginloader.cpp \
+ plugin/qfactoryloader.cpp \
+ plugin/quuid.cpp \
+ plugin/qlibrary.cpp \
+ plugin/qelfparser_p.cpp
+
+win32 {
+ SOURCES += \
+ plugin/qlibrary_win.cpp \
+ plugin/qsystemlibrary.cpp
+}
+
+unix {
+ SOURCES += plugin/qlibrary_unix.cpp
+}
+
+integrity {
+ SOURCES += plugin/qlibrary_unix.cpp
+}
+
+LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp
new file mode 100644
index 0000000000..198c6d79c5
--- /dev/null
+++ b/src/corelib/plugin/qelfparser_p.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelfparser_p.h"
+
+#ifndef QT_NO_LIBRARY
+#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
+
+#include "qlibrary_p.h"
+#include <qdebug.h>
+
+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<qelfword_t>(data);
+ data += sizeof(qelfword_t); // sh_size
+ return data;
+}
+
+int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen)
+{
+#if defined(QELFPARSER_DEBUG)
+ qDebug() << "QElfParser::parse " << library;
+#endif
+
+ if (fdlen < 64){
+ if (lib)
+ lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("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).arg(QLatin1String("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).arg(QLatin1String("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).arg(QLatin1String("odd endianess"));
+ 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).arg(QLatin1String("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).arg(QLatin1String("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)
+ lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library)
+ .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size"))
+ .arg(e_shnum).arg(e_shentsize);
+ return Corrupt;
+ }
+
+#if defined(QELFPARSER_DEBUG)
+ qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes";
+#endif
+
+ ElfSectionHeader strtab;
+ qulonglong soff = e_shoff + e_shentsize * (e_shtrndx);
+
+ if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
+ if (lib)
+ lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library)
+ .arg(QLatin1String("shstrtab section header seems to be at %1"))
+ .arg(QString::number(soff, 16));
+ return Corrupt;
+ }
+
+ parseSectionHeader(dataStart + soff, &strtab);
+ m_stringTableFileOffset = strtab.offset;
+
+ if ((quint32)(m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) {
+ if (lib)
+ lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library)
+ .arg(QLatin1String("string table seems to be at %1"))
+ .arg(QString::number(soff, 16));
+ return Corrupt;
+ }
+
+#if defined(QELFPARSER_DEBUG)
+ qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data());
+#endif
+
+ 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;
+ }
+ 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)
+ .arg(QLatin1String("section name %2 of %3 behind end of file"))
+ .arg(i).arg(e_shnum);
+ return Corrupt;
+ }
+
+#if defined(QELFPARSER_DEBUG)
+ qDebug() << "++++" << i << shnam;
+#endif
+
+ if (qstrcmp(shnam, ".qtplugin") == 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)
+ .arg(QLatin1String("empty .rodata. not a library."));
+ return Corrupt;
+ }
+#if defined(QELFPARSER_DEBUG)
+ qDebug()<<"section is not program data. skipped.";
+#endif
+ s += e_shentsize;
+ continue;
+ }
+
+ if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) {
+ if (lib)
+ lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library)
+ .arg(QLatin1String("missing section data. This is not a library."));
+ return Corrupt;
+ }
+ *pos = sh.offset;
+ *sectionlen = sh.size - 1;
+ if (shnam[1] == 'q')
+ return Ok;
+ }
+ s += e_shentsize;
+ }
+ return NoQtSection;
+}
+
+QT_END_NAMESPACE
+
+#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h
new file mode 100644
index 0000000000..3ccce10541
--- /dev/null
+++ b/src/corelib/plugin/qelfparser_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QELFPARSER_P_H
+#define QELFPARSER_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 <qendian.h>
+#include <qglobal.h>
+
+#ifndef QT_NO_LIBRARY
+#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
+
+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
+{
+public:
+ enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3};
+ enum {ElfLittleEndian = 0, ElfBigEndian = 1};
+
+ struct ElfSectionHeader
+ {
+ qelfword_t name;
+ qelfword_t type;
+ qelfoff_t offset;
+ qelfword_t size;
+ };
+
+ int m_endian;
+ int m_bits;
+ int m_stringTableFileOffset;
+
+ template <typename T>
+ T read(const char *s)
+ {
+ if (m_endian == ElfBigEndian)
+ return qFromBigEndian<T>(reinterpret_cast<const uchar *>(s));
+ else
+ return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(s));
+ }
+
+ const char *parseSectionHeader(const char* s, ElfSectionHeader *sh);
+ int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen);
+};
+
+QT_END_NAMESPACE
+
+#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // QT_NO_LIBRARY
+
+#endif // QELFPARSER_P_H
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h
new file mode 100644
index 0000000000..2b04e3b52a
--- /dev/null
+++ b/src/corelib/plugin/qfactoryinterface.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFACTORYINTERFACE_H
+#define QFACTORYINTERFACE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QFactoryInterface
+{
+ virtual ~QFactoryInterface() {}
+ virtual QStringList keys() const = 0;
+};
+
+
+Q_DECLARE_INTERFACE(QFactoryInterface, "com.trolltech.Qt.QFactoryInterface")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFACTORYINTERFACE_H
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
new file mode 100644
index 0000000000..c0b947ad19
--- /dev/null
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfactoryloader_p.h"
+
+#ifndef QT_NO_LIBRARY
+#include "qfactoryinterface.h"
+#include "qmap.h"
+#include <qdir.h>
+#include <qsettings.h>
+#include <qdebug.h>
+#include "qmutex.h"
+#include "qplugin.h"
+#include "qpluginloader.h"
+#include "private/qobject_p.h"
+#include "private/qcoreapplication_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive))
+
+class QFactoryLoaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFactoryLoader)
+public:
+ QFactoryLoaderPrivate(){}
+ ~QFactoryLoaderPrivate();
+ mutable QMutex mutex;
+ QByteArray iid;
+ QList<QLibraryPrivate*> libraryList;
+ QMap<QString,QLibraryPrivate*> keyMap;
+ QStringList keyList;
+ QString suffix;
+ Qt::CaseSensitivity cs;
+ QStringList loadedPaths;
+
+ void unloadPath(const QString &path);
+};
+
+QFactoryLoaderPrivate::~QFactoryLoaderPrivate()
+{
+ for (int i = 0; i < libraryList.count(); ++i)
+ libraryList.at(i)->release();
+}
+
+QFactoryLoader::QFactoryLoader(const char *iid,
+ const QString &suffix,
+ Qt::CaseSensitivity cs)
+ : QObject(*new QFactoryLoaderPrivate)
+{
+ moveToThread(QCoreApplicationPrivate::mainThread());
+ Q_D(QFactoryLoader);
+ d->iid = iid;
+ d->cs = cs;
+ d->suffix = suffix;
+
+
+ QMutexLocker locker(qt_factoryloader_mutex());
+ update();
+ qt_factory_loaders()->append(this);
+}
+
+
+
+void QFactoryLoader::update()
+{
+#ifdef QT_SHARED
+ Q_D(QFactoryLoader);
+ QStringList paths = QCoreApplication::libraryPaths();
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ for (int i = 0; i < paths.count(); ++i) {
+ const QString &pluginDir = paths.at(i);
+ // Already loaded, skip it...
+ if (d->loadedPaths.contains(pluginDir))
+ continue;
+ d->loadedPaths << pluginDir;
+
+ QString path = pluginDir + d->suffix;
+ if (!QDir(path).exists(QLatin1String(".")))
+ continue;
+
+ QStringList plugins = QDir(path).entryList(QDir::Files);
+ QLibraryPrivate *library = 0;
+ for (int j = 0; j < plugins.count(); ++j) {
+ QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
+ if (qt_debug_component()) {
+ qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
+ }
+ library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
+ if (!library->isPlugin(&settings)) {
+ if (qt_debug_component()) {
+ qDebug() << library->errorString;
+ qDebug() << " not a plugin";
+ }
+ library->release();
+ continue;
+ }
+ QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4")
+ .arg((QT_VERSION & 0xff0000) >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8)
+ .arg(QLatin1String(d->iid))
+ .arg(fileName);
+ QStringList reg, keys;
+ reg = settings.value(regkey).toStringList();
+ if (reg.count() && library->lastModified == reg[0]) {
+ keys = reg;
+ keys.removeFirst();
+ } else {
+ if (!library->loadPlugin()) {
+ if (qt_debug_component()) {
+ qDebug() << library->errorString;
+ qDebug() << " could not load";
+ }
+ library->release();
+ continue;
+ }
+ QObject *instance = library->instance();
+ if (!instance) {
+ library->release();
+ // ignore plugins that have a valid signature but cannot be loaded.
+ continue;
+ }
+ QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
+ if (instance && factory && instance->qt_metacast(d->iid))
+ keys = factory->keys();
+ if (keys.isEmpty())
+ library->unload();
+ reg.clear();
+ reg << library->lastModified;
+ reg += keys;
+ settings.setValue(regkey, reg);
+ }
+ if (qt_debug_component()) {
+ qDebug() << "keys" << keys;
+ }
+
+ if (keys.isEmpty()) {
+ library->release();
+ continue;
+ }
+ d->libraryList += library;
+ 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
+ QString key = keys.at(k);
+ if (!d->cs)
+ key = key.toLower();
+ QLibraryPrivate *previous = d->keyMap.value(key);
+ if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) {
+ d->keyMap[key] = library;
+ d->keyList += keys.at(k);
+ }
+ }
+ }
+ }
+#else
+ Q_D(QFactoryLoader);
+ if (qt_debug_component()) {
+ qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
+ << "since plugins are disabled in static builds";
+ }
+#endif
+}
+
+QFactoryLoader::~QFactoryLoader()
+{
+ QMutexLocker locker(qt_factoryloader_mutex());
+ qt_factory_loaders()->removeAll(this);
+}
+
+QStringList QFactoryLoader::keys() const
+{
+ Q_D(const QFactoryLoader);
+ QMutexLocker locker(&d->mutex);
+ QStringList keys = d->keyList;
+ QObjectList instances = QPluginLoader::staticInstances();
+ for (int i = 0; i < instances.count(); ++i)
+ if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
+ if (instances.at(i)->qt_metacast(d->iid))
+ keys += factory->keys();
+ return keys;
+}
+
+QObject *QFactoryLoader::instance(const QString &key) const
+{
+ Q_D(const QFactoryLoader);
+ QMutexLocker locker(&d->mutex);
+ QObjectList instances = QPluginLoader::staticInstances();
+ for (int i = 0; i < instances.count(); ++i)
+ if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
+ if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive))
+ return instances.at(i);
+
+ QString lowered = d->cs ? key : key.toLower();
+ if (QLibraryPrivate* library = d->keyMap.value(lowered)) {
+ if (library->instance || library->loadPlugin()) {
+ if (QObject *obj = library->instance()) {
+ if (obj && !obj->parent())
+ obj->moveToThread(QCoreApplicationPrivate::mainThread());
+ return obj;
+ }
+ }
+ }
+ return 0;
+}
+
+#ifdef Q_WS_X11
+QLibraryPrivate *QFactoryLoader::library(const QString &key) const
+{
+ Q_D(const QFactoryLoader);
+ return d->keyMap.value(d->cs ? key : key.toLower());
+}
+#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();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
new file mode 100644
index 0000000000..3133ccc0a7
--- /dev/null
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFACTORYLOADER_P_H
+#define QFACTORYLOADER_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/qobject.h"
+#include "QtCore/qstringlist.h"
+#include "private/qlibrary_p.h"
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+class QFactoryLoaderPrivate;
+
+class Q_CORE_EXPORT QFactoryLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFactoryLoader)
+
+public:
+ QFactoryLoader(const char *iid,
+ const QString &suffix = QString(),
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+ ~QFactoryLoader();
+
+ QStringList keys() const;
+ QObject *instance(const QString &key) const;
+
+#ifdef Q_WS_X11
+ QLibraryPrivate *library(const QString &key) const;
+#endif
+
+ void update();
+
+ static void refreshAll();
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
+
+#endif // QFACTORYLOADER_P_H
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
new file mode 100644
index 0000000000..80e927bcc9
--- /dev/null
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -0,0 +1,1295 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qplatformdefs.h"
+#include "qlibrary.h"
+
+#ifndef QT_NO_LIBRARY
+
+#include "qlibrary_p.h"
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qmutex.h>
+#include <qmap.h>
+#include <qsettings.h>
+#include <qdatetime.h>
+#ifdef Q_OS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+#ifndef NO_ERRNO_H
+#include <errno.h>
+#endif // NO_ERROR_H
+#include <qdebug.h>
+#include <qvector.h>
+#include <qdir.h>
+#include "qelfparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_NO_DEBUG
+# define QLIBRARY_AS_DEBUG false
+#else
+# define QLIBRARY_AS_DEBUG true
+#endif
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+// 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_GLOBAL_STATIC(QMutex, qt_library_mutex)
+
+/*!
+ \class QLibrary
+ \reentrant
+ \brief The QLibrary class loads shared libraries at runtime.
+
+
+ \ingroup plugins
+
+ An instance of a QLibrary object operates on a single shared
+ object file (which we call a "library", but is also known as a
+ "DLL"). A QLibrary provides access to the functionality in the
+ library in a platform independent way. You can either pass a file
+ name in the constructor, or set it explicitly with setFileName().
+ When loading the library, QLibrary searches in all the
+ system-specific library locations (e.g. \c LD_LIBRARY_PATH on
+ Unix), unless the file name has an absolute path. If the file
+ cannot be found, QLibrary tries the name with different
+ platform-specific file suffixes, like ".so" on Unix, ".dylib" on
+ the Mac, or ".dll" on Windows and Symbian. This makes it possible
+ to specify shared libraries that are only identified by their
+ basename (i.e. without their suffix), so the same code will work
+ on different operating systems.
+
+ The most important functions are load() to dynamically load the
+ library file, isLoaded() to check whether loading was successful,
+ and resolve() to resolve a symbol in the library. The resolve()
+ function implicitly tries to load the library if it has not been
+ loaded yet. Multiple instances of QLibrary can be used to access
+ the same physical library. Once loaded, libraries remain in memory
+ until the application terminates. You can attempt to unload a
+ library using unload(), but if other instances of QLibrary are
+ using the same library, the call will fail, and unloading will
+ only happen when every instance has called unload().
+
+ A typical use of QLibrary is to resolve an exported symbol in a
+ library, and to call the C function that this symbol represents.
+ This is called "explicit linking" in contrast to "implicit
+ linking", which is done by the link step in the build process when
+ linking an executable against a library.
+
+ Note: In Symbian resolving symbols using their names is supported
+ only if the library is built as STDDLL. Otherwise ordinals must
+ be used. Also, in Symbian the path of the library is ignored and
+ system default library location is always used.
+
+ The following code snippet loads a library, resolves the symbol
+ "mysymbol", and calls the function if everything succeeded. If
+ something goes wrong, e.g. the library file does not exist or the
+ symbol is not defined, the function pointer will be 0 and won't be
+ called.
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 0
+
+ The symbol must be exported as a C function from the library for
+ resolve() to work. This means that the function must be wrapped in
+ an \c{extern "C"} block if the library is compiled with a C++
+ compiler. On Windows, this also requires the use of a \c dllexport
+ macro; see resolve() for the details of how this is done. For
+ convenience, there is a static resolve() function which you can
+ use if you just want to call a function in a library without
+ explicitly loading the library first:
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 1
+
+ \sa QPluginLoader
+*/
+
+/*!
+ \enum QLibrary::LoadHint
+
+ This enum describes the possible hints that can be used to change the way
+ libraries are handled when they are loaded. These values indicate how
+ symbols are resolved when libraries are loaded, and are specified using
+ the setLoadHints() function.
+
+ \value ResolveAllSymbolsHint
+ Causes all symbols in a library to be resolved when it is loaded, not
+ simply when resolve() is called.
+ \value ExportExternalSymbolsHint
+ Exports unresolved and external symbols in the library so that they can be
+ resolved in other dynamically-loaded libraries loaded later.
+ \value LoadArchiveMemberHint
+ Allows the file name of the library to specify a particular object file
+ within an archive file.
+ If this hint is given, the filename of the library consists of
+ a path, which is a reference to an archive file, followed by
+ a reference to the archive member.
+
+ \sa loadHints
+*/
+
+
+#ifndef QT_NO_PLUGIN_CHECK
+struct qt_token_info
+{
+ qt_token_info(const char *f, const ulong fc)
+ : fields(f), field_count(fc), results(fc), lengths(fc)
+ {
+ results.fill(0);
+ lengths.fill(0);
+ }
+
+ const char *fields;
+ const ulong field_count;
+
+ QVector<const char *> results;
+ QVector<ulong> lengths;
+};
+
+/*
+ return values:
+ 1 parse ok
+ 0 eos
+ -1 parse error
+*/
+static int qt_tokenize(const char *s, ulong s_len, ulong *advance,
+ qt_token_info &token_info)
+{
+ ulong pos = 0, field = 0, fieldlen = 0;
+ char current;
+ int ret = -1;
+ *advance = 0;
+ for (;;) {
+ current = s[pos];
+
+ // next char
+ ++pos;
+ ++fieldlen;
+ ++*advance;
+
+ if (! current || pos == s_len + 1) {
+ // save result
+ token_info.results[(int)field] = s;
+ token_info.lengths[(int)field] = fieldlen - 1;
+
+ // end of string
+ ret = 0;
+ break;
+ }
+
+ if (current == token_info.fields[field]) {
+ // save result
+ token_info.results[(int)field] = s;
+ token_info.lengths[(int)field] = fieldlen - 1;
+
+ // end of field
+ fieldlen = 0;
+ ++field;
+ if (field == token_info.field_count - 1) {
+ // parse ok
+ ret = 1;
+ }
+ if (field == token_info.field_count) {
+ // done parsing
+ break;
+ }
+
+ // reset string and its length
+ s = s + pos;
+ s_len -= pos;
+ pos = 0;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ returns true if the string s was correctly parsed, false otherwise.
+*/
+static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key)
+{
+ bool ret = true;
+
+ qt_token_info pinfo("=\n", 2);
+ int parse;
+ ulong at = 0, advance, parselen = qstrlen(s);
+ do {
+ parse = qt_tokenize(s + at, parselen, &advance, pinfo);
+ if (parse == -1) {
+ ret = false;
+ break;
+ }
+
+ at += advance;
+ parselen -= advance;
+
+ if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) {
+ // parse version string
+ qt_token_info pinfo2("..-", 3);
+ if (qt_tokenize(pinfo.results[1], pinfo.lengths[1],
+ &advance, pinfo2) != -1) {
+ QByteArray m(pinfo2.results[0], pinfo2.lengths[0]);
+ QByteArray n(pinfo2.results[1], pinfo2.lengths[1]);
+ QByteArray p(pinfo2.results[2], pinfo2.lengths[2]);
+ *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt();
+ } else {
+ ret = false;
+ break;
+ }
+ } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) {
+ *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0;
+ } else if (qstrncmp("buildkey", pinfo.results[0],
+ pinfo.lengths[0]) == 0){
+ // save buildkey
+ *key = QByteArray(pinfo.results[1], pinfo.lengths[1]);
+ }
+ } while (parse == 1 && parselen > 0);
+
+ return ret;
+}
+#endif // QT_NO_PLUGIN_CHECK
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
+
+static long qt_find_pattern(const char *s, ulong s_len,
+ const char *pattern, ulong p_len)
+{
+ /*
+ 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 || p_len > s_len) return -1;
+ ulong 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;
+ if (i == 0)
+ break;
+ --i;
+ hs -= s[i + p_len];
+ hs += s[i];
+ }
+
+ return -1;
+}
+
+/*
+ This opens the specified library, mmaps it into memory, and searches
+ for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
+ we can get the verification data without have to actually load the library.
+ This lets us detect mismatches more safely.
+
+ Returns false if version/key information is not present, or if the
+ information could not be read.
+ Returns true if version/key information is present and successfully read.
+*/
+static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0)
+{
+ QFile file(library);
+ if (!file.open(QIODevice::ReadOnly)) {
+ if (lib)
+ lib->errorString = file.errorString();
+ if (qt_debug_component()) {
+ qWarning("%s: %s", (const char*) QFile::encodeName(library),
+ qPrintable(qt_error_string(errno)));
+ }
+ return false;
+ }
+
+ QByteArray data;
+ const char *filedata = 0;
+ ulong fdlen = file.size();
+ filedata = (char *) file.map(0, fdlen);
+ if (filedata == 0) {
+ // try reading the data into memory instead
+ data = file.readAll();
+ filedata = data.constData();
+ fdlen = data.size();
+ }
+
+ /*
+ ELF binaries on GNU, have .qplugin sections.
+ */
+ long pos = 0;
+ const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
+ 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::NoQtSection) {
+ if (pos > 0) {
+ // find inside .rodata
+ long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
+ if (rel < 0) {
+ pos = -1;
+ } else {
+ pos += rel;
+ }
+ } else {
+ pos = qt_find_pattern(filedata, fdlen, pattern, plen);
+ }
+ } else if (r != QElfParser::Ok) {
+ if (lib && qt_debug_component()) {
+ qWarning("QElfParser: %s",qPrintable(lib->errorString));
+ }
+ return false;
+ }
+#else
+ pos = qt_find_pattern(filedata, fdlen, pattern, plen);
+#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+ bool ret = false;
+ if (pos >= 0)
+ ret = qt_parse_pattern(filedata + pos, version, debug, key);
+
+ if (!ret && lib)
+ lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
+ file.close();
+ return ret;
+}
+
+#endif // Q_OS_UNIX && !Q_OS_MAC && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
+
+typedef QMap<QString, QLibraryPrivate*> LibraryMap;
+
+struct LibraryData {
+ LibraryData() : settings(0) { }
+ ~LibraryData() {
+ delete settings;
+ }
+
+ QSettings *settings;
+ LibraryMap libraryMap;
+ QSet<QLibraryPrivate*> loadedLibs;
+};
+
+Q_GLOBAL_STATIC(LibraryData, libraryData)
+
+static LibraryMap *libraryMap()
+{
+ LibraryData *data = libraryData();
+ return data ? &data->libraryMap : 0;
+}
+
+QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
+ :pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0),
+ libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin)
+{ libraryMap()->insert(canonicalFileName, this); }
+
+QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
+{
+ QMutexLocker locker(qt_library_mutex());
+ if (QLibraryPrivate *lib = libraryMap()->value(fileName)) {
+ lib->libraryRefCount.ref();
+ return lib;
+ }
+
+ return new QLibraryPrivate(fileName, version);
+}
+
+QLibraryPrivate::~QLibraryPrivate()
+{
+ LibraryMap * const map = libraryMap();
+ if (map) {
+ QLibraryPrivate *that = map->take(fileName);
+ Q_ASSERT(this == that);
+ Q_UNUSED(that);
+ }
+}
+
+void *QLibraryPrivate::resolve(const char *symbol)
+{
+ if (!pHnd)
+ return 0;
+ return resolve_sys(symbol);
+}
+
+
+bool QLibraryPrivate::load()
+{
+ libraryUnloadCount.ref();
+ if (pHnd)
+ return true;
+ if (fileName.isEmpty())
+ return false;
+
+ bool ret = load_sys();
+ 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
+ if (LibraryData *lib = libraryData()) {
+ lib->loadedLibs += this;
+ libraryRefCount.ref();
+ }
+ }
+
+ return ret;
+}
+
+bool QLibraryPrivate::unload()
+{
+ if (!pHnd)
+ return false;
+ if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
+ delete inst.data();
+ if (unload_sys()) {
+ if (qt_debug_component())
+ qWarning() << "QLibraryPrivate::unload succeeded on" << fileName;
+ //when the library is unloaded, we release the reference on it so that 'this'
+ //can get deleted
+ if (LibraryData *lib = libraryData()) {
+ if (lib->loadedLibs.remove(this))
+ libraryRefCount.deref();
+ }
+ pHnd = 0;
+ }
+ }
+
+ return (pHnd == 0);
+}
+
+void QLibraryPrivate::release()
+{
+ QMutexLocker locker(qt_library_mutex());
+ if (!libraryRefCount.deref())
+ delete this;
+}
+
+bool QLibraryPrivate::loadPlugin()
+{
+ if (instance) {
+ libraryUnloadCount.ref();
+ return true;
+ }
+ if (pluginState == IsNotAPlugin)
+ return false;
+ if (load()) {
+ instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
+#if defined(Q_OS_SYMBIAN)
+ if (!instance) {
+ // If resolving with function name failed (i.e. not STDDLL),
+ // try resolving using known ordinal, which for
+ // qt_plugin_instance function is always "2".
+ instance = (QtPluginInstanceFunction)resolve("2");
+ }
+#endif
+ return instance;
+ }
+ if (qt_debug_component())
+ qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
+ pluginState = IsNotAPlugin;
+ return false;
+}
+
+/*!
+ Returns true if \a fileName has a valid suffix for a loadable
+ library; otherwise returns false.
+
+ \table
+ \header \i Platform \i Valid suffixes
+ \row \i Windows \i \c .dll, \c .DLL
+ \row \i Unix/Linux \i \c .so
+ \row \i AIX \i \c .a
+ \row \i HP-UX \i \c .sl, \c .so (HP-UXi)
+ \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so
+ \row \i Symbian \i \c .dll
+ \endtable
+
+ Trailing versioning numbers on Unix are ignored.
+ */
+bool QLibrary::isLibrary(const QString &fileName)
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive);
+#elif defined(Q_OS_SYMBIAN)
+ // Plugin stubs are also considered libraries in Symbian.
+ return (fileName.endsWith(QLatin1String(".dll")) ||
+ fileName.endsWith(QLatin1String(".qtplugin")));
+#else
+ QString completeSuffix = QFileInfo(fileName).completeSuffix();
+ if (completeSuffix.isEmpty())
+ return false;
+ QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
+# if defined(Q_OS_DARWIN)
+
+ // On Mac, libs look like libmylib.1.0.0.dylib
+ const QString lastSuffix = suffixes.at(suffixes.count() - 1);
+ const QString firstSuffix = suffixes.at(0);
+
+ bool valid = (lastSuffix == QLatin1String("dylib")
+ || firstSuffix == QLatin1String("so")
+ || firstSuffix == QLatin1String("bundle"));
+
+ return valid;
+# else // Generic Unix
+ QStringList validSuffixList;
+
+# 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");
+# if defined __ia64
+ validSuffixList << QLatin1String("so");
+# endif
+# elif defined(Q_OS_AIX)
+ validSuffixList << QLatin1String("a") << QLatin1String("so");
+# elif defined(Q_OS_UNIX)
+ validSuffixList << QLatin1String("so");
+# endif
+
+ // Examples of valid library names:
+ // libfoo.so
+ // libfoo.so.0
+ // libfoo.so.0.3
+ // 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));
+
+ bool valid = suffixPos != -1;
+ for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
+ if (i != suffixPos)
+ suffixes.at(i).toInt(&valid);
+ return valid;
+# endif
+#endif
+
+}
+
+#if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL)
+#define QT_USE_MS_STD_EXCEPTION 1
+const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown)
+{
+ *exceptionThrown = false;
+ const char *szData = 0;
+ typedef const char * (*VerificationFunction)();
+ VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn);
+ __try {
+ if(func)
+ szData = func();
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ *exceptionThrown = true;
+ }
+ return szData;
+}
+#endif
+
+#ifdef Q_CC_BOR
+typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();
+#else
+typedef const char * (*QtPluginQueryVerificationDataFunction)();
+#endif
+
+bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown)
+{
+ *exceptionThrown = false;
+ const char *szData = 0;
+ if (!pfn)
+ return false;
+#ifdef QT_USE_MS_STD_EXCEPTION
+ szData = qt_try_versioninfo((void *)pfn, exceptionThrown);
+ if (*exceptionThrown)
+ return false;
+#else
+ szData = pfn();
+#endif
+ return qt_parse_pattern(szData, qt_version, debug, key);
+}
+
+bool QLibraryPrivate::isPlugin(QSettings *settings)
+{
+ errorString.clear();
+ if (pluginState != MightBeAPlugin)
+ return pluginState == IsAPlugin;
+
+#ifndef QT_NO_PLUGIN_CHECK
+ bool debug = !QLIBRARY_AS_DEBUG;
+ QByteArray key;
+ bool success = false;
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+ if (fileName.endsWith(QLatin1String(".debug"))) {
+ // 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
+ // and dlopen is known to crash while opening them
+
+ // pretend we didn't see the file
+ errorString = QLibrary::tr("The shared library was not found.");
+ pluginState = IsNotAPlugin;
+ return false;
+ }
+#endif
+
+ QFileInfo fileinfo(fileName);
+
+#ifndef QT_NO_DATESTRING
+ lastModified = fileinfo.lastModified().toString(Qt::ISODate);
+#endif
+ QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4")
+ .arg((QT_VERSION & 0xff0000) >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8)
+ .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
+ .arg(fileName);
+#ifdef Q_WS_MAC
+ // On Mac, add the application arch to the reg key in order to
+ // cache plugin information separately for each arch. This prevents
+ // Qt from wrongly caching plugin load failures when the archs
+ // don't match.
+#if defined(__x86_64__)
+ regkey += QLatin1String("-x86_64");
+#elif defined(__i386__)
+ regkey += QLatin1String("-i386");
+#elif defined(__ppc64__)
+ regkey += QLatin1String("-ppc64");
+#elif defined(__ppc__)
+ regkey += QLatin1String("-ppc");
+#endif
+#endif // Q_WS_MAC
+
+ QStringList reg;
+#ifndef QT_NO_SETTINGS
+ if (!settings) {
+ settings = libraryData()->settings;
+ if (!settings) {
+ settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
+ libraryData()->settings = settings;
+ }
+ }
+ reg = settings->value(regkey).toStringList();
+#endif
+ if (reg.count() == 4 && lastModified == reg.at(3)) {
+ qt_version = reg.at(0).toUInt(0, 16);
+ debug = bool(reg.at(1).toInt());
+ key = reg.at(2).toLatin1();
+ success = qt_version != 0;
+ } else {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)
+ if (!pHnd) {
+ // use unix shortcut to avoid loading the library
+ success = qt_unix_query(fileName, &qt_version, &debug, &key, this);
+ } else
+#endif
+ {
+ bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases)
+ do {
+ bool temporary_load = false;
+#ifdef Q_OS_WIN
+ HMODULE hTempModule = 0;
+#endif
+ if (!pHnd) {
+#ifdef Q_OS_WIN
+ DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES;
+ //avoid 'Bad Image' message box
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags);
+ SetErrorMode(oldmode);
+#else
+# if defined(Q_OS_SYMBIAN)
+ //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists
+ if (fileinfo.exists())
+# endif
+ temporary_load = load_sys();
+#endif
+ }
+#ifdef Q_OS_WIN
+ QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction)
+#ifdef Q_OS_WINCE
+ ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
+#else
+ ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
+#endif
+ : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
+#else
+ QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
+# if defined(Q_OS_SYMBIAN)
+ if (temporary_load) {
+ qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
+ // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal
+ if (!qtPluginQueryVerificationDataFunction)
+ qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1");
+ }
+# else
+ qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
+# endif
+#endif
+ bool exceptionThrown = false;
+ bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction,
+ &qt_version, &debug, &key, &exceptionThrown);
+ if (!exceptionThrown) {
+ if (!ret) {
+ qt_version = 0;
+ key = "unknown";
+ if (temporary_load)
+ unload_sys();
+ } else {
+ success = true;
+ }
+ retryLoadLibrary = false;
+ }
+#ifdef QT_USE_MS_STD_EXCEPTION
+ else {
+ // An exception was thrown when calling qt_plugin_query_verification_data().
+ // This usually happens when plugin is compiled with the /clr compiler flag,
+ // & will only work if the dependencies are loaded & DLLMain() is called.
+ // LoadLibrary() will do this, try once with this & if it fails dont load.
+ retryLoadLibrary = !retryLoadLibrary;
+ }
+#endif
+#ifdef Q_OS_WIN
+ if (hTempModule) {
+ BOOL ok = ::FreeLibrary(hTempModule);
+ if (ok) {
+ hTempModule = 0;
+ }
+
+ }
+#endif
+ } while(retryLoadLibrary); // Will be 'false' in all cases other than when an
+ // exception is thrown(will happen only when using a MS compiler)
+ }
+
+ // Qt 4.5 compatibility: stl doesn't affect binary compatibility
+ key.replace(" no-stl", "");
+
+#ifndef QT_NO_SETTINGS
+ QStringList queried;
+ queried << QString::number(qt_version,16)
+ << QString::number((int)debug)
+ << QLatin1String(key)
+ << lastModified;
+ settings->setValue(regkey, queried);
+#endif
+ }
+
+ if (!success) {
+ if (errorString.isEmpty()){
+ if (fileName.isEmpty())
+ errorString = QLibrary::tr("The shared library was not found.");
+ else
+ errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
+ }
+ return false;
+ }
+
+ pluginState = IsNotAPlugin; // be pessimistic
+
+ if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
+ if (qt_debug_component()) {
+ qWarning("In %s:\n"
+ " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
+ (const char*) QFile::encodeName(fileName),
+ (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"));
+ } else if (key != QT_BUILD_KEY
+ // we may have some compatibility keys, try them too:
+#ifdef QT_BUILD_KEY_COMPAT
+ && key != QT_BUILD_KEY_COMPAT
+#endif
+#ifdef QT_BUILD_KEY_COMPAT2
+ && key != QT_BUILD_KEY_COMPAT2
+#endif
+#ifdef QT_BUILD_KEY_COMPAT3
+ && key != QT_BUILD_KEY_COMPAT3
+#endif
+ ) {
+ if (qt_debug_component()) {
+ qWarning("In %s:\n"
+ " Plugin uses incompatible Qt library\n"
+ " expected build key \"%s\", got \"%s\"",
+ (const char*) QFile::encodeName(fileName),
+ QT_BUILD_KEY,
+ key.isEmpty() ? "<null>" : (const char *) key);
+ }
+ errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
+ " Expected build key \"%2\", got \"%3\"")
+ .arg(fileName)
+ .arg(QLatin1String(QT_BUILD_KEY))
+ .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key));
+#ifndef QT_NO_DEBUG_PLUGIN_CHECK
+ } else if(debug != QLIBRARY_AS_DEBUG) {
+ //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;
+ }
+
+ return pluginState == IsAPlugin;
+#else
+ Q_UNUSED(settings);
+ return pluginState == MightBeAPlugin;
+#endif
+}
+
+/*!
+ Loads the library and returns true if the library was loaded
+ successfully; otherwise returns false. Since resolve() always
+ calls this function before resolving any symbols it is not
+ necessary to call it explicitly. In some situations you might want
+ the library loaded in advance, in which case you would use this
+ function.
+
+ \sa unload()
+*/
+bool QLibrary::load()
+{
+ if (!d)
+ return false;
+ if (did_load)
+ return d->pHnd;
+ did_load = true;
+ return d->load();
+}
+
+/*!
+ Unloads the library and returns true if the library could be
+ unloaded; otherwise returns false.
+
+ This happens automatically on application termination, so you
+ shouldn't normally need to call this function.
+
+ If other instances of QLibrary are using the same library, the
+ 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.
+
+ \sa resolve(), load()
+*/
+bool QLibrary::unload()
+{
+ if (did_load) {
+ did_load = false;
+ return d->unload();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the library is loaded; otherwise returns false.
+
+ \sa load()
+ */
+bool QLibrary::isLoaded() const
+{
+ return d && d->pHnd;
+}
+
+
+/*!
+ Constructs a library with the given \a parent.
+ */
+QLibrary::QLibrary(QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+}
+
+
+/*!
+ Constructs a library object with the given \a parent that will
+ load the library specified by \a fileName.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+ */
+QLibrary::QLibrary(const QString& fileName, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ 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.
+ Currently, the version number is ignored on Windows and Symbian.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+*/
+QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ setFileNameAndVersion(fileName, verNum);
+}
+
+/*!
+ Constructs a library object with the given \a parent that will
+ load the library specified by \a fileName and full version number \a version.
+ Currently, the version number is ignored on Windows and Symbian.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+ */
+QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ setFileNameAndVersion(fileName, version);
+}
+
+/*!
+ Destroys the QLibrary object.
+
+ Unless unload() was called explicitly, the library stays in memory
+ until the application terminates.
+
+ \sa isLoaded(), unload()
+*/
+QLibrary::~QLibrary()
+{
+ if (d)
+ d->release();
+}
+
+
+/*!
+ \property QLibrary::fileName
+ \brief the file name of the library
+
+ We recommend omitting the file's suffix in the file name, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix (see isLibrary()).
+
+ When loading the library, QLibrary searches in all system-specific
+ library locations (e.g. \c LD_LIBRARY_PATH on Unix), unless the
+ file name has an absolute path. After loading the library
+ successfully, fileName() returns the fully-qualified file name of
+ the library, including the full path to the library if one was given
+ in the constructor or passed to setFileName().
+
+ For example, after successfully loading the "GL" library on Unix
+ platforms, fileName() will return "libGL.so". If the file name was
+ originally passed as "/usr/lib/libGL", fileName() will return
+ "/usr/lib/libGL.so".
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+*/
+
+void QLibrary::setFileName(const QString &fileName)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName);
+ d->loadHints = lh;
+}
+
+QString QLibrary::fileName() const
+{
+ if (d)
+ return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
+ return QString();
+}
+
+/*!
+ \fn void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)
+
+ Sets the fileName property and major version number to \a fileName
+ and \a versionNumber respectively.
+ The \a versionNumber is ignored on Windows and Symbian.
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+
+ \sa setFileName()
+*/
+void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
+ d->loadHints = lh;
+}
+
+/*!
+ \since 4.4
+
+ Sets the fileName property and full version number to \a fileName
+ and \a version respectively.
+ The \a version parameter is ignored on Windows and Symbian.
+
+ Note: In Symbian the path portion of the \a fileName is ignored.
+
+ \sa setFileName()
+*/
+void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName, version);
+ d->loadHints = lh;
+}
+
+/*!
+ Returns the address of the exported symbol \a symbol. The library is
+ loaded if necessary. The function returns 0 if the symbol could
+ not be resolved or if the library could not be loaded.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 2
+
+ The symbol must be exported as a C function from the library. This
+ means that the function must be wrapped in an \c{extern "C"} if
+ the library is compiled with a C++ compiler. On Windows you must
+ also explicitly export the function from the DLL using the
+ \c{__declspec(dllexport)} compiler directive, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 3
+
+ with \c MY_EXPORT defined as
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 4
+
+ Note: In Symbian resolving with symbol names works only if the loaded
+ library was built as STDDLL. Otherwise, the ordinals must be used.
+*/
+void *QLibrary::resolve(const char *symbol)
+{
+ if (!isLoaded() && !load())
+ return 0;
+ return d->resolve(symbol);
+}
+
+/*!
+ \overload
+
+ Loads the library \a fileName and returns the address of the
+ exported symbol \a symbol. Note that \a fileName should not
+ include the platform-specific file suffix; (see \l{fileName}). The
+ library remains loaded until the application exits.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ Note: In Symbian resolving with symbol names works only if the loaded
+ library was built as STDDLL. Otherwise, the ordinals must be used.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, const char *symbol)
+{
+ QLibrary library(fileName);
+ return library.resolve(symbol);
+}
+
+/*!
+ \overload
+
+ Loads the library \a fileName with major version number \a verNum and
+ returns the address of the exported symbol \a symbol.
+ Note that \a fileName should not include the platform-specific file suffix;
+ (see \l{fileName}). The library remains loaded until the application exits.
+ \a verNum is ignored on Windows.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ Note: In Symbian resolving with symbol names works only if the loaded
+ library was built as STDDLL. Otherwise, the ordinals must be used.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
+{
+ QLibrary library(fileName, verNum);
+ return library.resolve(symbol);
+}
+
+/*!
+ \overload
+ \since 4.4
+
+ Loads the library \a fileName with full version number \a version and
+ returns the address of the exported symbol \a symbol.
+ Note that \a fileName should not include the platform-specific file suffix;
+ (see \l{fileName}). The library remains loaded until the application exits.
+ \a version is ignored on Windows.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ Note: In Symbian resolving with symbol names works only if the loaded
+ library was built as STDDLL. Otherwise, the ordinals must be used.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
+{
+ QLibrary library(fileName, version);
+ return library.resolve(symbol);
+}
+
+/*!
+ \fn QString QLibrary::library() const
+
+ Use fileName() instead.
+*/
+
+/*!
+ \fn void QLibrary::setAutoUnload( bool b )
+
+ Use load(), isLoaded(), and unload() as necessary instead.
+*/
+
+/*!
+ \since 4.2
+
+ Returns a text string with the description of the last error that occurred.
+ Currently, errorString will only be set if load(), unload() or resolve() for some reason fails.
+*/
+QString QLibrary::errorString() const
+{
+ return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
+}
+
+/*!
+ \property QLibrary::loadHints
+ \brief Give the load() function some hints on how it should behave.
+
+ You can give some hints on how the symbols are resolved. Usually,
+ the symbols are not resolved at load time, but resolved lazily,
+ (that is, when resolve() is called). If you set the loadHint to
+ ResolveAllSymbolsHint, then all symbols will be resolved at load time
+ if the platform supports it.
+
+ Setting ExportExternalSymbolsHint will make the external symbols in the
+ library available for resolution in subsequent loaded libraries.
+
+ If LoadArchiveMemberHint is set, the file name
+ is composed of two components: A path which is a reference to an
+ archive file followed by the second component which is the reference to
+ the archive member. For instance, the fileName \c libGL.a(shr_64.o) will refer
+ to the library \c shr_64.o in the archive file named \c libGL.a. This
+ is only supported on the AIX platform.
+
+ The interpretation of the load hints is platform dependent, and if
+ you use it you are probably making some assumptions on which platform
+ you are compiling for, so use them only if you understand the consequences
+ of them.
+
+ By default, none of these flags are set, so libraries will be loaded with
+ lazy symbol resolution, and will not export external symbols for resolution
+ in other dynamically-loaded libraries.
+*/
+void QLibrary::setLoadHints(LoadHints hints)
+{
+ if (!d) {
+ d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ d->errorString.clear();
+ }
+ d->loadHints = hints;
+}
+
+QLibrary::LoadHints QLibrary::loadHints() const
+{
+ return d ? d->loadHints : (QLibrary::LoadHints)0;
+}
+
+/* Internal, for debugging */
+bool qt_debug_component()
+{
+ static int debug_env = -1;
+ if (debug_env == -1)
+ debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt();
+
+ return debug_env != 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
new file mode 100644
index 0000000000..72bd57f343
--- /dev/null
+++ b/src/corelib/plugin/qlibrary.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIBRARY_H
+#define QLIBRARY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#ifndef QT_NO_LIBRARY
+
+class QLibraryPrivate;
+
+class Q_CORE_EXPORT QLibrary : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName)
+ Q_PROPERTY(LoadHints loadHints READ loadHints WRITE setLoadHints)
+ Q_FLAGS(LoadHint LoadHints)
+public:
+ enum LoadHint {
+ ResolveAllSymbolsHint = 0x01,
+ ExportExternalSymbolsHint = 0x02,
+ LoadArchiveMemberHint = 0x04
+ };
+ Q_DECLARE_FLAGS(LoadHints, LoadHint)
+
+ explicit QLibrary(QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, int verNum, QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
+ ~QLibrary();
+
+ void *resolve(const char *symbol);
+ static void *resolve(const QString &fileName, const char *symbol);
+ static void *resolve(const QString &fileName, int verNum, const char *symbol);
+ static void *resolve(const QString &fileName, const QString &version, const char *symbol);
+
+ bool load();
+ bool unload();
+ bool isLoaded() const;
+
+ static bool isLibrary(const QString &fileName);
+
+ void setFileName(const QString &fileName);
+ QString fileName() const;
+
+ void setFileNameAndVersion(const QString &fileName, int verNum);
+ void setFileNameAndVersion(const QString &fileName, const QString &version);
+ QString errorString() const;
+
+ void setLoadHints(LoadHints hints);
+ LoadHints loadHints() const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QString library() const { return fileName(); }
+ inline QT3_SUPPORT void setAutoUnload( bool ) {}
+#endif
+private:
+ QLibraryPrivate *d;
+ bool did_load;
+ Q_DISABLE_COPY(QLibrary)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QLibrary::LoadHints)
+
+#endif //QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QLIBRARY_H
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
new file mode 100644
index 0000000000..e2e16d9bc2
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIBRARY_P_H
+#define QLIBRARY_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifdef Q_WS_WIN
+# include "QtCore/qt_windows.h"
+#endif
+#include "QtCore/qlibrary.h"
+#include "QtCore/qpointer.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qplugin.h"
+#include "QtCore/qsharedpointer.h"
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+bool qt_debug_component();
+
+class QSettings;
+class QLibraryPrivate
+{
+public:
+
+#ifdef Q_WS_WIN
+ HINSTANCE
+#else
+ void *
+#endif
+ pHnd;
+
+ QString fileName, qualifiedFileName;
+ QString fullVersion;
+
+ bool load();
+ bool loadPlugin(); // loads and resolves instance
+ bool unload();
+ void release();
+ void *resolve(const char *);
+
+ static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
+
+ QWeakPointer<QObject> inst;
+ QtPluginInstanceFunction instance;
+ uint qt_version;
+ QString lastModified;
+
+ QString errorString;
+ QLibrary::LoadHints loadHints;
+
+ bool isPlugin(QSettings *settings = 0);
+
+
+private:
+ explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version);
+ ~QLibraryPrivate();
+
+ bool load_sys();
+ bool unload_sys();
+ void *resolve_sys(const char *);
+
+ QAtomicInt libraryRefCount;
+ QAtomicInt libraryUnloadCount;
+
+ enum {IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState;
+ friend class QLibraryPrivateHasFriends;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
+
+#endif // QLIBRARY_P_H
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
new file mode 100644
index 0000000000..e32729a780
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include <qfile.h>
+#include "qlibrary_p.h"
+#include <qfileinfo.h>
+#include <qcoreapplication.h>
+
+#ifndef QT_NO_LIBRARY
+
+#ifdef Q_OS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+
+#if defined(QT_AOUT_UNDERSCORE)
+#include <string.h>
+#endif
+
+#if defined(Q_OS_VXWORKS) || defined (Q_OS_NACL)
+#define QT_NO_DYNAMIC_LIBRARY
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_HPUX_LD) && !defined(QT_NO_DYNAMIC_LIBRARY)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <dlfcn.h>
+QT_END_INCLUDE_NAMESPACE
+#endif
+
+static QString qdlerror()
+{
+#if defined(QT_NO_DYNAMIC_LIBRARY)
+ const char *err = "This platform does not support dynamic libraries.";
+#elif !defined(QT_HPUX_LD)
+ const char *err = dlerror();
+#else
+ const char *err = strerror(errno);
+#endif
+ return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString();
+}
+
+bool QLibraryPrivate::load_sys()
+{
+ QString attempt;
+#if !defined(QT_NO_DYNAMIC_LIBRARY)
+ QFileInfo fi(fileName);
+
+#if defined(Q_OS_SYMBIAN)
+ QString path; // In Symbian, always resolve with just the filename
+ QString name;
+
+ // Replace possible ".qtplugin" suffix with ".dll"
+ if (fi.suffix() == QLatin1String("qtplugin"))
+ name = fi.completeBaseName() + QLatin1String(".dll");
+ else
+ name = fi.fileName();
+#else
+ QString path = fi.path();
+ QString name = fi.fileName();
+ if (path == QLatin1String(".") && !fileName.startsWith(path))
+ path.clear();
+ else
+ path += QLatin1Char('/');
+#endif
+ // The first filename we want to attempt to load is the filename as the callee specified.
+ // Thus, the first attempt we do must be with an empty prefix and empty suffix.
+ QStringList suffixes(QLatin1String("")), prefixes(QLatin1String(""));
+ if (pluginState != IsAPlugin) {
+#if !defined(Q_OS_SYMBIAN)
+ prefixes << QLatin1String("lib");
+#endif
+#if defined(Q_OS_HPUX)
+ // according to
+ // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm
+
+ // 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.
+
+ // But since we don't know if we are built on HPUX or HPUXi,
+ // we support both .sl (and .<version>) and .so suffixes but
+ // .so is preferred.
+# if defined(__ia64)
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+# endif
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".sl");
+ }
+#elif defined(Q_OS_AIX)
+ suffixes << ".a";
+
+#elif defined(Q_OS_SYMBIAN)
+ suffixes << QLatin1String(".dll");
+#else
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+#endif
+# ifdef Q_OS_MAC
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
+ }
+#endif
+ }
+ int dlFlags = 0;
+#if defined(QT_HPUX_LD)
+ dlFlags = DYNAMIC_PATH | BIND_NONFATAL;
+ if (loadHints & QLibrary::ResolveAllSymbolsHint) {
+ dlFlags |= BIND_IMMEDIATE;
+ } else {
+ dlFlags |= BIND_DEFERRED;
+ }
+#else
+ if (loadHints & QLibrary::ResolveAllSymbolsHint) {
+ dlFlags |= RTLD_NOW;
+ } else {
+ dlFlags |= RTLD_LAZY;
+ }
+ if (loadHints & QLibrary::ExportExternalSymbolsHint) {
+ dlFlags |= RTLD_GLOBAL;
+ }
+#if !defined(Q_OS_CYGWIN)
+ else {
+#if defined(Q_OS_MAC)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+#endif
+ dlFlags |= RTLD_LOCAL;
+ }
+#endif
+#if defined(Q_OS_AIX) // Not sure if any other platform actually support this thing.
+ if (loadHints & QLibrary::LoadArchiveMemberHint) {
+ dlFlags |= RTLD_MEMBER;
+ }
+#endif
+#endif // QT_HPUX_LD
+ bool retry = true;
+ for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
+ for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
+ if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
+ continue;
+ if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix)))
+ continue;
+ if (loadHints & QLibrary::LoadArchiveMemberHint) {
+ attempt = name;
+ int lparen = attempt.indexOf(QLatin1Char('('));
+ if (lparen == -1)
+ lparen = attempt.count();
+ attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix));
+ } else {
+ attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
+ }
+#if defined(QT_HPUX_LD)
+ pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0);
+#else
+ pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+ // Never try again in symbian, dlopen already handles the library search logic,
+ // and there is only one possible suffix.
+ retry = false;
+#else
+ if (!pHnd && fileName.startsWith(QLatin1Char('/')) && 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...)
+ // This is all because dlerror is flawed and cannot tell us the reason why it failed.
+ retry = false;
+ }
+#endif
+ }
+ }
+
+#ifdef Q_OS_MAC
+ if (!pHnd) {
+ 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) {
+ QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle);
+ char executableFile[FILENAME_MAX];
+ CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
+ attempt = QString::fromUtf8(executableFile);
+ pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
+ }
+ }
+#endif
+#endif // QT_NO_DYNAMIC_LIBRARY
+ if (!pHnd) {
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror());
+ }
+ if (pHnd) {
+ qualifiedFileName = attempt;
+ errorString.clear();
+ }
+ return (pHnd != 0);
+}
+
+bool QLibraryPrivate::unload_sys()
+{
+#if !defined(QT_NO_DYNAMIC_LIBRARY)
+# if defined(QT_HPUX_LD)
+ if (shl_unload((shl_t)pHnd)) {
+# else
+ if (dlclose(pHnd)) {
+# endif
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror());
+ return false;
+ }
+#endif
+ errorString.clear();
+ return true;
+}
+
+#ifdef Q_OS_MAC
+Q_CORE_EXPORT void *qt_mac_resolve_sys(void *handle, const char *symbol)
+{
+ return dlsym(handle, symbol);
+}
+#endif
+
+void* QLibraryPrivate::resolve_sys(const char* symbol)
+{
+#if defined(QT_AOUT_UNDERSCORE)
+ // older a.out systems add an underscore in front of symbols
+ char* undrscr_symbol = new char[strlen(symbol)+2];
+ undrscr_symbol[0] = '_';
+ strcpy(undrscr_symbol+1, symbol);
+ void* address = dlsym(pHnd, undrscr_symbol);
+ delete [] undrscr_symbol;
+#elif defined(QT_HPUX_LD)
+ void* address = 0;
+ if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
+ address = 0;
+#elif defined (QT_NO_DYNAMIC_LIBRARY)
+ void *address = 0;
+#else
+ void* address = dlsym(pHnd, symbol);
+#endif
+ if (!address) {
+ errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
+ QString::fromAscii(symbol)).arg(fileName).arg(qdlerror());
+ } else {
+ errorString.clear();
+ }
+ return address;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
new file mode 100644
index 0000000000..1481042351
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qlibrary_p.h"
+#include "qfile.h"
+#include "qdir.h"
+#include "qfileinfo.h"
+#include "qdir.h"
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#include "qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+extern QString qt_error_string(int code);
+
+bool QLibraryPrivate::load_sys()
+{
+#ifdef Q_OS_WINCE
+ QString attempt = QFileInfo(fileName).absoluteFilePath();
+#else
+ QString attempt = fileName;
+#endif
+
+ //avoid 'Bad Image' message box
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+
+ if (pluginState != IsAPlugin) {
+#if defined(Q_OS_WINCE)
+ if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
+ QString secondAttempt = fileName;
+ pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16());
+ }
+#endif
+ if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
+ attempt += QLatin1String(".dll");
+ pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+ }
+ }
+
+ SetErrorMode(oldmode);
+ if (!pHnd) {
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
+ }
+ if (pHnd) {
+ errorString.clear();
+
+ wchar_t buffer[MAX_PATH];
+ ::GetModuleFileName(pHnd, buffer, MAX_PATH);
+ attempt = QString::fromWCharArray(buffer);
+
+ const QDir dir = QFileInfo(fileName).dir();
+ const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
+ if (dir.path() == QLatin1String("."))
+ qualifiedFileName = realfilename;
+ else
+ qualifiedFileName = dir.filePath(realfilename);
+ }
+ return (pHnd != 0);
+}
+
+bool QLibraryPrivate::unload_sys()
+{
+ if (!FreeLibrary(pHnd)) {
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
+ return false;
+ }
+ errorString.clear();
+ return true;
+}
+
+void* QLibraryPrivate::resolve_sys(const char* symbol)
+{
+#ifdef Q_OS_WINCE
+ void* address = (void*)GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
+#else
+ void* address = (void*)GetProcAddress(pHnd, symbol);
+#endif
+ if (!address) {
+ errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
+ QString::fromAscii(symbol)).arg(fileName).arg(qt_error_string());
+ } else {
+ errorString.clear();
+ }
+ return address;
+}
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
new file mode 100644
index 0000000000..2fe67ae7bd
--- /dev/null
+++ b/src/corelib/plugin/qplugin.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLUGIN_H
+#define QPLUGIN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef Q_EXTERN_C
+# ifdef __cplusplus
+# define Q_EXTERN_C extern "C"
+# else
+# define Q_EXTERN_C extern
+# endif
+#endif
+
+typedef QObject *(*QtPluginInstanceFunction)();
+
+void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function);
+
+#define Q_IMPORT_PLUGIN(PLUGIN) \
+ extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \
+ class Static##PLUGIN##PluginInstance{ \
+ public: \
+ Static##PLUGIN##PluginInstance() { \
+ qRegisterStaticPluginInstanceFunction(qt_plugin_instance_##PLUGIN); \
+ } \
+ }; \
+ static Static##PLUGIN##PluginInstance static##PLUGIN##Instance;
+
+#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
+ { \
+ static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
+ if (!_instance) \
+ _instance = new IMPLEMENTATION; \
+ return _instance; \
+ }
+
+# define Q_EXPORT_PLUGIN(PLUGIN) \
+ Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
+
+# define Q_EXPORT_STATIC_PLUGIN(PLUGIN) \
+ Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGIN)
+
+#if defined(QT_STATICPLUGIN)
+
+# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ QT_PREPEND_NAMESPACE(QObject) \
+ *qt_plugin_instance_##PLUGIN() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS)
+
+# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS)
+
+#else
+// NOTE: if you change pattern, you MUST change the pattern in
+// qlibrary.cpp as well. changing the pattern will break all
+// backwards compatibility as well (no old plugins will be loaded).
+// QT5: should probably remove the entire pattern thing and do the section
+// trick for all platforms. for now, keep it and fallback to scan for it.
+# ifdef QPLUGIN_DEBUG_STR
+# undef QPLUGIN_DEBUG_STR
+# endif
+# ifdef QT_NO_DEBUG
+# define QPLUGIN_DEBUG_STR "false"
+# define QPLUGIN_SECTION_DEBUG_STR ""
+# else
+# define QPLUGIN_DEBUG_STR "true"
+# define QPLUGIN_SECTION_DEBUG_STR ".debug"
+# endif
+# define Q_PLUGIN_VERIFICATION_DATA \
+ static const char qt_plugin_verification_data[] = \
+ "pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" \
+ "version="QT_VERSION_STR"\n" \
+ "debug="QPLUGIN_DEBUG_STR"\n" \
+ "buildkey="QT_BUILD_KEY;
+
+# if defined (Q_OF_ELF) && defined (Q_CC_GNU)
+# define Q_PLUGIN_VERIFICATION_SECTION \
+ __attribute__ ((section (".qtplugin"))) __attribute__((used))
+# else
+# define Q_PLUGIN_VERIFICATION_SECTION
+# endif
+
+# if defined (Q_OS_WIN32) && defined(Q_CC_BOR)
+# define Q_STANDARD_CALL __stdcall
+# else
+# define Q_STANDARD_CALL
+# endif
+
+# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \
+ Q_EXTERN_C Q_DECL_EXPORT \
+ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \
+ { return qt_plugin_verification_data; } \
+ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS)
+
+# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS)
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q_PLUGIN_H
diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc
new file mode 100644
index 0000000000..7043fa0a27
--- /dev/null
+++ b/src/corelib/plugin/qplugin.qdoc
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtPlugin>
+ \title Macros for Defining Plugins
+
+ \brief The <QtPlugin> header files defines macros for defining plugins.
+
+ \sa {How to Create Qt Plugins}
+*/
+
+/*!
+ \macro Q_DECLARE_INTERFACE(ClassName, Identifier)
+ \relates <QtPlugin>
+
+ 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 examples/tools/plugandpaint/interfaces.h 3
+
+ This macro is normally used right after the class definition for
+ \a ClassName, in a header file. See the
+ \l{tools/plugandpaint}{Plug & Paint} example for details.
+
+ 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
+ is not inside a namespace though. For example:
+ \snippet doc/src/snippets/code/doc_src_qplugin.cpp 0
+
+ \sa Q_INTERFACES(), Q_EXPORT_PLUGIN2(), {How to Create Qt Plugins}
+*/
+
+/*!
+ \macro Q_EXPORT_PLUGIN(ClassName)
+ \relates <QtPlugin>
+ \obsolete
+
+ Use Q_EXPORT_PLUGIN2() instead. This macro is equivalent to
+ Q_EXPORT_PLUGIN2(\a ClassName, \a ClassName).
+*/
+
+/*!
+ \macro Q_EXPORT_PLUGIN2(PluginName, ClassName)
+ \relates <QtPlugin>
+ \since 4.1
+ \keyword Q_EXPORT_PLUGIN2
+
+ This macro exports the plugin class \a ClassName for the plugin specified
+ by \a PluginName. The value of \a PluginName should correspond to the
+ \l{qmake Variable Reference#TARGET}{TARGET} specified in the plugin's
+ project file.
+
+ There should be exactly one occurrence of this macro in the source code
+ for a Qt plugin, and it should be used where the implementation is written
+ rather than in a header file.
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qplugin.cpp 1
+
+ See the \l{tools/plugandpaint}{Plug & Paint} example for details.
+
+ \sa Q_DECLARE_INTERFACE(), {How to Create Qt Plugins}
+*/
+
+/*!
+ \macro Q_IMPORT_PLUGIN(PluginName)
+ \relates <QtPlugin>
+
+ This macro imports the plugin named \a PluginName, corresponding
+ to the \l{qmake Variable Reference#TARGET}{TARGET} specified in the
+ plugin's project file.
+
+ Inserting this macro into your application's source code will allow
+ you to make use of a static plugin.
+
+ Example:
+
+ \snippet doc/src/snippets/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:
+
+ \snippet doc/src/snippets/code/doc_src_qplugin.pro 3
+
+ \sa {Static Plugins}, {How to Create Qt Plugins}, {Using qmake}
+*/
+
+/*!
+ \macro Q_EXPORT_STATIC_PLUGIN(ClassName)
+ \relates <QtPlugin>
+ \internal
+*/
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
new file mode 100644
index 0000000000..2997293577
--- /dev/null
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qplugin.h"
+#include "qpluginloader.h"
+#include <qfileinfo.h>
+#include "qlibrary_p.h"
+#include "qdebug.h"
+#include "qdir.h"
+
+#if defined(Q_OS_SYMBIAN)
+# include <f32file.h>
+# include "private/qcore_symbian_p.h"
+#endif
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPluginLoader
+ \reentrant
+ \brief The QPluginLoader class loads a plugin at run-time.
+
+
+ \ingroup plugins
+
+ QPluginLoader provides access to a \l{How to Create Qt
+ Plugins}{Qt plugin}. A Qt plugin is stored in a shared library (a
+ DLL) and offers these benefits over shared libraries accessed
+ using QLibrary:
+
+ \list
+ \o QPluginLoader checks that a plugin is linked against the same
+ version of Qt as the application.
+ \o QPluginLoader provides direct access to a root component object
+ (instance()), instead of forcing you to resolve a C function manually.
+ \endlist
+
+ An instance of a QPluginLoader object operates on a single shared
+ library file, which we call a plugin. It provides access to the
+ functionality in the plugin in a platform-independent way. To
+ specify which plugin to load, either pass a file name in
+ the constructor or set it with setFileName().
+
+ The most important functions are load() to dynamically load the
+ plugin file, isLoaded() to check whether loading was successful,
+ and instance() to access the root component in the plugin. The
+ instance() function implicitly tries to load the plugin if it has
+ not been loaded yet. Multiple instances of QPluginLoader can be
+ used to access the same physical plugin.
+
+ Once loaded, plugins remain in memory until all instances of
+ QPluginLoader has been unloaded, or until the application
+ terminates. You can attempt to unload a plugin using unload(),
+ but if other instances of QPluginLoader are using the same
+ library, the call will fail, and unloading will only happen when
+ every instance has called unload(). Right before the unloading
+ happen, the root component will also be deleted.
+
+ In order to speed up loading and validation of plugins, some of
+ the information that is collected during loading is cached in
+ persistent memory (through QSettings). For instance, the result
+ of a load operation (e.g. succeeded or failed) is stored in the
+ cache, so that subsequent load operations don't try to load an
+ invalid plugin. However, if the "last modified" timestamp of
+ a plugin has changed, the plugin's cache entry is invalidated
+ and the plugin is reloaded regardless of the values in the cache
+ entry. The cache entry is then updated with the new result of the
+ load operation.
+
+ This also means that the timestamp must be updated each time the
+ plugin or any dependent resources (such as a shared library) is
+ updated, since the dependent resources might influence the result
+ of loading a plugin.
+
+ See \l{How to Create Qt Plugins} for more information about
+ how to make your application extensible through plugins.
+
+ Note that the QPluginLoader cannot be used if your application is
+ statically linked against Qt. In this case, you will also have to
+ link to plugins statically. You can use QLibrary if you need to
+ load dynamic libraries in a statically linked application.
+
+ \note In Symbian the plugin stub files must be used whenever a
+ path to plugin is needed. For the purposes of loading plugins,
+ the stubs can be considered to have the same name as the actual
+ plugin binary. In practice they have ".qtplugin" extension
+ instead of ".dll", but this difference is handled transparently
+ by QPluginLoader and QLibrary to avoid need for Symbian specific
+ plugin handling in most Qt applications. Plugin stubs are needed
+ because Symbian Platform Security denies all access to the directory
+ where the actual plugin binaries are located.
+
+ \sa QLibrary, {Plug & Paint Example}
+*/
+
+/*!
+ Constructs a plugin loader with the given \a parent.
+*/
+QPluginLoader::QPluginLoader(QObject *parent)
+ : QObject(parent), d(0), did_load(false)
+{
+}
+
+/*!
+ Constructs a plugin loader with the given \a parent that will
+ load the plugin specified by \a fileName.
+
+ To be loadable, the file's suffix must be a valid suffix for a
+ loadable library in accordance with the platform, e.g. \c .so on
+ Unix, - \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
+ can be verified with QLibrary::isLibrary().
+
+ Note: In Symbian the \a fileName must point to plugin stub file.
+
+ \sa setFileName()
+*/
+QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
+ : QObject(parent), d(0), did_load(false)
+{
+ setFileName(fileName);
+}
+
+/*!
+ Destroys the QPluginLoader object.
+
+ Unless unload() was called explicitly, the plugin stays in memory
+ until the application terminates.
+
+ \sa isLoaded(), unload()
+*/
+QPluginLoader::~QPluginLoader()
+{
+ if (d)
+ d->release();
+}
+
+/*!
+ Returns the root component object of the plugin. The plugin is
+ loaded if necessary. The function returns 0 if the plugin could
+ not be loaded or if the root component object could not be
+ instantiated.
+
+ If the root component object was destroyed, calling this function
+ creates a new instance.
+
+ The root component, returned by this function, is not deleted when
+ the QPluginLoader is destroyed. If you want to ensure that the root
+ component is deleted, you should call unload() as soon you don't
+ need to access the core component anymore. When the library is
+ finally unloaded, the root component will automatically be deleted.
+
+ The component object is a QObject. Use qobject_cast() to access
+ interfaces you are interested in.
+
+ \sa load()
+*/
+QObject *QPluginLoader::instance()
+{
+ if (!isLoaded() && !load())
+ return 0;
+ if (!d->inst && d->instance)
+ d->inst = d->instance();
+ return d->inst.data();
+}
+
+/*!
+ Loads the plugin and returns true if the plugin was loaded
+ successfully; otherwise returns false. Since instance() always
+ calls this function before resolving any symbols it is not
+ necessary to call it explicitly. In some situations you might want
+ the plugin loaded in advance, in which case you would use this
+ function.
+
+ \sa unload()
+*/
+bool QPluginLoader::load()
+{
+ if (!d || d->fileName.isEmpty())
+ return false;
+ if (did_load)
+ return d->pHnd && d->instance;
+ if (!d->isPlugin())
+ return false;
+ did_load = true;
+ return d->loadPlugin();
+}
+
+
+/*!
+ Unloads the plugin and returns true if the plugin could be
+ unloaded; otherwise returns false.
+
+ This happens automatically on application termination, so you
+ shouldn't normally need to call this function.
+
+ If other instances of QPluginLoader are using the same plugin, the
+ call will fail, and unloading will only happen when every instance
+ has called unload().
+
+ Don't try to delete the root component. Instead rely on
+ that unload() will automatically delete it when needed.
+
+ \sa instance(), load()
+*/
+bool QPluginLoader::unload()
+{
+ if (did_load) {
+ did_load = false;
+ return d->unload();
+ }
+ if (d) // Ouch
+ d->errorString = tr("The plugin was not loaded.");
+ return false;
+}
+
+/*!
+ Returns true if the plugin is loaded; otherwise returns false.
+
+ \sa load()
+ */
+bool QPluginLoader::isLoaded() const
+{
+ return d && d->pHnd && d->instance;
+}
+
+/*!
+ \property QPluginLoader::fileName
+ \brief the file name of the plugin
+
+ To be loadable, the file's suffix must be a valid suffix for a
+ loadable library in accordance with the platform, e.g. \c .so on
+ Unix, \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
+ can be verified with QLibrary::isLibrary().
+
+ If the file name does not exist, it will not be set. This property
+ will then contain an empty string.
+
+ By default, this property contains an empty string.
+
+ Note: In Symbian the \a fileName must point to plugin stub file.
+
+ \sa load()
+*/
+void QPluginLoader::setFileName(const QString &fileName)
+{
+#if defined(QT_SHARED)
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+
+#if defined(Q_OS_SYMBIAN)
+ // In Symbian we actually look for plugin stub, so modify the filename
+ // to make canonicalFilePath find the file, if .dll is specified.
+ QFileInfo fi(fileName);
+
+ if (fi.suffix() == QLatin1String("dll")) {
+ QString stubName = fileName;
+ stubName.chop(3);
+ stubName += QLatin1String("qtplugin");
+ fi = QFileInfo(stubName);
+ }
+
+ QString fn = fi.canonicalFilePath();
+ // If not found directly, check also all the available drives
+ if (!fn.length()) {
+ QString stubPath(fi.fileName().length() ? fi.absoluteFilePath() : QString());
+ if (stubPath.length() > 1) {
+ if (stubPath.at(1).toAscii() == ':')
+ stubPath.remove(0,2);
+ QFileInfoList driveList(QDir::drives());
+ RFs rfs = qt_s60GetRFs();
+ foreach(const QFileInfo& drive, driveList) {
+ QString testFilePath(drive.absolutePath() + stubPath);
+ testFilePath = QDir::cleanPath(testFilePath);
+ // Use native Symbian code to check for file existence, because checking
+ // for file from under non-existent protected dir like E:/private/<uid> using
+ // QFile::exists causes platform security violations on most apps.
+ QString nativePath = QDir::toNativeSeparators(testFilePath);
+ TPtrC ptr(qt_QString2TPtrC(nativePath));
+ TUint attributes;
+ TInt err = rfs.Att(ptr, attributes);
+ if (err == KErrNone) {
+ fn = testFilePath;
+ break;
+ }
+ }
+ }
+ }
+
+#else
+ QString fn = QFileInfo(fileName).canonicalFilePath();
+#endif
+
+ d = QLibraryPrivate::findOrCreate(fn);
+ d->loadHints = lh;
+ if (fn.isEmpty())
+ d->errorString = QLibrary::tr("The shared library was not found.");
+#else
+ if (qt_debug_component()) {
+ qWarning("Cannot load %s into a statically linked Qt library.",
+ (const char*)QFile::encodeName(fileName));
+ }
+ Q_UNUSED(fileName);
+#endif
+}
+
+QString QPluginLoader::fileName() const
+{
+ if (d)
+ return d->fileName;
+ return QString();
+}
+
+/*!
+ \since 4.2
+
+ Returns a text string with the description of the last error that occurred.
+*/
+QString QPluginLoader::errorString() const
+{
+ return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
+}
+
+typedef QList<QtPluginInstanceFunction> StaticInstanceFunctionList;
+Q_GLOBAL_STATIC(StaticInstanceFunctionList, staticInstanceFunctionList)
+
+/*! \since 4.4
+
+ \property QPluginLoader::loadHints
+ \brief Give the load() function some hints on how it should behave.
+
+ You can give hints on how the symbols in the plugin are
+ resolved. By default, none of the hints are set.
+
+ See the documentation of QLibrary::loadHints for a complete
+ description of how this property works.
+
+ \sa QLibrary::loadHints
+*/
+
+void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
+{
+ if (!d) {
+ d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ d->errorString.clear();
+ }
+ d->loadHints = loadHints;
+}
+
+QLibrary::LoadHints QPluginLoader::loadHints() const
+{
+ if (!d) {
+ QPluginLoader *that = const_cast<QPluginLoader *>(this);
+ that->d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ that->d->errorString.clear();
+ }
+ return d->loadHints;
+}
+
+/*!
+ \relates QPluginLoader
+ \since 4.4
+
+ Registers the given \a function with the plugin loader.
+*/
+void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function)
+{
+ staticInstanceFunctionList()->append(function);
+}
+
+/*!
+ Returns a list of static plugin instances (root components) held
+ by the plugin loader.
+*/
+QObjectList QPluginLoader::staticInstances()
+{
+ QObjectList instances;
+ StaticInstanceFunctionList *functions = staticInstanceFunctionList();
+ if (functions) {
+ for (int i = 0; i < functions->count(); ++i)
+ instances.append((*functions)[i]());
+ }
+ return instances;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qpluginloader.h b/src/corelib/plugin/qpluginloader.h
new file mode 100644
index 0000000000..323415f622
--- /dev/null
+++ b/src/corelib/plugin/qpluginloader.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLUGINLOADER_H
+#define QPLUGINLOADER_H
+
+#include <QtCore/qlibrary.h>
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QLibraryPrivate;
+
+class Q_CORE_EXPORT QPluginLoader : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName)
+ Q_PROPERTY(QLibrary::LoadHints loadHints READ loadHints WRITE setLoadHints)
+public:
+ explicit QPluginLoader(QObject *parent = 0);
+ explicit QPluginLoader(const QString &fileName, QObject *parent = 0);
+ ~QPluginLoader();
+
+ QObject *instance();
+
+ static QObjectList staticInstances();
+
+ bool load();
+ bool unload();
+ bool isLoaded() const;
+
+ void setFileName(const QString &fileName);
+ QString fileName() const;
+
+ QString errorString() const;
+
+ void setLoadHints(QLibrary::LoadHints loadHints);
+ QLibrary::LoadHints loadHints() const;
+
+private:
+ QLibraryPrivate *d;
+ bool did_load;
+ Q_DISABLE_COPY(QPluginLoader)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_LIBRARY
+
+#endif //QPLUGINLOADER_H
diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp
new file mode 100644
index 0000000000..b953fc6b6d
--- /dev/null
+++ b/src/corelib/plugin/qsystemlibrary.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemlibrary_p.h"
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qfileinfo.h>
+
+/*!
+
+ \internal
+ \class QSystemLibrary
+
+ The purpose of this class is to load only libraries that are located in
+ well-known and trusted locations on the filesystem. It does not suffer from
+ the security problem that QLibrary has, therefore it will never search in
+ the current directory.
+
+ The search order is the same as the order in DLL Safe search mode Windows,
+ except that we don't search:
+ * The current directory
+ * The 16-bit system directory. (normally \c{c:\windows\system})
+ * The Windows directory. (normally \c{c:\windows})
+
+ This means that the effective search order is:
+ 1. Application path.
+ 2. System libraries path.
+ 3. Trying all paths inside the PATH environment variable.
+
+ Note, when onlySystemDirectory is true it will skip 1) and 3).
+
+ DLL Safe search mode is documented in the "Dynamic-Link Library Search
+ Order" document on MSDN.
+
+ Since library loading code is sometimes shared between Windows and WinCE,
+ this class can also be used on WinCE. However, its implementation just
+ calls the LoadLibrary() function. This is ok since it is documented as not
+ loading from the current directory on WinCE. This behaviour is documented
+ in the documentation for LoadLibrary for Windows CE at MSDN.
+ (http://msdn.microsoft.com/en-us/library/ms886736.aspx)
+*/
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_WINCE)
+HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory /* = true */)
+{
+ return ::LoadLibrary(libraryName);
+}
+#else
+
+#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));
+}
+
+HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory /* = true */)
+{
+ QStringList searchOrder;
+
+#if !defined(QT_BOOTSTRAPPED)
+ if (!onlySystemDirectory)
+ searchOrder << QFileInfo(qAppFileName()).path();
+#endif
+ searchOrder << qSystemDirectory();
+
+ if (!onlySystemDirectory) {
+ const QString PATH(QLatin1String(qgetenv("PATH").constData()));
+ searchOrder << PATH.split(QLatin1Char(';'), QString::SkipEmptyParts);
+ }
+ QString fileName = QString::fromWCharArray(libraryName);
+ fileName.append(QLatin1String(".dll"));
+
+ // 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('\\'));
+ }
+ fullPathAttempt.append(fileName);
+ HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16());
+ if (inst != 0)
+ return inst;
+ }
+ return 0;
+
+}
+
+#endif //Q_OS_WINCE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h
new file mode 100644
index 0000000000..f72df0082b
--- /dev/null
+++ b/src/corelib/plugin/qsystemlibrary_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSYSTEMLIBRARY_P_H
+#define QSYSTEMLIBRARY_P_H
+
+#include <QtCore/qglobal.h>
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSystemLibrary
+{
+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);
+ }
+
+ bool isLoaded()
+ {
+ return (m_handle != 0);
+ }
+
+ void *resolve(const char *symbol)
+ {
+ if (!m_didLoad)
+ load();
+ if (!m_handle)
+ return 0;
+#ifdef Q_OS_WINCE
+ return (void*)GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16());
+#else
+ return (void*)GetProcAddress(m_handle, symbol);
+#endif
+ }
+
+ static void *resolve(const QString &libraryName, const char *symbol)
+ {
+ return QSystemLibrary(libraryName).resolve(symbol);
+ }
+
+ static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true);
+private:
+ HINSTANCE m_handle;
+ QString m_libraryName;
+ bool m_didLoad;
+};
+
+QT_END_NAMESPACE
+
+#endif //Q_OS_WIN
+
+#endif //QSYSTEMLIBRARY_P_H
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
new file mode 100644
index 0000000000..ba47beccb2
--- /dev/null
+++ b/src/corelib/plugin/quuid.cpp
@@ -0,0 +1,676 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quuid.h"
+
+#include "qdatastream.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QUuid
+ \brief The QUuid class stores a Universally Unique Identifier (UUID).
+
+ \reentrant
+
+ Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
+ standard way to uniquely identify entities in a distributed
+ computing environment. A UUID is a 16-byte (128-bit) number
+ generated by some algorithm that is meant to guarantee that the
+ UUID will be unique in the distributed computing environment where
+ it is used. The acronym GUID is often used instead, \e{G}lobally
+ \e{U}nique \e{ID}entifiers, but it refers to the same thing.
+
+ \target Variant field
+ Actually, the GUID is one \e{variant} of UUID. Multiple variants
+ are in use. Each UUID contains a bit field that specifies which
+ type (variant) of UUID it is. Call variant() to discover which
+ type of UUID an instance of QUuid contains. It extracts the three
+ most signifcant bits of byte 8 of the 16 bytes. In QUuid, byte 8
+ is \c{QUuid::data4[0]}. If you create instances of QUuid using the
+ constructor that accepts all the numeric values as parameters, use
+ the following table to set the three most significant bits of
+ parameter \c{b1}, which becomes \c{QUuid::data4[0]} and contains
+ the variant field in its three most significant bits. In the
+ table, 'x' means \e {don't care}.
+
+ \table
+ \header
+ \o msb0
+ \o msb1
+ \o msb2
+ \o Variant
+
+ \row
+ \o 0
+ \o x
+ \o x
+ \o NCS (Network Computing System)
+
+ \row
+ \o 1
+ \o 0
+ \o x
+ \o DCE (Distributed Computing Environment)
+
+ \row
+ \o 1
+ \o 1
+ \o 0
+ \o Microsoft (GUID)
+
+ \row
+ \o 1
+ \o 1
+ \o 1
+ \o Reserved for future expansion
+
+ \endtable
+
+ \target Version field
+ If variant() returns QUuid::DCE, the UUID also contains a
+ \e{version} field in the four most significant bits of
+ \c{QUuid::data3}, and you can call version() to discover which
+ version your QUuid contains. If you create instances of QUuid
+ using the constructor that accepts all the numeric values as
+ parameters, use the following table to set the four most
+ significant bits of parameter \c{w2}, which becomes
+ \c{QUuid::data3} and contains the version field in its four most
+ significant bits.
+
+ \table
+ \header
+ \o msb0
+ \o msb1
+ \o msb2
+ \o msb3
+ \o Version
+
+ \row
+ \o 0
+ \o 0
+ \o 0
+ \o 1
+ \o Time
+
+ \row
+ \o 0
+ \o 0
+ \o 1
+ \o 0
+ \o Embedded POSIX
+
+ \row
+ \o 0
+ \o 0
+ \o 1
+ \o 1
+ \o Name
+
+ \row
+ \o 0
+ \o 1
+ \o 0
+ \o 0
+ \o Random
+
+ \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}
+ {Network Working Group UUID Specification}.
+
+ Most platforms provide a tool for generating new UUIDs, e.g. \c
+ uuidgen and \c guidgen. You can also use createUuid(). UUIDs
+ generated by createUuid() are of the random type. Their
+ QUuid::Version bits are set to QUuid::Random, and their
+ QUuid::Variant bits are set to QUuid::DCE. The rest of the UUID is
+ composed of random numbers. Theoretically, this means there is a
+ small chance that a UUID generated by createUuid() will not be
+ unique. But it is
+ \l{http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Random_UUID_probability_of_duplicates}
+ {a \e{very} small chance}.
+
+ UUIDs can be constructed from numeric values or from strings, or
+ using the static createUuid() function. They can be converted to a
+ string with toString(). UUIDs have a variant() and a version(),
+ and null UUIDs return true from isNull().
+*/
+
+/*!
+ \fn QUuid::QUuid(const GUID &guid)
+
+ Casts a Windows \a guid to a Qt QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid &QUuid::operator=(const GUID &guid)
+
+ Assigns a Windows \a guid to a Qt QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid::operator GUID() const
+
+ Returns a Windows GUID from a QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid::QUuid()
+
+ Creates the null UUID. toString() will output the null UUID
+ as "{00000000-0000-0000-0000-000000000000}".
+*/
+
+/*!
+ \fn QUuid::QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8)
+
+ Creates a UUID with the value specified by the parameters, \a l,
+ \a w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a
+ b8.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_plugin_quuid.cpp 0
+*/
+
+#ifndef QT_NO_QUUID_STRING
+/*!
+ 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 '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
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
+
+ \sa toString(), QUuid()
+*/
+QUuid::QUuid(const QString &text)
+{
+ bool ok;
+ if (text.isEmpty()) {
+ *this = QUuid();
+ return;
+ }
+ QString temp = text.toUpper();
+ if (temp[0] != QLatin1Char('{'))
+ temp = QLatin1Char('{') + text;
+ if (text[(int)text.length()-1] != QLatin1Char('}'))
+ temp += QLatin1Char('}');
+
+ data1 = temp.mid(1, 8).toULongLong(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+
+ data2 = temp.mid(10, 4).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data3 = temp.mid(15, 4).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data4[0] = temp.mid(20, 2).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data4[1] = temp.mid(22, 2).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ for (int i = 2; i<8; i++) {
+ data4[i] = temp.mid(25 + (i-2)*2, 2).toUShort(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+QUuid::QUuid(const char *text)
+{
+ *this = QUuid(QString::fromLatin1(text));
+}
+#endif
+
+/*!
+ \fn bool QUuid::operator==(const QUuid &other) const
+
+ Returns true if this QUuid and the \a other QUuid are identical;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QUuid::operator!=(const QUuid &other) const
+
+ Returns true if this QUuid and the \a other QUuid are different;
+ otherwise returns false.
+*/
+#ifndef QT_NO_QUUID_STRING
+/*!
+ \fn QUuid::operator QString() const
+
+ Returns the string representation of the uuid.
+
+ \sa toString()
+*/
+
+static QString uuidhex(uint data, int digits)
+{
+ return QString::number(data, 16).rightJustified(digits, QLatin1Char('0'));
+}
+
+/*!
+ 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
+ \o Field #
+ \o Source
+
+ \row
+ \o 1
+ \o data1
+
+ \row
+ \o 2
+ \o data2
+
+ \row
+ \o 3
+ \o data3
+
+ \row
+ \o 4
+ \o data4[0] .. data4[1]
+
+ \row
+ \o 5
+ \o data4[2] .. data4[7]
+
+ \endtable
+*/
+QString QUuid::toString() const
+{
+ QString result;
+
+ QChar dash = QLatin1Char('-');
+ result = QLatin1Char('{') + uuidhex(data1,8);
+ result += dash;
+ result += uuidhex(data2,4);
+ result += dash;
+ result += uuidhex(data3,4);
+ result += dash;
+ result += uuidhex(data4[0],2);
+ result += uuidhex(data4[1],2);
+ result += dash;
+ for (int i = 2; i < 8; i++)
+ result += uuidhex(data4[i],2);
+
+ return result + QLatin1Char('}');
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QUuid
+ Writes the UUID \a id to the data stream \a s.
+*/
+QDataStream &operator<<(QDataStream &s, const QUuid &id)
+{
+ s << (quint32)id.data1;
+ s << (quint16)id.data2;
+ s << (quint16)id.data3;
+ for (int i = 0; i < 8; i++)
+ s << (quint8)id.data4[i];
+ return s;
+}
+
+/*!
+ \relates QUuid
+ Reads a UUID from the stream \a s into \a id.
+*/
+QDataStream &operator>>(QDataStream &s, QUuid &id)
+{
+ quint32 u32;
+ quint16 u16;
+ quint8 u8;
+ s >> u32;
+ id.data1 = u32;
+ s >> u16;
+ id.data2 = u16;
+ s >> u16;
+ id.data3 = u16;
+ for (int i = 0; i < 8; i++) {
+ s >> u8;
+ id.data4[i] = u8;
+ }
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ Returns true if this is the null UUID
+ {00000000-0000-0000-0000-000000000000}; otherwise returns false.
+*/
+bool QUuid::isNull() const
+{
+ return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
+ data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
+ data1 == 0 && data2 == 0 && data3 == 0;
+}
+
+/*!
+ \enum QUuid::Variant
+
+ This enum defines the values used in the \l{Variant field}
+ {variant field} of the UUID. The value in the variant field
+ determines the layout of the 128-bit value.
+
+ \value VarUnknown Variant is unknown
+ \value NCS Reserved for NCS (Network Computing System) backward compatibility
+ \value DCE Distributed Computing Environment, the scheme used by QUuid
+ \value Microsoft Reserved for Microsoft backward compatibility (GUID)
+ \value Reserved Reserved for future definition
+*/
+
+/*!
+ \enum QUuid::Version
+
+ This enum defines the values used in the \l{Version field}
+ {version field} of the UUID. The version field is meaningful
+ only if the value in the \l{Variant field} {variant field}
+ is QUuid::DCE.
+
+ \value VerUnknown Version is unknown
+ \value Time Time-based, by using timestamp, clock sequence, and
+ MAC network card address (if available) for the node sections
+ \value EmbeddedPOSIX DCE Security version, with embedded POSIX UUIDs
+ \value Name Name-based, by using values from a name for all sections
+ \value Random Random-based, by using random numbers for all sections
+*/
+
+/*!
+ \fn QUuid::Variant QUuid::variant() const
+
+ Returns the value in the \l{Variant field} {variant field} of the
+ UUID. If the return value is QUuid::DCE, call version() to see
+ which layout it uses. The null UUID is considered to be of an
+ unknown variant.
+
+ \sa version()
+*/
+QUuid::Variant QUuid::variant() const
+{
+ if (isNull())
+ return VarUnknown;
+ // Check the 3 MSB of data4[0]
+ if ((data4[0] & 0x80) == 0x00) return NCS;
+ else if ((data4[0] & 0xC0) == 0x80) return DCE;
+ else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
+ else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
+ return VarUnknown;
+}
+
+/*!
+ \fn QUuid::Version QUuid::version() const
+
+ Returns the \l{Version field} {version field} of the UUID, if the
+ UUID's \l{Variant field} {variant field} is QUuid::DCE. Otherwise
+ it returns QUuid::VerUnknown.
+
+ \sa variant()
+*/
+QUuid::Version QUuid::version() const
+{
+ // Check the 4 MSB of data3
+ Version ver = (Version)(data3>>12);
+ if (isNull()
+ || (variant() != DCE)
+ || ver < Time
+ || ver > Random)
+ return VerUnknown;
+ return ver;
+}
+
+/*!
+ \fn bool QUuid::operator<(const QUuid &other) const
+
+ Returns true if this QUuid has the same \l{Variant field}
+ {variant field} as the \a other QUuid and is lexicographically
+ \e{before} the \a other QUuid. If the \a other QUuid has a
+ different variant field, the return value is determined by
+ comparing the two \l{QUuid::Variant} {variants}.
+
+ \sa variant()
+*/
+#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
+bool QUuid::operator<(const QUuid &other) const
+{
+ if (variant() != other.variant())
+ return variant() < other.variant();
+
+ ISLESS(data1, other.data1);
+ ISLESS(data2, other.data2);
+ ISLESS(data3, other.data3);
+ for (int n = 0; n < 8; n++) {
+ ISLESS(data4[n], other.data4[n]);
+ }
+ return false;
+}
+
+/*!
+ \fn bool QUuid::operator>(const QUuid &other) const
+
+ Returns true if this QUuid has the same \l{Variant field}
+ {variant field} as the \a other QUuid and is lexicographically
+ \e{after} the \a other QUuid. If the \a other QUuid has a
+ different variant field, the return value is determined by
+ comparing the two \l{QUuid::Variant} {variants}.
+
+ \sa variant()
+*/
+#define ISMORE(f1, f2) if (f1!=f2) return (f1>f2);
+bool QUuid::operator>(const QUuid &other) const
+{
+ if (variant() != other.variant())
+ return variant() > other.variant();
+
+ ISMORE(data1, other.data1);
+ ISMORE(data2, other.data2);
+ ISMORE(data3, other.data3);
+ for (int n = 0; n < 8; n++) {
+ ISMORE(data4[n], other.data4[n]);
+ }
+ return false;
+}
+
+/*!
+ \fn QUuid QUuid::createUuid()
+
+ On any platform other than Windows, this function returns a new
+ UUID with variant QUuid::DCE and version QUuid::Random. If
+ the /dev/urandom device exists, then the numbers used to construct
+ the UUID will be of cryptographic quality, which will make the UUID
+ unique. Otherwise, the numbers of the UUID will be obtained from
+ the local pseudo-random number generator (qrand(), which is seeded
+ by qsrand()) which is usually not of cryptograhic quality, which
+ means that the UUID can't be guaranteed to be unique.
+
+ On a Windows platform, a GUID is generated, which almost certainly
+ \e{will} be unique, on this or any other system, networked or not.
+
+ \sa variant(), version()
+*/
+#if defined(Q_OS_WIN32) && ! defined(Q_CC_MWERKS)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <objbase.h> // For CoCreateGuid
+QT_END_INCLUDE_NAMESPACE
+
+QUuid QUuid::createUuid()
+{
+ GUID guid;
+ CoCreateGuid(&guid);
+ QUuid result = guid;
+ return result;
+}
+
+#else // !Q_OS_WIN32
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qdatetime.h"
+#include "qfile.h"
+#include "qthreadstorage.h"
+#include <stdlib.h> // for RAND_MAX
+QT_END_INCLUDE_NAMESPACE
+
+#if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_UNIX)
+Q_GLOBAL_STATIC(QThreadStorage<QFile *>, devUrandomStorage);
+#endif
+
+QUuid QUuid::createUuid()
+{
+ QUuid result;
+ uint *data = &(result.data1);
+
+#if defined(Q_OS_UNIX)
+ QFile *devUrandom;
+# if !defined(QT_BOOTSTRAPPED)
+ devUrandom = devUrandomStorage()->localData();
+ if (!devUrandom) {
+ devUrandom = new QFile(QLatin1String("/dev/urandom"));
+ devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+ devUrandomStorage()->setLocalData(devUrandom);
+ }
+# else
+ QFile file(QLatin1String("/dev/urandom"));
+ devUrandom = &file;
+ devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+# endif
+ enum { AmountToRead = 4 * sizeof(uint) };
+ if (devUrandom->isOpen()
+ && devUrandom->read((char *) data, AmountToRead) == AmountToRead) {
+ // we got what we wanted, nothing more to do
+ ;
+ } else
+#endif
+ {
+ static const int intbits = sizeof(int)*8;
+ static int randbits = 0;
+ if (!randbits) {
+ int r = 0;
+ int max = RAND_MAX;
+ do { ++r; } while ((max=max>>1));
+ randbits = r;
+ }
+
+ // Seed the PRNG once per thread with a combination of current time, a
+ // stack address and a serial counter (since thread stack addresses are
+ // re-used).
+#ifndef QT_BOOTSTRAPPED
+ static QThreadStorage<int *> uuidseed;
+ if (!uuidseed.hasLocalData())
+ {
+ int *pseed = new int;
+ static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(2);
+ qsrand(*pseed = QDateTime::currentDateTime().toTime_t()
+ + quintptr(&pseed)
+ + serial.fetchAndAddRelaxed(1));
+ uuidseed.setLocalData(pseed);
+ }
+#else
+ static bool seeded = false;
+ if (!seeded)
+ qsrand(QDateTime::currentDateTime().toTime_t()
+ + quintptr(&seeded));
+#endif
+
+ int chunks = 16 / sizeof(uint);
+ while (chunks--) {
+ uint randNumber = 0;
+ for (int filled = 0; filled < intbits; filled += randbits)
+ randNumber |= qrand()<<filled;
+ *(data+chunks) = randNumber;
+ }
+ }
+
+ result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
+ result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
+
+ return result;
+}
+#endif // !Q_OS_WIN32
+
+/*!
+ \fn bool QUuid::operator==(const GUID &guid) const
+
+ Returns true if this UUID is equal to the Windows GUID \a guid;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QUuid::operator!=(const GUID &guid) const
+
+ Returns true if this UUID is not equal to the Windows GUID \a
+ guid; otherwise returns false.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
new file mode 100644
index 0000000000..37bcd08b5f
--- /dev/null
+++ b/src/corelib/plugin/quuid.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUUID_H
+#define QUUID_H
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+#if defined(Q_OS_WIN)
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+ ulong Data1;
+ ushort Data2;
+ ushort Data3;
+ uchar Data4[8];
+} GUID, *REFGUID, *LPGUID;
+#endif
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QUuid
+{
+ enum Variant {
+ VarUnknown =-1,
+ NCS = 0, // 0 - -
+ DCE = 2, // 1 0 -
+ Microsoft = 6, // 1 1 0
+ Reserved = 7 // 1 1 1
+ };
+
+ enum Version {
+ VerUnknown =-1,
+ Time = 1, // 0 0 0 1
+ EmbeddedPOSIX = 2, // 0 0 1 0
+ Name = 3, // 0 0 1 1
+ Random = 4 // 0 1 0 0
+ };
+
+ QUuid()
+ {
+ 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)
+ {
+ 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;
+ }
+#ifndef QT_NO_QUUID_STRING
+ QUuid(const QString &);
+ QUuid(const char *);
+ QString toString() const;
+ operator QString() const { return toString(); }
+#endif
+ bool isNull() const;
+
+ bool operator==(const QUuid &orig) const
+ {
+ uint i;
+ if (data1 != orig.data1 || data2 != orig.data2 ||
+ data3 != orig.data3)
+ return false;
+
+ for(i = 0; i < 8; i++)
+ if (data4[i] != orig.data4[i])
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const QUuid &orig) const
+ {
+ return !(*this == orig);
+ }
+
+ bool operator<(const QUuid &other) const;
+ bool operator>(const QUuid &other) const;
+
+#if defined(Q_OS_WIN)
+ // 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.
+ QUuid(const GUID &guid)
+ {
+ data1 = guid.Data1;
+ data2 = guid.Data2;
+ data3 = guid.Data3;
+ for(int i = 0; i < 8; i++)
+ data4[i] = guid.Data4[i];
+ }
+
+ QUuid &operator=(const GUID &guid)
+ {
+ *this = QUuid(guid);
+ return *this;
+ }
+
+ operator GUID() const
+ {
+ GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
+ return guid;
+ }
+
+ bool operator==(const GUID &guid) const
+ {
+ return *this == QUuid(guid);
+ }
+
+ bool operator!=(const GUID &guid) const
+ {
+ return !(*this == guid);
+ }
+#endif
+ static QUuid createUuid();
+ QUuid::Variant variant() const;
+ QUuid::Version version() const;
+
+ uint data1;
+ ushort data2;
+ ushort data3;
+ uchar data4[8];
+};
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUuid &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUuid &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QUUID_H
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
new file mode 100644
index 0000000000..9b40695f8e
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstractstate_p.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractState
+
+ \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.
+*/
+
+QAbstractStatePrivate::QAbstractStatePrivate(StateType type)
+ : stateType(type), isMachine(false), parentState(0)
+{
+}
+
+QAbstractStatePrivate *QAbstractStatePrivate::get(QAbstractState *q)
+{
+ return q->d_func();
+}
+
+const QAbstractStatePrivate *QAbstractStatePrivate::get(const QAbstractState *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractStatePrivate::machine() const
+{
+ QObject *par = parent;
+ while (par != 0) {
+ if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
+ return mach;
+ par = par->parent();
+ }
+ return 0;
+}
+
+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();
+}
+
+void QAbstractStatePrivate::emitExited()
+{
+ Q_Q(QAbstractState);
+ emit q->exited();
+}
+
+/*!
+ 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 0 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 0 if the state is
+ not part of a state machine.
+*/
+QStateMachine *QAbstractState::machine() const
+{
+ Q_D(const QAbstractState);
+ return d->machine();
+}
+
+/*!
+ \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).
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractState::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
new file mode 100644
index 0000000000..4931df38f1
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTSTATE_H
+#define QABSTRACTSTATE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QState;
+class QStateMachine;
+
+class QAbstractStatePrivate;
+class Q_CORE_EXPORT QAbstractState : public QObject
+{
+ Q_OBJECT
+public:
+ ~QAbstractState();
+
+ QState *parentState() const;
+ QStateMachine *machine() const;
+
+Q_SIGNALS:
+#if !defined(Q_MOC_RUN) && !defined(qdoc)
+private: // can only be emitted by QAbstractState
+#endif
+ void entered();
+ void exited();
+
+protected:
+ QAbstractState(QState *parent = 0);
+
+ virtual void onEntry(QEvent *event) = 0;
+ virtual void onExit(QEvent *event) = 0;
+
+ bool event(QEvent *e);
+
+protected:
+ QAbstractState(QAbstractStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractState)
+ Q_DECLARE_PRIVATE(QAbstractState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
new file mode 100644
index 0000000000..950dc1a8eb
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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>
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QAbstractState;
+class QAbstractStatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractState)
+
+public:
+ enum StateType {
+ AbstractState,
+ StandardState,
+ FinalState,
+ HistoryState
+ };
+
+ QAbstractStatePrivate(StateType type);
+
+ static QAbstractStatePrivate *get(QAbstractState *q);
+ static const QAbstractStatePrivate *get(const QAbstractState *q);
+
+ QStateMachine *machine() const;
+
+ void callOnEntry(QEvent *e);
+ void callOnExit(QEvent *e);
+
+ void emitEntered();
+ void emitExited();
+
+ uint stateType:31;
+ uint isMachine:1;
+ mutable QState *parentState;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
new file mode 100644
index 0000000000..d8a551f5bd
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstracttransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstracttransition_p.h"
+#include "qabstractstate.h"
+#include "qstate.h"
+#include "qstatemachine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractTransition
+
+ \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.
+*/
+
+QAbstractTransitionPrivate::QAbstractTransitionPrivate()
+{
+}
+
+QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(QAbstractTransition *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractTransitionPrivate::machine() const
+{
+ QState *source = sourceState();
+ if (!source)
+ return 0;
+ return source->machine();
+}
+
+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();
+}
+
+/*!
+ 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 0 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 0 if the transition has no
+ target.
+*/
+QAbstractState *QAbstractTransition::targetState() const
+{
+ Q_D(const QAbstractTransition);
+ if (d->targetStates.isEmpty())
+ return 0;
+ return d->targetStates.first().data();
+}
+
+/*!
+ Sets the \a target state of this transition.
+*/
+void QAbstractTransition::setTargetState(QAbstractState* target)
+{
+ Q_D(QAbstractTransition);
+ if (!target)
+ d->targetStates.clear();
+ else
+ setTargetStates(QList<QAbstractState*>() << target);
+}
+
+/*!
+ 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);
+
+ for (int i = 0; i < targets.size(); ++i) {
+ QAbstractState *target = targets.at(i);
+ if (!target) {
+ qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
+ return;
+ }
+ }
+
+ d->targetStates.clear();
+ for (int i = 0; i < targets.size(); ++i)
+ d->targetStates.append(targets.at(i));
+}
+
+/*!
+ Returns the state machine that this transition is part of, or 0 if the
+ transition is not part of a state machine.
+*/
+QStateMachine *QAbstractTransition::machine() const
+{
+ Q_D(const QAbstractTransition);
+ return d->machine();
+}
+
+#ifndef QT_NO_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).
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractTransition::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
new file mode 100644
index 0000000000..74bb843c84
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTTRANSITION_H
+#define QABSTRACTTRANSITION_H
+
+#include <QtCore/qobject.h>
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QEvent;
+class QAbstractState;
+class QState;
+class QStateMachine;
+
+#ifndef QT_NO_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)
+ Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates)
+public:
+ QAbstractTransition(QState *sourceState = 0);
+ virtual ~QAbstractTransition();
+
+ QState *sourceState() const;
+ QAbstractState *targetState() const;
+ void setTargetState(QAbstractState* target);
+ QList<QAbstractState*> targetStates() const;
+ void setTargetStates(const QList<QAbstractState*> &targets);
+
+ QStateMachine *machine() const;
+
+#ifndef QT_NO_ANIMATION
+ void addAnimation(QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation*> animations() const;
+#endif
+
+Q_SIGNALS:
+#if !defined(Q_MOC_RUN) && !defined(qdoc)
+private: // can only be emitted by QAbstractTransition
+#endif
+ void triggered();
+
+protected:
+ virtual bool eventTest(QEvent *event) = 0;
+
+ virtual void onTransition(QEvent *event) = 0;
+
+ bool event(QEvent *e);
+
+protected:
+ QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractTransition)
+ Q_DECLARE_PRIVATE(QAbstractTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
new file mode 100644
index 0000000000..3de8447965
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qsharedpointer.h>
+
+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);
+
+ bool callEventTest(QEvent *e);
+ virtual void callOnTransition(QEvent *e);
+ QState *sourceState() const;
+ QStateMachine *machine() const;
+ void emitTriggered();
+
+ QList<QWeakPointer<QAbstractState> > targetStates;
+
+#ifndef QT_NO_ANIMATION
+ QList<QAbstractAnimation*> animations;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
new file mode 100644
index 0000000000..539c307f87
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#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
+
+ \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 = 0;
+ eventType = QEvent::None;
+ registered = false;
+}
+
+QEventTransitionPrivate *QEventTransitionPrivate::get(QEventTransition *q)
+{
+ return q->d_func();
+}
+
+void QEventTransitionPrivate::unregister()
+{
+ Q_Q(QEventTransition);
+ if (!registered || !machine())
+ return;
+ QStateMachinePrivate::get(machine())->unregisterEventTransition(q);
+}
+
+void QEventTransitionPrivate::maybeRegister()
+{
+ Q_Q(QEventTransition);
+ if (!machine() || !machine()->configuration().contains(sourceState()))
+ return;
+ QStateMachinePrivate::get(machine())->registerEventTransition(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;
+}
+
+/*!
+ \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;
+}
+
+/*!
+ 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
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h
new file mode 100644
index 0000000000..838c12e7a9
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTTRANSITION_H
+#define QEVENTTRANSITION_H
+
+#include <QtCore/qabstracttransition.h>
+#include <QtCore/qcoreevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+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 = 0);
+ QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0);
+ ~QEventTransition();
+
+ QObject *eventSource() const;
+ void setEventSource(QObject *object);
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+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)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h
new file mode 100644
index 0000000000..b021f307b4
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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_BEGIN_NAMESPACE
+
+class QEventTransition;
+class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QEventTransition)
+public:
+ QEventTransitionPrivate();
+
+ static QEventTransitionPrivate *get(QEventTransition *q);
+
+ void unregister();
+ void maybeRegister();
+
+ bool registered;
+ QObject *object;
+ QEvent::Type eventType;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp
new file mode 100644
index 0000000000..260b3653b9
--- /dev/null
+++ b/src/corelib/statemachine/qfinalstate.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfinalstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstractstate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFinalState
+
+ \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 QStateMachine::finished(), QState::finished()
+*/
+
+class QFinalStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QFinalState)
+
+public:
+ QFinalStatePrivate();
+};
+
+QFinalStatePrivate::QFinalStatePrivate()
+ : QAbstractStatePrivate(FinalState)
+{
+}
+
+/*!
+ Constructs a new QFinalState object with the given \a parent state.
+*/
+QFinalState::QFinalState(QState *parent)
+ : QAbstractState(*new QFinalStatePrivate, 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
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h
new file mode 100644
index 0000000000..27c3fa1786
--- /dev/null
+++ b/src/corelib/statemachine/qfinalstate.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFINALSTATE_H
+#define QFINALSTATE_H
+
+#include <QtCore/qabstractstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QFinalStatePrivate;
+class Q_CORE_EXPORT QFinalState : public QAbstractState
+{
+ Q_OBJECT
+public:
+ QFinalState(QState *parent = 0);
+ ~QFinalState();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QFinalState)
+ Q_DECLARE_PRIVATE(QFinalState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
new file mode 100644
index 0000000000..7093c327ac
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhistorystate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qhistorystate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QHistoryState
+
+ \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 of the
+ 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
+
+ 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::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.
+*/
+
+QHistoryStatePrivate::QHistoryStatePrivate()
+ : QAbstractStatePrivate(HistoryState),
+ defaultState(0), historyType(QHistoryState::ShallowHistory)
+{
+}
+
+QHistoryStatePrivate *QHistoryStatePrivate::get(QHistoryState *q)
+{
+ return q->d_func();
+}
+
+/*!
+ 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 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->defaultState;
+}
+
+/*!
+ 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;
+ }
+ d->defaultState = state;
+}
+
+/*!
+ 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);
+ d->historyType = type;
+}
+
+/*!
+ \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);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
new file mode 100644
index 0000000000..5e52b7942e
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHISTORYSTATE_H
+#define QHISTORYSTATE_H
+
+#include <QtCore/qabstractstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QHistoryStatePrivate;
+class Q_CORE_EXPORT QHistoryState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState)
+ Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType)
+ Q_ENUMS(HistoryType)
+public:
+ enum HistoryType {
+ ShallowHistory,
+ DeepHistory
+ };
+
+ QHistoryState(QState *parent = 0);
+ QHistoryState(HistoryType type, QState *parent = 0);
+ ~QHistoryState();
+
+ QAbstractState *defaultState() const;
+ void setDefaultState(QAbstractState *state);
+
+ HistoryType historyType() const;
+ void setHistoryType(HistoryType type);
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QHistoryState)
+ Q_DECLARE_PRIVATE(QHistoryState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h
new file mode 100644
index 0000000000..07dc6e8051
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHistoryState;
+class QHistoryStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QHistoryState)
+
+public:
+ QHistoryStatePrivate();
+
+ static QHistoryStatePrivate *get(QHistoryState *q);
+
+ QAbstractState *defaultState;
+ QHistoryState::HistoryType historyType;
+ QList<QAbstractState*> configuration;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
new file mode 100644
index 0000000000..9409bc9806
--- /dev/null
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QSignalEventGenerator : public QObject
+{
+public:
+ QSignalEventGenerator(QStateMachine *parent);
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+private:
+ Q_DISABLE_COPY(QSignalEventGenerator)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
new file mode 100644
index 0000000000..b0b735bb9b
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsignaltransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#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
+
+ \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 = 0;
+ signalIndex = -1;
+}
+
+QSignalTransitionPrivate *QSignalTransitionPrivate::get(QSignalTransition *q)
+{
+ return q->d_func();
+}
+
+void QSignalTransitionPrivate::unregister()
+{
+ Q_Q(QSignalTransition);
+ if ((signalIndex == -1) || !machine())
+ return;
+ QStateMachinePrivate::get(machine())->unregisterSignalTransition(q);
+}
+
+void QSignalTransitionPrivate::maybeRegister()
+{
+ Q_Q(QSignalTransition);
+ if (!machine() || !machine()->configuration().contains(sourceState()))
+ return;
+ QStateMachinePrivate::get(machine())->registerSignalTransition(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(QObject *sender, const char *signal,
+ QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
+{
+ Q_D(QSignalTransition);
+ d->sender = sender;
+ d->signal = signal;
+}
+
+/*!
+ Destroys this signal transition.
+*/
+QSignalTransition::~QSignalTransition()
+{
+}
+
+/*!
+ Returns the sender object associated with this signal transition.
+*/
+QObject *QSignalTransition::senderObject() const
+{
+ Q_D(const QSignalTransition);
+ return d->sender;
+}
+
+/*!
+ Sets the \a sender object associated with this signal transition.
+*/
+void QSignalTransition::setSenderObject(QObject *sender)
+{
+ Q_D(QSignalTransition);
+ if (sender == d->sender)
+ return;
+ d->unregister();
+ d->sender = sender;
+ d->maybeRegister();
+}
+
+/*!
+ 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();
+}
+
+/*!
+ \reimp
+
+ The default implementation returns true if the \a event is a
+ QStateMachine::SignalEvent object and the event's sender and signal index
+ match this transition, and returns 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);
+}
+
+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
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
new file mode 100644
index 0000000000..93ec73433a
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALTRANSITION_H
+#define QSIGNALTRANSITION_H
+
+#include <QtCore/qabstracttransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QSignalTransitionPrivate;
+class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject)
+ Q_PROPERTY(QByteArray signal READ signal WRITE setSignal)
+public:
+ QSignalTransition(QState *sourceState = 0);
+ QSignalTransition(QObject *sender, const char *signal,
+ QState *sourceState = 0);
+ ~QSignalTransition();
+
+ QObject *senderObject() const;
+ void setSenderObject(QObject *sender);
+
+ QByteArray signal() const;
+ void setSignal(const QByteArray &signal);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QSignalTransition)
+ Q_DECLARE_PRIVATE(QSignalTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h
new file mode 100644
index 0000000000..5becfe5b13
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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_BEGIN_NAMESPACE
+
+class QSignalTransition;
+class QSignalTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QSignalTransition)
+public:
+ QSignalTransitionPrivate();
+
+ static QSignalTransitionPrivate *get(QSignalTransition *q);
+
+ void unregister();
+ void maybeRegister();
+
+ virtual void callOnTransition(QEvent *e);
+
+ 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
new file mode 100644
index 0000000000..f8f4f510b7
--- /dev/null
+++ b/src/corelib/statemachine/qstate.cpp
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#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
+
+ \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.
+*/
+
+QStatePrivate::QStatePrivate()
+ : QAbstractStatePrivate(StandardState),
+ errorState(0), initialState(0), childMode(QState::ExclusiveStates),
+ childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true)
+{
+}
+
+QStatePrivate::~QStatePrivate()
+{
+}
+
+void QStatePrivate::emitFinished()
+{
+ Q_Q(QState);
+ emit q->finished();
+}
+
+void QStatePrivate::emitPropertiesAssigned()
+{
+ Q_Q(QState);
+ emit q->propertiesAssigned();
+}
+
+/*!
+ 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.object == object) && (assn.propertyName == 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 0, 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 != 0 && qobject_cast<QStateMachine*>(state)) {
+ qWarning("QStateMachine::setErrorState: root state cannot be error state");
+ return;
+ }
+ if (state != 0 && (!state->machine() || ((state->machine() != machine()) && !qobject_cast<QStateMachine*>(this)))) {
+ qWarning("QState::setErrorState: error state cannot belong "
+ "to a different state machine");
+ return;
+ }
+
+ d->errorState = state;
+}
+
+/*!
+ 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 QList<QWeakPointer<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 (machine() != 0 && machine()->configuration().contains(this))
+ QStateMachinePrivate::get(machine())->registerTransitions(this);
+}
+
+/*!
+ 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(QObject *sender, const char *signal,
+ QAbstractState *target)
+{
+ if (!sender) {
+ qWarning("QState::addTransition: sender cannot be null");
+ return 0;
+ }
+ if (!signal) {
+ qWarning("QState::addTransition: signal cannot be null");
+ return 0;
+ }
+ if (!target) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ 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 0;
+ }
+ }
+ 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 *) {}
+ bool eventTest(QEvent *) { 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 0;
+ }
+ 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(0);
+}
+
+/*!
+ \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 0 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;
+ }
+ d->initialState = state;
+}
+
+/*!
+ 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);
+ d->childMode = mode;
+}
+
+/*!
+ \reimp
+*/
+bool QState::event(QEvent *e)
+{
+ Q_D(QState);
+ if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) {
+ d->childStatesListNeedsRefresh = true;
+ d->transitionsListNeedsRefresh = true;
+ }
+ 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()
+*/
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
new file mode 100644
index 0000000000..654dda53b1
--- /dev/null
+++ b/src/corelib/statemachine/qstate.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATE_H
+#define QSTATE_H
+
+#include <QtCore/qabstractstate.h>
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QAbstractTransition;
+class QSignalTransition;
+
+class QStatePrivate;
+class Q_CORE_EXPORT QState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
+ Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode)
+ Q_ENUMS(ChildMode)
+public:
+ enum ChildMode {
+ ExclusiveStates,
+ ParallelStates
+ };
+
+ QState(QState *parent = 0);
+ QState(ChildMode childMode, QState *parent = 0);
+ ~QState();
+
+ QAbstractState *errorState() const;
+ void setErrorState(QAbstractState *state);
+
+ void addTransition(QAbstractTransition *transition);
+ QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target);
+ 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();
+ void propertiesAssigned();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QState(QStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QState)
+ Q_DECLARE_PRIVATE(QState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
new file mode 100644
index 0000000000..08b13979e2
--- /dev/null
+++ b/src/corelib/statemachine/qstate_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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 "private/qabstractstate_p.h"
+
+#include <QtCore/qlist.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QPropertyAssignment
+{
+ QPropertyAssignment()
+ : object(0), explicitlySet(true) {}
+ QPropertyAssignment(QObject *o, const QByteArray &n,
+ const QVariant &v, bool es = true)
+ : object(o), propertyName(n), value(v), explicitlySet(es)
+ {}
+ QObject *object;
+ QByteArray propertyName;
+ QVariant value;
+ bool explicitlySet;
+};
+
+class QAbstractTransition;
+class QHistoryState;
+
+class QState;
+class Q_AUTOTEST_EXPORT QStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QState)
+public:
+ QStatePrivate();
+ ~QStatePrivate();
+
+ static QStatePrivate *get(QState *q) { return q ? q->d_func() : 0; }
+ static const QStatePrivate *get(const QState *q) { return q? q->d_func() : 0; }
+
+ 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 QList<QAbstractState*> childStatesList;
+ mutable bool transitionsListNeedsRefresh;
+ mutable QList<QAbstractTransition*> transitionsList;
+
+ QList<QPropertyAssignment> propertyAssignments;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
new file mode 100644
index 0000000000..b2af5ca961
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -0,0 +1,2401 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstatemachine.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#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"
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+#include "qeventtransition.h"
+#include "qeventtransition_p.h"
+#endif
+
+#ifndef QT_NO_ANIMATION
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include <private/qvariantanimation_p.h>
+#endif
+
+#include <QtCore/qmetaobject.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStateMachine
+ \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{Statecharts: A visual formalism for complex
+ systems}{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{State Chart XML: State
+ Machine Notation for Control Abstraction}{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 doc/src/snippets/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.
+
+ \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
+ QStateMachine::DontRestoreProperties.
+*/
+
+#ifndef QT_NO_ANIMATION
+/*!
+ \property QStateMachine::animated
+
+ \brief whether animations are enabled
+
+ The default value of this property is true.
+
+ \sa QAbstractTransition::addAnimation()
+*/
+#endif
+
+// #define QSTATEMACHINE_DEBUG
+
+QStateMachinePrivate::QStateMachinePrivate()
+{
+ isMachine = true;
+
+ state = NotRunning;
+ _startState = 0;
+ processing = false;
+ processingScheduled = false;
+ stop = false;
+ stopProcessingReason = EventQueueEmpty;
+ error = QStateMachine::NoError;
+ globalRestorePolicy = QStateMachine::DontRestoreProperties;
+ signalEventGenerator = 0;
+#ifndef QT_NO_ANIMATION
+ animated = true;
+#endif
+}
+
+QStateMachinePrivate::~QStateMachinePrivate()
+{
+ qDeleteAll(internalEventQueue);
+ qDeleteAll(externalEventQueue);
+}
+
+QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q)
+{
+ if (q)
+ return q->d_func();
+ return 0;
+}
+
+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 0;
+}
+
+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) || QStateMachinePrivate::isDescendantOf(desc, c)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return false;
+ } else if (isDescendantOf(s2, s1)) {
+ return true;
+ } else {
+ Q_ASSERT(s1->machine() != 0);
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
+ QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return true;
+ } else if (isDescendantOf(s2, s1)) {
+ return false;
+ } else {
+ Q_ASSERT(s1->machine() != 0);
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
+ QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const
+{
+ if (states.isEmpty())
+ return 0;
+ QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState());
+ for (int i = 0; i < ancestors.size(); ++i) {
+ QState *anc = ancestors.at(i);
+ bool ok = true;
+ for (int j = states.size() - 1; (j > 0) && ok; --j) {
+ const QAbstractState *s = states.at(j);
+ if (!isDescendantOf(s, anc))
+ ok = false;
+ }
+ if (ok)
+ return anc;
+ }
+ return 0;
+}
+
+bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const
+{
+ QSet<QAbstractTransition*>::const_iterator it;
+ for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
+ QAbstractTransition *t = *it;
+ QList<QAbstractState*> lst = t->targetStates();
+ if (!lst.isEmpty()) {
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (isDescendantOf(s, lca)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from"
+ << s << "because" << s << "is a descendant of" << lca;
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const
+{
+ Q_Q(const QStateMachine);
+ QSet<QAbstractTransition*> enabledTransitions;
+ QSet<QAbstractState*>::const_iterator it;
+ const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *state = *it;
+ if (!isAtomic(state))
+ continue;
+ if (isPreempted(state, enabledTransitions))
+ continue;
+ QList<QState*> lst = properAncestors(state, rootState()->parentState());
+ 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.insert(t);
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ const_cast<QStateMachine*>(q)->endSelectTransitions(event);
+ return enabledTransitions;
+}
+
+void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
+ qDebug() << q_func() << ": configuration before exiting states:" << configuration;
+#endif
+ QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after exiting states:" << configuration;
+#endif
+ executeTransitionContent(event, enabledTransitions);
+ QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions);
+#ifndef QT_NO_PROPERTIES
+ applyProperties(enabledTransitions, exitedStates, enteredStates);
+#endif
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after entering states:" << configuration;
+ qDebug() << q_func() << ": end microstep";
+#endif
+}
+
+QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+// qDebug() << "exitStates(" << enabledTransitions << ')';
+ QSet<QAbstractState*> statesToExit;
+// QSet<QAbstractState*> statesToSnapshot;
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (lca == 0) {
+ setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
+ lst = pendingErrorStates.toList();
+ lst.prepend(t->sourceState());
+
+ lca = findLCA(lst);
+ Q_ASSERT(lca != 0);
+ }
+
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *s = *it;
+ if (isDescendantOf(s, lca))
+ statesToExit.insert(s);
+ }
+ }
+ }
+ QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
+ qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
+ 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) && isDescendantOf(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);
+ configuration.remove(s);
+ QAbstractStatePrivate::get(s)->emitExited();
+ }
+ return statesToExit_sorted;
+}
+
+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::enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ Q_Q(QStateMachine);
+#endif
+// qDebug() << "enterStates(" << enabledTransitions << ')';
+ QSet<QAbstractState*> statesToEnter;
+ QSet<QAbstractState*> statesForDefaultEntry;
+
+ if (pendingErrorStates.isEmpty()) {
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QState *lca = findLCA(lst);
+ for (int j = 1; j < lst.size(); ++j) {
+ QAbstractState *s = lst.at(j);
+ addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
+ if (isParallel(lca)) {
+ QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates();
+ foreach (QAbstractState* child,lcac) {
+ if (!statesToEnter.contains(child))
+ addStatesToEnter(child,lca,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.toList();
+ qSort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
+
+ 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);
+ QAbstractStatePrivate::get(s)->callOnEntry(event);
+ QAbstractStatePrivate::get(s)->emitEntered();
+ if (statesForDefaultEntry.contains(s)) {
+ // ### executeContent(s.initial.transition.children())
+ }
+ if (isFinal(s)) {
+ QState *parent = s->parentState();
+ if (parent) {
+ if (parent != rootState()) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << parent;
+#endif
+ QStatePrivate::get(parent)->emitFinished();
+ }
+ 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())) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << grandparent;
+#endif
+ QStatePrivate::get(grandparent)->emitFinished();
+ }
+ }
+ }
+ }
+ }
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ if (isFinal(*it) && (*it)->parentState() == rootState()) {
+ processing = false;
+ stopProcessingReason = Finished;
+ break;
+ }
+ }
+ }
+// qDebug() << "configuration:" << configuration.toList();
+ return statesToEnter_sorted;
+}
+
+void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry)
+{
+ if (QHistoryState *h = toHistoryState(s)) {
+ QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
+ if (!hconf.isEmpty()) {
+ for (int k = 0; k < hconf.size(); ++k) {
+ QAbstractState *s0 = hconf.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() <<q_func() << ": restoring"
+ << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history from" << s << ':' << hconf;
+ #endif
+ } else {
+ QList<QAbstractState*> hlst;
+ if (QHistoryStatePrivate::get(h)->defaultState)
+ hlst.append(QHistoryStatePrivate::get(h)->defaultState);
+
+ if (hlst.isEmpty()) {
+ setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
+ } else {
+ for (int k = 0; k < hlst.size(); ++k) {
+ QAbstractState *s0 = hlst.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": initial history targets for" << s << ':' << hlst;
+ #endif
+ }
+ }
+ } else {
+ if (s == rootState()) {
+ // Error has already been set by exitStates().
+ Q_ASSERT(error != QStateMachine::NoError);
+ return;
+ }
+ statesToEnter.insert(s);
+ if (isParallel(s)) {
+ QState *grp = toStandardState(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *child = lst.at(i);
+ addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
+ }
+ } else if (isCompound(s)) {
+ statesForDefaultEntry.insert(s);
+ QState *grp = toStandardState(s);
+ QAbstractState *initial = grp->initialState();
+ if (initial != 0) {
+ Q_ASSERT(initial->machine() == q_func());
+ addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
+ } else {
+ setError(QStateMachine::NoInitialStateError, grp);
+ return;
+ }
+ }
+ QList<QState*> ancs = properAncestors(s, root);
+ for (int i = 0; i < ancs.size(); ++i) {
+ QState *anc = ancs.at(i);
+ if (!anc->parentState())
+ continue;
+ statesToEnter.insert(anc);
+ if (isParallel(anc)) {
+ QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates();
+ for (int j = 0; j < lst.size(); ++j) {
+ QAbstractState *child = lst.at(j);
+ bool hasDescendantInList = false;
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
+ if (isDescendantOf(*it, child)) {
+ hasDescendantInList = true;
+ break;
+ }
+ }
+ if (!hasDescendantInList)
+ addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
+ }
+ }
+ }
+ }
+}
+
+#ifndef QT_NO_PROPERTIES
+
+void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates)
+{
+#ifdef QT_NO_ANIMATION
+ Q_UNUSED(transitionList);
+ Q_UNUSED(exitedStates);
+#else
+ Q_Q(QStateMachine);
+#endif
+ // Process the property assignments of the entered states.
+ QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
+ QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = toStandardState(enteredStates.at(i));
+ if (!s)
+ continue;
+
+ QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
+ for (int j = 0; j < assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ if (globalRestorePolicy == QStateMachine::RestoreProperties) {
+ registerRestorable(assn.object, assn.propertyName);
+ }
+ pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ propertyAssignmentsForState[s].append(assn);
+ }
+
+ // Remove pending restorables for all parent states to avoid restoring properties
+ // before the state that assigned them is exited. If state does not explicitly
+ // assign a property which is assigned by the parent, it inherits the parent's assignment.
+ QState *parentState = s;
+ while ((parentState = parentState->parentState()) != 0) {
+ assignments = QStatePrivate::get(parentState)->propertyAssignments;
+ for (int j=0; j<assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ if (c > 0)
+ propertyAssignmentsForState[s].append(assn);
+ }
+ }
+ }
+ if (!pendingRestorables.isEmpty()) {
+ QAbstractState *s;
+ if (!enteredStates.isEmpty())
+ s = enteredStates.last(); // ### handle if parallel
+ else
+ s = 0;
+ propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables);
+ }
+
+#ifndef QT_NO_ANIMATION
+ // Gracefully terminate playing animations for states that are exited.
+ for (int i = 0; i < exitedStates.size(); ++i) {
+ QAbstractState *s = exitedStates.at(i);
+ QList<QAbstractAnimation*> animations = animationsForState.take(s);
+ for (int j = 0; j < animations.size(); ++j) {
+ QAbstractAnimation *anim = animations.at(j);
+ 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 != 0);
+ // If there is no property assignment that sets this property,
+ // set the property to its target value.
+ bool found = false;
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int k = 0; k < assignments.size(); ++k) {
+ if ((assignments.at(k).object == assn.object)
+ && (assignments.at(k).propertyName == assn.propertyName)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Find the animations to use for the state change.
+ 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;
+ }
+
+ // Initialize animations from property assignments.
+ for (int i = 0; i < selectedAnimations.size(); ++i) {
+ QAbstractAnimation *anim = selectedAnimations.at(i);
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::iterator it;
+ for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) {
+ QList<QPropertyAssignment>::iterator it2;
+ QAbstractState *s = it.key();
+ QList<QPropertyAssignment> &assignments = it.value();
+ for (it2 = assignments.begin(); it2 != assignments.end(); ) {
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(anim, *it2);
+ QList<QAbstractAnimation*> handlers = ret.first;
+ if (!handlers.isEmpty()) {
+ for (int j = 0; j < handlers.size(); ++j) {
+ QAbstractAnimation *a = handlers.at(j);
+ propertyForAnimation.insert(a, *it2);
+ stateForAnimation.insert(a, s);
+ animationsForState[s].append(a);
+ // ### connect to just the top-level animation?
+ QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()), Qt::UniqueConnection);
+ }
+ it2 = assignments.erase(it2);
+ } else {
+ ++it2;
+ }
+ for (int j = 0; j < ret.second.size(); ++j)
+ resetAnimationEndValues.insert(ret.second.at(j));
+ }
+ if (assignments.isEmpty())
+ it = propertyAssignmentsForState.erase(it);
+ else
+ ++it;
+ }
+ // 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();
+ }
+ }
+#endif // !QT_NO_ANIMATION
+
+ // Immediately set the properties that are not animated.
+ {
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int i = 0; i < assignments.size(); ++i) {
+ const QPropertyAssignment &assn = assignments.at(i);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Emit propertiesAssigned signal for entered states that have no animated properties.
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = toStandardState(enteredStates.at(i));
+ if (s
+#ifndef QT_NO_ANIMATION
+ && !animationsForState.contains(s)
+#endif
+ )
+ QStatePrivate::get(s)->emitPropertiesAssigned();
+ }
+}
+
+#endif // QT_NO_PROPERTIES
+
+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())
+ || isMachine;
+}
+
+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()));
+}
+
+
+bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
+{
+ Q_ASSERT(state != 0);
+ for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
+ if (s == other)
+ return true;
+ }
+ return false;
+}
+
+QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound)
+{
+ Q_ASSERT(state != 0);
+ QList<QState*> result;
+ for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
+ result.append(s);
+ }
+ return result;
+}
+
+QState *QStateMachinePrivate::toStandardState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
+ return static_cast<QState*>(state);
+ return 0;
+}
+
+const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
+ return static_cast<const QState*>(state);
+ return 0;
+}
+
+QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState))
+ return static_cast<QFinalState*>(state);
+ return 0;
+}
+
+QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState))
+ return static_cast<QHistoryState*>(state);
+ return 0;
+}
+
+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
+
+void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName)
+{
+ RestorableId id(object, propertyName);
+ if (!registeredRestorables.contains(id))
+ registeredRestorables.insert(id, object->property(propertyName));
+}
+
+QList<QPropertyAssignment> QStateMachinePrivate::restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const
+{
+ QList<QPropertyAssignment> result;
+ QHash<RestorableId, QVariant>::const_iterator it;
+ for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
+// qDebug() << "restorable:" << it.key().first << it.key().second << it.value();
+ result.append(QPropertyAssignment(it.key().first, it.key().second, it.value(), /*explicitlySet=*/false));
+ }
+ return result;
+}
+
+/*!
+ \internal
+ Returns true if the variable with the given \a id has been registered for restoration.
+*/
+bool QStateMachinePrivate::hasRestorable(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.contains(RestorableId(object, propertyName));
+}
+
+QVariant QStateMachinePrivate::restorableValue(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.value(RestorableId(object, propertyName), QVariant());
+}
+
+
+/*!
+ \internal
+ Unregisters the variable identified by \a id
+*/
+void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArray &propertyName)
+{
+// qDebug() << "unregisterRestorable(" << object << propertyName << ')';
+ RestorableId id(object, propertyName);
+ registeredRestorables.remove(id);
+}
+
+#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 = 0;
+ if (context != 0) {
+ QState *s = toStandardState(context);
+ if (s != 0)
+ errorState = s->errorState();
+
+ if (errorState == 0)
+ 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 != 0);
+
+ errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
+ .arg(currentContext->objectName());
+
+ break;
+ case QStateMachine::NoDefaultStateInHistoryStateError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("Missing default state in history state '%1'")
+ .arg(currentContext->objectName());
+ break;
+
+ case QStateMachine::NoCommonAncestorForTransitionError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
+ .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 = 0;
+
+ Q_ASSERT(currentErrorState != rootState());
+
+ if (currentErrorState != 0) {
+ QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
+ addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
+ } else {
+ qWarning("Unrecoverable error detected in running state machine: %s",
+ qPrintable(errorString));
+ q->stop();
+ }
+}
+
+#ifndef QT_NO_ANIMATION
+
+QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation,
+ const QPropertyAssignment &prop)
+{
+ QList<QAbstractAnimation*> handledAnimations;
+ QList<QAbstractAnimation*> localResetEndValues;
+ QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
+ if (group) {
+ for (int i = 0; i < group->animationCount(); ++i) {
+ QAbstractAnimation *animationChild = group->animationAt(i);
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(animationChild, prop);
+ handledAnimations << ret.first;
+ localResetEndValues << ret.second;
+ }
+ } else {
+ QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
+ if (animation != 0
+ && prop.object == animation->targetObject()
+ && prop.propertyName == animation->propertyName()) {
+
+ // Only change end value if it is undefined
+ if (!animation->endValue().isValid()) {
+ animation->setEndValue(prop.value);
+ localResetEndValues.append(animation);
+ }
+ handledAnimations.append(animation);
+ }
+ }
+ return qMakePair(handledAnimations, localResetEndValues);
+}
+
+void QStateMachinePrivate::_q_animationFinished()
+{
+ Q_Q(QStateMachine);
+ QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
+ Q_ASSERT(anim != 0);
+ QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ if (resetAnimationEndValues.contains(anim)) {
+ qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
+ resetAnimationEndValues.remove(anim);
+ }
+
+#ifndef QT_NO_PROPERTIES
+ // Set the final property value.
+ QPropertyAssignment assn = propertyForAnimation.take(anim);
+ Q_ASSERT(assn.object != 0);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ if (!assn.explicitlySet)
+ unregisterRestorable(assn.object, assn.propertyName);
+#endif
+
+ QAbstractState *state = stateForAnimation.take(anim);
+ Q_ASSERT(state != 0);
+ 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();
+ }
+}
+
+#endif // !QT_NO_ANIMATION
+
+namespace {
+
+class StartState : public QState
+{
+public:
+ StartState(QState *parent)
+ : QState(parent) {}
+protected:
+ void onEntry(QEvent *) {}
+ void onExit(QEvent *) {}
+};
+
+class InitialTransition : public QAbstractTransition
+{
+public:
+ InitialTransition(QAbstractState *target)
+ : QAbstractTransition()
+ { setTargetState(target); }
+protected:
+ virtual bool eventTest(QEvent *) { return true; }
+ virtual void onTransition(QEvent *) {}
+};
+
+} // namespace
+
+QState *QStateMachinePrivate::startState()
+{
+ Q_Q(QStateMachine);
+ if (_startState == 0)
+ _startState = new StartState(q);
+ return _startState;
+}
+
+void QStateMachinePrivate::removeStartState()
+{
+ delete _startState;
+ _startState = 0;
+}
+
+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();
+ }
+}
+
+void QStateMachinePrivate::_q_start()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Starting);
+ Q_ASSERT(rootState() != 0);
+ QAbstractState *initial = rootState()->initialState();
+ configuration.clear();
+ qDeleteAll(internalEventQueue);
+ internalEventQueue.clear();
+ qDeleteAll(externalEventQueue);
+ externalEventQueue.clear();
+ clearHistory();
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting";
+#endif
+ state = Running;
+ processingScheduled = true; // we call _q_process() below
+ emit q->started();
+
+ QState *start = startState();
+ Q_ASSERT(start != 0);
+
+ QList<QAbstractTransition*> transitions = QStatePrivate::get(start)->transitions();
+
+ // If a transition has already been added, then we skip this step, as the
+ // initial transition in that case has been overridden.
+ if (transitions.isEmpty()) {
+ QAbstractTransition *initialTransition = new InitialTransition(initial);
+ start->addTransition(initialTransition);
+ transitions.append(initialTransition);
+ }
+
+ QEvent nullEvent(QEvent::None);
+ executeTransitionContent(&nullEvent, transitions);
+ QList<QAbstractState*> enteredStates = enterStates(&nullEvent, transitions);
+#ifndef QT_NO_PROPERTIES
+ applyProperties(transitions, QList<QAbstractState*>() << start,
+ enteredStates);
+#endif
+ removeStartState();
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": initial configuration:" << configuration;
+#endif
+ _q_process();
+}
+
+void QStateMachinePrivate::_q_process()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Running);
+ Q_ASSERT(!processing);
+ processing = true;
+ processingScheduled = false;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting the event processing loop";
+#endif
+ while (processing) {
+ if (stop) {
+ processing = false;
+ break;
+ }
+ QSet<QAbstractTransition*> enabledTransitions;
+ QEvent *e = new QEvent(QEvent::None);
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ }
+ if (enabledTransitions.isEmpty()) {
+ if ((e = dequeueExternalEvent()) != 0) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ } else {
+ if (isInternalEventQueueEmpty()) {
+ processing = false;
+ stopProcessingReason = EventQueueEmpty;
+ }
+ }
+ }
+ if (!enabledTransitions.isEmpty()) {
+ q->beginMicrostep(e);
+ microstep(e, enabledTransitions.toList());
+ q->endMicrostep(e);
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ else {
+ qDebug() << q << ": no transitions enabled";
+ }
+#endif
+ delete e;
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": finished the event processing loop";
+#endif
+ if (stop) {
+ stop = false;
+ stopProcessingReason = Stopped;
+ }
+
+ switch (stopProcessingReason) {
+ case EventQueueEmpty:
+ break;
+ case Finished:
+ state = NotRunning;
+ cancelAllDelayedEvents();
+ unregisterAllTransitions();
+ emit q->finished();
+ break;
+ case Stopped:
+ state = NotRunning;
+ cancelAllDelayedEvents();
+ unregisterAllTransitions();
+ emit q->stopped();
+ break;
+ }
+}
+
+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 0;
+ return internalEventQueue.takeFirst();
+}
+
+QEvent *QStateMachinePrivate::dequeueExternalEvent()
+{
+ QMutexLocker locker(&externalEventMutex);
+ if (externalEventQueue.isEmpty())
+ return 0;
+ 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;
+ } // fallthrough -- processing must be done in the machine thread
+ case QueuedProcessing:
+ processingScheduled = true;
+ QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection);
+ break;
+ }
+}
+
+void QStateMachinePrivate::cancelAllDelayedEvents()
+{
+ Q_Q(QStateMachine);
+ QMutexLocker locker(&delayedEventsMutex);
+ QHash<int, QEvent*>::const_iterator it;
+ for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
+ int id = it.key();
+ QEvent *e = it.value();
+ q->killTimer(id);
+ delete e;
+ }
+ delayedEvents.clear();
+}
+
+namespace _QStateMachine_Internal{
+
+class GoToStateTransition : public QAbstractTransition
+{
+public:
+ GoToStateTransition(QAbstractState *target)
+ : QAbstractTransition()
+ { setTargetState(target); }
+protected:
+ void onTransition(QEvent *) { deleteLater(); }
+ bool eventTest(QEvent *) { 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;
+
+ QState *sourceState = 0;
+ if (state == Running) {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ sourceState = toStandardState(*it);
+ if (sourceState != 0)
+ break;
+ }
+ } else {
+ sourceState = startState();
+ }
+
+ Q_ASSERT(sourceState != 0);
+ // 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);
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(t)) {
+ registerSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(t)) {
+ registerEventTransition(oet);
+ }
+#endif
+ }
+}
+
+void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
+{
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
+ unregisterSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
+ unregisterEventTransition(oet);
+ }
+#endif
+}
+
+void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
+ return; // already registered
+ QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ if (!sender)
+ return;
+ QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
+ 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;
+ }
+ }
+ // 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;
+
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ if (connectedSignalIndexes.size() <= signalIndex)
+ connectedSignalIndexes.resize(signalIndex+1);
+ if (connectedSignalIndexes.at(signalIndex) == 0) {
+ if (!signalEventGenerator)
+ signalEventGenerator = new QSignalEventGenerator(q);
+ bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ 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];
+ 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
+ QSignalTransitionPrivate::get(transition)->signalIndex = -1;
+ const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
+ Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
+ if (--connectedSignalIndexes[signalIndex] == 0) {
+ Q_ASSERT(signalEventGenerator != 0);
+ QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ int sum = 0;
+ for (int i = 0; i < connectedSignalIndexes.size(); ++i)
+ sum += connectedSignalIndexes.at(i);
+ if (sum == 0)
+ connections.remove(sender);
+ }
+}
+
+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);
+ }
+ }
+ {
+ 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);
+ }
+ }
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+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->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)
+{
+ Q_ASSERT(connections[sender].at(signalIndex) != 0);
+ const QMetaObject *meta = sender->metaObject();
+ QMetaMethod method = meta->method(signalIndex);
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+ int argc = parameterTypes.count();
+ QList<QVariant> vargs;
+ for (int i = 0; i < argc; ++i) {
+ int type = QMetaType::type(parameterTypes.at(i));
+ vargs.append(QVariant(type, argv[i+1]));
+ }
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": sending signal event ( sender =" << sender
+ << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
+#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=*/0)
+{
+ // 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);
+}
+
+/*!
+ \internal
+*/
+QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
+ : QState(dd, /*parentState=*/0)
+{
+ 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.
+
+ \sa setErrorState()
+*/
+
+/*!
+ \enum QStateMachine::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()
+*/
+
+
+/*!
+ 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()
+*/
+QStateMachine::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 QAbstractState::DontRestoreProperties.
+
+ \sa globalRestorePolicy()
+*/
+void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy)
+{
+ Q_D(QStateMachine);
+ d->globalRestorePolicy = restorePolicy;
+}
+
+/*!
+ Adds the given \a state to this state machine. The state becomes a top-level
+ 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(0);
+}
+
+/*!
+ Returns whether this state machine is running.
+
+ start(), stop()
+*/
+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()
+*/
+void QStateMachine::start()
+{
+ Q_D(QStateMachine);
+
+ if (initialState() == 0) {
+ 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()
+*/
+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;
+ }
+}
+
+/*!
+ \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.
+
+ \sa postDelayedEvent()
+*/
+void QStateMachine::postEvent(QEvent *event, EventPriority priority)
+{
+ Q_D(QStateMachine);
+ if (d->state != QStateMachinePrivate::Running) {
+ 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 tid = startTimer(delay);
+ d->delayedEvents[tid] = event;
+ return tid;
+}
+
+/*!
+ \threadsafe
+
+ Cancels the delayed event identified by the given \a id. The id should be a
+ value returned by a call to postDelayedEvent(). Returns true if the event
+ was successfully cancelled, otherwise returns 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);
+ QEvent *e = d->delayedEvents.take(id);
+ if (!e)
+ return false;
+ killTimer(id);
+ delete e;
+ 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->delayedEvents.contains(tid));
+ return true;
+ }
+ d->delayedEventsMutex.lock();
+ QEvent *ee = d->delayedEvents.take(tid);
+ if (ee != 0) {
+ killTimer(tid);
+ d->delayedEventsMutex.unlock();
+ d->postExternalEvent(ee);
+ d->processEvents(QStateMachinePrivate::DirectProcessing);
+ return true;
+ } else {
+ d->delayedEventsMutex.unlock();
+ }
+ }
+ return QState::event(e);
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+/*!
+ \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);
+}
+
+#ifndef QT_NO_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 // QT_NO_ANIMATION
+
+
+static const uint qt_meta_data_QSignalEventGenerator[] = {
+
+ // content:
+ 2, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 12, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+
+ // slots: signature, parameters, type, tag, flags
+ 23, 22, 22, 22, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QSignalEventGenerator[] = {
+ "QSignalEventGenerator\0\0execute()\0"
+};
+
+const QMetaObject QSignalEventGenerator::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
+ qt_meta_data_QSignalEventGenerator, 0 }
+};
+
+const QMetaObject *QSignalEventGenerator::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QSignalEventGenerator::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
+ return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: {
+// ### in Qt 4.6 we can use QObject::senderSignalIndex()
+ QObjectPrivate *d = static_cast<QObjectPrivate *>(d_ptr.data());
+ int signalIndex = -1;
+ QObject *sender = this->sender();
+ if (sender && d->currentSender)
+ signalIndex = d->currentSender->signal;
+
+ Q_ASSERT(signalIndex != -1);
+ QStateMachine *machine = qobject_cast<QStateMachine*>(parent());
+ QStateMachinePrivate::get(machine)->handleTransitionSignal(sender, signalIndex, _a);
+ break;
+ }
+ default: ;
+ }
+ _id -= 1;
+ }
+ return _id;
+}
+
+QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \class QStateMachine::SignalEvent
+
+ \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
+
+ \brief The WrappedEvent class 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.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qstatemachine.cpp"
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
new file mode 100644
index 0000000000..8c4fb025e7
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QStateMachinePrivate;
+class QAbstractAnimation;
+class Q_CORE_EXPORT QStateMachine : public QState
+{
+ Q_OBJECT
+ Q_PROPERTY(QString errorString READ errorString)
+ Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
+ Q_ENUMS(RestorePolicy)
+#ifndef QT_NO_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 RestorePolicy {
+ DontRestoreProperties,
+ RestoreProperties
+ };
+
+ enum Error {
+ NoError,
+ NoInitialStateError,
+ NoDefaultStateInHistoryStateError,
+ NoCommonAncestorForTransitionError
+ };
+
+ QStateMachine(QObject *parent = 0);
+ ~QStateMachine();
+
+ void addState(QAbstractState *state);
+ void removeState(QAbstractState *state);
+
+ Error error() const;
+ QString errorString() const;
+ void clearError();
+
+ bool isRunning() const;
+
+#ifndef QT_NO_ANIMATION
+ bool isAnimated() const;
+ void setAnimated(bool enabled);
+
+ void addDefaultAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation *> defaultAnimations() const;
+ void removeDefaultAnimation(QAbstractAnimation *animation);
+#endif // QT_NO_ANIMATION
+
+ QStateMachine::RestorePolicy globalRestorePolicy() const;
+ void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy);
+
+ void postEvent(QEvent *event, EventPriority priority = NormalPriority);
+ int postDelayedEvent(QEvent *event, int delay);
+ bool cancelDelayedEvent(int id);
+
+ QSet<QAbstractState*> configuration() const;
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ bool eventFilter(QObject *watched, QEvent *event);
+#endif
+
+public Q_SLOTS:
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void started();
+ void stopped();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ virtual void beginSelectTransitions(QEvent *event);
+ virtual void endSelectTransitions(QEvent *event);
+
+ virtual void beginMicrostep(QEvent *event);
+ virtual void endMicrostep(QEvent *event);
+
+ bool event(QEvent *e);
+
+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())
+#ifndef QT_NO_ANIMATION
+ Q_PRIVATE_SLOT(d_func(), void _q_animationFinished())
+#endif
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
new file mode 100644
index 0000000000..70b7b8f104
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qset.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+class QEventTransition;
+#endif
+class QSignalEventGenerator;
+class QSignalTransition;
+class QAbstractState;
+class QAbstractTransition;
+class QFinalState;
+class QHistoryState;
+class QState;
+
+#ifndef QT_NO_ANIMATION
+class QAbstractAnimation;
+#endif
+
+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);
+
+ QState *findLCA(const QList<QAbstractState*> &states) const;
+
+ 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();
+#ifndef QT_NO_ANIMATION
+ void _q_animationFinished();
+#endif
+
+ QState *rootState() const;
+
+ QState *startState();
+ void removeStartState();
+
+ void clearHistory();
+
+ void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
+ QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
+ QList<QAbstractState*> exitStates(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ QList<QAbstractState*> enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions);
+ void addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry);
+
+ void applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates);
+
+ 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;
+ static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other);
+ static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound);
+
+ void goToState(QAbstractState *targetState);
+
+ void registerTransitions(QAbstractState *state);
+ void registerSignalTransition(QSignalTransition *transition);
+ void unregisterSignalTransition(QSignalTransition *transition);
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ 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();
+
+#ifndef QT_NO_PROPERTIES
+ typedef QPair<QObject *, QByteArray> RestorableId;
+ QHash<RestorableId, QVariant> registeredRestorables;
+ void registerRestorable(QObject *object, const QByteArray &propertyName);
+ void unregisterRestorable(QObject *object, const QByteArray &propertyName);
+ bool hasRestorable(QObject *object, const QByteArray &propertyName) const;
+ QVariant restorableValue(QObject *object, const QByteArray &propertyName) const;
+ QList<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const;
+#endif
+
+ State state;
+ QState *_startState;
+ bool processing;
+ bool processingScheduled;
+ bool stop;
+ StopProcessingReason stopProcessingReason;
+ QSet<QAbstractState*> configuration;
+ QList<QEvent*> internalEventQueue;
+ QList<QEvent*> externalEventQueue;
+ QMutex internalEventMutex;
+ QMutex externalEventMutex;
+
+ QStateMachine::Error error;
+ QStateMachine::RestorePolicy globalRestorePolicy;
+
+ QString errorString;
+ QSet<QAbstractState *> pendingErrorStates;
+ QSet<QAbstractState *> pendingErrorStatesForDefaultEntry;
+
+#ifndef QT_NO_ANIMATION
+ bool animated;
+
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+ 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;
+
+#endif // QT_NO_ANIMATION
+
+ QSignalEventGenerator *signalEventGenerator;
+
+ QHash<const QObject*, QVector<int> > connections;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents;
+#endif
+ QHash<int, QEvent*> delayedEvents;
+ QMutex delayedEventsMutex;
+
+ typedef QEvent* (*f_cloneEvent)(QEvent*);
+ struct Handler {
+ f_cloneEvent cloneEvent;
+ };
+
+ static const Handler *handler;
+};
+
+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
new file mode 100644
index 0000000000..910cf5e9b3
--- /dev/null
+++ b/src/corelib/statemachine/statemachine.pri
@@ -0,0 +1,28 @@
+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/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
+
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+HEADERS += $$PWD/qeventtransition.h \
+ $$PWD/qeventtransition_p.h
+SOURCES += $$PWD/qeventtransition.cpp
+}
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
new file mode 100644
index 0000000000..dd8853b90e
--- /dev/null
+++ b/src/corelib/thread/qatomic.cpp
@@ -0,0 +1,1125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAtomicInt
+ \brief The QAtomicInt class provides platform-independent atomic operations on integers.
+ \since 4.4
+
+ \ingroup thread
+
+ For atomic operations on pointers, see the QAtomicPointer class.
+
+ An \e atomic operation is a complex operation that completes without interruption.
+ The QAtomicInt class provides atomic reference counting, test-and-set, fetch-and-store,
+ and fetch-and-add for integers.
+
+ \section1 Non-atomic convenience operators
+
+ For convenience, QAtomicInt provides integer comparison, cast, and
+ assignment operators. Note that a combination of these operators
+ is \e not an atomic operation.
+
+ \section1 The Atomic API
+
+ \section2 Reference counting
+
+ The ref() and deref() functions provide an efficient reference
+ counting API. The return value of these functions are used to
+ indicate when the last reference has been released. These
+ functions allow you to implement your own implicitly shared
+ classes.
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 0
+
+ \section2 Memory ordering
+
+ QAtomicInt provides several implementations of the atomic
+ test-and-set, fetch-and-store, and fetch-and-add functions. Each
+ implementation defines a memory ordering semantic that describes
+ how memory accesses surrounding the atomic instruction are
+ executed by the processor. Since many modern architectures allow
+ out-of-order execution and memory ordering, using the correct
+ semantic is necessary to ensure that your application functions
+ properly on all processors.
+
+ \list
+
+ \o Relaxed - memory ordering is unspecified, leaving the compiler
+ and processor to freely reorder memory accesses.
+
+ \o Acquire - memory access following the atomic operation (in
+ program order) may not be re-ordered before the atomic operation.
+
+ \o Release - memory access before the atomic operation (in program
+ order) may not be re-ordered after the atomic operation.
+
+ \o Ordered - the same Acquire and Release semantics combined.
+
+ \endlist
+
+ \section2 Test-and-set
+
+ If the current value of the QAtomicInt is an expected value, the
+ test-and-set functions assign a new value to the QAtomicInt and
+ return true. If values are \a not the same, these functions do
+ nothing and return false. This operation equates to the following
+ code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 1
+
+ There are 4 test-and-set functions: testAndSetRelaxed(),
+ testAndSetAcquire(), testAndSetRelease(), and
+ testAndSetOrdered(). See above for an explanation of the different
+ memory ordering semantics.
+
+ \section2 Fetch-and-store
+
+ The atomic fetch-and-store functions read the current value of the
+ QAtomicInt and then assign a new value, returning the original
+ value. This operation equates to the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 2
+
+ There are 4 fetch-and-store functions: fetchAndStoreRelaxed(),
+ fetchAndStoreAcquire(), fetchAndStoreRelease(), and
+ fetchAndStoreOrdered(). See above for an explanation of the
+ different memory ordering semantics.
+
+ \section2 Fetch-and-add
+
+ The atomic fetch-and-add functions read the current value of the
+ QAtomicInt and then add the given value to the current value,
+ returning the original value. This operation equates to the
+ following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 3
+
+ There are 4 fetch-and-add functions: fetchAndAddRelaxed(),
+ fetchAndAddAcquire(), fetchAndAddRelease(), and
+ fetchAndAddOrdered(). See above for an explanation of the
+ different memory ordering semantics.
+
+ \section1 Feature Tests for the Atomic API
+
+ Providing a platform-independent atomic API that works on all
+ processors is challenging. The API provided by QAtomicInt is
+ guaranteed to work atomically on all processors. However, since
+ not all processors implement support for every operation provided
+ by QAtomicInt, it is necessary to expose information about the
+ processor.
+
+ You can check at compile time which features are supported on your
+ hardware using various macros. These will tell you if your
+ hardware always, sometimes, or does not support a particular
+ operation. The macros have the form
+ Q_ATOMIC_INT_\e{OPERATION}_IS_\e{HOW}_NATIVE. \e{OPERATION}
+ is one of REFERENCE_COUNTING, TEST_AND_SET,
+ FETCH_AND_STORE, or FETCH_AND_ADD, and \e{HOW} is one of
+ ALWAYS, SOMETIMES, or NOT. There will always be exactly one
+ defined macro per operation. For example, if
+ Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE is defined,
+ neither Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE nor
+ Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE will be defined.
+
+ An operation that completes in constant time is said to be
+ wait-free. Such operations are not implemented using locks or
+ loops of any kind. For atomic operations that are always
+ supported, and that are wait-free, Qt defines the
+ Q_ATOMIC_INT_\e{OPERATION}_IS_WAIT_FREE in addition to the
+ Q_ATOMIC_INT_\e{OPERATION}_IS_ALWAYS_NATIVE.
+
+ In cases where an atomic operation is only supported in newer
+ generations of the processor, QAtomicInt also provides a way to
+ check at runtime what your hardware supports with the
+ isReferenceCountingNative(), isTestAndSetNative(),
+ isFetchAndStoreNative(), and isFetchAndAddNative()
+ functions. Wait-free implementations can be detected using the
+ isReferenceCountingWaitFree(), isTestAndSetWaitFree(),
+ isFetchAndStoreWaitFree(), and isFetchAndAddWaitFree() functions.
+
+ Below is a complete list of all feature macros for QAtomicInt:
+
+ \list
+
+ \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+ \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+ \o Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+ \o Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+ \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+ \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+ \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+
+ \endlist
+
+ \sa QAtomicPointer
+*/
+
+/*! \fn QAtomicInt::QAtomicInt(int value)
+
+ Constructs a QAtomicInt with the given \a value.
+*/
+
+/*! \fn QAtomicInt::QAtomicInt(const QAtomicInt &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QAtomicInt &QAtomicInt::operator=(int value)
+
+ Assigns the \a value to this QAtomicInt and returns a reference to
+ this QAtomicInt.
+*/
+
+/*! \fn QAtomicInt &QAtomicInt::operator=(const QAtomicInt &other)
+
+ Assigns \a other to this QAtomicInt and returns a reference to
+ this QAtomicInt.
+*/
+
+/*! \fn bool QAtomicInt::operator==(int value) const
+
+ Returns true if the \a value is equal to the value in this
+ QAtomicInt; otherwise returns false.
+*/
+
+/*! \fn bool QAtomicInt::operator!=(int value) const
+
+ Returns true if the value of this QAtomicInt is not equal to \a
+ value; otherwise returns false.
+*/
+
+/*! \fn bool QAtomicInt::operator!() const
+
+ Returns true is the value of this QAtomicInt is zero; otherwise
+ returns false.
+*/
+
+/*! \fn QAtomicInt::operator int() const
+
+ Returns the value stored by the QAtomicInt object as an integer.
+*/
+
+/*! \fn bool QAtomicInt::isReferenceCountingNative()
+
+ Returns true if reference counting is implemented using atomic
+ processor instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicInt::isReferenceCountingWaitFree()
+
+ Returns true if atomic reference counting is wait-free, false
+ otherwise.
+*/
+
+/*! \fn bool QAtomicInt::ref()
+ Atomically increments the value of this QAtomicInt. Returns true
+ if the new value is non-zero, false otherwise.
+
+ This function uses \e ordered \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa deref()
+*/
+
+/*! \fn bool QAtomicInt::deref()
+ Atomically decrements the value of this QAtomicInt. Returns true
+ if the new value is non-zero, false otherwise.
+
+ This function uses \e ordered \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa ref()
+*/
+
+/*! \fn bool QAtomicInt::isTestAndSetNative()
+
+ Returns true if test-and-set is implemented using atomic processor
+ instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicInt::isTestAndSetWaitFree()
+
+ Returns true if atomic test-and-set is wait-free, false otherwise.
+*/
+
+/*! \fn bool QAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInt is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicInt and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e relaxed \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn bool QAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInt is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicInt and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e acquire \l {QAtomicInt#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.
+*/
+
+/*! \fn bool QAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInt is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicInt and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e release \l {QAtomicInt#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.
+*/
+
+/*! \fn bool QAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInt is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicInt and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e ordered \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*! \fn bool QAtomicInt::isFetchAndStoreNative()
+
+ Returns true if fetch-and-store is implemented using atomic
+ processor instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicInt::isFetchAndStoreWaitFree()
+
+ Returns true if atomic fetch-and-store is wait-free, false
+ otherwise.
+*/
+
+/*! \fn int QAtomicInt::fetchAndStoreRelaxed(int newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicInt and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn int QAtomicInt::fetchAndStoreAcquire(int newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicInt and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInt#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.
+*/
+
+/*! \fn int QAtomicInt::fetchAndStoreRelease(int newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicInt and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e release \l {QAtomicInt#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.
+*/
+
+/*! \fn int QAtomicInt::fetchAndStoreOrdered(int newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicInt and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*! \fn bool QAtomicInt::isFetchAndAddNative()
+
+ Returns true if fetch-and-add is implemented using atomic
+ processor instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicInt::isFetchAndAddWaitFree()
+
+ Returns true if atomic fetch-and-add is wait-free, false
+ otherwise.
+*/
+
+/*! \fn int QAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicInt and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn int QAtomicInt::fetchAndAddAcquire(int valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicInt and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInt#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.
+*/
+
+/*! \fn int QAtomicInt::fetchAndAddRelease(int valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicInt and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicInt#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.
+*/
+
+/*! \fn int QAtomicInt::fetchAndAddOrdered(int valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicInt and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInt#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined if and only if all generations of your
+ processor support atomic reference counting.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when only certain generations of the
+ processor support atomic reference counting. Use the
+ QAtomicInt::isReferenceCountingNative() function to check what
+ your processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when the hardware does not support atomic
+ reference counting.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+ \relates QAtomicInt
+
+ This macro is defined together with
+ Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE to indicate that
+ the reference counting is wait-free.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined if and only if your processor supports
+ atomic test-and-set on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when only certain generations of the
+ processor support atomic test-and-set on integers. Use the
+ QAtomicInt::isTestAndSetNative() function to check what your
+ processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when the hardware does not support atomic
+ test-and-set on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+ \relates QAtomicInt
+
+ This macro is defined together with
+ Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE to indicate that the
+ atomic test-and-set on integers is wait-free.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined if and only if your processor supports
+ atomic fetch-and-store on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when only certain generations of the
+ processor support atomic fetch-and-store on integers. Use the
+ QAtomicInt::isFetchAndStoreNative() function to check what your
+ processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when the hardware does not support atomic
+ fetch-and-store on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+ \relates QAtomicInt
+
+ This macro is defined together with
+ Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE to indicate that the
+ atomic fetch-and-store on integers is wait-free.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined if and only if your processor supports
+ atomic fetch-and-add on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when only certain generations of the
+ processor support atomic fetch-and-add on integers. Use the
+ QAtomicInt::isFetchAndAddNative() function to check what your
+ processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+ \relates QAtomicInt
+
+ This macro is defined when the hardware does not support atomic
+ fetch-and-add on integers.
+*/
+
+/*!
+ \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+ \relates QAtomicInt
+
+ This macro is defined together with
+ Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that the
+ atomic fetch-and-add on integers is wait-free.
+*/
+
+
+
+
+/*!
+ \class QAtomicPointer
+ \brief The QAtomicPointer class is a template class that provides platform-independent atomic operations on pointers.
+ \since 4.4
+
+ \ingroup thread
+
+ For atomic operations on integers, see the QAtomicInt class.
+
+ An \e atomic operation is a complex operation that completes without interruption.
+ The QAtomicPointer class provides atomic test-and-set, fetch-and-store, and fetch-and-add for pointers.
+
+ \section1 Non-atomic convenience operators
+
+ For convenience, QAtomicPointer provides pointer comparison, cast,
+ dereference, and assignment operators. Note that these operators
+ are \e not atomic.
+
+ \section1 The Atomic API
+
+ \section2 Memory ordering
+
+ QAtomicPointer provides several implementations of the atomic
+ test-and-set, fetch-and-store, and fetch-and-add functions. Each
+ implementation defines a memory ordering semantic that describes
+ how memory accesses surrounding the atomic instruction are
+ executed by the processor. Since many modern architectures allow
+ out-of-order execution and memory ordering, using the correct
+ semantic is necessary to ensure that your application functions
+ properly on all processors.
+
+ \list
+
+ \o Relaxed - memory ordering is unspecified, leaving the compiler
+ and processor to freely reorder memory accesses.
+
+ \o Acquire - memory access following the atomic operation (in
+ program order) may not be re-ordered before the atomic operation.
+
+ \o Release - memory access before the atomic operation (in program
+ order) may not be re-ordered after the atomic operation.
+
+ \o Ordered - the same Acquire and Release semantics combined.
+
+ \endlist
+
+ \section2 Test-and-set
+
+ If the current value of the QAtomicPointer is an expected value,
+ the test-and-set functions assign a new value to the
+ QAtomicPointer and return true. If values are \a not the same,
+ these functions do nothing and return false. This operation
+ equates to the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 4
+
+ There are 4 test-and-set functions: testAndSetRelaxed(),
+ testAndSetAcquire(), testAndSetRelease(), and
+ testAndSetOrdered(). See above for an explanation of the different
+ memory ordering semantics.
+
+ \section2 Fetch-and-store
+
+ The atomic fetch-and-store functions read the current value of the
+ QAtomicPointer and then assign a new value, returning the original
+ value. This operation equates to the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 5
+
+ There are 4 fetch-and-store functions: fetchAndStoreRelaxed(),
+ fetchAndStoreAcquire(), fetchAndStoreRelease(), and
+ fetchAndStoreOrdered(). See above for an explanation of the
+ different memory ordering semantics.
+
+ \section2 Fetch-and-add
+
+ The atomic fetch-and-add functions read the current value of the
+ QAtomicPointer and then add the given value to the current value,
+ returning the original value. This operation equates to the
+ following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qatomic.cpp 6
+
+ There are 4 fetch-and-add functions: fetchAndAddRelaxed(),
+ fetchAndAddAcquire(), fetchAndAddRelease(), and
+ fetchAndAddOrdered(). See above for an explanation of the
+ different memory ordering semantics.
+
+ \section1 Feature Tests for the Atomic API
+
+ Providing a platform-independent atomic API that works on all
+ processors is challenging. The API provided by QAtomicPointer is
+ guaranteed to work atomically on all processors. However, since
+ not all processors implement support for every operation provided
+ by QAtomicPointer, it is necessary to expose information about the
+ processor.
+
+ You can check at compile time which features are supported on your
+ hardware using various macros. These will tell you if your
+ hardware always, sometimes, or does not support a particular
+ operation. The macros have the form
+ Q_ATOMIC_POINTER_\e{OPERATION}_IS_\e{HOW}_NATIVE. \e{OPERATION} is
+ one of TEST_AND_SET, FETCH_AND_STORE, or FETCH_AND_ADD, and
+ \e{HOW} is one of ALWAYS, SOMETIMES, or NOT. There will always be
+ exactly one defined macro per operation. For example, if
+ Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE is defined, neither
+ Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE nor
+ Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE will be defined.
+
+ An operation that completes in constant time is said to be
+ wait-free. Such operations are not implemented using locks or
+ loops of any kind. For atomic operations that are always
+ supported, and that are wait-free, Qt defines the
+ Q_ATOMIC_POINTER_\e{OPERATION}_IS_WAIT_FREE in addition to the
+ Q_ATOMIC_POINTER_\e{OPERATION}_IS_ALWAYS_NATIVE.
+
+ In cases where an atomic operation is only supported in newer
+ generations of the processor, QAtomicPointer also provides a way
+ to check at runtime what your hardware supports with the
+ isTestAndSetNative(), isFetchAndStoreNative(), and
+ isFetchAndAddNative() functions. Wait-free implementations can be
+ detected using the isTestAndSetWaitFree(),
+ isFetchAndStoreWaitFree(), and isFetchAndAddWaitFree() functions.
+
+ Below is a complete list of all feature macros for QAtomicPointer:
+
+ \list
+
+ \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+ \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+ \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+ \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+ \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+
+ \endlist
+
+ \sa QAtomicInt
+*/
+
+/*! \fn QAtomicPointer::QAtomicPointer(T *value)
+
+ Constructs a QAtomicPointer with the given \a value.
+*/
+
+/*! \fn QAtomicPointer::QAtomicPointer(const QAtomicPointer<T> &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QAtomicPointer<T> &QAtomicPointer::operator=(T *value)
+
+ Assigns the \a value to this QAtomicPointer and returns a
+ reference to this QAtomicPointer.
+*/
+
+/*! \fn QAtomicPointer<T> &QAtomicPointer::operator=(const QAtomicPointer<T> &other)
+
+ Assigns \a other to this QAtomicPointer and returns a reference to
+ this QAtomicPointer.
+*/
+
+/*! \fn bool QAtomicPointer::operator==(T *value) const
+
+ Returns true if the \a value is equal to the value in this
+ QAtomicPointer; otherwise returns false.
+*/
+
+/*! \fn bool QAtomicPointer::operator!=(T *value) const
+
+ Returns true if the value of this QAtomicPointer is not equal to
+ \a value; otherwise returns false.
+*/
+
+/*! \fn bool QAtomicPointer::operator!() const
+
+ Returns true is the current value of this QAtomicPointer is zero;
+ otherwise returns false.
+*/
+
+/*! \fn QAtomicPointer::operator T *() const
+
+ Returns the current pointer value stored by this QAtomicPointer
+ object.
+*/
+
+/*! \fn T *QAtomicPointer::operator->() const
+
+*/
+
+/*! \fn bool QAtomicPointer::isTestAndSetNative()
+
+ Returns true if test-and-set is implemented using atomic processor
+ instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicPointer::isTestAndSetWaitFree()
+
+ Returns true if atomic test-and-set is wait-free, false otherwise.
+*/
+
+/*! \fn bool QAtomicPointer::testAndSetRelaxed(T *expectedValue, T *newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicPointer is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicPointer and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e relaxed \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn bool QAtomicPointer::testAndSetAcquire(T *expectedValue, T *newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicPointer is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicPointer and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e acquire \l {QAtomicPointer#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.
+*/
+
+/*! \fn bool QAtomicPointer::testAndSetRelease(T *expectedValue, T *newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicPointer is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicPointer and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e release \l {QAtomicPointer#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.
+*/
+
+/*! \fn bool QAtomicPointer::testAndSetOrdered(T *expectedValue, T *newValue)
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicPointer is the \a expectedValue,
+ the test-and-set functions assign the \a newValue to this
+ QAtomicPointer and return true. If the values are \e not the same,
+ this function does nothing and returns false.
+
+ This function uses \e ordered \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*! \fn bool QAtomicPointer::isFetchAndStoreNative()
+
+ Returns true if fetch-and-store is implemented using atomic
+ processor instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicPointer::isFetchAndStoreWaitFree()
+
+ Returns true if atomic fetch-and-store is wait-free, false
+ otherwise.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndStoreRelaxed(T *newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicPointer and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndStoreAcquire(T *newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicPointer and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e acquire \l {QAtomicPointer#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.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndStoreRelease(T *newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicPointer and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e release \l {QAtomicPointer#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.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndStoreOrdered(T *newValue)
+
+ Atomic fetch-and-store.
+
+ Reads the current value of this QAtomicPointer and then assigns it the
+ \a newValue, returning the original value.
+
+ This function uses \e ordered \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*! \fn bool QAtomicPointer::isFetchAndAddNative()
+
+ Returns true if fetch-and-add is implemented using atomic
+ processor instructions, false otherwise.
+*/
+
+/*! \fn bool QAtomicPointer::isFetchAndAddWaitFree()
+
+ Returns true if atomic fetch-and-add is wait-free, false
+ otherwise.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndAddRelaxed(qptrdiff valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicPointer and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndAddAcquire(qptrdiff valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicPointer and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicPointer#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.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndAddRelease(qptrdiff valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicPointer and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicPointer#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.
+*/
+
+/*! \fn T *QAtomicPointer::fetchAndAddOrdered(qptrdiff valueToAdd)
+
+ Atomic fetch-and-add.
+
+ Reads the current value of this QAtomicPointer and then adds
+ \a valueToAdd to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicPointer#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined if and only if your processor supports
+ atomic test-and-set on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when only certain generations of the
+ processor support atomic test-and-set on pointers. Use the
+ QAtomicPointer::isTestAndSetNative() function to check what your
+ processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when the hardware does not support atomic
+ test-and-set on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+ \relates QAtomicPointer
+
+ This macro is defined together with
+ Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE to indicate that
+ the atomic test-and-set on pointers is wait-free.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined if and only if your processor supports
+ atomic fetch-and-store on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when only certain generations of the
+ processor support atomic fetch-and-store on pointers. Use the
+ QAtomicPointer::isFetchAndStoreNative() function to check what
+ your processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when the hardware does not support atomic
+ fetch-and-store on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+ \relates QAtomicPointer
+
+ This macro is defined together with
+ Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE to indicate that
+ the atomic fetch-and-store on pointers is wait-free.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined if and only if your processor supports
+ atomic fetch-and-add on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when only certain generations of the
+ processor support atomic fetch-and-add on pointers. Use the
+ QAtomicPointer::isFetchAndAddNative() function to check what your
+ processor supports.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+ \relates QAtomicPointer
+
+ This macro is defined when the hardware does not support atomic
+ fetch-and-add on pointers.
+*/
+
+/*!
+ \macro Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+ \relates QAtomicPointer
+
+ This macro is defined together with
+ Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that
+ the atomic fetch-and-add on pointers is wait-free.
+*/
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
new file mode 100644
index 0000000000..94dc2e3b4e
--- /dev/null
+++ b/src/corelib/thread/qatomic.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_H
+#define QATOMIC_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qbasicatomic.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// High-level atomic integer operations
+class Q_CORE_EXPORT QAtomicInt : public QBasicAtomicInt
+{
+public:
+ inline QAtomicInt(int value = 0)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ _q_value = value;
+ }
+ inline QAtomicInt(const QAtomicInt &other)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ _q_value = other._q_value;
+ }
+
+ inline QAtomicInt &operator=(int value)
+ {
+ (void) QBasicAtomicInt::operator=(value);
+ return *this;
+ }
+
+ inline QAtomicInt &operator=(const QAtomicInt &other)
+ {
+ (void) QBasicAtomicInt::operator=(other);
+ return *this;
+ }
+
+#ifdef qdoc
+ bool operator==(int value) const;
+ bool operator!=(int value) const;
+ bool operator!() const;
+ operator int() const;
+
+ static bool isReferenceCountingNative();
+ static bool isReferenceCountingWaitFree();
+
+ bool ref();
+ bool deref();
+
+ static bool isTestAndSetNative();
+ static bool isTestAndSetWaitFree();
+
+ bool testAndSetRelaxed(int expectedValue, int newValue);
+ bool testAndSetAcquire(int expectedValue, int newValue);
+ bool testAndSetRelease(int expectedValue, int newValue);
+ bool testAndSetOrdered(int expectedValue, int newValue);
+
+ static bool isFetchAndStoreNative();
+ static bool isFetchAndStoreWaitFree();
+
+ int fetchAndStoreRelaxed(int newValue);
+ int fetchAndStoreAcquire(int newValue);
+ int fetchAndStoreRelease(int newValue);
+ int fetchAndStoreOrdered(int newValue);
+
+ static bool isFetchAndAddNative();
+ static bool isFetchAndAddWaitFree();
+
+ int fetchAndAddRelaxed(int valueToAdd);
+ int fetchAndAddAcquire(int valueToAdd);
+ int fetchAndAddRelease(int valueToAdd);
+ int fetchAndAddOrdered(int valueToAdd);
+#endif
+};
+
+// High-level atomic pointer operations
+template <typename T>
+class QAtomicPointer : public QBasicAtomicPointer<T>
+{
+public:
+ inline QAtomicPointer(T *value = 0)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ QBasicAtomicPointer<T>::_q_value = value;
+ }
+ inline QAtomicPointer(const QAtomicPointer<T> &other)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ QBasicAtomicPointer<T>::_q_value = other._q_value;
+ }
+
+ inline QAtomicPointer<T> &operator=(T *value)
+ {
+ (void) QBasicAtomicPointer<T>::operator=(value);
+ return *this;
+ }
+
+ inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other)
+ {
+ (void) QBasicAtomicPointer<T>::operator=(other);
+ return *this;
+ }
+
+#ifdef qdoc
+ bool operator==(T *value) const;
+ bool operator!=(T *value) const;
+ bool operator!() const;
+ operator T *() const;
+ T *operator->() const;
+
+ static bool isTestAndSetNative();
+ static 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 bool isFetchAndStoreNative();
+ static bool isFetchAndStoreWaitFree();
+
+ T *fetchAndStoreRelaxed(T *newValue);
+ T *fetchAndStoreAcquire(T *newValue);
+ T *fetchAndStoreRelease(T *newValue);
+ T *fetchAndStoreOrdered(T *newValue);
+
+ static bool isFetchAndAddNative();
+ static bool isFetchAndAddWaitFree();
+
+ T *fetchAndAddRelaxed(qptrdiff valueToAdd);
+ T *fetchAndAddAcquire(qptrdiff valueToAdd);
+ T *fetchAndAddRelease(qptrdiff valueToAdd);
+ T *fetchAndAddOrdered(qptrdiff valueToAdd);
+#endif
+};
+
+/*!
+ This is a helper for the assignment operators of implicitly
+ shared classes. Your assignment operator should look like this:
+
+ \snippet doc/src/snippets/code/src.corelib.thread.qatomic.h 0
+*/
+template <typename T>
+inline void qAtomicAssign(T *&d, T *x)
+{
+ if (d == x)
+ return;
+ x->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = x;
+}
+
+/*!
+ This is a helper for the detach method of implicitly shared
+ classes. Your private class needs a copy constructor which copies
+ the members and sets the refcount to 1. After that, your detach
+ function should look like this:
+
+ \snippet doc/src/snippets/code/src.corelib.thread.qatomic.h 1
+*/
+template <typename T>
+inline void qAtomicDetach(T *&d)
+{
+ if (d->ref == 1)
+ return;
+ T *x = d;
+ d = new T(*d);
+ if (!x->ref.deref())
+ delete x;
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QATOMIC_H
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
new file mode 100644
index 0000000000..72fd55ad7f
--- /dev/null
+++ b/src/corelib/thread/qbasicatomic.h
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICATOMIC_H
+#define QBASICATOMIC_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QBasicAtomicInt
+{
+public:
+#ifdef QT_ARCH_PARISC
+ int _q_lock[4];
+#endif
+#if defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE)
+ union { // needed for Q_BASIC_ATOMIC_INITIALIZER
+ volatile long _q_value;
+ };
+#else
+ volatile int _q_value;
+#endif
+
+ // Non-atomic API
+ inline bool operator==(int value) const
+ {
+ return _q_value == value;
+ }
+
+ inline bool operator!=(int value) const
+ {
+ return _q_value != value;
+ }
+
+ inline bool operator!() const
+ {
+ return _q_value == 0;
+ }
+
+ inline operator int() const
+ {
+ return _q_value;
+ }
+
+ inline QBasicAtomicInt &operator=(int value)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ _q_value = value;
+ return *this;
+ }
+
+ // Atomic API, implemented in qatomic_XXX.h
+
+ static bool isReferenceCountingNative();
+ static bool isReferenceCountingWaitFree();
+
+ bool ref();
+ bool deref();
+
+ static bool isTestAndSetNative();
+ static bool isTestAndSetWaitFree();
+
+ bool testAndSetRelaxed(int expectedValue, int newValue);
+ bool testAndSetAcquire(int expectedValue, int newValue);
+ bool testAndSetRelease(int expectedValue, int newValue);
+ bool testAndSetOrdered(int expectedValue, int newValue);
+
+ static bool isFetchAndStoreNative();
+ static bool isFetchAndStoreWaitFree();
+
+ int fetchAndStoreRelaxed(int newValue);
+ int fetchAndStoreAcquire(int newValue);
+ int fetchAndStoreRelease(int newValue);
+ int fetchAndStoreOrdered(int newValue);
+
+ static bool isFetchAndAddNative();
+ static bool isFetchAndAddWaitFree();
+
+ int fetchAndAddRelaxed(int valueToAdd);
+ int fetchAndAddAcquire(int valueToAdd);
+ int fetchAndAddRelease(int valueToAdd);
+ int fetchAndAddOrdered(int valueToAdd);
+};
+
+template <typename T>
+class QBasicAtomicPointer
+{
+public:
+#ifdef QT_ARCH_PARISC
+ int _q_lock[4];
+#endif
+#if defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE)
+ union {
+ T * volatile _q_value;
+# if !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86)
+ qint64
+# else
+ long
+# endif
+ volatile _q_value_integral;
+ };
+#else
+ T * volatile _q_value;
+#endif
+
+ // Non-atomic API
+ inline bool operator==(T *value) const
+ {
+ return _q_value == value;
+ }
+
+ inline bool operator!=(T *value) const
+ {
+ return !operator==(value);
+ }
+
+ inline bool operator!() const
+ {
+ return operator==(0);
+ }
+
+ inline operator T *() const
+ {
+ return _q_value;
+ }
+
+ inline T *operator->() const
+ {
+ return _q_value;
+ }
+
+ inline QBasicAtomicPointer<T> &operator=(T *value)
+ {
+#ifdef QT_ARCH_PARISC
+ this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
+#endif
+ _q_value = value;
+ return *this;
+ }
+
+ // Atomic API, implemented in qatomic_XXX.h
+
+ static bool isTestAndSetNative();
+ static 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 bool isFetchAndStoreNative();
+ static bool isFetchAndStoreWaitFree();
+
+ T *fetchAndStoreRelaxed(T *newValue);
+ T *fetchAndStoreAcquire(T *newValue);
+ T *fetchAndStoreRelease(T *newValue);
+ T *fetchAndStoreOrdered(T *newValue);
+
+ static bool isFetchAndAddNative();
+ static bool isFetchAndAddWaitFree();
+
+ T *fetchAndAddRelaxed(qptrdiff valueToAdd);
+ T *fetchAndAddAcquire(qptrdiff valueToAdd);
+ T *fetchAndAddRelease(qptrdiff valueToAdd);
+ T *fetchAndAddOrdered(qptrdiff valueToAdd);
+};
+
+#ifdef QT_ARCH_PARISC
+# define Q_BASIC_ATOMIC_INITIALIZER(a) {{-1,-1,-1,-1},(a)}
+#elif defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE)
+# define Q_BASIC_ATOMIC_INITIALIZER(a) { {(a)} }
+#else
+# define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC) || defined(QT_BOOTSTRAPPED)
+# include <QtCore/qatomic_bootstrap.h>
+#else
+# include <QtCore/qatomic_arch.h>
+#endif
+
+#endif // QBASIC_ATOMIC
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
new file mode 100644
index 0000000000..001506cf7d
--- /dev/null
+++ b/src/corelib/thread/qmutex.cpp
@@ -0,0 +1,515 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmutex.h"
+#include <qdebug.h>
+
+#ifndef QT_NO_THREAD
+#include "qatomic.h"
+#include "qelapsedtimer.h"
+#include "qthread.h"
+#include "qmutex_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMutex
+ \brief The QMutex class provides access serialization between threads.
+
+ \threadsafe
+
+ \ingroup thread
+
+ The purpose of a QMutex is to protect an object, data structure or
+ section of code so that only one thread can access it at a time
+ (this is similar to the Java \c synchronized keyword). It is
+ usually best to use a mutex with a QMutexLocker since this makes
+ it easy to ensure that locking and unlocking are performed
+ consistently.
+
+ For example, say there is a method that prints a message to the
+ user on two lines:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 0
+
+ If these two methods are called in succession, the following happens:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 1
+
+ If these two methods are called simultaneously from two threads then the
+ following sequence could result:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 2
+
+ If we add a mutex, we should get the result we want:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 3
+
+ Then only one thread can modify \c number at any given time and
+ the result is correct. This is a trivial example, of course, but
+ applies to any other case where things need to happen in a
+ particular sequence.
+
+ When you call lock() in a thread, other threads that try to call
+ lock() in the same place will block until the thread that got the
+ lock calls unlock(). A non-blocking alternative to lock() is
+ tryLock().
+
+ \sa QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
+*/
+
+/*!
+ \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.
+
+ \value NonRecursive In this mode, a thread may only lock a mutex
+ once.
+
+ \sa QMutex()
+*/
+
+/*!
+ Constructs a new mutex. The mutex is created in an unlocked state.
+
+ 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. The
+ default is QMutex::NonRecursive.
+
+ \sa lock(), unlock()
+*/
+QMutex::QMutex(RecursionMode mode)
+ : d(new QMutexPrivate(mode))
+{ }
+
+/*!
+ Destroys the mutex.
+
+ \warning Destroying a locked mutex may result in undefined behavior.
+*/
+QMutex::~QMutex()
+{ delete static_cast<QMutexPrivate *>(d); }
+
+/*!
+ 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 if this mutex is a
+ \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
+ \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \e dead-lock when the mutex is locked recursively.
+
+ \sa unlock()
+*/
+void QMutex::lock()
+{
+ QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
+ Qt::HANDLE self;
+
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+ if (d->owner == self) {
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
+ return;
+ }
+
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
+ if (!isLocked) {
+ // didn't get the lock, wait for it
+ isLocked = d->wait();
+ Q_ASSERT_X(isLocked, "QMutex::lock",
+ "Internal error, infinite wait has timed out.");
+ }
+
+ d->owner = self;
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
+ return;
+ }
+
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
+ if (!isLocked) {
+ lockInternal();
+ }
+}
+
+/*!
+ Attempts to lock the mutex. If the lock was obtained, this function
+ returns true. If another thread has locked the mutex, this
+ function returns false immediately.
+
+ 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 if this mutex is a
+ \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
+ \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \e always return false when attempting to lock the mutex
+ recursively.
+
+ \sa lock(), unlock()
+*/
+bool QMutex::tryLock()
+{
+ QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
+ Qt::HANDLE self;
+
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+ if (d->owner == self) {
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
+ return true;
+ }
+
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
+ if (!isLocked) {
+ // some other thread has the mutex locked, or we tried to
+ // recursively lock an non-recursive mutex
+ return isLocked;
+ }
+
+ d->owner = self;
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
+ return isLocked;
+ }
+
+ return d->contenders.testAndSetAcquire(0, 1);
+}
+
+/*! \overload
+
+ Attempts to lock the mutex. This function returns true if the lock
+ was obtained; otherwise it returns 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 if this mutex is a
+ \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
+ \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \e always return false when attempting to lock the mutex
+ recursively.
+
+ \sa lock(), unlock()
+*/
+bool QMutex::tryLock(int timeout)
+{
+ QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
+ Qt::HANDLE self;
+
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+ if (d->owner == self) {
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
+ return true;
+ }
+
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
+ if (!isLocked) {
+ // didn't get the lock, wait for it
+ isLocked = d->wait(timeout);
+ if (!isLocked)
+ return false;
+ }
+
+ d->owner = self;
+ ++d->count;
+ Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
+ return true;
+ }
+
+ return (d->contenders.testAndSetAcquire(0, 1)
+ // didn't get the lock, wait for it
+ || d->wait(timeout));
+}
+
+
+/*!
+ 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 QMutex::unlock()
+{
+ QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
+ if (d->recursive) {
+ if (!--d->count) {
+ d->owner = 0;
+ if (!d->contenders.testAndSetRelease(1, 0))
+ d->wakeUp();
+ }
+ } else {
+ if (!d->contenders.testAndSetRelease(1, 0))
+ d->wakeUp();
+ }
+}
+
+/*!
+ \fn bool QMutex::locked()
+
+ Returns true if the mutex is locked by another thread; otherwise
+ returns false.
+
+ It is generally a bad idea to use this function, because code
+ that uses it has a race condition. Use tryLock() and unlock()
+ instead.
+
+ \oldcode
+ bool isLocked = mutex.locked();
+ \newcode
+ bool isLocked = true;
+ if (mutex.tryLock()) {
+ mutex.unlock();
+ isLocked = false;
+ }
+ \endcode
+*/
+
+/*!
+ \class QMutexLocker
+ \brief The QMutexLocker class is a convenience class that simplifies
+ locking and unlocking mutexes.
+
+ \threadsafe
+
+ \ingroup thread
+
+ Locking and unlocking a QMutex 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.
+
+ QMutexLocker should be created within a function where a
+ QMutex needs to be locked. The mutex is locked when QMutexLocker
+ is created. You can unlock and relock the mutex with \c unlock()
+ and \c relock(). If locked, the mutex will be unlocked when the
+ QMutexLocker is destroyed.
+
+ For example, this complex function locks a QMutex upon entering
+ the function and unlocks the mutex at all the exit points:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 4
+
+ This example function will get more complicated as it is
+ developed, which increases the likelihood that errors will occur.
+
+ Using QMutexLocker greatly simplifies the code, and makes it more
+ readable:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 5
+
+ Now, the mutex will always be unlocked when the QMutexLocker
+ object is destroyed (when the function returns since \c locker is
+ an auto variable).
+
+ The same principle applies to code that throws and catches
+ exceptions. An exception that is not caught in the function that
+ has locked the mutex has no way of unlocking the mutex before the
+ exception is passed up the stack to the calling function.
+
+ QMutexLocker also provides a \c mutex() member function that returns
+ the mutex on which the QMutexLocker is operating. This is useful
+ for code that needs access to the mutex, such as
+ QWaitCondition::wait(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutex.cpp 6
+
+ \sa QReadLocker, QWriteLocker, QMutex
+*/
+
+/*!
+ \fn QMutexLocker::QMutexLocker(QMutex *mutex)
+
+ Constructs a QMutexLocker and locks \a mutex. The mutex will be
+ unlocked when the QMutexLocker is destroyed. If \a mutex is zero,
+ QMutexLocker does nothing.
+
+ \sa QMutex::lock()
+*/
+
+/*!
+ \fn QMutexLocker::~QMutexLocker()
+
+ Destroys the QMutexLocker and unlocks the mutex that was locked
+ in the constructor.
+
+ \sa QMutex::unlock()
+*/
+
+/*!
+ \fn QMutex *QMutexLocker::mutex() const
+
+ Returns a pointer to the mutex that was locked in the
+ constructor.
+*/
+
+/*!
+ \fn void QMutexLocker::unlock()
+
+ Unlocks this mutex locker. You can use \c relock() to lock
+ it again. It does not need to be locked when destroyed.
+
+ \sa relock()
+*/
+
+/*!
+ \fn void QMutexLocker::relock()
+
+ Relocks an unlocked mutex locker.
+
+ \sa unlock()
+*/
+
+/*!
+ \fn QMutex::QMutex(bool recursive)
+
+ Use the constructor that takes a RecursionMode parameter instead.
+*/
+
+/*!
+ \internal helper for lockInline()
+ */
+void QMutex::lockInternal()
+{
+ QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
+
+ if (QThread::idealThreadCount() == 1) {
+ // don't spin on single cpu machines
+ bool isLocked = d->wait();
+ Q_ASSERT_X(isLocked, "QMutex::lock",
+ "Internal error, infinite wait has timed out.");
+ Q_UNUSED(isLocked);
+ return;
+ }
+
+ QElapsedTimer elapsedTimer;
+ elapsedTimer.start();
+ do {
+ qint64 spinTime = elapsedTimer.nsecsElapsed();
+ if (spinTime > d->maximumSpinTime) {
+ // didn't get the lock, wait for it, since we're not going to gain anything by spinning more
+ elapsedTimer.start();
+ bool isLocked = d->wait();
+ Q_ASSERT_X(isLocked, "QMutex::lock",
+ "Internal error, infinite wait has timed out.");
+ Q_UNUSED(isLocked);
+
+ qint64 maximumSpinTime = d->maximumSpinTime;
+ qint64 averageWaitTime = d->averageWaitTime;
+ qint64 actualWaitTime = elapsedTimer.nsecsElapsed();
+ if (actualWaitTime < (QMutexPrivate::MaximumSpinTimeThreshold * 3 / 2)) {
+ // measure the wait times
+ averageWaitTime = d->averageWaitTime = qMin((averageWaitTime + actualWaitTime) / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ }
+
+ // adjust the spin count when spinning does not benefit contention performance
+ if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
+ // long waits, stop spinning
+ d->maximumSpinTime = 0;
+ } else {
+ // allow spinning if wait times decrease, but never spin more than the average wait time (otherwise we may perform worse)
+ d->maximumSpinTime = qBound(qint64(averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ }
+ return;
+ }
+ // be a good citizen... yielding lets something else run if there is something to run, but may also relieve memory pressure if not
+ QThread::yieldCurrentThread();
+ } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1));
+
+ // spinning is working, do not change the spin time (unless we are using much less time than allowed to spin)
+ qint64 maximumSpinTime = d->maximumSpinTime;
+ qint64 spinTime = elapsedTimer.nsecsElapsed();
+ if (spinTime < maximumSpinTime / 2) {
+ // we are using much less time than we need, adjust the limit
+ d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ }
+}
+
+/*!
+ \internal
+*/
+void QMutex::unlockInternal()
+{
+ static_cast<QMutexPrivate *>(d)->wakeUp();
+}
+
+/*!
+ \fn QMutex::lockInline()
+ \internal
+ inline version of QMutex::lock()
+*/
+
+/*!
+ \fn QMutex::unlockInline()
+ \internal
+ inline version of QMutex::unlock()
+*/
+
+/*!
+ \fn QMutex::tryLockInline()
+ \internal
+ inline version of QMutex::tryLock()
+*/
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
new file mode 100644
index 0000000000..5f75195b4e
--- /dev/null
+++ b/src/corelib/thread/qmutex.h
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMUTEX_H
+#define QMUTEX_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+#include <new>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_THREAD
+
+class QAtomicInt;
+class QMutexData;
+
+class Q_CORE_EXPORT QMutex
+{
+ friend class QWaitCondition;
+ friend class QWaitConditionPrivate;
+
+public:
+ enum RecursionMode { NonRecursive, Recursive };
+
+ explicit QMutex(RecursionMode mode = NonRecursive);
+ ~QMutex();
+
+ void lock(); //### Qt5: make inline;
+ inline void lockInline();
+ bool tryLock(); //### Qt5: make inline;
+ bool tryLock(int timeout);
+ inline bool tryLockInline();
+ void unlock(); //### Qt5: make inline;
+ inline void unlockInline();
+
+#if defined(QT3_SUPPORT)
+ inline QT3_SUPPORT bool locked()
+ {
+ if (!tryLock())
+ return true;
+ unlock();
+ return false;
+ }
+ inline QT3_SUPPORT_CONSTRUCTOR QMutex(bool recursive)
+ {
+ new (this) QMutex(recursive ? Recursive : NonRecursive);
+ }
+#endif
+
+private:
+ void lockInternal();
+ void unlockInternal();
+ Q_DISABLE_COPY(QMutex)
+
+ QMutexData *d;
+};
+
+class Q_CORE_EXPORT QMutexLocker
+{
+public:
+ inline explicit QMutexLocker(QMutex *m)
+ {
+ Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
+ "QMutexLocker", "QMutex pointer is misaligned");
+ if (m) {
+ m->lockInline();
+ val = reinterpret_cast<quintptr>(m) | quintptr(1u);
+ } else {
+ val = 0;
+ }
+ }
+ inline ~QMutexLocker() { unlock(); }
+
+ inline void unlock()
+ {
+ if ((val & quintptr(1u)) == quintptr(1u)) {
+ val &= ~quintptr(1u);
+ mutex()->unlockInline();
+ }
+ }
+
+ inline void relock()
+ {
+ if (val) {
+ if ((val & quintptr(1u)) == quintptr(0u)) {
+ mutex()->lockInline();
+ val |= quintptr(1u);
+ }
+ }
+ }
+
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
+#endif
+
+ inline QMutex *mutex() const
+ {
+ return reinterpret_cast<QMutex *>(val & ~quintptr(1u));
+ }
+
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+
+private:
+ Q_DISABLE_COPY(QMutexLocker)
+
+ quintptr val;
+};
+
+class QMutexData
+{
+ public:
+ QAtomicInt contenders;
+ const uint recursive : 1;
+ uint reserved : 31;
+ protected:
+ QMutexData(QMutex::RecursionMode mode);
+ ~QMutexData();
+};
+
+#ifdef QT_NO_DEBUG
+inline void QMutex::unlockInline()
+{
+ if (d->recursive) {
+ unlock();
+ } else if (!d->contenders.testAndSetRelease(1, 0)) {
+ unlockInternal();
+ }
+}
+
+inline bool QMutex::tryLockInline()
+{
+ if (d->recursive) {
+ return tryLock();
+ } else {
+ return d->contenders.testAndSetAcquire(0, 1);
+ }
+}
+
+inline void QMutex::lockInline()
+{
+ if (d->recursive) {
+ lock();
+ } else if(!tryLockInline()) {
+ lockInternal();
+ }
+}
+#else // QT_NO_DEBUG
+//in debug we do not use inline calls in order to allow debugging tools
+// to hook the mutex locking functions.
+inline void QMutex::unlockInline() { unlock(); }
+inline bool QMutex::tryLockInline() { return tryLock(); }
+inline void QMutex::lockInline() { lock(); }
+#endif // QT_NO_DEBUG
+
+
+#else // QT_NO_THREAD
+
+
+class Q_CORE_EXPORT QMutex
+{
+public:
+ enum RecursionMode { NonRecursive, Recursive };
+
+ inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
+ inline ~QMutex() {}
+
+ static inline void lock() {}
+ static inline void lockInline() {}
+ static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
+ static inline bool tryLockInline() { return true; }
+ static inline void unlock() {}
+ static inline void unlockInline() {}
+
+#if defined(QT3_SUPPORT)
+ static inline QT3_SUPPORT bool locked() { return false; }
+#endif
+
+private:
+ Q_DISABLE_COPY(QMutex)
+};
+
+class Q_CORE_EXPORT QMutexLocker
+{
+public:
+ inline explicit QMutexLocker(QMutex *) {}
+ inline ~QMutexLocker() {}
+
+ static inline void unlock() {}
+ static void relock() {}
+ static inline QMutex *mutex() { return 0; }
+
+private:
+ Q_DISABLE_COPY(QMutexLocker)
+};
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMUTEX_H
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
new file mode 100644
index 0000000000..70860b149e
--- /dev/null
+++ b/src/corelib/thread/qmutex_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMUTEX_P_H
+#define QMUTEX_P_H
+
+//
+// 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.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qmutex.h>
+
+#if defined(Q_OS_MAC)
+# include <mach/semaphore.h>
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+# include <e32std.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QMutexPrivate : public QMutexData {
+public:
+ QMutexPrivate(QMutex::RecursionMode mode);
+ ~QMutexPrivate();
+
+ bool wait(int timeout = -1);
+ void wakeUp();
+
+ // 1ms = 1000000ns
+ enum { MaximumSpinTimeThreshold = 1000000 };
+ volatile qint64 maximumSpinTime;
+ volatile qint64 averageWaitTime;
+ Qt::HANDLE owner;
+ uint count;
+
+#if defined(Q_OS_MAC)
+ semaphore_t mach_semaphore;
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) && !defined(Q_OS_SYMBIAN)
+ volatile bool wakeup;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ HANDLE event;
+#elif defined(Q_OS_SYMBIAN)
+ RSemaphore lock;
+#endif
+};
+
+inline QMutexData::QMutexData(QMutex::RecursionMode mode)
+ : recursive(mode == QMutex::Recursive)
+{}
+
+inline QMutexData::~QMutexData() {}
+
+QT_END_NAMESPACE
+
+#endif // QMUTEX_P_H
diff --git a/src/corelib/thread/qmutex_symbian.cpp b/src/corelib/thread/qmutex_symbian.cpp
new file mode 100644
index 0000000000..288c576d02
--- /dev/null
+++ b/src/corelib/thread/qmutex_symbian.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmutex.h"
+
+#ifndef QT_NO_THREAD
+#include "qatomic.h"
+#include "qelapsedtimer.h"
+#include "qthread.h"
+#include "qmutex_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
+{
+ int r = lock.CreateLocal(0);
+ if (r != KErrNone)
+ qWarning("QMutex: failed to create lock, error %d", r);
+ qt_symbian_throwIfError(r);
+}
+
+QMutexPrivate::~QMutexPrivate()
+{
+ lock.Close();
+}
+
+bool QMutexPrivate::wait(int timeout)
+{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ int r = KErrTimedOut;
+ if (timeout < 0) {
+ lock.Wait();
+ r = KErrNone;
+ } else {
+ // Symbian lock waits are specified in microseconds.
+ // The wait is therefore chunked.
+ // KErrNone indicates success, KErrGeneral and KErrArgument are real fails, anything else is a timeout
+ do {
+ int waitTime = qMin(KMaxTInt / 1000, timeout);
+ timeout -= waitTime;
+ // Symbian undocumented feature - 0us means no timeout! Use a minimum of 1
+ r = lock.Wait(qMax(1, waitTime * 1000));
+ } while (r != KErrNone && r != KErrGeneral && r != KErrArgument && timeout > 0);
+ }
+ bool returnValue = (r == KErrNone);
+ contenders.deref();
+ return returnValue;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ lock.Signal();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
new file mode 100644
index 0000000000..11e20604e2
--- /dev/null
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmutex.h"
+#include "qstring.h"
+
+#ifndef QT_NO_THREAD
+#include "qatomic.h"
+#include "qmutex_p.h"
+
+#include <errno.h>
+
+#if defined(Q_OS_VXWORKS) && defined(wakeup)
+#undef wakeup
+#endif
+
+#if defined(Q_OS_MAC)
+# include <mach/mach.h>
+# include <mach/task.h>
+#elif defined(Q_OS_LINUX)
+# include <linux/futex.h>
+# include <sys/syscall.h>
+# include <unistd.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_MAC) && !defined(Q_OS_LINUX)
+static void report_error(int code, const char *where, const char *what)
+{
+ if (code != 0)
+ qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+}
+#endif
+
+
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
+{
+#if defined(Q_OS_MAC)
+ kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to create semaphore, error %d", r);
+#elif !defined(Q_OS_LINUX)
+ wakeup = false;
+ report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
+ report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
+#endif
+}
+
+QMutexPrivate::~QMutexPrivate()
+{
+#if defined(Q_OS_MAC)
+ kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to destroy semaphore, error %d", r);
+#elif !defined(Q_OS_LINUX)
+ report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
+ report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
+#endif
+}
+
+#if defined(Q_OS_MAC)
+
+bool QMutexPrivate::wait(int timeout)
+{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ bool returnValue;
+ if (timeout < 0) {
+ returnValue = semaphore_wait(mach_semaphore) == KERN_SUCCESS;
+ } else {
+ mach_timespec_t ts;
+ ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
+ ts.tv_sec = (timeout / 1000);
+ kern_return_t r = semaphore_timedwait(mach_semaphore, ts);
+ returnValue = r == KERN_SUCCESS;
+ }
+ contenders.deref();
+ return returnValue;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ semaphore_signal(mach_semaphore);
+}
+
+#elif defined(Q_OS_LINUX)
+
+static inline int _q_futex(volatile int *addr, int op, int val, const struct timespec *timeout, int *addr2, int val2)
+{
+ return syscall(SYS_futex, addr, op, val, timeout, addr2, val2);
+}
+
+bool QMutexPrivate::wait(int timeout)
+{
+ while (contenders.fetchAndStoreAcquire(2) > 0) {
+ struct timespec ts, *pts = 0;
+ if (timeout >= 0) {
+ ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
+ ts.tv_sec = (timeout / 1000);
+ pts = &ts;
+ }
+ int r = _q_futex(&contenders._q_value, FUTEX_WAIT, 2, pts, 0, 0);
+ if (r != 0 && errno == ETIMEDOUT)
+ return false;
+ }
+ return true;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ (void) contenders.fetchAndStoreRelease(0);
+ (void) _q_futex(&contenders._q_value, FUTEX_WAKE, 1, 0, 0, 0);
+}
+
+#else // !Q_OS_MAC && !Q_OS_LINUX
+
+bool QMutexPrivate::wait(int timeout)
+{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ 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 {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ timespec ti;
+ ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
+ ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
+ ti.tv_nsec %= 1000000000;
+
+ errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
+ }
+ if (errorCode) {
+ if (errorCode == ETIMEDOUT) {
+ if (wakeup)
+ errorCode = 0;
+ break;
+ }
+ report_error(errorCode, "QMutex::lock()", "cv wait");
+ }
+ }
+ wakeup = false;
+ report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
+ contenders.deref();
+ return errorCode == 0;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ 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");
+}
+
+#endif // !Q_OS_MAC && !Q_OS_LINUX
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
new file mode 100644
index 0000000000..3a535c16ab
--- /dev/null
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qt_windows.h>
+
+#include "qmutex.h"
+#include <qatomic.h>
+#include "qmutex_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
+{
+ event = CreateEvent(0, FALSE, FALSE, 0);
+ if (!event)
+ qWarning("QMutexPrivate::QMutexPrivate: Cannot create event");
+}
+
+QMutexPrivate::~QMutexPrivate()
+{ CloseHandle(event); }
+
+bool QMutexPrivate::wait(int timeout)
+{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ bool returnValue = (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
+ contenders.deref();
+ return returnValue;
+}
+
+void QMutexPrivate::wakeUp()
+{ SetEvent(event); }
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
new file mode 100644
index 0000000000..144fa35137
--- /dev/null
+++ b/src/corelib/thread/qmutexpool.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qatomic.h"
+#include "qmutexpool_p.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+// qt_global_mutexpool is here for backwards compatibility only,
+// use QMutexpool::instance() in new clode.
+Q_CORE_EXPORT QMutexPool *qt_global_mutexpool = 0;
+Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
+
+/*!
+ \class QMutexPool
+ \brief The QMutexPool class provides a pool of QMutex objects.
+
+ \internal
+
+ \ingroup thread
+
+ QMutexPool is a convenience class that provides access to a fixed
+ number of QMutex objects.
+
+ Typical use of a QMutexPool is in situations where it is not
+ possible or feasible to use one QMutex for every protected object.
+ The mutex pool will return a mutex based on the address of the
+ object that needs protection.
+
+ For example, consider this simple class:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutexpool.cpp 0
+
+ Adding a QMutex member to the Number class does not make sense,
+ because it is so small. However, in order to ensure that access to
+ each Number is protected, you need to use a mutex. In this case, a
+ QMutexPool would be ideal.
+
+ Code to calculate the square of a number would then look something
+ like this:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qmutexpool.cpp 1
+
+ This function will safely calculate the square of a number, since
+ it uses a mutex from a QMutexPool. The mutex is locked and
+ unlocked automatically by the QMutexLocker class. See the
+ QMutexLocker documentation for more details.
+*/
+
+/*!
+ Constructs a QMutexPool, reserving space for \a size QMutexes. All
+ mutexes in the pool are created with \a recursionMode. By default,
+ all mutexes are non-recursive.
+
+ The QMutexes are created when needed, and deleted when the
+ QMutexPool is destructed.
+*/
+QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
+ : mutexes(size), recursionMode(recursionMode)
+{
+ for (int index = 0; index < mutexes.count(); ++index) {
+ mutexes[index] = 0;
+ }
+}
+
+/*!
+ Destructs a QMutexPool. All QMutexes that were created by the pool
+ are deleted.
+*/
+QMutexPool::~QMutexPool()
+{
+ for (int index = 0; index < mutexes.count(); ++index) {
+ delete mutexes[index];
+ mutexes[index] = 0;
+ }
+}
+
+/*!
+ Returns the global QMutexPool instance.
+*/
+QMutexPool *QMutexPool::instance()
+{
+ return globalMutexPool();
+}
+
+/*! \fn QMutexPool::get(void *address)
+ Returns a QMutex from the pool. QMutexPool uses the value \a address
+ to determine which mutex is returned from the pool.
+*/
+
+/*! \internal
+ create the mutex for the given index
+ */
+QMutex *QMutexPool::createMutex(int index)
+{
+ // mutex not created, create one
+ QMutex *newMutex = new QMutex(recursionMode);
+ if (!mutexes[index].testAndSetOrdered(0, newMutex))
+ delete newMutex;
+ return mutexes[index];
+}
+
+/*!
+ Returns a QMutex from the global mutex pool.
+*/
+QMutex *QMutexPool::globalInstanceGet(const void *address)
+{
+ QMutexPool * const globalInstance = globalMutexPool();
+ if (globalInstance == 0)
+ return 0;
+ return globalInstance->get(address);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
new file mode 100644
index 0000000000..b2cd210d71
--- /dev/null
+++ b/src/corelib/thread/qmutexpool_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMUTEXPOOL_P_H
+#define QMUTEXPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QSettings. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qatomic.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qvarlengtharray.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QMutexPool
+{
+public:
+ explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131);
+ ~QMutexPool();
+
+ inline QMutex *get(const void *address) {
+ int index = uint(quintptr(address)) % mutexes.count();
+ QMutex *m = mutexes[index];
+ if (m)
+ return m;
+ else
+ return createMutex(index);
+ }
+ static QMutexPool *instance();
+ static QMutex *globalInstanceGet(const void *address);
+
+private:
+ QMutex *createMutex(int index);
+ QVarLengthArray<QAtomicPointer<QMutex>, 131> mutexes;
+ QMutex::RecursionMode recursionMode;
+};
+
+extern Q_CORE_EXPORT QMutexPool *qt_global_mutexpool;
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
+
+#endif // QMUTEXPOOL_P_H
diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h
new file mode 100644
index 0000000000..ddabfb7977
--- /dev/null
+++ b/src/corelib/thread/qorderedmutexlocker_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QORDEREDMUTEXLOCKER_P_H
+#define QORDEREDMUTEXLOCKER_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.
+//
+
+QT_BEGIN_NAMESPACE
+
+#include <QtCore/qmutex.h>
+
+/*
+ Locks 2 mutexes in a defined order, avoiding a recursive lock if
+ we're trying to lock the same mutex twice.
+*/
+class QOrderedMutexLocker
+{
+public:
+ QOrderedMutexLocker(QMutex *m1, QMutex *m2)
+ : mtx1((m1 == m2) ? m1 : (m1 < m2 ? m1 : m2)),
+ mtx2((m1 == m2) ? 0 : (m1 < m2 ? m2 : m1)),
+ locked(false)
+ {
+ relock();
+ }
+ ~QOrderedMutexLocker()
+ {
+ unlock();
+ }
+
+ void relock()
+ {
+ if (!locked) {
+ if (mtx1) mtx1->lockInline();
+ if (mtx2) mtx2->lockInline();
+ locked = true;
+ }
+ }
+
+ void unlock()
+ {
+ if (locked) {
+ if (mtx1) mtx1->unlockInline();
+ if (mtx2) mtx2->unlockInline();
+ locked = false;
+ }
+ }
+
+ static bool relock(QMutex *mtx1, QMutex *mtx2)
+ {
+ // mtx1 is already locked, mtx2 not... do we need to unlock and relock?
+ if (mtx1 == mtx2)
+ return false;
+ if (mtx1 < mtx2) {
+ mtx2->lockInline();
+ return true;
+ }
+ if (!mtx2->tryLockInline()) {
+ mtx1->unlock();
+ mtx2->lock();
+ mtx1->lock();
+ }
+ return true;
+ }
+
+private:
+ QMutex *mtx1, *mtx2;
+ bool locked;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
new file mode 100644
index 0000000000..aabd26e07b
--- /dev/null
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -0,0 +1,581 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qreadwritelock.h"
+
+#ifndef QT_NO_THREAD
+#include "qmutex.h"
+#include "qthread.h"
+#include "qwaitcondition.h"
+
+#include "qreadwritelock_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class QReadWriteLock
+ \brief The QReadWriteLock class provides read-write locking.
+
+ \threadsafe
+
+ \ingroup thread
+
+ A read-write lock is a synchronization tool for protecting
+ resources that can be accessed for reading and writing. This type
+ of lock is useful if you want to allow multiple threads to have
+ simultaneous read-only access, but as soon as one thread wants to
+ write to the resource, all other threads must be blocked until
+ the writing is complete.
+
+ In many cases, QReadWriteLock is a direct competitor to QMutex.
+ QReadWriteLock is a good choice if there are many concurrent
+ reads and writing occurs infrequently.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qreadwritelock.cpp 0
+
+ To ensure that writers aren't blocked forever by readers, readers
+ attempting to obtain a lock will not succeed if there is a blocked
+ writer waiting for access, even if the lock is currently only
+ accessed by other readers. Also, if the lock is accessed by a
+ writer and another writer comes in, that writer will have
+ priority over any readers that might also be waiting.
+
+ Like QMutex, a QReadWriteLock can be recursively locked by the
+ same thread when constructed in
+ \l{QReadWriteLock::RecursionMode}. In such cases,
+ unlock() must be called the same number of times lockForWrite() or
+ lockForRead() was called. Note that the lock type cannot be
+ changed when trying to lock recursively, i.e. it is not possible
+ to lock for reading in a thread that already has locked for
+ writing (and vice versa).
+
+ \sa QReadLocker, QWriteLocker, QMutex, QSemaphore
+*/
+
+/*!
+ \enum QReadWriteLock::RecursionMode
+ \since 4.4
+
+ \value Recursive In this mode, a thread can lock the same
+ QReadWriteLock multiple times and the mutex won't be unlocked
+ until a corresponding number of unlock() calls have been made.
+
+ \value NonRecursive In this mode, a thread may only lock a
+ QReadWriteLock once.
+
+ \sa QReadWriteLock()
+*/
+
+/*!
+ Constructs a QReadWriteLock object in NonRecursive mode.
+
+ \sa lockForRead(), lockForWrite()
+*/
+QReadWriteLock::QReadWriteLock()
+ :d(new QReadWriteLockPrivate(NonRecursive))
+{ }
+
+/*!
+ \since 4.4
+
+ Constructs a QReadWriteLock object in the given \a recursionMode.
+
+ \sa lockForRead(), lockForWrite(), RecursionMode
+*/
+QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
+ : d(new QReadWriteLockPrivate(recursionMode))
+{ }
+
+/*!
+ Destroys the QReadWriteLock object.
+
+ \warning Destroying a read-write lock that is in use may result
+ in undefined behavior.
+*/
+QReadWriteLock::~QReadWriteLock()
+{
+ delete d;
+}
+
+/*!
+ Locks the lock for reading. This function will block the current
+ thread if any thread (including the current) has locked for
+ writing.
+
+ \sa unlock() lockForWrite() tryLockForRead()
+*/
+void QReadWriteLock::lockForRead()
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
+ if (it != d->currentReaders.end()) {
+ ++it.value();
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()",
+ "Overflow in lock counter");
+ return;
+ }
+ }
+
+ while (d->accessCount < 0 || d->waitingWriters) {
+ ++d->waitingReaders;
+ d->readerWait.wait(&d->mutex);
+ --d->waitingReaders;
+ }
+ if (d->recursive)
+ d->currentReaders.insert(self, 1);
+
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", "Overflow in lock counter");
+}
+
+/*!
+ Attempts to lock for reading. If the lock was obtained, this
+ function returns true, otherwise it returns false instead of
+ waiting for the lock to become available, i.e. it does not block.
+
+ The lock attempt will fail if another thread has locked for
+ writing.
+
+ If the lock was obtained, the lock must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ \sa unlock() lockForRead()
+*/
+bool QReadWriteLock::tryLockForRead()
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
+ if (it != d->currentReaders.end()) {
+ ++it.value();
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
+ "Overflow in lock counter");
+ return true;
+ }
+ }
+
+ if (d->accessCount < 0)
+ return false;
+ if (d->recursive)
+ d->currentReaders.insert(self, 1);
+
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
+
+ return true;
+}
+
+/*! \overload
+
+ Attempts to lock for reading. This function returns true if the
+ lock was obtained; otherwise it returns 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.
+
+ \sa unlock() lockForRead()
+*/
+bool QReadWriteLock::tryLockForRead(int timeout)
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
+ if (it != d->currentReaders.end()) {
+ ++it.value();
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
+ "Overflow in lock counter");
+ return true;
+ }
+ }
+
+ while (d->accessCount < 0 || d->waitingWriters) {
+ ++d->waitingReaders;
+ bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout));
+ --d->waitingReaders;
+ if (!success)
+ return false;
+ }
+ if (d->recursive)
+ d->currentReaders.insert(self, 1);
+
+ ++d->accessCount;
+ Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
+
+ return true;
+}
+
+/*!
+ Locks the lock for writing. This function will block the current
+ thread if another thread has locked for reading or writing.
+
+ \sa unlock() lockForRead() tryLockForWrite()
+*/
+void QReadWriteLock::lockForWrite()
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ if (d->currentWriter == self) {
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
+ "Overflow in lock counter");
+ return;
+ }
+ }
+
+ while (d->accessCount != 0) {
+ ++d->waitingWriters;
+ d->writerWait.wait(&d->mutex);
+ --d->waitingWriters;
+ }
+ if (d->recursive)
+ d->currentWriter = self;
+
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", "Overflow in lock counter");
+}
+
+/*!
+ Attempts to lock for writing. If the lock was obtained, this
+ function returns true; otherwise, it returns false immediately.
+
+ The lock attempt will fail if another thread has locked for
+ reading or writing.
+
+ If the lock was obtained, the lock must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ \sa unlock() lockForWrite()
+*/
+bool QReadWriteLock::tryLockForWrite()
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ if (d->currentWriter == self) {
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
+ "Overflow in lock counter");
+ return true;
+ }
+ }
+
+ if (d->accessCount != 0)
+ return false;
+ if (d->recursive)
+ d->currentWriter = self;
+
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()",
+ "Overflow in lock counter");
+
+ return true;
+}
+
+/*! \overload
+
+ Attempts to lock for writing. This function returns true if the
+ lock was obtained; otherwise it returns 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.
+
+ 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.
+
+ \sa unlock() lockForWrite()
+*/
+bool QReadWriteLock::tryLockForWrite(int timeout)
+{
+ QMutexLocker lock(&d->mutex);
+
+ Qt::HANDLE self = 0;
+ if (d->recursive) {
+ self = QThread::currentThreadId();
+
+ if (d->currentWriter == self) {
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
+ "Overflow in lock counter");
+ return true;
+ }
+ }
+
+ while (d->accessCount != 0) {
+ ++d->waitingWriters;
+ bool success = d->writerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout));
+ --d->waitingWriters;
+
+ if (!success)
+ return false;
+ }
+ if (d->recursive)
+ d->currentWriter = self;
+
+ --d->accessCount;
+ Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()",
+ "Overflow in lock counter");
+
+ return true;
+}
+
+/*!
+ Unlocks the lock.
+
+ Attempting to unlock a lock that is not locked is an error, and will result
+ in program termination.
+
+ \sa lockForRead() lockForWrite() tryLockForRead() tryLockForWrite()
+*/
+void QReadWriteLock::unlock()
+{
+ QMutexLocker lock(&d->mutex);
+
+ Q_ASSERT_X(d->accessCount != 0, "QReadWriteLock::unlock()", "Cannot unlock an unlocked lock");
+
+ bool unlocked = false;
+ if (d->accessCount > 0) {
+ // releasing a read lock
+ if (d->recursive) {
+ Qt::HANDLE self = QThread::currentThreadId();
+ QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
+ if (it != d->currentReaders.end()) {
+ if (--it.value() <= 0)
+ d->currentReaders.erase(it);
+ }
+ }
+
+ unlocked = --d->accessCount == 0;
+ } else if (d->accessCount < 0 && ++d->accessCount == 0) {
+ // released a write lock
+ unlocked = true;
+ d->currentWriter = 0;
+ }
+
+ if (unlocked) {
+ if (d->waitingWriters) {
+ d->writerWait.wakeOne();
+ } else if (d->waitingReaders) {
+ d->readerWait.wakeAll();
+ }
+ }
+}
+
+/*!
+ \class QReadLocker
+ \brief The QReadLocker class is a convenience class that
+ simplifies locking and unlocking read-write locks for read access.
+
+ \threadsafe
+
+ \ingroup thread
+
+ The purpose of QReadLocker (and QWriteLocker) is to simplify
+ QReadWriteLock locking and unlocking. Locking and unlocking
+ statements or in exception handling code is error-prone and
+ difficult to debug. QReadLocker can be used in such situations
+ to ensure that the state of the lock is always well-defined.
+
+ Here's an example that uses QReadLocker to lock and unlock a
+ read-write lock for reading:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qreadwritelock.cpp 1
+
+ It is equivalent to the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qreadwritelock.cpp 2
+
+ The QMutexLocker documentation shows examples where the use of a
+ locker object greatly simplifies programming.
+
+ \sa QWriteLocker, QReadWriteLock
+*/
+
+/*!
+ \fn QReadLocker::QReadLocker(QReadWriteLock *lock)
+
+ Constructs a QReadLocker and locks \a lock for reading. The lock
+ will be unlocked when the QReadLocker is destroyed. If \c lock is
+ zero, QReadLocker does nothing.
+
+ \sa QReadWriteLock::lockForRead()
+*/
+
+/*!
+ \fn QReadLocker::~QReadLocker()
+
+ Destroys the QReadLocker and unlocks the lock that was passed to
+ the constructor.
+
+ \sa QReadWriteLock::unlock()
+*/
+
+/*!
+ \fn void QReadLocker::unlock()
+
+ Unlocks the lock associated with this locker.
+
+ \sa QReadWriteLock::unlock()
+*/
+
+/*!
+ \fn void QReadLocker::relock()
+
+ Relocks an unlocked lock.
+
+ \sa unlock()
+*/
+
+/*!
+ \fn QReadWriteLock *QReadLocker::readWriteLock() const
+
+ Returns a pointer to the read-write lock that was passed
+ to the constructor.
+*/
+
+/*!
+ \class QWriteLocker
+ \brief The QWriteLocker class is a convenience class that
+ simplifies locking and unlocking read-write locks for write access.
+
+ \threadsafe
+
+ \ingroup thread
+
+ The purpose of QWriteLocker (and QReadLocker is to simplify
+ QReadWriteLock locking and unlocking. Locking and unlocking
+ statements or in exception handling code is error-prone and
+ difficult to debug. QWriteLocker can be used in such situations
+ to ensure that the state of the lock is always well-defined.
+
+ Here's an example that uses QWriteLocker to lock and unlock a
+ read-write lock for writing:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qreadwritelock.cpp 3
+
+ It is equivalent to the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qreadwritelock.cpp 4
+
+ The QMutexLocker documentation shows examples where the use of a
+ locker object greatly simplifies programming.
+
+ \sa QReadLocker, QReadWriteLock
+*/
+
+/*!
+ \fn QWriteLocker::QWriteLocker(QReadWriteLock *lock)
+
+ Constructs a QWriteLocker and locks \a lock for writing. The lock
+ will be unlocked when the QWriteLocker is destroyed. If \c lock is
+ zero, QWriteLocker does nothing.
+
+ \sa QReadWriteLock::lockForWrite()
+*/
+
+/*!
+ \fn QWriteLocker::~QWriteLocker()
+
+ Destroys the QWriteLocker and unlocks the lock that was passed to
+ the constructor.
+
+ \sa QReadWriteLock::unlock()
+*/
+
+/*!
+ \fn void QWriteLocker::unlock()
+
+ Unlocks the lock associated with this locker.
+
+ \sa QReadWriteLock::unlock()
+*/
+
+/*!
+ \fn void QWriteLocker::relock()
+
+ Relocks an unlocked lock.
+
+ \sa unlock()
+*/
+
+/*!
+ \fn QReadWriteLock *QWriteLocker::readWriteLock() const
+
+ Returns a pointer to the read-write lock that was passed
+ to the constructor.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
new file mode 100644
index 0000000000..e4fd18e0e3
--- /dev/null
+++ b/src/corelib/thread/qreadwritelock.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREADWRITELOCK_H
+#define QREADWRITELOCK_H
+
+#include <QtCore/qglobal.h>
+#include <limits.h> // ### Qt 5: remove
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_THREAD
+
+struct QReadWriteLockPrivate;
+
+class Q_CORE_EXPORT QReadWriteLock
+{
+public:
+ enum RecursionMode { NonRecursive, Recursive };
+
+ QReadWriteLock(); // ### Qt 5: merge with below
+ QReadWriteLock(RecursionMode recursionMode);
+ ~QReadWriteLock();
+
+ void lockForRead();
+ bool tryLockForRead();
+ bool tryLockForRead(int timeout);
+
+ void lockForWrite();
+ bool tryLockForWrite();
+ bool tryLockForWrite(int timeout);
+
+ void unlock();
+
+private:
+ Q_DISABLE_COPY(QReadWriteLock)
+ QReadWriteLockPrivate *d;
+
+ friend class QWaitCondition;
+};
+
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
+#endif
+
+class Q_CORE_EXPORT QReadLocker
+{
+public:
+ inline QReadLocker(QReadWriteLock *readWriteLock);
+
+ inline ~QReadLocker()
+ { unlock(); }
+
+ inline void unlock()
+ {
+ if (q_val) {
+ if ((q_val & quintptr(1u)) == quintptr(1u)) {
+ q_val &= ~quintptr(1u);
+ readWriteLock()->unlock();
+ }
+ }
+ }
+
+ inline void relock()
+ {
+ if (q_val) {
+ if ((q_val & quintptr(1u)) == quintptr(0u)) {
+ readWriteLock()->lockForRead();
+ q_val |= quintptr(1u);
+ }
+ }
+ }
+
+ inline QReadWriteLock *readWriteLock() const
+ { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
+
+private:
+ Q_DISABLE_COPY(QReadLocker)
+ quintptr q_val;
+};
+
+inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
+ : q_val(reinterpret_cast<quintptr>(areadWriteLock))
+{
+ Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
+ "QReadLocker", "QReadWriteLock pointer is misaligned");
+ relock();
+}
+
+class Q_CORE_EXPORT QWriteLocker
+{
+public:
+ inline QWriteLocker(QReadWriteLock *readWriteLock);
+
+ inline ~QWriteLocker()
+ { unlock(); }
+
+ inline void unlock()
+ {
+ if (q_val) {
+ if ((q_val & quintptr(1u)) == quintptr(1u)) {
+ q_val &= ~quintptr(1u);
+ readWriteLock()->unlock();
+ }
+ }
+ }
+
+ inline void relock()
+ {
+ if (q_val) {
+ if ((q_val & quintptr(1u)) == quintptr(0u)) {
+ readWriteLock()->lockForWrite();
+ q_val |= quintptr(1u);
+ }
+ }
+ }
+
+ inline QReadWriteLock *readWriteLock() const
+ { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
+
+
+private:
+ Q_DISABLE_COPY(QWriteLocker)
+ quintptr q_val;
+};
+
+inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
+ : q_val(reinterpret_cast<quintptr>(areadWriteLock))
+{
+ Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
+ "QWriteLocker", "QReadWriteLock pointer is misaligned");
+ relock();
+}
+
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+
+#else // QT_NO_THREAD
+
+class Q_CORE_EXPORT QReadWriteLock
+{
+public:
+ enum RecursionMode { NonRecursive, Recursive };
+ inline explicit QReadWriteLock(RecursionMode = NonRecursive) { }
+ inline ~QReadWriteLock() { }
+
+ static inline void lockForRead() { }
+ static inline bool tryLockForRead() { return true; }
+ static inline bool tryLockForRead(int timeout) { Q_UNUSED(timeout); return true; }
+
+ static inline void lockForWrite() { }
+ static inline bool tryLockForWrite() { return true; }
+ static inline bool tryLockForWrite(int timeout) { Q_UNUSED(timeout); return true; }
+
+ static inline void unlock() { }
+
+private:
+ Q_DISABLE_COPY(QReadWriteLock)
+};
+
+class Q_CORE_EXPORT QReadLocker
+{
+public:
+ inline QReadLocker(QReadWriteLock *) { }
+ inline ~QReadLocker() { }
+
+ static inline void unlock() { }
+ static inline void relock() { }
+ static inline QReadWriteLock *readWriteLock() { return 0; }
+
+private:
+ Q_DISABLE_COPY(QReadLocker)
+};
+
+class Q_CORE_EXPORT QWriteLocker
+{
+public:
+ inline explicit QWriteLocker(QReadWriteLock *) { }
+ inline ~QWriteLocker() { }
+
+ static inline void unlock() { }
+ static inline void relock() { }
+ static inline QReadWriteLock *readWriteLock() { return 0; }
+
+private:
+ Q_DISABLE_COPY(QWriteLocker)
+};
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QREADWRITELOCK_H
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
new file mode 100644
index 0000000000..26f26d78a4
--- /dev/null
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREADWRITELOCK_P_H
+#define QREADWRITELOCK_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 implementation. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qhash.h>
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+struct QReadWriteLockPrivate
+{
+ QReadWriteLockPrivate(QReadWriteLock::RecursionMode recursionMode)
+ : accessCount(0), waitingReaders(0), waitingWriters(0),
+ recursive(recursionMode == QReadWriteLock::Recursive), currentWriter(0)
+ { }
+
+ QMutex mutex;
+ QWaitCondition readerWait;
+ QWaitCondition writerWait;
+
+ int accessCount;
+ int waitingReaders;
+ int waitingWriters;
+
+ bool recursive;
+ Qt::HANDLE currentWriter;
+ QHash<Qt::HANDLE, int> currentReaders;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
+
+#endif // QREADWRITELOCK_P_H
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
new file mode 100644
index 0000000000..ba6fa6ef9b
--- /dev/null
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsemaphore.h"
+
+#ifndef QT_NO_THREAD
+#include "qmutex.h"
+#include "qwaitcondition.h"
+#include "qelapsedtimer.h"
+#include "qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSemaphore
+ \brief The QSemaphore class provides a general counting semaphore.
+
+ \threadsafe
+
+ \ingroup thread
+
+ A semaphore is a generalization of a mutex. While a mutex can
+ only be locked once, it's possible to acquire a semaphore
+ multiple times. Semaphores are typically used to protect a
+ certain number of identical resources.
+
+ Semaphores support two fundamental operations, acquire() and
+ release():
+
+ \list
+ \o acquire(\e{n}) tries to acquire \e n resources. If there aren't
+ that many resources available, the call will block until this
+ is the case.
+ \o release(\e{n}) releases \e n resources.
+ \endlist
+
+ There's also a tryAcquire() function that returns immediately if
+ it cannot acquire the resources, and an available() function that
+ returns the number of available resources at any time.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qsemaphore.cpp 0
+
+ A typical application of semaphores is for controlling access to
+ a circular buffer shared by a producer thread and a consumer
+ thread. The \l{threads/semaphores}{Semaphores} example shows how
+ to use QSemaphore to solve that problem.
+
+ A non-computing example of a semaphore would be dining at a
+ restaurant. A semaphore is initialized with the number of chairs
+ in the restaurant. As people arrive, they want a seat. As seats
+ are filled, available() is decremented. As people leave, the
+ available() is incremented, allowing more people to enter. If a
+ party of 10 people want to be seated, but there are only 9 seats,
+ those 10 people will wait, but a party of 4 people would be
+ seated (taking the available seats to 5, making the party of 10
+ people wait longer).
+
+ \sa QMutex, QWaitCondition, QThread, {Semaphores Example}
+*/
+
+class QSemaphorePrivate {
+public:
+ inline QSemaphorePrivate(int n) : avail(n) { }
+
+ QMutex mutex;
+ QWaitCondition cond;
+
+ int avail;
+};
+
+/*!
+ Creates a new semaphore and initializes the number of resources
+ it guards to \a n (by default, 0).
+
+ \sa release(), available()
+*/
+QSemaphore::QSemaphore(int n)
+{
+ Q_ASSERT_X(n >= 0, "QSemaphore", "parameter 'n' must be non-negative");
+ d = new QSemaphorePrivate(n);
+}
+
+/*!
+ Destroys the semaphore.
+
+ \warning Destroying a semaphore that is in use may result in
+ undefined behavior.
+*/
+QSemaphore::~QSemaphore()
+{ delete d; }
+
+/*!
+ Tries to acquire \c n resources guarded by the semaphore. If \a n
+ > available(), this call will block until enough resources are
+ available.
+
+ \sa release(), available(), tryAcquire()
+*/
+void QSemaphore::acquire(int n)
+{
+ Q_ASSERT_X(n >= 0, "QSemaphore::acquire", "parameter 'n' must be non-negative");
+ QMutexLocker locker(&d->mutex);
+ while (n > d->avail)
+ d->cond.wait(locker.mutex());
+ d->avail -= n;
+}
+
+/*!
+ Releases \a n resources guarded by the semaphore.
+
+ This function can be used to "create" resources as well. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qsemaphore.cpp 1
+
+ \sa acquire(), available()
+*/
+void QSemaphore::release(int n)
+{
+ Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative");
+ QMutexLocker locker(&d->mutex);
+ d->avail += n;
+ d->cond.wakeAll();
+}
+
+/*!
+ Returns the number of resources currently available to the
+ semaphore. This number can never be negative.
+
+ \sa acquire(), release()
+*/
+int QSemaphore::available() const
+{
+ QMutexLocker locker(&d->mutex);
+ return d->avail;
+}
+
+/*!
+ Tries to acquire \c n resources guarded by the semaphore and
+ returns true on success. If available() < \a n, this call
+ immediately returns false without acquiring any resources.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qsemaphore.cpp 2
+
+ \sa acquire()
+*/
+bool QSemaphore::tryAcquire(int n)
+{
+ Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
+ QMutexLocker locker(&d->mutex);
+ if (n > d->avail)
+ return false;
+ d->avail -= n;
+ return true;
+}
+
+/*!
+ Tries to acquire \c n resources guarded by the semaphore and
+ returns true on success. If available() < \a n, this call will
+ wait for at most \a timeout milliseconds for resources to become
+ available.
+
+ Note: Passing a negative number as the \a timeout is equivalent to
+ calling acquire(), i.e. this function will wait forever for
+ resources to become available if \a timeout is negative.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qsemaphore.cpp 3
+
+ \sa acquire()
+*/
+bool QSemaphore::tryAcquire(int n, int timeout)
+{
+ Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
+ QMutexLocker locker(&d->mutex);
+ if (timeout < 0) {
+ while (n > d->avail)
+ d->cond.wait(locker.mutex());
+ } else {
+ QElapsedTimer timer;
+ timer.start();
+ while (n > d->avail) {
+ const qint64 elapsed = timer.elapsed();
+ if (timeout - elapsed <= 0
+ || !d->cond.wait(locker.mutex(), timeout - elapsed))
+ return false;
+ }
+ }
+ d->avail -= n;
+ return true;
+
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
new file mode 100644
index 0000000000..e820175528
--- /dev/null
+++ b/src/corelib/thread/qsemaphore.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEMAPHORE_H
+#define QSEMAPHORE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_THREAD
+
+class QSemaphorePrivate;
+
+class Q_CORE_EXPORT QSemaphore
+{
+public:
+ explicit QSemaphore(int n = 0);
+ ~QSemaphore();
+
+ void acquire(int n = 1);
+ bool tryAcquire(int n = 1);
+ bool tryAcquire(int n, int timeout);
+
+ void release(int n = 1);
+
+ int available() const;
+
+private:
+ Q_DISABLE_COPY(QSemaphore)
+
+ QSemaphorePrivate *d;
+};
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSEMAPHORE_H
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
new file mode 100644
index 0000000000..aaa1e6dc36
--- /dev/null
+++ b/src/corelib/thread/qthread.cpp
@@ -0,0 +1,772 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthread.h"
+#include "qthreadstorage.h"
+#include "qmutex.h"
+#include "qmutexpool_p.h"
+#include "qreadwritelock.h"
+#include "qabstracteventdispatcher.h"
+
+#include <qeventloop.h>
+#include <qhash.h>
+
+#include "qthread_p.h"
+#include "private/qcoreapplication_p.h"
+
+/*
+#ifdef Q_OS_WIN32
+# include "qt_windows.h"
+#else
+# include <unistd.h>
+# include <netinet/in.h>
+# include <sys/utsname.h>
+# include <sys/socket.h>
+*/
+/*
+# elif defined(Q_OS_HPUX)
+# include <sys/pstat.h>
+# elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_MAC)
+# include <sys/sysctl.h>
+# endif
+#endif
+*/
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QThreadData
+*/
+
+QThreadData::QThreadData(int initialRefCount)
+ : _ref(initialRefCount), thread(0), threadId(0),
+ quitNow(false), loopLevel(0), eventDispatcher(0), canWait(true), isAdopted(false)
+{
+ // fprintf(stderr, "QThreadData %p created\n", this);
+}
+
+QThreadData::~QThreadData()
+{
+ Q_ASSERT(_ref == 0);
+
+ // In the odd case that Qt is running on a secondary thread, the main
+ // thread instance will have been dereffed asunder because of the deref in
+ // QThreadData::current() and the deref in the pthread_destroy. To avoid
+ // 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 == QCoreApplicationPrivate::theMainThread) {
+ QCoreApplicationPrivate::theMainThread = 0;
+ }
+
+ QThread *t = thread;
+ thread = 0;
+ delete t;
+
+ for (int i = 0; i < postEventList.size(); ++i) {
+ const QPostEvent &pe = postEventList.at(i);
+ if (pe.event) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ }
+ }
+
+ // fprintf(stderr, "QThreadData %p destroyed\n", this);
+}
+
+void QThreadData::ref()
+{
+#ifndef QT_NO_THREAD
+ (void) _ref.ref();
+ Q_ASSERT(_ref != 0);
+#endif
+}
+
+void QThreadData::deref()
+{
+#ifndef QT_NO_THREAD
+ if (!_ref.deref())
+ delete this;
+#endif
+}
+
+/*
+ QAdoptedThread
+*/
+
+QAdoptedThread::QAdoptedThread(QThreadData *data)
+ : QThread(*new QThreadPrivate(data))
+{
+ // thread should be running and not finished for the lifetime
+ // of the application (even if QCoreApplication goes away)
+#ifndef QT_NO_THREAD
+ d_func()->running = true;
+ d_func()->finished = false;
+ init();
+#endif
+
+ // fprintf(stderr, "new QAdoptedThread = %p\n", this);
+}
+
+QAdoptedThread::~QAdoptedThread()
+{
+ // fprintf(stderr, "~QAdoptedThread = %p\n", this);
+}
+
+QThread *QAdoptedThread::createThreadForAdoption()
+{
+ QScopedPointer<QThread> t(new QAdoptedThread(0));
+ t->moveToThread(t.data());
+ return t.take();
+}
+
+void QAdoptedThread::run()
+{
+ // this function should never be called
+ qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called.");
+}
+#ifndef QT_NO_THREAD
+/*
+ QThreadPrivate
+*/
+
+QThreadPrivate::QThreadPrivate(QThreadData *d)
+ : QObjectPrivate(), running(false), finished(false), terminated(false),
+ isInFinish(false), exited(false), returnCode(-1),
+ stackSize(0), priority(QThread::InheritPriority), data(d)
+{
+#if defined (Q_OS_UNIX)
+ thread_id = 0;
+#elif defined (Q_WS_WIN)
+ handle = 0;
+ id = 0;
+ waiters = 0;
+#endif
+#if defined (Q_WS_WIN) || defined (Q_OS_SYMBIAN)
+ terminationEnabled = true;
+ terminatePending = false;
+#endif
+
+ if (!data)
+ data = new QThreadData;
+}
+
+QThreadPrivate::~QThreadPrivate()
+{
+ data->deref();
+}
+
+/*!
+ \class QThread
+ \brief The QThread class provides platform-independent threads.
+
+ \ingroup thread
+
+ A QThread represents a separate thread of control within the
+ program; it shares data with all the other threads within the
+ process but executes independently in the way that a separate
+ program does on a multitasking operating system. Instead of
+ starting in \c main(), QThreads begin executing in run(). By
+ default, run() starts the event loop by calling exec() (see
+ below). To create your own threads, subclass QThread and
+ reimplement run(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qthread.cpp 0
+
+ This will create a QTcpSocket in the thread and then execute the
+ thread's event loop. Use the start() method to begin execution.
+ Execution ends when you return from run(), just as an application
+ does when it leaves main(). QThread will notifiy you via a signal
+ when the thread is started(), finished(), and terminated(), or
+ you can use isFinished() and isRunning() to query the state of
+ the thread. Use wait() to block until the thread has finished
+ execution.
+
+ Each thread gets its own stack from the operating system. The
+ operating system also determines the default size of the stack.
+ You can use setStackSize() to set a custom stack size.
+
+ Each QThread can have its own event loop. You can start the event
+ loop by calling exec(); you can stop it by calling exit() or
+ quit(). Having an event loop in a thread makes it possible to
+ connect signals from other threads to slots in this thread, using
+ a mechanism called \l{Qt::QueuedConnection}{queued
+ connections}. It also makes it possible to use classes that
+ require the event loop, such as QTimer and QTcpSocket, in the
+ thread. Note, however, that it is not possible to use any widget
+ classes in the thread.
+
+ In extreme cases, you may want to forcibly terminate() an
+ executing thread. However, doing so is dangerous and discouraged.
+ Please read the documentation for terminate() and
+ setTerminationEnabled() for detailed information.
+
+ The static functions currentThreadId() and currentThread() return
+ identifiers for the currently executing thread. The former
+ returns a platform specific ID for the thread; the latter returns
+ a QThread pointer.
+
+ QThread also provides platform independent sleep functions in
+ varying resolutions. Use sleep() for full second resolution,
+ msleep() for millisecond resolution, and usleep() for microsecond
+ resolution.
+
+ \sa {Thread Support in Qt}, QThreadStorage, QMutex, QSemaphore, QWaitCondition,
+ {Mandelbrot Example}, {Semaphores Example}, {Wait Conditions Example}
+*/
+
+/*!
+ \fn Qt::HANDLE QThread::currentThreadId()
+
+ Returns the thread handle of the currently executing thread.
+
+ \warning The handle returned by this function is used for internal
+ purposes and should not be used in any application code.
+
+ \warning On Windows, the returned value is a pseudo-handle for the
+ current thread. It can't be used for numerical comparison. i.e.,
+ this function returns the DWORD (Windows-Thread ID) returned by
+ the Win32 function getCurrentThreadId(), not the HANDLE
+ (Windows-Thread HANDLE) returned by the Win32 function
+ getCurrentThread().
+*/
+
+/*!
+ \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.
+*/
+
+/*!
+ \fn void QThread::yieldCurrentThread()
+
+ Yields execution of the current thread to another runnable thread,
+ if any. Note that the operating system decides to which thread to
+ switch.
+*/
+
+/*!
+ \fn void QThread::start(Priority priority)
+
+ Begins execution of the thread by calling run(), which should be
+ reimplemented in a QThread subclass to contain your code. The
+ operating system will schedule the thread according to the \a
+ priority parameter. If the thread is already running, this
+ function does nothing.
+
+ The effect of the \a priority parameter is dependent on the
+ operating system's scheduling policy. In particular, the \a priority
+ will be ignored on systems that do not support thread priorities
+ (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler
+ for more details).
+
+ \sa run(), terminate()
+*/
+
+/*!
+ \fn void QThread::started()
+
+ This signal is emitted when the thread starts executing.
+
+ \sa finished(), terminated()
+*/
+
+/*!
+ \fn void QThread::finished()
+
+ This signal is emitted when the thread has finished executing.
+
+ \sa started(), terminated()
+*/
+
+/*!
+ \fn void QThread::terminated()
+
+ This signal is emitted when the thread is terminated.
+
+ \sa started(), finished()
+*/
+
+/*!
+ \enum QThread::Priority
+
+ This enum type indicates how the operating system should schedule
+ newly created threads.
+
+ \value IdlePriority scheduled only when no other threads are
+ running.
+
+ \value LowestPriority scheduled less often than LowPriority.
+ \value LowPriority scheduled less often than NormalPriority.
+
+ \value NormalPriority the default priority of the operating
+ system.
+
+ \value HighPriority scheduled more often than NormalPriority.
+ \value HighestPriority scheduled more often than HighPriority.
+
+ \value TimeCriticalPriority scheduled as often as possible.
+
+ \value InheritPriority use the same priority as the creating
+ thread. This is the default.
+*/
+
+/*!
+ Returns a pointer to a QThread which represents the currently
+ executing thread.
+*/
+QThread *QThread::currentThread()
+{
+ QThreadData *data = QThreadData::current();
+ Q_ASSERT(data != 0);
+ return data->thread;
+}
+
+/*!
+ Constructs a new thread with the given \a parent. The thread does
+ not begin executing until start() is called.
+
+ \sa start()
+*/
+QThread::QThread(QObject *parent)
+ : QObject(*(new QThreadPrivate), parent)
+{
+ Q_D(QThread);
+ // fprintf(stderr, "QThreadData %p created for thread %p\n", d->data, this);
+ d->data->thread = this;
+}
+
+/*! \internal
+ */
+QThread::QThread(QThreadPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QThread);
+ // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
+ d->data->thread = this;
+}
+
+/*!
+ Destroys the thread.
+
+ Note that deleting a QThread object will not stop the execution
+ of the thread it represents. Deleting a running QThread (i.e.
+ isFinished() returns false) will probably result in a program
+ crash. You can wait() on a thread to make sure that it has
+ finished.
+*/
+QThread::~QThread()
+{
+ Q_D(QThread);
+ {
+ QMutexLocker locker(&d->mutex);
+ if (d->isInFinish) {
+ locker.unlock();
+ wait();
+ locker.relock();
+ }
+ if (d->running && !d->finished && !d->data->isAdopted)
+ qWarning("QThread: Destroyed while thread is still running");
+
+ d->data->thread = 0;
+ }
+}
+
+/*!
+ Returns true if the thread is finished; otherwise returns false.
+
+ \sa isRunning()
+*/
+bool QThread::isFinished() const
+{
+ Q_D(const QThread);
+ QMutexLocker locker(&d->mutex);
+ return d->finished;
+}
+
+/*!
+ Returns true if the thread is running; otherwise returns false.
+
+ \sa isFinished()
+*/
+bool QThread::isRunning() const
+{
+ Q_D(const QThread);
+ QMutexLocker locker(&d->mutex);
+ return d->running;
+}
+
+/*!
+ 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.
+
+ \warning Most operating systems place minimum and maximum limits
+ on thread stack sizes. The thread will fail to start if the stack
+ size is outside these limits.
+
+ \sa stackSize()
+*/
+void QThread::setStackSize(uint stackSize)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ Q_ASSERT_X(!d->running, "QThread::setStackSize",
+ "cannot change stack size while the thread is running");
+ d->stackSize = stackSize;
+}
+
+/*!
+ Returns the maximum stack size for the thread (if set with
+ setStackSize()); otherwise returns zero.
+
+ \sa setStackSize()
+*/
+uint QThread::stackSize() const
+{
+ Q_D(const QThread);
+ QMutexLocker locker(&d->mutex);
+ return d->stackSize;
+}
+
+/*!
+ 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().
+
+ It is necessary to call this function to start event handling.
+
+ \sa quit(), exit()
+*/
+int QThread::exec()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ d->data->quitNow = false;
+ if (d->exited) {
+ d->exited = false;
+ return d->returnCode;
+ }
+ locker.unlock();
+
+ QEventLoop eventLoop;
+ int returnCode = eventLoop.exec();
+
+ locker.relock();
+ d->exited = false;
+ d->returnCode = -1;
+ return returnCode;
+}
+
+/*!
+ Tells the thread's event loop to exit with a return code.
+
+ After calling this function, the thread leaves the event loop and
+ returns from the call to QEventLoop::exec(). The
+ QEventLoop::exec() function returns \a returnCode.
+
+ By convention, a \a returnCode of 0 means success, any non-zero value
+ indicates an error.
+
+ Note that unlike the C library function of the same name, this
+ function \e does return to the caller -- it is event processing
+ that stops.
+
+ No QEventLoops will be started anymore in this thread until
+ QThread::exec() has been called again. If the eventloop in QThread::exec()
+ is not running then the next call to QThread::exec() will also return
+ immediately.
+
+ \sa quit() QEventLoop
+*/
+void QThread::exit(int returnCode)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ d->exited = true;
+ d->returnCode = returnCode;
+ d->data->quitNow = true;
+ for (int i = 0; i < d->data->eventLoops.size(); ++i) {
+ QEventLoop *eventLoop = d->data->eventLoops.at(i);
+ eventLoop->exit(returnCode);
+ }
+}
+
+/*!
+ Tells the thread's event loop to exit with return code 0 (success).
+ Equivalent to calling QThread::exit(0).
+
+ This function does nothing if the thread does not have an event
+ loop.
+
+ \sa exit() QEventLoop
+*/
+void QThread::quit()
+{ exit(); }
+
+/*!
+ The starting point for the thread. After calling start(), the
+ newly created thread calls this function. The default
+ implementation simply calls exec().
+
+ You can reimplemented this function to do other useful
+ work. Returning from this method will end the execution of the
+ thread.
+
+ \sa start() wait()
+*/
+void QThread::run()
+{
+ (void) exec();
+}
+
+/*! \internal
+ Initializes the QThread system.
+*/
+#if defined (Q_OS_WIN)
+void qt_create_tls();
+#endif
+
+void QThread::initialize()
+{
+ if (qt_global_mutexpool)
+ return;
+ qt_global_mutexpool = QMutexPool::instance();
+
+#if defined (Q_OS_WIN)
+ qt_create_tls();
+#endif
+}
+
+
+/*! \internal
+ Cleans up the QThread system.
+*/
+void QThread::cleanup()
+{
+ qt_global_mutexpool = 0;
+}
+
+/*!
+ \fn bool QThread::finished() const
+
+ Use isFinished() instead.
+*/
+
+/*!
+ \fn bool QThread::running() const
+
+ Use isRunning() instead.
+*/
+
+/*! \fn void QThread::setPriority(Priority priority)
+ \since 4.1
+
+ This function sets the \a priority for a running thread. If the
+ thread is not running, this function does nothing and returns
+ immediately. Use start() to start a thread with a specific
+ priority.
+
+ The \a priority argument can be any value in the \c
+ QThread::Priority enum except for \c InheritPriorty.
+
+ The effect of the \a priority parameter is dependent on the
+ operating system's scheduling policy. In particular, the \a priority
+ will be ignored on systems that do not support thread priorities
+ (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler
+ for more details).
+
+ \sa Priority priority() start()
+*/
+
+/*!
+ \since 4.1
+
+ Returns the priority for a running thread. If the thread is not
+ running, this function returns \c InheritPriority.
+
+ \sa Priority setPriority() start()
+*/
+QThread::Priority QThread::priority() const
+{
+ Q_D(const QThread);
+ QMutexLocker locker(&d->mutex);
+
+ // mask off the high bits that are used for flags
+ return Priority(d->priority & 0xffff);
+}
+
+/*!
+ \fn void QThread::sleep(unsigned long secs)
+
+ Forces the current thread to sleep for \a secs seconds.
+
+ \sa msleep(), usleep()
+*/
+
+/*!
+ \fn void QThread::msleep(unsigned long msecs)
+
+ Causes the current thread to sleep for \a msecs milliseconds.
+
+ \sa sleep(), usleep()
+*/
+
+/*!
+ \fn void QThread::usleep(unsigned long usecs)
+
+ Causes the current thread to sleep for \a usecs microseconds.
+
+ \sa sleep(), msleep()
+*/
+
+/*!
+ \fn void QThread::terminate()
+
+ Terminates the execution of the thread. The thread may or may not
+ be terminated immediately, depending on the operating systems
+ scheduling policies. Use QThread::wait() after terminate() for
+ synchronous termination.
+
+ When the thread is terminated, all threads waiting for the thread
+ to finish will be woken up.
+
+ \warning This function is dangerous and its use is discouraged.
+ The thread can be terminated at any point in its code path.
+ Threads can be terminated while modifying data. There is no
+ chance for the thread to clean up after itself, unlock any held
+ mutexes, etc. In short, use this function only if absolutely
+ necessary.
+
+ Termination can be explicitly enabled or disabled by calling
+ QThread::setTerminationEnabled(). Calling this function while
+ termination is disabled results in the termination being
+ deferred, until termination is re-enabled. See the documentation
+ of QThread::setTerminationEnabled() for more information.
+
+ \sa setTerminationEnabled()
+*/
+
+/*!
+ \fn bool QThread::wait(unsigned long time)
+
+ Blocks the thread until either of these conditions is met:
+
+ \list
+ \o The thread associated with this QThread object has finished
+ execution (i.e. when it returns from \l{run()}). This function
+ will return true if the thread has finished. It also returns
+ true if the thread has not been started yet.
+ \o \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
+ default), then the wait will never timeout (the thread must
+ return from \l{run()}). This function will return false if the
+ wait timed out.
+ \endlist
+
+ This provides similar functionality to the POSIX \c
+ pthread_join() function.
+
+ \sa sleep(), terminate()
+*/
+
+/*!
+ \fn void QThread::setTerminationEnabled(bool enabled)
+
+ Enables or disables termination of the current thread based on the
+ \a enabled parameter. The thread must have been started by
+ QThread.
+
+ When \a enabled is false, termination is disabled. Future calls
+ to QThread::terminate() will return immediately without effect.
+ Instead, the termination is deferred until termination is enabled.
+
+ When \a enabled is true, termination is enabled. Future calls to
+ QThread::terminate() will terminate the thread normally. If
+ termination has been deferred (i.e. QThread::terminate() was
+ called with termination disabled), this function will terminate
+ the calling thread \e immediately. Note that this function will
+ not return in this case.
+
+ \sa terminate()
+*/
+
+#else // QT_NO_THREAD
+
+QThread::QThread(QObject *parent)
+ : QObject(*(new QThreadPrivate), (QObject*)0){
+ Q_D(QThread);
+ d->data->thread = this;
+}
+
+QThread *QThread::currentThread()
+{
+ return QThreadData::current()->thread;
+}
+
+QThreadData* QThreadData::current()
+{
+ static QThreadData *data = 0; // reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
+ if (!data) {
+ QScopedPointer<QThreadData> newdata(new QThreadData);
+ newdata->thread = new QAdoptedThread(newdata.data());
+ data = newdata.take();
+ data->deref();
+ }
+ return data;
+}
+
+/*! \internal
+ */
+QThread::QThread(QThreadPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QThread);
+ // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
+ d->data->thread = this;
+}
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
new file mode 100644
index 0000000000..014a0062fe
--- /dev/null
+++ b/src/corelib/thread/qthread.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREAD_H
+#define QTHREAD_H
+
+#include <QtCore/qobject.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QThreadData;
+class QThreadPrivate;
+
+#ifndef QT_NO_THREAD
+class Q_CORE_EXPORT QThread : public QObject
+{
+public:
+ static Qt::HANDLE currentThreadId();
+ static QThread *currentThread();
+ static int idealThreadCount();
+ static void yieldCurrentThread();
+
+ explicit QThread(QObject *parent = 0);
+ ~QThread();
+
+ enum Priority {
+ IdlePriority,
+
+ LowestPriority,
+ LowPriority,
+ NormalPriority,
+ HighPriority,
+ HighestPriority,
+
+ TimeCriticalPriority,
+
+ InheritPriority
+ };
+
+ void setPriority(Priority priority);
+ Priority priority() const;
+
+ bool isFinished() const;
+ bool isRunning() const;
+
+ void setStackSize(uint stackSize);
+ uint stackSize() const;
+
+ void exit(int retcode = 0);
+
+public Q_SLOTS:
+ void start(Priority = InheritPriority);
+ void terminate();
+ void quit();
+
+public:
+ // default argument causes thread to block indefinately
+ bool wait(unsigned long time = ULONG_MAX);
+
+Q_SIGNALS:
+ void started();
+ void finished();
+ void terminated();
+
+protected:
+ virtual void run();
+ int exec();
+
+ static void setTerminationEnabled(bool enabled = true);
+
+ static void sleep(unsigned long);
+ static void msleep(unsigned long);
+ static void usleep(unsigned long);
+
+#ifdef QT3_SUPPORT
+public:
+ inline QT3_SUPPORT bool finished() const { return isFinished(); }
+ inline QT3_SUPPORT bool running() const { return isRunning(); }
+#endif
+
+protected:
+ QThread(QThreadPrivate &dd, QObject *parent = 0);
+
+private:
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QThread)
+
+ static void initialize();
+ static void cleanup();
+
+ friend class QCoreApplication;
+ friend class QThreadData;
+};
+
+#else // QT_NO_THREAD
+
+class Q_CORE_EXPORT QThread : public QObject
+{
+public:
+ static Qt::HANDLE currentThreadId() { return Qt::HANDLE(currentThread()); }
+ static QThread* currentThread();
+
+protected:
+ QThread(QThreadPrivate &dd, QObject *parent = 0);
+
+private:
+ explicit QThread(QObject *parent = 0);
+ static QThread *instance;
+
+ friend class QCoreApplication;
+ friend class QThreadData;
+ friend class QAdoptedThread;
+ Q_DECLARE_PRIVATE(QThread)
+};
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTHREAD_H
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
new file mode 100644
index 0000000000..b43a456919
--- /dev/null
+++ b/src/corelib/thread/qthread_p.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREAD_P_H
+#define QTHREAD_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 "qplatformdefs.h"
+#include "QtCore/qthread.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qstack.h"
+#include "QtCore/qwaitcondition.h"
+#include "QtCore/qmap.h"
+#include "private/qobject_p.h"
+
+#ifdef Q_OS_SYMBIAN
+#include <e32base.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractEventDispatcher;
+class QEventLoop;
+
+class QPostEvent
+{
+public:
+ QObject *receiver;
+ QEvent *event;
+ int priority;
+ inline QPostEvent()
+ : receiver(0), event(0), priority(0)
+ { }
+ inline QPostEvent(QObject *r, QEvent *e, int p)
+ : receiver(r), event(e), priority(p)
+ { }
+};
+inline bool operator<(int priority, const QPostEvent &pe)
+{
+ return pe.priority < priority;
+}
+inline bool operator<(const QPostEvent &pe, int priority)
+{
+ return priority < pe.priority;
+}
+
+class QPostEventList : public QList<QPostEvent>
+{
+public:
+ // recursion == recursion count for sendPostedEvents()
+ int recursion;
+
+ // sendOffset == the current event to start sending
+ int startOffset;
+ // insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions
+ int insertionOffset;
+
+ QMutex mutex;
+
+ inline QPostEventList()
+ : QList<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0)
+ { }
+};
+
+#ifndef QT_NO_THREAD
+
+class QThreadPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QThread)
+
+public:
+ QThreadPrivate(QThreadData *d = 0);
+ ~QThreadPrivate();
+
+ mutable QMutex mutex;
+
+ bool running;
+ bool finished;
+ bool terminated;
+ bool isInFinish; //when in QThreadPrivate::finish
+
+ bool exited;
+ int returnCode;
+
+ uint stackSize;
+ QThread::Priority priority;
+
+ static QThread *threadForId(int id);
+
+#ifdef Q_OS_UNIX
+ pthread_t thread_id;
+ QWaitCondition thread_done;
+
+ static void *start(void *arg);
+#if defined(Q_OS_SYMBIAN)
+ static void finish(void *arg, bool lockAnyway=true, bool closeNativeHandle=true);
+#else
+ static void finish(void *);
+#endif
+
+#endif // Q_OS_UNIX
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ HANDLE handle;
+ unsigned int id;
+ int waiters;
+
+ static unsigned int __stdcall start(void *);
+ static void finish(void *, bool lockAnyway=true);
+#endif // Q_OS_WIN32
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined (Q_OS_SYMBIAN)
+ bool terminationEnabled, terminatePending;
+# endif
+ QThreadData *data;
+
+ static void createEventDispatcher(QThreadData *data);
+};
+
+#else // QT_NO_THREAD
+
+class QThreadPrivate : public QObjectPrivate
+{
+public:
+ QThreadPrivate(QThreadData *d = 0) : data(d ? d : new QThreadData) {}
+ ~QThreadPrivate() { delete data; }
+
+ QThreadData *data;
+
+ static void setCurrentThread(QThread*) {}
+ static QThread *threadForId(int) { return QThread::currentThread(); }
+ static void createEventDispatcher(QThreadData *data);
+
+ Q_DECLARE_PUBLIC(QThread)
+};
+
+#endif // QT_NO_THREAD
+
+class QThreadData
+{
+ QAtomicInt _ref;
+
+public:
+ QThreadData(int initialRefCount = 1);
+ ~QThreadData();
+
+ static QThreadData *current();
+ static QThreadData *get2(QThread *thread)
+ { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
+
+
+ void ref();
+ void deref();
+
+ QThread *thread;
+ Qt::HANDLE threadId;
+ bool quitNow;
+ int loopLevel;
+ QAbstractEventDispatcher *eventDispatcher;
+ QStack<QEventLoop *> eventLoops;
+ QPostEventList postEventList;
+ bool canWait;
+ QVector<void *> tls;
+ bool isAdopted;
+
+# ifdef Q_OS_SYMBIAN
+ RThread symbian_thread_handle;
+# endif
+};
+
+// thread wrapper for the main() thread
+class QAdoptedThread : public QThread
+{
+ Q_DECLARE_PRIVATE(QThread)
+
+public:
+ QAdoptedThread(QThreadData *data = 0);
+ ~QAdoptedThread();
+ void init();
+
+ static QThread *createThreadForAdoption();
+private:
+ void run();
+};
+
+QT_END_NAMESPACE
+
+#endif // QTHREAD_P_H
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp
new file mode 100644
index 0000000000..5d8b5cbf0d
--- /dev/null
+++ b/src/corelib/thread/qthread_symbian.cpp
@@ -0,0 +1,609 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthread.h"
+#include "qplatformdefs.h"
+#include <private/qcoreapplication_p.h>
+#include <private/qeventdispatcher_symbian_p.h>
+#include "qthreadstorage.h"
+#include "qthread_p.h"
+#include <private/qsystemerror_p.h>
+
+#include <sched.h>
+#include <hal.h>
+#include <hal_data.h>
+
+// You only find these enumerations on Symbian^3 onwards, so we need to provide our own
+// to remain compatible with older releases. They won't be called by pre-Sym^3 SDKs.
+
+// HALData::ENumCpus
+#define QT_HALData_ENumCpus 119
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_THREAD
+
+enum { ThreadPriorityResetFlag = 0x80000000 };
+
+// Utility functions for getting, setting and clearing thread specific data.
+static QThreadData *get_thread_data()
+{
+ return reinterpret_cast<QThreadData *>(Dll::Tls());
+}
+
+static void set_thread_data(QThreadData *data)
+{
+ qt_symbian_throwIfError(Dll::SetTls(data));
+}
+
+static void clear_thread_data()
+{
+ Dll::FreeTls();
+}
+
+
+static void init_symbian_thread_handle(RThread &thread)
+{
+ thread = RThread();
+ TThreadId threadId = thread.Id();
+ qt_symbian_throwIfError(thread.Open(threadId, EOwnerProcess));
+}
+
+QThreadData *QThreadData::current()
+{
+ QThreadData *data = get_thread_data();
+ if (!data) {
+ void *a;
+ if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
+ QThread *adopted = static_cast<QThread*>(a);
+ Q_ASSERT(adopted);
+ data = QThreadData::get2(adopted);
+ set_thread_data(data);
+ adopted->d_func()->running = true;
+ adopted->d_func()->finished = false;
+ static_cast<QAdoptedThread *>(adopted)->init();
+ } else {
+ data = new QThreadData;
+ QT_TRY {
+ set_thread_data(data);
+ data->thread = new QAdoptedThread(data);
+ } QT_CATCH(...) {
+ clear_thread_data();
+ data->deref();
+ data = 0;
+ QT_RETHROW;
+ }
+ data->deref();
+ }
+ data->isAdopted = true;
+ data->threadId = QThread::currentThreadId();
+ if (!QCoreApplicationPrivate::theMainThread)
+ QCoreApplicationPrivate::theMainThread = data->thread;
+ }
+ return data;
+}
+
+
+class QCAdoptedThreadMonitor : public CActive
+{
+public:
+ QCAdoptedThreadMonitor(QThread *thread)
+ : CActive(EPriorityStandard), data(QThreadData::get2(thread))
+ {
+ CActiveScheduler::Add(this);
+ data->symbian_thread_handle.Logon(iStatus);
+ SetActive();
+ }
+ ~QCAdoptedThreadMonitor()
+ {
+ Cancel();
+ }
+ void DoCancel()
+ {
+ data->symbian_thread_handle.LogonCancel(iStatus);
+ }
+ void RunL();
+private:
+ QThreadData* data;
+};
+
+class QCAddAdoptedThread : public CActive
+{
+public:
+ QCAddAdoptedThread()
+ : CActive(EPriorityStandard)
+ {
+ CActiveScheduler::Add(this);
+ }
+ void ConstructL()
+ {
+ User::LeaveIfError(monitorThread.Open(RThread().Id()));
+ start();
+ }
+ ~QCAddAdoptedThread()
+ {
+ Cancel();
+ monitorThread.Close();
+ }
+ void DoCancel()
+ {
+ User::RequestComplete(stat, KErrCancel);
+ }
+ void start()
+ {
+ iStatus = KRequestPending;
+ SetActive();
+ stat = &iStatus;
+ }
+ void RunL()
+ {
+ if (iStatus.Int() != KErrNone)
+ return;
+
+ QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex);
+ for (int i=threadsToAdd.size()-1; i>=0; i--) {
+ // Create an active object to monitor the thread
+ new (ELeave) QCAdoptedThreadMonitor(threadsToAdd[i]);
+ count++;
+ threadsToAdd.pop_back();
+ }
+ start();
+ }
+ static void add(QThread *thread)
+ {
+ QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex);
+ if (!adoptedThreadAdder) {
+ RThread monitorThread;
+ qt_symbian_throwIfError(monitorThread.Create(KNullDesC(), &monitorThreadFunc, 1024, &User::Allocator(), 0));
+ TRequestStatus started;
+ monitorThread.Rendezvous(started);
+ monitorThread.Resume();
+ User::WaitForRequest(started);
+ monitorThread.Close();
+ }
+ if (RThread().Id() == adoptedThreadAdder->monitorThread.Id())
+ return;
+ adoptedThreadAdder->threadsToAdd.push_back(thread);
+ if (adoptedThreadAdder->stat) {
+ adoptedThreadAdder->monitorThread.RequestComplete(adoptedThreadAdder->stat, KErrNone);
+ }
+ }
+ static void monitorThreadFuncL()
+ {
+ CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ adoptedThreadAdder = new(ELeave) QCAddAdoptedThread();
+ CleanupStack::PushL(adoptedThreadAdder);
+ adoptedThreadAdder->ConstructL();
+ QCAddAdoptedThread *adder = adoptedThreadAdder;
+
+ RThread::Rendezvous(KErrNone);
+ CActiveScheduler::Start();
+
+ CleanupStack::PopAndDestroy(adder);
+ CleanupStack::PopAndDestroy(scheduler);
+ }
+ static int monitorThreadFunc(void *)
+ {
+ _LIT(KMonitorThreadName, "adoptedMonitorThread");
+ RThread::RenameMe(KMonitorThreadName());
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ TRAPD(ret, monitorThreadFuncL());
+ delete cleanup;
+ return ret;
+ }
+ static void threadDied()
+ {
+ QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex);
+ if (adoptedThreadAdder) {
+ adoptedThreadAdder->count--;
+ if (adoptedThreadAdder->count <= 0 && adoptedThreadAdder->threadsToAdd.size() == 0) {
+ CActiveScheduler::Stop();
+ adoptedThreadAdder = 0;
+ }
+ }
+ }
+
+private:
+ QVector<QThread*> threadsToAdd;
+ RThread monitorThread;
+ static QMutex adoptedThreadMonitorMutex;
+ static QCAddAdoptedThread *adoptedThreadAdder;
+ int count;
+ TRequestStatus *stat;
+};
+
+QMutex QCAddAdoptedThread::adoptedThreadMonitorMutex;
+QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0;
+
+void QCAdoptedThreadMonitor::RunL()
+{
+ if (data->isAdopted) {
+ QThread *thread = data->thread;
+ Q_ASSERT(thread);
+ QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_ASSERT(!thread_p->finished);
+ thread_p->finish(thread);
+ }
+ data->deref();
+ QCAddAdoptedThread::threadDied();
+ delete this;
+}
+
+void QAdoptedThread::init()
+{
+ Q_D(QThread);
+ d->thread_id = RThread().Id(); // type operator to TUint
+ init_symbian_thread_handle(d->data->symbian_thread_handle);
+ QCAddAdoptedThread::add(this);
+}
+
+/*
+ QThreadPrivate
+*/
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+typedef void*(*QtThreadCallback)(void*);
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+#endif // QT_NO_THREAD
+
+void QThreadPrivate::createEventDispatcher(QThreadData *data)
+{
+ data->eventDispatcher = new QEventDispatcherSymbian;
+ data->eventDispatcher->startingUp();
+}
+
+#ifndef QT_NO_THREAD
+
+void *QThreadPrivate::start(void *arg)
+{
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadData *data = QThreadData::get2(thr);
+
+ // do we need to reset the thread priority?
+ if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
+ thr->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
+ }
+
+ // On symbian, threads other than the main thread are non critical by default
+ // This means a worker thread can crash without crashing the application - to
+ // use this feature, we would need to use RThread::Logon in the main thread
+ // to catch abnormal thread exit and emit the finished signal.
+ // For the sake of cross platform consistency, we set the thread as process critical
+ // - advanced users who want the symbian behaviour can change the critical
+ // attribute of the thread again once the app gains control in run()
+ User::SetCritical(User::EProcessCritical);
+
+ data->threadId = QThread::currentThreadId();
+ set_thread_data(data);
+
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
+ data->quitNow = thr->d_func()->exited;
+ }
+
+ // ### TODO: allow the user to create a custom event dispatcher
+ createEventDispatcher(data);
+
+ emit thr->started();
+ thr->run();
+
+ QThreadPrivate::finish(arg);
+
+ return 0;
+}
+
+void QThreadPrivate::finish(void *arg, bool lockAnyway, bool closeNativeHandle)
+{
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadPrivate *d = thr->d_func();
+
+ QMutexLocker locker(lockAnyway ? &d->mutex : 0);
+
+ d->isInFinish = true;
+ d->priority = QThread::InheritPriority;
+ bool terminated = d->terminated;
+ void *data = &d->data->tls;
+ locker.unlock();
+ if (terminated)
+ emit thr->terminated();
+ emit thr->finished();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish((void **)data);
+ locker.relock();
+ d->terminated = false;
+
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ if (eventDispatcher) {
+ d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ d->thread_id = 0;
+ if (closeNativeHandle)
+ d->data->symbian_thread_handle.Close();
+ d->running = false;
+ d->finished = true;
+
+ d->isInFinish = false;
+ d->thread_done.wakeAll();
+}
+
+
+
+
+/**************************************************************************
+ ** QThread
+ *************************************************************************/
+
+Qt::HANDLE QThread::currentThreadId()
+{
+ return (Qt::HANDLE) (TUint) RThread().Id();
+}
+
+int QThread::idealThreadCount()
+{
+ int cores = 1;
+
+ if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) {
+ TInt inumcpus;
+ TInt err;
+ err = HAL::Get((HALData::TAttribute)QT_HALData_ENumCpus, inumcpus);
+ if (err == KErrNone) {
+ cores = qMax(inumcpus, 1);
+ }
+ }
+
+ return cores;
+}
+
+void QThread::yieldCurrentThread()
+{
+ sched_yield();
+}
+
+/* \internal
+ helper function to do thread sleeps
+*/
+static void thread_sleep(unsigned long remaining, unsigned long scale)
+{
+ // maximum Symbian wait is 2^31 microseconds
+ unsigned long maxWait = KMaxTInt / scale;
+ do {
+ unsigned long waitTime = qMin(maxWait, remaining);
+ remaining -= waitTime;
+ User::AfterHighRes(waitTime * scale);
+ } while (remaining);
+}
+
+void QThread::sleep(unsigned long secs)
+{
+ thread_sleep(secs, 1000000ul);
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ thread_sleep(msecs, 1000ul);
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ thread_sleep(usecs, 1ul);
+}
+
+TThreadPriority calculateSymbianPriority(QThread::Priority priority)
+ {
+ // Both Qt & Symbian use limited enums; this matches the mapping previously done through conversion to Posix granularity
+ TThreadPriority symPriority;
+ switch (priority)
+ {
+ case QThread::IdlePriority:
+ symPriority = EPriorityMuchLess;
+ break;
+ case QThread::LowestPriority:
+ case QThread::LowPriority:
+ symPriority = EPriorityLess;
+ break;
+ case QThread::NormalPriority:
+ symPriority = EPriorityNormal;
+ break;
+ case QThread::HighPriority:
+ symPriority = EPriorityMore;
+ break;
+ case QThread::HighestPriority:
+ case QThread::TimeCriticalPriority:
+ symPriority = EPriorityMuchMore;
+ break;
+ case QThread::InheritPriority:
+ default:
+ symPriority = RThread().Priority();
+ break;
+ }
+ return symPriority;
+ }
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->isInFinish)
+ d->thread_done.wait(locker.mutex());
+
+ if (d->running)
+ return;
+
+ d->running = true;
+ d->finished = false;
+ d->terminated = false;
+ d->returnCode = 0;
+ d->exited = false;
+
+ d->priority = priority;
+
+ if (d->stackSize == 0)
+ // The default stack size on Symbian is very small, making even basic
+ // operations like file I/O fail, so we increase it by default.
+ d->stackSize = 0x14000; // Maximum stack size on Symbian.
+
+ int code = d->data->symbian_thread_handle.Create(KNullDesC, (TThreadFunction) QThreadPrivate::start, d->stackSize, NULL, this);
+ if (code == KErrNone) {
+ d->thread_id = d->data->symbian_thread_handle.Id();
+ TThreadPriority symPriority = calculateSymbianPriority(priority);
+ d->data->symbian_thread_handle.SetPriority(symPriority);
+ d->data->symbian_thread_handle.Resume();
+ } else {
+ qWarning("QThread::start: Thread creation error: %s", qPrintable(QSystemError(code, QSystemError::NativeError).toString()));
+
+ d->running = false;
+ d->finished = false;
+ d->thread_id = 0;
+ d->data->symbian_thread_handle.Close();
+ }
+}
+
+void QThread::terminate()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (!d->thread_id)
+ return;
+
+ if (!d->running)
+ return;
+ if (!d->terminationEnabled) {
+ d->terminatePending = true;
+ return;
+ }
+
+ d->terminated = true;
+ // "false, false" meaning:
+ // 1. lockAnyway = false. Don't lock the mutex because it's already locked
+ // (see above).
+ // 2. closeNativeSymbianHandle = false. We don't want to close the thread handle,
+ // because we need it here to terminate the thread.
+ QThreadPrivate::finish(this, false, false);
+ d->data->symbian_thread_handle.Terminate(KErrNone);
+ d->data->symbian_thread_handle.Close();
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->thread_id == (TUint) RThread().Id()) {
+ qWarning("QThread::wait: Thread tried to wait on itself");
+ return false;
+ }
+
+ if (d->finished || !d->running)
+ return true;
+
+ while (d->running) {
+ // Check if thread still exists. Needed because kernel will kill it without notification
+ // before global statics are deleted at application exit.
+ if (d->data->symbian_thread_handle.Handle()
+ && d->data->symbian_thread_handle.ExitType() != EExitPending) {
+ // Cannot call finish here as wait is typically called from another thread.
+ // It won't be necessary anyway, as we should never get here under normal operations;
+ // all QThreads are EProcessCritical and therefore cannot normally exit
+ // undetected (i.e. panic) as long as all thread control is via QThread.
+ return true;
+ }
+ if (!d->thread_done.wait(locker.mutex(), time))
+ return false;
+ }
+ return true;
+}
+
+void QThread::setTerminationEnabled(bool enabled)
+{
+ QThread *thr = currentThread();
+ Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
+ "Current thread was not started with QThread.");
+ QThreadPrivate *d = thr->d_func();
+ QMutexLocker locker(&d->mutex);
+ d->terminationEnabled = enabled;
+ if (enabled && d->terminatePending) {
+ d->terminated = true;
+ // "false" meaning:
+ // - lockAnyway = false. Don't lock the mutex because it's already locked
+ // (see above).
+ QThreadPrivate::finish(thr, false);
+ locker.unlock(); // don't leave the mutex locked!
+ User::Exit(0); // may be some other cleanup required? what if AS or cleanup stack?
+ }
+}
+
+void QThread::setPriority(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running) {
+ qWarning("QThread::setPriority: Cannot set priority, thread is not running");
+ return;
+ }
+
+ d->priority = priority;
+
+ // copied from start() with a few modifications:
+ TThreadPriority symPriority = calculateSymbianPriority(priority);
+ d->data->symbian_thread_handle.SetPriority(symPriority);
+}
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
new file mode 100644
index 0000000000..044eb05913
--- /dev/null
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -0,0 +1,716 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthread.h"
+
+#include "qplatformdefs.h"
+
+#include <private/qcoreapplication_p.h>
+#if !defined(QT_NO_GLIB)
+# include "../kernel/qeventdispatcher_glib_p.h"
+#endif
+
+#include <private/qeventdispatcher_unix_p.h>
+
+#include "qthreadstorage.h"
+
+#include "qthread_p.h"
+
+#include "qdebug.h"
+
+#include <sched.h>
+#include <errno.h>
+
+#ifdef 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))
+# include <vxCpuLib.h>
+# include <cpuset.h>
+# define QT_VXWORKS_HAS_CPUSET
+# endif
+#endif
+
+#ifdef Q_OS_HPUX
+#include <sys/pstat.h>
+#endif
+
+#if defined(Q_OS_MAC)
+# ifdef qDebug
+# define old_qDebug qDebug
+# undef qDebug
+# endif
+#ifndef QT_NO_CORESERVICES
+# include <CoreServices/CoreServices.h>
+#endif //QT_NO_CORESERVICES
+
+# ifdef old_qDebug
+# undef qDebug
+# define qDebug QT_NO_QDEBUG_MACRO
+# undef old_qDebug
+# endif
+#endif
+
+#if defined(Q_OS_LINUX) && !defined(SCHED_IDLE)
+// from linux/sched.h
+# define SCHED_IDLE 5
+#endif
+
+#if defined(Q_OS_DARWIN) || !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)
+#define QT_HAS_THREAD_PRIORITY_SCHEDULING
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_THREAD
+
+enum { ThreadPriorityResetFlag = 0x80000000 };
+
+#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL))
+#define HAVE_TLS
+#endif
+#if defined(Q_CC_XLC) || defined (Q_CC_SUN)
+#define HAVE_TLS
+#endif
+
+#ifdef HAVE_TLS
+static __thread QThreadData *currentThreadData = 0;
+#endif
+
+static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
+static pthread_key_t current_thread_data_key;
+
+static void destroy_current_thread_data(void *p)
+{
+#if defined(Q_OS_VXWORKS)
+ // Calling setspecific(..., 0) sets the value to 0 for ALL threads.
+ // The 'set to 1' workaround adds a bit of an overhead though,
+ // since this function is called twice now.
+ if (p == (void *)1)
+ return;
+#endif
+ // POSIX says the value in our key is set to zero before calling
+ // this destructor function, so we need to set it back to the
+ // right value...
+ pthread_setspecific(current_thread_data_key, p);
+ QThreadData *data = static_cast<QThreadData *>(p);
+ if (data->isAdopted) {
+ QThread *thread = data->thread;
+ 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
+ // called again (POSIX allows implementations to call destructor
+ // functions repeatedly until all values are zero)
+ pthread_setspecific(current_thread_data_key,
+#if defined(Q_OS_VXWORKS)
+ (void *)1);
+#else
+ 0);
+#endif
+}
+
+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);
+}
+Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
+
+
+// Utility functions for getting, setting and clearing thread specific data.
+static QThreadData *get_thread_data()
+{
+#ifdef HAVE_TLS
+ return currentThreadData;
+#else
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
+#endif
+}
+
+static void set_thread_data(QThreadData *data)
+{
+#ifdef HAVE_TLS
+ currentThreadData = data;
+#endif
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ pthread_setspecific(current_thread_data_key, data);
+}
+
+static void clear_thread_data()
+{
+#ifdef HAVE_TLS
+ currentThreadData = 0;
+#endif
+ pthread_setspecific(current_thread_data_key, 0);
+}
+
+QThreadData *QThreadData::current()
+{
+ QThreadData *data = get_thread_data();
+ if (!data) {
+ void *a;
+ if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
+ QThread *adopted = static_cast<QThread*>(a);
+ Q_ASSERT(adopted);
+ data = QThreadData::get2(adopted);
+ set_thread_data(data);
+ adopted->d_func()->running = true;
+ adopted->d_func()->finished = false;
+ static_cast<QAdoptedThread *>(adopted)->init();
+ } else {
+ data = new QThreadData;
+ QT_TRY {
+ set_thread_data(data);
+ data->thread = new QAdoptedThread(data);
+ } QT_CATCH(...) {
+ clear_thread_data();
+ data->deref();
+ data = 0;
+ QT_RETHROW;
+ }
+ data->deref();
+ }
+ data->isAdopted = true;
+ data->threadId = (Qt::HANDLE)pthread_self();
+ if (!QCoreApplicationPrivate::theMainThread)
+ QCoreApplicationPrivate::theMainThread = data->thread;
+ }
+ return data;
+}
+
+
+void QAdoptedThread::init()
+{
+ Q_D(QThread);
+ d->thread_id = pthread_self();
+}
+
+/*
+ QThreadPrivate
+*/
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+typedef void*(*QtThreadCallback)(void*);
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+#endif // QT_NO_THREAD
+
+void QThreadPrivate::createEventDispatcher(QThreadData *data)
+{
+#if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty()
+ && qgetenv("QT_NO_THREADED_GLIB").isEmpty()
+ && QEventDispatcherGlib::versionSupported())
+ data->eventDispatcher = new QEventDispatcherGlib;
+ else
+#endif
+ data->eventDispatcher = new QEventDispatcherUNIX;
+ data->eventDispatcher->startingUp();
+}
+
+#ifndef QT_NO_THREAD
+
+void *QThreadPrivate::start(void *arg)
+{
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ pthread_cleanup_push(QThreadPrivate::finish, arg);
+
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadData *data = QThreadData::get2(thr);
+
+ // do we need to reset the thread priority?
+ if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
+ thr->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
+ }
+
+ data->threadId = (Qt::HANDLE)pthread_self();
+ set_thread_data(data);
+
+ data->ref();
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
+ data->quitNow = thr->d_func()->exited;
+ }
+
+ // ### TODO: allow the user to create a custom event dispatcher
+ createEventDispatcher(data);
+
+ emit thr->started();
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_testcancel();
+ thr->run();
+
+ pthread_cleanup_pop(1);
+
+ return 0;
+}
+
+void QThreadPrivate::finish(void *arg)
+{
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadPrivate *d = thr->d_func();
+
+ QMutexLocker locker(&d->mutex);
+
+ d->isInFinish = true;
+ d->priority = QThread::InheritPriority;
+ bool terminated = d->terminated;
+ void *data = &d->data->tls;
+ locker.unlock();
+ if (terminated)
+ emit thr->terminated();
+ emit thr->finished();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish((void **)data);
+ locker.relock();
+ d->terminated = false;
+
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ if (eventDispatcher) {
+ d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ d->thread_id = 0;
+ d->running = false;
+ d->finished = true;
+
+ d->isInFinish = false;
+ d->thread_done.wakeAll();
+}
+
+
+
+
+/**************************************************************************
+ ** QThread
+ *************************************************************************/
+
+Qt::HANDLE QThread::currentThreadId()
+{
+ // requires a C cast here otherwise we run into trouble on AIX
+ return (Qt::HANDLE)pthread_self();
+}
+
+#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
+// LSB doesn't define _SC_NPROCESSORS_ONLN.
+# define _SC_NPROCESSORS_ONLN 84
+#endif
+
+int QThread::idealThreadCount()
+{
+ int cores = -1;
+
+#if defined(Q_OS_MAC) && !defined(Q_WS_QPA)
+ // Mac OS X
+ cores = MPProcessorsScheduled();
+#elif defined(Q_OS_HPUX)
+ // HP-UX
+ struct pst_dynamic psd;
+ if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1) {
+ perror("pstat_getdynamic");
+ cores = -1;
+ } else {
+ cores = (int)psd.psd_proc_cnt;
+ }
+#elif defined(Q_OS_BSD4)
+ // FreeBSD, OpenBSD, NetBSD, BSD/OS
+ size_t len = sizeof(cores);
+ int mib[2];
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) {
+ perror("sysctl");
+ cores = -1;
+ }
+#elif defined(Q_OS_IRIX)
+ // IRIX
+ cores = (int)sysconf(_SC_NPROC_ONLN);
+#elif defined(Q_OS_INTEGRITY)
+ // as of aug 2008 Integrity only supports one single core CPU
+ cores = 1;
+#elif defined(Q_OS_VXWORKS)
+ // VxWorks
+# if defined(QT_VXWORKS_HAS_CPUSET)
+ cpuset_t cpus = vxCpuEnabledGet();
+ cores = 0;
+
+ // 128 cores should be enough for everyone ;)
+ for (int i = 0; i < 128 && !CPUSET_ISZERO(cpus); ++i) {
+ if (CPUSET_ISSET(cpus, i)) {
+ CPUSET_CLR(cpus, i);
+ cores++;
+ }
+ }
+# else
+ // as of aug 2008 VxWorks < 6.6 only supports one single core CPU
+ cores = 1;
+# endif
+#else
+ // the rest: Linux, Solaris, AIX, Tru64
+ cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+
+ return cores;
+}
+
+void QThread::yieldCurrentThread()
+{
+ sched_yield();
+}
+
+/* \internal
+ helper function to do thread sleeps, since usleep()/nanosleep()
+ aren't reliable enough (in terms of behavior and availability)
+*/
+static void thread_sleep(struct timespec *ti)
+{
+ pthread_mutex_t mtx;
+ pthread_cond_t cnd;
+
+ pthread_mutex_init(&mtx, 0);
+ pthread_cond_init(&cnd, 0);
+
+ pthread_mutex_lock(&mtx);
+ (void) pthread_cond_timedwait(&cnd, &mtx, ti);
+ pthread_mutex_unlock(&mtx);
+
+ pthread_cond_destroy(&cnd);
+ pthread_mutex_destroy(&mtx);
+}
+
+void QThread::sleep(unsigned long secs)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ struct timespec ti;
+ ti.tv_sec = tv.tv_sec + secs;
+ ti.tv_nsec = (tv.tv_usec * 1000);
+ thread_sleep(&ti);
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ struct timespec ti;
+
+ ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000;
+ ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000);
+ ti.tv_nsec %= 1000000000;
+ thread_sleep(&ti);
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ struct timespec ti;
+
+ ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000;
+ ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000);
+ ti.tv_nsec %= 1000000000;
+ thread_sleep(&ti);
+}
+
+#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
+// Does some magic and calculate the Unix scheduler priorities
+// sched_policy is IN/OUT: it must be set to a valid policy before calling this function
+// sched_priority is OUT only
+static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
+{
+#ifdef SCHED_IDLE
+ if (priority == QThread::IdlePriority) {
+ *sched_policy = SCHED_IDLE;
+ *sched_priority = 0;
+ return true;
+ }
+ const int lowestPriority = QThread::LowestPriority;
+#else
+ const int lowestPriority = QThread::IdlePriority;
+#endif
+ const int highestPriority = QThread::TimeCriticalPriority;
+
+ int prio_min = sched_get_priority_min(*sched_policy);
+ int prio_max = sched_get_priority_max(*sched_policy);
+ if (prio_min == -1 || prio_max == -1)
+ return false;
+
+ int prio;
+ // crudely scale our priority enum values to the prio_min/prio_max
+ prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
+ prio = qMax(prio_min, qMin(prio_max, prio));
+
+ *sched_priority = prio;
+ return true;
+}
+#endif
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->isInFinish)
+ d->thread_done.wait(locker.mutex());
+
+ if (d->running)
+ return;
+
+ d->running = true;
+ d->finished = false;
+ d->terminated = false;
+ d->returnCode = 0;
+ d->exited = false;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ d->priority = priority;
+
+#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
+ switch (priority) {
+ case InheritPriority:
+ {
+ pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+ break;
+ }
+
+ default:
+ {
+ int sched_policy;
+ if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
+ // failed to get the scheduling policy, don't bother
+ // setting the priority
+ qWarning("QThread::start: Cannot determine default scheduler policy");
+ break;
+ }
+
+ int prio;
+ if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
+ // failed to get the scheduling parameters, don't
+ // bother setting the priority
+ qWarning("QThread::start: Cannot determine scheduler priority range");
+ break;
+ }
+
+ sched_param sp;
+ sp.sched_priority = prio;
+
+ if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
+ || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
+ || pthread_attr_setschedparam(&attr, &sp) != 0) {
+ // 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);
+ }
+ break;
+ }
+ }
+#endif // QT_HAS_THREAD_PRIORITY_SCHEDULING
+
+
+ if (d->stackSize > 0) {
+#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
+ int code = pthread_attr_setstacksize(&attr, d->stackSize);
+#else
+ int code = ENOSYS; // stack size not supported, automatically fail
+#endif // _POSIX_THREAD_ATTR_STACKSIZE
+
+ if (code) {
+ qWarning("QThread::start: Thread stack size error: %s",
+ qPrintable(qt_error_string(code)));
+
+ // we failed to set the stacksize, and as the documentation states,
+ // the thread will fail to run...
+ d->running = false;
+ d->finished = false;
+ return;
+ }
+ }
+
+ int code =
+ pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
+ if (code == EPERM) {
+ // caller does not have permission to set the scheduling
+ // parameters/policy
+ pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+ code =
+ pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
+ }
+
+ pthread_attr_destroy(&attr);
+
+ if (code) {
+ qWarning("QThread::start: Thread creation error: %s", qPrintable(qt_error_string(code)));
+
+ d->running = false;
+ d->finished = false;
+ d->thread_id = 0;
+ }
+}
+
+void QThread::terminate()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (!d->thread_id)
+ return;
+
+ int code = pthread_cancel(d->thread_id);
+ if (code) {
+ qWarning("QThread::start: Thread termination error: %s",
+ qPrintable(qt_error_string((code))));
+ } else {
+ d->terminated = true;
+ }
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->thread_id == pthread_self()) {
+ qWarning("QThread::wait: Thread tried to wait on itself");
+ return false;
+ }
+
+ if (d->finished || !d->running)
+ return true;
+
+ while (d->running) {
+ if (!d->thread_done.wait(locker.mutex(), time))
+ return false;
+ }
+ return true;
+}
+
+void QThread::setTerminationEnabled(bool enabled)
+{
+ QThread *thr = currentThread();
+ Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
+ "Current thread was not started with QThread.");
+
+ Q_UNUSED(thr)
+ pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL);
+ if (enabled)
+ pthread_testcancel();
+}
+
+void QThread::setPriority(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running) {
+ qWarning("QThread::setPriority: Cannot set priority, thread is not running");
+ return;
+ }
+
+ d->priority = priority;
+
+ // copied from start() with a few modifications:
+
+#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
+ int sched_policy;
+ sched_param param;
+
+ if (pthread_getschedparam(d->thread_id, &sched_policy, &param) != 0) {
+ // failed to get the scheduling policy, don't bother setting
+ // the priority
+ qWarning("QThread::setPriority: Cannot get scheduler parameters");
+ return;
+ }
+
+ int prio;
+ if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
+ // failed to get the scheduling parameters, don't
+ // bother setting the priority
+ qWarning("QThread::setPriority: Cannot determine scheduler priority range");
+ return;
+ }
+
+ param.sched_priority = prio;
+ int status = pthread_setschedparam(d->thread_id, sched_policy, &param);
+
+# ifdef SCHED_IDLE
+ // were we trying to set to idle priority and failed?
+ if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
+ // reset to lowest priority possible
+ pthread_getschedparam(d->thread_id, &sched_policy, &param);
+ param.sched_priority = sched_get_priority_min(sched_policy);
+ pthread_setschedparam(d->thread_id, sched_policy, &param);
+ }
+# else
+ Q_UNUSED(status);
+# endif // SCHED_IDLE
+#endif
+}
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
new file mode 100644
index 0000000000..bab6cf85de
--- /dev/null
+++ b/src/corelib/thread/qthread_win.cpp
@@ -0,0 +1,637 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define WINVER 0x0500
+#if _WIN32_WINNT < 0x0400
+#define _WIN32_WINNT 0x0400
+#endif
+
+
+#include "qthread.h"
+#include "qthread_p.h"
+#include "qthreadstorage.h"
+#include "qmutex.h"
+
+#include <qcoreapplication.h>
+#include <qpointer.h>
+
+#include <private/qcoreapplication_p.h>
+#include <private/qeventdispatcher_win_p.h>
+
+#include <qt_windows.h>
+
+
+#ifndef Q_OS_WINCE
+#ifndef _MT
+#define _MT
+#endif
+#include <process.h>
+#else
+#include "qfunctions_wince.h"
+#endif
+
+#ifndef QT_NO_THREAD
+QT_BEGIN_NAMESPACE
+
+void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread);
+void qt_adopted_thread_watcher_function(void *);
+
+static DWORD qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
+void qt_create_tls()
+{
+ if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
+ return;
+ static QMutex mutex;
+ QMutexLocker locker(&mutex);
+ qt_current_thread_data_tls_index = TlsAlloc();
+}
+
+static void qt_free_tls()
+{
+ if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES) {
+ TlsFree(qt_current_thread_data_tls_index);
+ qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
+ }
+}
+Q_DESTRUCTOR_FUNCTION(qt_free_tls)
+
+/*
+ QThreadData
+*/
+QThreadData *QThreadData::current()
+{
+ qt_create_tls();
+ QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
+ if (!threadData) {
+ QThread *adopted = 0;
+ if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, (void **) &adopted)) {
+ Q_ASSERT(adopted);
+ threadData = QThreadData::get2(adopted);
+ TlsSetValue(qt_current_thread_data_tls_index, threadData);
+ adopted->d_func()->running = true;
+ adopted->d_func()->finished = false;
+ static_cast<QAdoptedThread *>(adopted)->init();
+ } else {
+ threadData = new QThreadData;
+ // This needs to be called prior to new AdoptedThread() to
+ // avoid recursion.
+ TlsSetValue(qt_current_thread_data_tls_index, threadData);
+ QT_TRY {
+ threadData->thread = new QAdoptedThread(threadData);
+ } QT_CATCH(...) {
+ TlsSetValue(qt_current_thread_data_tls_index, 0);
+ threadData->deref();
+ threadData = 0;
+ QT_RETHROW;
+ }
+ threadData->deref();
+ }
+ threadData->isAdopted = true;
+ threadData->threadId = (Qt::HANDLE)GetCurrentThreadId();
+
+ if (!QCoreApplicationPrivate::theMainThread) {
+ QCoreApplicationPrivate::theMainThread = threadData->thread;
+ } else {
+ HANDLE realHandle = INVALID_HANDLE_VALUE;
+#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
+ DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &realHandle,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS);
+#else
+ realHandle = (HANDLE)GetCurrentThreadId();
+#endif
+ qt_watch_adopted_thread(realHandle, threadData->thread);
+ }
+ }
+ return threadData;
+}
+
+void QAdoptedThread::init()
+{
+ d_func()->handle = GetCurrentThread();
+ d_func()->id = GetCurrentThreadId();
+}
+
+static QVector<HANDLE> qt_adopted_thread_handles;
+static QVector<QThread *> qt_adopted_qthreads;
+static QMutex qt_adopted_thread_watcher_mutex;
+static HANDLE qt_adopted_thread_watcher_handle = 0;
+static HANDLE qt_adopted_thread_wakeup = 0;
+
+/*! \internal
+ Adds an adopted thread to the list of threads that Qt watches to make sure
+ the thread data is properly cleaned up. This function starts the watcher
+ thread if necessary.
+*/
+void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread)
+{
+ QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
+ qt_adopted_thread_handles.append(adoptedThreadHandle);
+ qt_adopted_qthreads.append(qthread);
+
+ // Start watcher thread if it is not already running.
+ if (qt_adopted_thread_watcher_handle == 0) {
+ if (qt_adopted_thread_wakeup == 0) {
+ qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0);
+ qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup);
+ }
+
+ qt_adopted_thread_watcher_handle =
+ (HANDLE)_beginthread(qt_adopted_thread_watcher_function, 0, NULL);
+ } else {
+ SetEvent(qt_adopted_thread_wakeup);
+ }
+}
+
+/*! \internal
+ This function loops and waits for native adopted threads to finish.
+ When this happens it derefs the QThreadData for the adopted thread
+ to make sure it gets cleaned up properly.
+*/
+void qt_adopted_thread_watcher_function(void *)
+{
+ forever {
+ qt_adopted_thread_watcher_mutex.lock();
+
+ if (qt_adopted_thread_handles.count() == 1) {
+ qt_adopted_thread_watcher_handle = 0;
+ qt_adopted_thread_watcher_mutex.unlock();
+ break;
+ }
+
+ QVector<HANDLE> handlesCopy = qt_adopted_thread_handles;
+ qt_adopted_thread_watcher_mutex.unlock();
+
+ DWORD ret = WAIT_TIMEOUT;
+ int loops = (handlesCopy.count() / MAXIMUM_WAIT_OBJECTS) + 1, offset, count;
+ if (loops == 1) {
+ // no need to loop, no timeout
+ offset = 0;
+ count = handlesCopy.count();
+ ret = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
+ } else {
+ int loop = 0;
+ do {
+ offset = loop * MAXIMUM_WAIT_OBJECTS;
+ count = qMin(handlesCopy.count() - offset, MAXIMUM_WAIT_OBJECTS);
+ ret = WaitForMultipleObjects(count, handlesCopy.constData() + offset, false, 100);
+ loop = (loop + 1) % loops;
+ } while (ret == WAIT_TIMEOUT);
+ }
+
+ if (ret == WAIT_FAILED || !(ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + uint(count))) {
+ qWarning("QThread internal error while waiting for adopted threads: %d", int(GetLastError()));
+ continue;
+ }
+
+ const int handleIndex = offset + ret - WAIT_OBJECT_0;
+ if (handleIndex == 0){
+ // New handle to watch was added.
+ continue;
+ } else {
+// printf("(qt) - qt_adopted_thread_watcher_function... called\n");
+ const int qthreadIndex = handleIndex - 1;
+
+ QThreadData *data = QThreadData::get2(qt_adopted_qthreads.at(qthreadIndex));
+ if (data->isAdopted) {
+ QThread *thread = data->thread;
+ Q_ASSERT(thread);
+ QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_ASSERT(!thread_p->finished);
+ thread_p->finish(thread);
+ }
+ data->deref();
+
+#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
+ CloseHandle(qt_adopted_thread_handles.at(handleIndex));
+#endif
+ QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
+ qt_adopted_thread_handles.remove(handleIndex);
+ qt_adopted_qthreads.remove(qthreadIndex);
+ }
+ }
+}
+
+#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
+
+#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), (const ULONG_PTR*)&info);
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE
+
+/**************************************************************************
+ ** QThreadPrivate
+ *************************************************************************/
+
+#endif // QT_NO_THREAD
+
+void QThreadPrivate::createEventDispatcher(QThreadData *data)
+{
+ data->eventDispatcher = new QEventDispatcherWin32;
+ data->eventDispatcher->startingUp();
+}
+
+#ifndef QT_NO_THREAD
+
+unsigned int __stdcall QThreadPrivate::start(void *arg)
+{
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadData *data = QThreadData::get2(thr);
+
+ qt_create_tls();
+ TlsSetValue(qt_current_thread_data_tls_index, data);
+ data->threadId = (Qt::HANDLE)GetCurrentThreadId();
+
+ QThread::setTerminationEnabled(false);
+
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
+ data->quitNow = thr->d_func()->exited;
+ }
+ // ### TODO: allow the user to create a custom event dispatcher
+ createEventDispatcher(data);
+
+#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
+ // 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
+
+ emit thr->started();
+ QThread::setTerminationEnabled(true);
+ thr->run();
+
+ finish(arg);
+ return 0;
+}
+
+void QThreadPrivate::finish(void *arg, bool lockAnyway)
+{
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadPrivate *d = thr->d_func();
+
+ QMutexLocker locker(lockAnyway ? &d->mutex : 0);
+ d->isInFinish = true;
+ d->priority = QThread::InheritPriority;
+ bool terminated = d->terminated;
+ void **tls_data = reinterpret_cast<void **>(&d->data->tls);
+ locker.unlock();
+ if (terminated)
+ emit thr->terminated();
+ emit thr->finished();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish(tls_data);
+ locker.relock();
+
+ d->terminated = false;
+
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ if (eventDispatcher) {
+ d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ d->running = false;
+ d->finished = true;
+ d->isInFinish = false;
+
+ if (!d->waiters) {
+ CloseHandle(d->handle);
+ d->handle = 0;
+ }
+
+ d->id = 0;
+
+}
+
+/**************************************************************************
+ ** QThread
+ *************************************************************************/
+
+Qt::HANDLE QThread::currentThreadId()
+{
+ return (Qt::HANDLE)GetCurrentThreadId();
+}
+
+int QThread::idealThreadCount()
+{
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+}
+
+void QThread::yieldCurrentThread()
+{
+#ifndef Q_OS_WINCE
+ SwitchToThread();
+#else
+ ::Sleep(0);
+#endif
+}
+
+void QThread::sleep(unsigned long secs)
+{
+ ::Sleep(secs * 1000);
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ ::Sleep(msecs);
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ ::Sleep((usecs / 1000) + 1);
+}
+
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->isInFinish) {
+ locker.unlock();
+ wait();
+ locker.relock();
+ }
+
+ if (d->running)
+ return;
+
+ d->running = true;
+ d->finished = false;
+ d->terminated = false;
+ d->exited = false;
+ d->returnCode = 0;
+
+ /*
+ NOTE: we create the thread in the suspended state, set the
+ priority and then resume the thread.
+
+ since threads are created with normal priority by default, we
+ could get into a case where a thread (with priority less than
+ NormalPriority) tries to create a new thread (also with priority
+ less than NormalPriority), but the newly created thread preempts
+ its 'parent' and runs at normal priority.
+ */
+ d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start,
+ this, CREATE_SUSPENDED, &(d->id));
+
+ if (!d->handle) {
+ qErrnoWarning(errno, "QThread::start: Failed to create thread");
+ d->running = false;
+ d->finished = true;
+ return;
+ }
+
+ int prio;
+ d->priority = priority;
+ switch (d->priority) {
+ case IdlePriority:
+ prio = THREAD_PRIORITY_IDLE;
+ break;
+
+ case LowestPriority:
+ prio = THREAD_PRIORITY_LOWEST;
+ break;
+
+ case LowPriority:
+ prio = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+
+ case NormalPriority:
+ prio = THREAD_PRIORITY_NORMAL;
+ break;
+
+ case HighPriority:
+ prio = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+
+ case HighestPriority:
+ prio = THREAD_PRIORITY_HIGHEST;
+ break;
+
+ case TimeCriticalPriority:
+ prio = THREAD_PRIORITY_TIME_CRITICAL;
+ break;
+
+ case InheritPriority:
+ default:
+ prio = GetThreadPriority(GetCurrentThread());
+ break;
+ }
+
+ if (!SetThreadPriority(d->handle, prio)) {
+ qErrnoWarning("QThread::start: Failed to set thread priority");
+ }
+
+ if (ResumeThread(d->handle) == (DWORD) -1) {
+ qErrnoWarning("QThread::start: Failed to resume new thread");
+ }
+}
+
+void QThread::terminate()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running)
+ return;
+ if (!d->terminationEnabled) {
+ d->terminatePending = true;
+ return;
+ }
+ TerminateThread(d->handle, 0);
+ d->terminated = true;
+ QThreadPrivate::finish(this, false);
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->id == GetCurrentThreadId()) {
+ qWarning("QThread::wait: Thread tried to wait on itself");
+ return false;
+ }
+ if (d->finished || !d->running)
+ return true;
+
+ ++d->waiters;
+ locker.mutex()->unlock();
+
+ bool ret = false;
+ switch (WaitForSingleObject(d->handle, time)) {
+ case WAIT_OBJECT_0:
+ ret = true;
+ break;
+ case WAIT_FAILED:
+ qErrnoWarning("QThread::wait: Thread wait failure");
+ break;
+ case WAIT_ABANDONED:
+ case WAIT_TIMEOUT:
+ default:
+ break;
+ }
+
+ locker.mutex()->lock();
+ --d->waiters;
+
+ if (ret && !d->finished) {
+ // thread was terminated by someone else
+ d->terminated = true;
+ QThreadPrivate::finish(this, false);
+ }
+
+ if (d->finished && !d->waiters) {
+ CloseHandle(d->handle);
+ d->handle = 0;
+ }
+
+ return ret;
+}
+
+void QThread::setTerminationEnabled(bool enabled)
+{
+ QThread *thr = currentThread();
+ Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
+ "Current thread was not started with QThread.");
+ QThreadPrivate *d = thr->d_func();
+ QMutexLocker locker(&d->mutex);
+ d->terminationEnabled = enabled;
+ if (enabled && d->terminatePending) {
+ d->terminated = true;
+ QThreadPrivate::finish(thr, false);
+ locker.unlock(); // don't leave the mutex locked!
+ _endthreadex(0);
+ }
+}
+
+void QThread::setPriority(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running) {
+ qWarning("QThread::setPriority: Cannot set priority, thread is not running");
+ return;
+ }
+
+ // copied from start() with a few modifications:
+
+ int prio;
+ d->priority = priority;
+ switch (d->priority) {
+ case IdlePriority:
+ prio = THREAD_PRIORITY_IDLE;
+ break;
+
+ case LowestPriority:
+ prio = THREAD_PRIORITY_LOWEST;
+ break;
+
+ case LowPriority:
+ prio = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+
+ case NormalPriority:
+ prio = THREAD_PRIORITY_NORMAL;
+ break;
+
+ case HighPriority:
+ prio = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+
+ case HighestPriority:
+ prio = THREAD_PRIORITY_HIGHEST;
+ break;
+
+ case TimeCriticalPriority:
+ prio = THREAD_PRIORITY_TIME_CRITICAL;
+ break;
+
+ case InheritPriority:
+ default:
+ qWarning("QThread::setPriority: Argument cannot be InheritPriority");
+ return;
+ }
+
+ if (!SetThreadPriority(d->handle, prio)) {
+ qErrnoWarning("QThread::setPriority: Failed to set thread priority");
+ }
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
new file mode 100644
index 0000000000..2b353333ee
--- /dev/null
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthreadstorage.h"
+
+#ifndef QT_NO_THREAD
+#include "qthread.h"
+#include "qthread_p.h"
+#include "qmutex.h"
+
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+// #define THREADSTORAGE_DEBUG
+#ifdef THREADSTORAGE_DEBUG
+# define DEBUG_MSG qtsDebug
+
+# include <stdio.h>
+# include <stdarg.h>
+void qtsDebug(const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+
+ fprintf(stderr, "QThreadStorage: ");
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ va_end(va);
+}
+#else
+# define DEBUG_MSG if(false)qDebug
+#endif
+
+Q_GLOBAL_STATIC(QMutex, mutex)
+typedef QVector<void (*)(void *)> DestructorMap;
+Q_GLOBAL_STATIC(DestructorMap, destructors)
+
+QThreadStorageData::QThreadStorageData(void (*func)(void *))
+{
+ QMutexLocker locker(mutex());
+ DestructorMap *destr = destructors();
+ if (!destr) {
+ /*
+ the destructors vector has already been destroyed, yet a new
+ QThreadStorage is being allocated. this can only happen during global
+ destruction, at which point we assume that there is only one thread.
+ in order to keep QThreadStorage working, we need somewhere to store
+ the data, best place we have in this situation is at the tail of the
+ current thread's tls vector. the destructor is ignored, since we have
+ no where to store it, and no way to actually call it.
+ */
+ QThreadData *data = QThreadData::current();
+ id = data->tls.count();
+ 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)
+ break;
+ }
+ if (id == destr->count()) {
+ destr->append(func);
+ } else {
+ (*destr)[id] = func;
+ }
+ DEBUG_MSG("QThreadStorageData: Allocated id %d, destructor %p", id, func);
+}
+
+QThreadStorageData::~QThreadStorageData()
+{
+ DEBUG_MSG("QThreadStorageData: Released id %d", id);
+ QMutexLocker locker(mutex());
+ if (destructors())
+ (*destructors())[id] = 0;
+}
+
+void **QThreadStorageData::get() const
+{
+ QThreadData *data = QThreadData::current();
+ if (!data) {
+ qWarning("QThreadStorage::get: QThreadStorage can only be used with threads started with QThread");
+ return 0;
+ }
+ QVector<void *> &tls = data->tls;
+ if (tls.size() <= id)
+ tls.resize(id + 1);
+ void **v = &tls[id];
+
+ DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
+ id,
+ *v,
+ data->thread);
+
+ return *v ? v : 0;
+}
+
+void **QThreadStorageData::set(void *p)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data) {
+ qWarning("QThreadStorage::set: QThreadStorage can only be used with threads started with QThread");
+ return 0;
+ }
+ QVector<void *> &tls = data->tls;
+ if (tls.size() <= id)
+ tls.resize(id + 1);
+
+ void *&value = tls[id];
+ // delete any previous data
+ if (value != 0) {
+ DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
+ id,
+ value,
+ data->thread);
+
+ QMutexLocker locker(mutex());
+ DestructorMap *destr = destructors();
+ void (*destructor)(void *) = destr ? destr->value(id) : 0;
+ locker.unlock();
+
+ void *q = value;
+ value = 0;
+
+ if (destructor)
+ destructor(q);
+ }
+
+ // store new data
+ value = p;
+ DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p);
+ return &value;
+}
+
+void QThreadStorageData::finish(void **p)
+{
+ QVector<void *> *tls = reinterpret_cast<QVector<void *> *>(p);
+ if (!tls || tls->isEmpty() || !mutex())
+ return; // nothing to do
+
+ DEBUG_MSG("QThreadStorageData: Destroying storage for thread %p", QThread::currentThread());
+ while (!tls->isEmpty()) {
+ void *&value = tls->last();
+ void *q = value;
+ value = 0;
+ int i = tls->size() - 1;
+ tls->resize(i);
+
+ if (!q) {
+ // data already deleted
+ continue;
+ }
+
+ QMutexLocker locker(mutex());
+ void (*destructor)(void *) = destructors()->value(i);
+ locker.unlock();
+
+ if (!destructor) {
+ if (QThread::currentThread())
+ qWarning("QThreadStorage: Thread %p exited after QThreadStorage %d destroyed",
+ QThread::currentThread(), i);
+ continue;
+ }
+ destructor(q); //crash here might mean the thread exited after qthreadstorage was destroyed
+
+ if (tls->size() > i) {
+ //re reset the tls in case it has been recreated by its own destructor.
+ (*tls)[i] = 0;
+ }
+ }
+ tls->clear();
+}
+
+/*!
+ \class QThreadStorage
+ \brief The QThreadStorage class provides per-thread data storage.
+
+ \threadsafe
+
+ \ingroup thread
+
+ QThreadStorage is a template class that provides per-thread data
+ storage.
+
+ The setLocalData() function stores a single thread-specific value
+ for the calling thread. The data can be accessed later using
+ localData().
+
+ 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.
+
+ 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
+ the thread exits, either normally or via termination.
+
+ For example, the following code uses QThreadStorage to store a
+ single cache for each thread that calls the cacheObject() and
+ removeFromCache() functions. The cache is automatically
+ deleted when the calling thread exits.
+
+ \snippet doc/src/snippets/threads/threads.cpp 7
+ \snippet doc/src/snippets/threads/threads.cpp 8
+ \snippet doc/src/snippets/threads/threads.cpp 9
+
+ \section1 Caveats
+
+ \list
+
+ \o The QThreadStorage destructor does not delete per-thread data.
+ QThreadStorage only deletes per-thread data when the thread exits
+ or when setLocalData() is called multiple times.
+
+ \o QThreadStorage can be used to store data for the \c main()
+ thread. QThreadStorage deletes all data set for the \c main()
+ thread when QApplication is destroyed, regardless of whether or
+ not the \c main() thread has actually finished.
+
+ \endlist
+
+ \sa QThread
+*/
+
+/*!
+ \fn QThreadStorage::QThreadStorage()
+
+ Constructs a new per-thread data storage object.
+*/
+
+/*!
+ \fn QThreadStorage::~QThreadStorage()
+
+ Destroys the per-thread data storage object.
+
+ Note: The per-thread data stored is not deleted. Any data left
+ in QThreadStorage is leaked. Make sure that all threads using
+ QThreadStorage have exited before deleting the QThreadStorage.
+
+ \sa hasLocalData()
+*/
+
+/*!
+ \fn bool QThreadStorage::hasLocalData() const
+
+ If T is a pointer type, returns true if the calling thread has
+ non-zero data available.
+
+ If T is a value type, returns whether the data has already been
+ constructed by calling setLocalData or localData.
+
+ \sa localData()
+*/
+
+/*!
+ \fn T &QThreadStorage::localData()
+
+ Returns a reference to the data that was set by the calling
+ thread.
+
+ If no data has been set, this will create a default constructed
+ instance of type T.
+
+ \sa hasLocalData()
+*/
+
+/*!
+ \fn const T QThreadStorage::localData() const
+ \overload
+
+ Returns a copy of the data that was set by the calling thread.
+
+ \sa hasLocalData()
+*/
+
+/*!
+ \fn void QThreadStorage::setLocalData(T data)
+
+ Sets the local data for the calling thread to \a data. It can be
+ accessed later using the localData() functions.
+
+ If T is a pointer type, QThreadStorage takes ownership of the data
+ and deletes it automatically either when the thread exits (either
+ normally or via termination) or when setLocalData() is called again.
+
+ \sa localData(), hasLocalData()
+*/
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h
new file mode 100644
index 0000000000..e1cafb65cb
--- /dev/null
+++ b/src/corelib/thread/qthreadstorage.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREADSTORAGE_H
+#define QTHREADSTORAGE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QThreadStorageData
+{
+public:
+ explicit QThreadStorageData(void (*func)(void *));
+ ~QThreadStorageData();
+
+ void** get() const;
+ void** set(void* p);
+
+ static void finish(void**);
+ int id;
+};
+
+#if !defined(QT_MOC_CPP)
+// MOC_SKIP_BEGIN
+
+// pointer specialization
+template <typename T>
+inline
+T *&qThreadStorage_localData(QThreadStorageData &d, T **)
+{
+ void **v = d.get();
+ if (!v) v = d.set(0);
+ return *(reinterpret_cast<T**>(v));
+}
+
+template <typename T>
+inline
+T *qThreadStorage_localData_const(const QThreadStorageData &d, T **)
+{
+ void **v = d.get();
+ return v ? *(reinterpret_cast<T**>(v)) : 0;
+}
+
+template <typename T>
+inline
+void qThreadStorage_setLocalData(QThreadStorageData &d, T **t)
+{ (void) d.set(*t); }
+
+template <typename T>
+inline
+void qThreadStorage_deleteData(void *d, T **)
+{ delete static_cast<T *>(d); }
+
+// value-based specialization
+template <typename T>
+inline
+T &qThreadStorage_localData(QThreadStorageData &d, T *)
+{
+ void **v = d.get();
+ if (!v) v = d.set(new T());
+ return *(reinterpret_cast<T*>(*v));
+}
+
+template <typename T>
+inline
+T qThreadStorage_localData_const(const QThreadStorageData &d, T *)
+{
+ void **v = d.get();
+ return v ? *(reinterpret_cast<T*>(*v)) : T();
+}
+
+template <typename T>
+inline
+void qThreadStorage_setLocalData(QThreadStorageData &d, T *t)
+{ (void) d.set(new T(*t)); }
+
+template <typename T>
+inline
+void qThreadStorage_deleteData(void *d, T *)
+{ delete static_cast<T *>(d); }
+
+
+// MOC_SKIP_END
+#endif
+
+template <class T>
+class QThreadStorage
+{
+private:
+ QThreadStorageData d;
+
+ Q_DISABLE_COPY(QThreadStorage)
+
+ static inline void deleteData(void *x)
+ { qThreadStorage_deleteData(x, reinterpret_cast<T*>(0)); }
+
+public:
+ inline QThreadStorage() : d(deleteData) { }
+ inline ~QThreadStorage() { }
+
+ inline bool hasLocalData() const
+ { return d.get() != 0; }
+
+ inline T& localData()
+ { return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); }
+ inline T localData() const
+ { return qThreadStorage_localData_const(d, reinterpret_cast<T*>(0)); }
+
+ inline void setLocalData(T t)
+ { qThreadStorage_setLocalData(d, &t); }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_THREAD
+
+#endif // QTHREADSTORAGE_H
diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h
new file mode 100644
index 0000000000..c49f36d256
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAITCONDITION_H
+#define QWAITCONDITION_H
+
+#include <QtCore/qglobal.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_THREAD
+
+class QWaitConditionPrivate;
+class QMutex;
+class QReadWriteLock;
+
+class Q_CORE_EXPORT QWaitCondition
+{
+public:
+ QWaitCondition();
+ ~QWaitCondition();
+
+ bool wait(QMutex *mutex, unsigned long time = ULONG_MAX);
+ bool wait(QReadWriteLock *readWriteLock, unsigned long time = ULONG_MAX);
+
+ void wakeOne();
+ void wakeAll();
+
+private:
+ Q_DISABLE_COPY(QWaitCondition)
+
+ QWaitConditionPrivate * d;
+};
+
+#else
+
+class QMutex;
+class Q_CORE_EXPORT QWaitCondition
+{
+public:
+ QWaitCondition() {}
+ ~QWaitCondition() {}
+
+ bool wait(QMutex *mutex, unsigned long time = ULONG_MAX)
+ {
+ Q_UNUSED(mutex);
+ Q_UNUSED(time);
+ return true;
+ }
+
+ void wakeOne() {}
+ void wakeAll() {}
+};
+
+#endif // QT_NO_THREAD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWAITCONDITION_H
diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc
new file mode 100644
index 0000000000..8138763f55
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition.qdoc
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QWaitCondition
+ \brief The QWaitCondition class provides a condition variable for
+ synchronizing threads.
+
+ \threadsafe
+
+ \ingroup thread
+
+ QWaitCondition allows a thread to tell other threads that some
+ sort of condition has been met. One or many threads can block
+ waiting for a QWaitCondition to set a condition with wakeOne() or
+ wakeAll(). Use wakeOne() to wake one randomly selected condition or
+ wakeAll() to wake them all.
+
+ For example, let's suppose that we have three tasks that should
+ be performed whenever the user presses a key. Each task could be
+ split into a thread, each of which would have a
+ \l{QThread::run()}{run()} body like this:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp 0
+
+ Here, the \c keyPressed variable is a global variable of type
+ QWaitCondition.
+
+ A fourth thread would read key presses and wake the other three
+ threads up every time it receives one, like this:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp 1
+
+ The order in which the three threads are woken up is undefined.
+ Also, if some of the threads are still in \c do_something() when
+ the key is pressed, they won't be woken up (since they're not
+ waiting on the condition variable) and so the task will not be
+ performed for that key press. This issue can be solved using a
+ counter and a QMutex to guard it. For example, here's the new
+ code for the worker threads:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp 2
+
+ Here's the code for the fourth thread:
+
+ \snippet doc/src/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp 3
+
+ The mutex is necessary because the results of two threads
+ attempting to change the value of the same variable
+ simultaneously are unpredictable.
+
+ Wait conditions are a powerful thread synchronization primitive.
+ The \l{threads/waitconditions}{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}
+*/
+
+/*!
+ \fn QWaitCondition::QWaitCondition()
+
+ Constructs a new wait condition object.
+*/
+
+/*!
+ \fn QWaitCondition::~QWaitCondition()
+
+ Destroys the wait condition object.
+*/
+
+/*!
+ \fn void QWaitCondition::wakeOne()
+
+ Wakes one thread waiting on the wait condition. The thread that
+ is woken up depends on the operating system's scheduling
+ policies, and cannot be controlled or predicted.
+
+ If you want to wake up a specific thread, the solution is
+ typically to use different wait conditions and have different
+ threads wait on different conditions.
+
+ \sa wakeAll()
+*/
+
+/*!
+ \fn void QWaitCondition::wakeAll()
+
+ Wakes all threads waiting on the wait condition. The order in
+ which the threads are woken up depends on the operating system's
+ scheduling policies and cannot be controlled or predicted.
+
+ \sa wakeOne()
+*/
+
+/*!
+ \fn bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
+
+ Releases the locked \a mutex and waits on the wait condition. The
+ \a mutex must be initially locked by the calling thread. If \a
+ mutex is not in a locked state, this function returns
+ immediately. If \a mutex is a recursive mutex, this function
+ returns immediately. The \a mutex will be unlocked, and the
+ calling thread will block until either of these conditions is met:
+
+ \list
+ \o Another thread signals it using wakeOne() or wakeAll(). This
+ function will return true in this case.
+ \o \a time milliseconds has elapsed. If \a time is \c ULONG_MAX
+ (the default), then the wait will never timeout (the event
+ must be signalled). This function will return false if the
+ wait timed out.
+ \endlist
+
+ The mutex will be returned to the same locked state. This
+ function is provided to allow the atomic transition from the
+ locked state to the wait state.
+
+ \sa wakeOne(), wakeAll()
+*/
+
+/*!
+ \fn bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
+ \since 4.4
+
+ Releases the locked \a readWriteLock and waits on the wait
+ condition. The \a readWriteLock must be initially locked by the
+ calling thread. If \a readWriteLock is not in a locked state, this
+ function returns immediately. The \a readWriteLock must not be
+ locked recursively, otherwise this function will not release the
+ lock properly. The \a readWriteLock will be unlocked, and the
+ calling thread will block until either of these conditions is met:
+
+ \list
+ \o Another thread signals it using wakeOne() or wakeAll(). This
+ function will return true in this case.
+ \o \a time milliseconds has elapsed. If \a time is \c ULONG_MAX
+ (the default), then the wait will never timeout (the event
+ must be signalled). This function will return false if the
+ wait timed out.
+ \endlist
+
+ The \a readWriteLock will be returned to the same locked
+ state. This function is provided to allow the atomic transition
+ from the locked state to the wait state.
+
+ \sa wakeOne(), wakeAll()
+*/
diff --git a/src/corelib/thread/qwaitcondition_symbian.cpp b/src/corelib/thread/qwaitcondition_symbian.cpp
new file mode 100644
index 0000000000..9967382735
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition_symbian.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qwaitcondition.h"
+#include "qmutex.h"
+#include "qreadwritelock.h"
+#include "qatomic.h"
+#include "qstring.h"
+#include "qelapsedtimer.h"
+
+#include "qmutex_p.h"
+#include "qreadwritelock_p.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+static void report_error(int err, const char *where, const char *what)
+{
+ if (err != KErrNone)
+ qWarning("%s: %s failure: %d", where, what, err);
+}
+
+class QWaitConditionPrivate {
+public:
+ RMutex mutex;
+ RCondVar cond;
+ int waiters;
+ int wakeups;
+
+ QWaitConditionPrivate()
+ : waiters(0), wakeups(0)
+ {
+ qt_symbian_throwIfError(mutex.CreateLocal());
+ int err = cond.CreateLocal();
+ if (err != KErrNone) {
+ mutex.Close();
+ qt_symbian_throwIfError(err);
+ }
+ }
+
+ ~QWaitConditionPrivate()
+ {
+ cond.Close();
+ mutex.Close();
+ }
+
+ bool wait(unsigned long time)
+ {
+ TInt err = KErrNone;
+ if (time == ULONG_MAX) {
+ // untimed wait, loop because RCondVar::Wait may return before the condition is triggered
+ do {
+ err = cond.Wait(mutex);
+ } while (err == KErrNone && wakeups == 0);
+ } else {
+ unsigned long maxWait = KMaxTInt / 1000;
+ QElapsedTimer waitTimer;
+ do {
+ waitTimer.start();
+ unsigned long waitTime = qMin(maxWait, time);
+ // wait at least 1ms, as 0 means no wait
+ err = cond.TimedWait(mutex, qMax(1ul, waitTime) * 1000);
+ // RCondVar::TimedWait may return before the condition is triggered, update the timeout with actual wait time
+ time -= qMin((unsigned long)waitTimer.elapsed(), waitTime);
+ } while ((err == KErrNone && wakeups == 0) || (err == KErrTimedOut && time > 0));
+ }
+
+ Q_ASSERT_X(waiters > 0, "QWaitCondition::wait", "internal error (waiters)");
+ --waiters;
+ if (err == KErrNone) {
+ Q_ASSERT_X(wakeups > 0, "QWaitCondition::wait", "internal error (wakeups)");
+ --wakeups;
+ }
+
+ mutex.Signal();
+
+ if (err && err != KErrTimedOut)
+ report_error(err, "QWaitCondition::wait()", "cv wait");
+ return err == KErrNone;
+ }
+};
+
+QWaitCondition::QWaitCondition()
+{
+ d = new QWaitConditionPrivate;
+}
+
+QWaitCondition::~QWaitCondition()
+{
+ delete d;
+}
+
+void QWaitCondition::wakeOne()
+{
+ d->mutex.Wait();
+ d->wakeups = qMin(d->wakeups + 1, d->waiters);
+ d->cond.Signal();
+ d->mutex.Signal();
+}
+
+void QWaitCondition::wakeAll()
+{
+ d->mutex.Wait();
+ d->wakeups = d->waiters;
+ d->cond.Broadcast();
+ d->mutex.Signal();
+}
+
+bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
+{
+ if (! mutex)
+ return false;
+ if (mutex->d->recursive) {
+ qWarning("QWaitCondition: cannot wait on recursive mutexes");
+ return false;
+ }
+
+ d->mutex.Wait();
+ ++d->waiters;
+ mutex->unlock();
+
+ bool returnValue = d->wait(time);
+
+ mutex->lock();
+
+ return returnValue;
+}
+
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
+{
+ if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ return false;
+ if (readWriteLock->d->accessCount < -1) {
+ qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
+ return false;
+ }
+
+ d->mutex.Wait();
+ ++d->waiters;
+
+ int previousAccessCount = readWriteLock->d->accessCount;
+ readWriteLock->unlock();
+
+ bool returnValue = d->wait(time);
+
+ if (previousAccessCount < 0)
+ readWriteLock->lockForWrite();
+ else
+ readWriteLock->lockForRead();
+
+ return returnValue;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
new file mode 100644
index 0000000000..d0f23b5342
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qwaitcondition.h"
+#include "qmutex.h"
+#include "qreadwritelock.h"
+#include "qatomic.h"
+#include "qstring.h"
+
+#include "qmutex_p.h"
+#include "qreadwritelock_p.h"
+
+#include <errno.h>
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+static void report_error(int code, const char *where, const char *what)
+{
+ if (code != 0)
+ qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+}
+
+class QWaitConditionPrivate {
+public:
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int waiters;
+ int wakeups;
+
+ bool wait(unsigned long time)
+ {
+ int code;
+ forever {
+ if (time != ULONG_MAX) {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ timespec ti;
+ ti.tv_nsec = (tv.tv_usec + (time % 1000) * 1000) * 1000;
+ ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000);
+ ti.tv_nsec %= 1000000000;
+
+ code = pthread_cond_timedwait(&cond, &mutex, &ti);
+ } else {
+ code = pthread_cond_wait(&cond, &mutex);
+ }
+ if (code == 0 && wakeups == 0) {
+ // many vendors warn of spurios wakeups from
+ // pthread_cond_wait(), especially after signal delivery,
+ // even though POSIX doesn't allow for it... sigh
+ continue;
+ }
+ break;
+ }
+
+ Q_ASSERT_X(waiters > 0, "QWaitCondition::wait", "internal error (waiters)");
+ --waiters;
+ if (code == 0) {
+ Q_ASSERT_X(wakeups > 0, "QWaitCondition::wait", "internal error (wakeups)");
+ --wakeups;
+ }
+ report_error(pthread_mutex_unlock(&mutex), "QWaitCondition::wait()", "mutex unlock");
+
+ if (code && code != ETIMEDOUT)
+ report_error(code, "QWaitCondition::wait()", "cv wait");
+
+ return (code == 0);
+ }
+};
+
+
+QWaitCondition::QWaitCondition()
+{
+ d = new QWaitConditionPrivate;
+ report_error(pthread_mutex_init(&d->mutex, NULL), "QWaitCondition", "mutex init");
+ report_error(pthread_cond_init(&d->cond, NULL), "QWaitCondition", "cv init");
+ 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");
+ delete d;
+}
+
+void QWaitCondition::wakeOne()
+{
+ report_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");
+}
+
+void QWaitCondition::wakeAll()
+{
+ report_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");
+}
+
+bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
+{
+ if (! mutex)
+ return false;
+ if (mutex->d->recursive) {
+ qWarning("QWaitCondition: cannot wait on recursive mutexes");
+ return false;
+ }
+
+ report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
+ ++d->waiters;
+ mutex->unlock();
+
+ bool returnValue = d->wait(time);
+
+ mutex->lock();
+
+ return returnValue;
+}
+
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
+{
+ if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ return false;
+ if (readWriteLock->d->accessCount < -1) {
+ qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
+ return false;
+ }
+
+ report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
+ ++d->waiters;
+
+ int previousAccessCount = readWriteLock->d->accessCount;
+ readWriteLock->unlock();
+
+ bool returnValue = d->wait(time);
+
+ if (previousAccessCount < 0)
+ readWriteLock->lockForWrite();
+ else
+ readWriteLock->lockForRead();
+
+ return returnValue;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
new file mode 100644
index 0000000000..ee1c7ba01f
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaitcondition.h"
+#include "qnamespace.h"
+#include "qmutex.h"
+#include "qreadwritelock.h"
+#include "qlist.h"
+#include "qalgorithms.h"
+#include "qt_windows.h"
+
+#ifndef QT_NO_THREAD
+
+#define Q_MUTEX_T void*
+#include <private/qmutex_p.h>
+#include <private/qreadwritelock_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//***********************************************************************
+// QWaitConditionPrivate
+// **********************************************************************
+
+class QWaitConditionEvent
+{
+public:
+ inline QWaitConditionEvent() : priority(0), wokenUp(false)
+ {
+ event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+ inline ~QWaitConditionEvent() { CloseHandle(event); }
+ int priority;
+ bool wokenUp;
+ HANDLE event;
+};
+
+typedef QList<QWaitConditionEvent *> EventQueue;
+
+class QWaitConditionPrivate
+{
+public:
+ QMutex mtx;
+ EventQueue queue;
+ EventQueue freeQueue;
+
+ QWaitConditionEvent *pre();
+ bool wait(QWaitConditionEvent *wce, unsigned long time);
+ void post(QWaitConditionEvent *wce, bool ret);
+};
+
+QWaitConditionEvent *QWaitConditionPrivate::pre()
+{
+ mtx.lock();
+ QWaitConditionEvent *wce =
+ freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst();
+ wce->priority = GetThreadPriority(GetCurrentThread());
+ wce->wokenUp = false;
+
+ // insert 'wce' into the queue (sorted by priority)
+ int index = 0;
+ for (; index < queue.size(); ++index) {
+ QWaitConditionEvent *current = queue.at(index);
+ if (current->priority < wce->priority)
+ break;
+ }
+ queue.insert(index, wce);
+ mtx.unlock();
+
+ return wce;
+}
+
+bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time)
+{
+ // wait for the event
+ bool ret = false;
+ switch (WaitForSingleObject(wce->event, time)) {
+ default: break;
+
+ case WAIT_OBJECT_0:
+ ret = true;
+ break;
+ }
+ return ret;
+}
+
+void QWaitConditionPrivate::post(QWaitConditionEvent *wce, bool ret)
+{
+ mtx.lock();
+
+ // remove 'wce' from the queue
+ queue.removeAll(wce);
+ ResetEvent(wce->event);
+ freeQueue.append(wce);
+
+ // wakeups delivered after the timeout should be forwarded to the next waiter
+ if (!ret && wce->wokenUp && !queue.isEmpty()) {
+ QWaitConditionEvent *other = queue.first();
+ SetEvent(other->event);
+ other->wokenUp = true;
+ }
+
+ mtx.unlock();
+}
+
+//***********************************************************************
+// QWaitCondition implementation
+//***********************************************************************
+
+QWaitCondition::QWaitCondition()
+{
+ d = new QWaitConditionPrivate;
+}
+
+QWaitCondition::~QWaitCondition()
+{
+ if (!d->queue.isEmpty()) {
+ qWarning("QWaitCondition: Destroyed while threads are still waiting");
+ qDeleteAll(d->queue);
+ }
+
+ qDeleteAll(d->freeQueue);
+ delete d;
+}
+
+bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
+{
+ if (!mutex)
+ return false;
+ if (mutex->d->recursive) {
+ qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
+ return false;
+ }
+
+ QWaitConditionEvent *wce = d->pre();
+ mutex->unlock();
+
+ bool returnValue = d->wait(wce, time);
+
+ mutex->lock();
+ d->post(wce, returnValue);
+
+ return returnValue;
+}
+
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
+{
+ if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ return false;
+ if (readWriteLock->d->accessCount < -1) {
+ qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
+ return false;
+ }
+
+ QWaitConditionEvent *wce = d->pre();
+ int previousAccessCount = readWriteLock->d->accessCount;
+ readWriteLock->unlock();
+
+ bool returnValue = d->wait(wce, time);
+
+ if (previousAccessCount < 0)
+ readWriteLock->lockForWrite();
+ else
+ readWriteLock->lockForRead();
+ d->post(wce, returnValue);
+
+ return returnValue;
+}
+
+void QWaitCondition::wakeOne()
+{
+ // wake up the first waiting thread in the queue
+ QMutexLocker locker(&d->mtx);
+ for (int i = 0; i < d->queue.size(); ++i) {
+ QWaitConditionEvent *current = d->queue.at(i);
+ if (current->wokenUp)
+ continue;
+ SetEvent(current->event);
+ current->wokenUp = true;
+ break;
+ }
+}
+
+void QWaitCondition::wakeAll()
+{
+ // wake up the all threads in the queue
+ QMutexLocker locker(&d->mtx);
+ for (int i = 0; i < d->queue.size(); ++i) {
+ QWaitConditionEvent *current = d->queue.at(i);
+ SetEvent(current->event);
+ current->wokenUp = true;
+ }
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
new file mode 100644
index 0000000000..592ab1644b
--- /dev/null
+++ b/src/corelib/thread/thread.pri
@@ -0,0 +1,41 @@
+# Qt core thread module
+
+# public headers
+HEADERS += thread/qmutex.h \
+ thread/qreadwritelock.h \
+ thread/qsemaphore.h \
+ thread/qthread.h \
+ thread/qthreadstorage.h \
+ thread/qwaitcondition.h \
+ thread/qatomic.h
+
+# private headers
+HEADERS += thread/qmutex_p.h \
+ thread/qmutexpool_p.h \
+ thread/qorderedmutexlocker_p.h \
+ thread/qreadwritelock_p.h \
+ thread/qthread_p.h
+
+SOURCES += thread/qatomic.cpp \
+ thread/qmutex.cpp \
+ thread/qreadwritelock.cpp \
+ thread/qmutexpool.cpp \
+ thread/qsemaphore.cpp \
+ thread/qthread.cpp \
+ thread/qthreadstorage.cpp
+
+unix:!symbian:SOURCES += thread/qmutex_unix.cpp \
+ thread/qthread_unix.cpp \
+ thread/qwaitcondition_unix.cpp
+
+symbian:SOURCES += thread/qmutex_symbian.cpp \
+ thread/qthread_symbian.cpp \
+ thread/qwaitcondition_symbian.cpp
+
+win32:SOURCES += thread/qmutex_win.cpp \
+ thread/qthread_win.cpp \
+ thread/qwaitcondition_win.cpp
+
+integrity:SOURCES += thread/qmutex_unix.cpp \
+ thread/qthread_unix.cpp \
+ thread/qwaitcondition_unix.cpp
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
new file mode 100644
index 0000000000..6b870397b6
--- /dev/null
+++ b/src/corelib/tools/qalgorithms.h
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QALGORITHMS_H
+#define QALGORITHMS_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*
+ 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 {
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
+template <typename RandomAccessIterator, typename T>
+inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy);
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
+template <typename RandomAccessIterator, typename T>
+inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &);
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+
+}
+
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest)
+{
+ while (begin != end)
+ *dest++ = *begin++;
+ return dest;
+}
+
+template <typename BiIterator1, typename BiIterator2>
+inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest)
+{
+ while (begin != end)
+ *--dest = *--end;
+ return dest;
+}
+
+template <typename InputIterator1, typename InputIterator2>
+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>
+inline void qFill(ForwardIterator first, ForwardIterator last, const T &val)
+{
+ for (; first != last; ++first)
+ *first = val;
+}
+
+template <typename Container, typename T>
+inline void qFill(Container &container, const T &val)
+{
+ qFill(container.begin(), container.end(), val);
+}
+
+template <typename InputIterator, typename T>
+inline InputIterator qFind(InputIterator first, InputIterator last, const T &val)
+{
+ while (first != last && !(*first == val))
+ ++first;
+ return first;
+}
+
+template <typename Container, typename T>
+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>
+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>
+inline void qCount(const Container &container, const T &value, Size &n)
+{
+ qCount(container.constBegin(), container.constEnd(), value, n);
+}
+
+#ifdef qdoc
+template <typename T>
+LessThan qLess()
+{
+}
+
+template <typename T>
+LessThan qGreater()
+{
+}
+#else
+template <typename T>
+class qLess
+{
+public:
+ inline bool operator()(const T &t1, const T &t2) const
+ {
+ return (t1 < t2);
+ }
+};
+
+template <typename T>
+class qGreater
+{
+public:
+ inline bool operator()(const T &t1, const T &t2) const
+ {
+ return (t2 < t1);
+ }
+};
+#endif
+
+template <typename RandomAccessIterator>
+inline void qSort(RandomAccessIterator start, RandomAccessIterator end)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qSortHelper(start, end, *start);
+}
+
+template <typename RandomAccessIterator, typename LessThan>
+inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan);
+}
+
+template<typename Container>
+inline void qSort(Container &c)
+{
+#ifdef Q_CC_BOR
+ // Work around Borland 5.5 optimizer bug
+ c.detach();
+#endif
+ if (!c.empty())
+ QAlgorithmsPrivate::qSortHelper(c.begin(), c.end(), *c.begin());
+}
+
+template <typename RandomAccessIterator>
+inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qStableSortHelper(start, end, *start);
+}
+
+template <typename RandomAccessIterator, typename LessThan>
+inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan);
+}
+
+template<typename Container>
+inline void qStableSort(Container &c)
+{
+#ifdef Q_CC_BOR
+ // Work around Borland 5.5 optimizer bug
+ c.detach();
+#endif
+ if (!c.empty())
+ QAlgorithmsPrivate::qStableSortHelper(c.begin(), c.end(), *c.begin());
+}
+
+template <typename RandomAccessIterator, typename T>
+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>
+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>
+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>
+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>
+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>
+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>
+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>
+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>
+Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value)
+{
+ return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
+}
+
+template <typename ForwardIterator>
+Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
+{
+ while (begin != end) {
+ delete *begin;
+ ++begin;
+ }
+}
+
+template <typename Container>
+inline void qDeleteAll(const Container &c)
+{
+ qDeleteAll(c.begin(), c.end());
+}
+
+/*
+ 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 {
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+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>
+inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
+{
+ qSortHelper(begin, end, dummy, qLess<T>());
+}
+
+template <typename RandomAccessIterator>
+Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end)
+{
+ --end;
+ while (begin < end)
+ qSwap(*begin++, *end--);
+}
+
+template <typename RandomAccessIterator>
+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>
+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>
+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>
+inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
+{
+ qStableSortHelper(begin, end, dummy, qLess<T>());
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+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>
+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>
+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;
+}
+
+} //namespace QAlgorithmsPrivate
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QALGORITHMS_H
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
new file mode 100644
index 0000000000..a9b7ddca7a
--- /dev/null
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -0,0 +1,637 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtAlgorithms>
+ \title Generic Algorithms
+ \ingroup funclists
+
+ \brief The <QtAlgorithms> header includes the generic, template-based algorithms.
+
+ Qt provides a number of global template functions in \c
+ <QtAlgorithms> that work on containers and perform well-know
+ algorithms. You can use these algorithms with any \l {container
+ class} that provides STL-style iterators, including Qt's QList,
+ QLinkedList, QVector, QMap, and QHash classes.
+
+ These functions have taken their inspiration from similar
+ functions available in the STL \c <algorithm> header. Most of them
+ have a direct STL equivalent; for example, qCopyBackward() is the
+ same as STL's copy_backward() algorithm.
+
+ If STL is available on all your target platforms, you can use the
+ STL algorithms instead of their Qt counterparts. One reason why
+ you might want to use the STL algorithms is that STL provides
+ dozens and dozens of algorithms, whereas Qt only provides the most
+ important ones, making no attempt to duplicate functionality that
+ is already provided by the C++ standard.
+
+ Most algorithms take \l {STL-style iterators} as parameters. The
+ algorithms are generic in the sense that they aren't bound to a
+ specific iterator class; you can use them with any iterators that
+ meet a certain set of requirements.
+
+ Let's take the qFill() algorithm as an example. Unlike QVector,
+ QList has no fill() function that can be used to fill a list with
+ a particular value. If you need that functionality, you can use
+ qFill():
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 0
+
+ qFill() takes a begin iterator, an end iterator, and a value.
+ In the example above, we pass \c list.begin() and \c list.end()
+ as the begin and end iterators, but this doesn't have to be
+ the case:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 1
+
+ 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
+ for each algorithm. If an iterator of the wrong type is passed (for
+ example, if QList::ConstIterator is passed as an \l {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, qEqual() requires that the
+ value type supports operator==(), which it uses to compare items.
+ Similarly, 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.
+
+ \target binaryFind example
+
+ 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 doc/src/snippets/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 doc/src/snippets/code/doc_src_qalgorithms.cpp 3
+
+ \section1 Types of Iterators
+
+ The algorithms have certain requirements on the iterator types
+ they accept, and these are specified individually for each
+ function. The compiler will produce an error if a requirement
+ isn't met.
+
+ \section2 Input Iterators
+
+ An \e{input iterator} is an iterator that can be used for reading
+ data sequentially from a container. It must provide the following
+ operators: \c{==} and \c{!=} for comparing two iterators, unary
+ \c{*} for retrieving the value stored in the item, and prefix
+ \c{++} for advancing to the next item.
+
+ The Qt containers' iterator types (const and non-const) are all
+ input iterators.
+
+ \section2 Output Iterators
+
+ An \e{output iterator} is an iterator that can be used for
+ writing data sequentially to a container or to some output
+ stream. It must provide the following operators: unary \c{*} for
+ writing a value (i.e., \c{*it = val}) and prefix \c{++} for
+ advancing to the next item.
+
+ The Qt containers' non-const iterator types are all output
+ iterators.
+
+ \section2 Forward Iterators
+
+ A \e{forward iterator} is an iterator that meets the requirements
+ of both input iterators and output iterators.
+
+ The Qt containers' non-const iterator types are all forward
+ iterators.
+
+ \section2 Bidirectional Iterators
+
+ A \e{bidirectional iterator} is an iterator that meets the
+ requirements of forward iterators but that in addition supports
+ prefix \c{--} for iterating backward.
+
+ The Qt containers' non-const iterator types are all bidirectional
+ iterators.
+
+ \section2 Random Access Iterators
+
+ The last category, \e{random access iterators}, is the most
+ powerful type of iterator. It supports all the requirements of a
+ bidirectional iterator, and supports the following operations:
+
+ \table
+ \row \i \c{i += n} \i advances iterator \c i by \c n positions
+ \row \i \c{i -= n} \i moves iterator \c i back by \c n positions
+ \row \i \c{i + n} or \c{n + i} \i returns the iterator for the item \c
+ n positions ahead of iterator \c i
+ \row \i \c{i - n} \i returns the iterator for the item \c n positions behind of iterator \c i
+ \row \i \c{i - j} \i returns the number of items between iterators \c i and \c j
+ \row \i \c{i[n]} \i same as \c{*(i + n)}
+ \row \i \c{i < j} \i returns true if iterator \c j comes after iterator \c i
+ \endtable
+
+ QList and QVector's non-const iterator types are random access iterators.
+
+ \sa {container classes}, <QtGlobal>
+*/
+
+/*! \fn OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/code/doc_src_qalgorithms.cpp 4
+
+ \sa qCopyBackward(), {input iterators}, {output iterators}
+*/
+
+/*! \fn BiIterator2 qCopyBackward(BiIterator1 begin1, BiIterator1 end1, BiIterator2 end2)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/code/doc_src_qalgorithms.cpp 5
+
+ \sa qCopy(), {bidirectional iterators}
+*/
+
+/*! \fn bool qEqual(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
+ \relates <QtAlgorithms>
+
+ Compares the items in the range [\a begin1, \a end1) with the
+ items in the range [\a begin2, ...). Returns true if all the
+ items compare equal; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/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 void qFill(ForwardIterator begin, ForwardIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Fills the range [\a begin, \a end) with \a value.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 7
+
+ \sa qCopy(), {forward iterators}
+*/
+
+/*! \fn void qFill(Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFill(\a{container}.begin(), \a{container}.end(), \a value);
+*/
+
+/*! \fn InputIterator qFind(InputIterator begin, InputIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/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 void qFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFind(\a{container}.constBegin(), \a{container}.constEnd(), value);
+*/
+
+/*! \fn void qCount(InputIterator begin, InputIterator end, const T &value, Size &n)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/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 void qCount(const Container &container, const T &value, Size &n)
+\relates <QtAlgorithms>
+
+\overload
+
+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 void qSwap(T &var1, T &var2)
+ \relates <QtAlgorithms>
+
+ Exchanges the values of variables \a var1 and \a var2.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 10
+*/
+
+/*! \fn void qSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ Sorts the items in range [\a begin, \a end) in ascending order
+ using the quicksort algorithm.
+
+ Example:
+ \snippet doc/src/snippets/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 void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/doc_src_qalgorithms.cpp 14
+
+ \sa QMap
+*/
+
+/*! \fn void qSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*!
+ \fn void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/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 void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 doc/src/snippets/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 doc/src/snippets/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 void qStableSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qStableSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*! \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of the first ocurrence 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 doc/src/snippets/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 doc/src/snippets/code/doc_src_qalgorithms.cpp 19
+
+ \sa qUpperBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 void qLowerBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/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 doc/src/snippets/code/doc_src_qalgorithms.cpp 21
+
+ \sa qLowerBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 void qUpperBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qUpperBound(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ 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 doc/src/snippets/code/doc_src_qalgorithms.cpp 22
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator<().
+
+ See the \l{<QtAlgorithms>#binaryFind example}{detailed
+ description} for an example usage.
+
+ \sa qLowerBound(), qUpperBound(), {random access iterators}
+*/
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ 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 void qBinaryFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qBinaryFind(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*!
+ \fn void qDeleteAll(ForwardIterator begin, ForwardIterator end)
+ \relates <QtAlgorithms>
+
+ Deletes all the items in the range [\a begin, \a end) using the
+ C++ \c delete operator. The item type must be a pointer type (for
+ example, \c{QWidget *}).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 23
+
+ Notice that qDeleteAll() doesn't remove the items from the
+ container; it merely calls \c delete on them. In the example
+ above, we call clear() on the container to remove the items.
+
+ This function can also be used to delete items stored in
+ associative containers, such as QMap and QHash. Only the objects
+ stored in each container will be deleted by this function; objects
+ used as keys will not be deleted.
+
+ \sa {forward iterators}
+*/
+
+/*!
+ \fn void qDeleteAll(const Container &c)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qDeleteAll(\a{c}.begin(), \a{c}.end()).
+*/
+
+/*! \fn LessThan qLess()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 24
+
+ \sa {qGreater()}{qGreater<T>()}
+*/
+
+/*! \fn LessThan qGreater()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 25
+
+ \sa {qLess()}{qLess<T>()}
+*/
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
new file mode 100644
index 0000000000..6181c82580
--- /dev/null
+++ b/src/corelib/tools/qbitarray.cpp
@@ -0,0 +1,738 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbitarray.h"
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBitArray
+ \brief The QBitArray class provides an array of bits.
+
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+ A QBitArray is an array that gives access to individual bits and
+ provides operators (\link operator&() AND\endlink, \link
+ operator|() OR\endlink, \link operator^() XOR\endlink, and \link
+ operator~() NOT\endlink) that work on entire arrays of bits. It
+ uses \l{implicit sharing} (copy-on-write) to reduce memory usage
+ and to avoid the needless copying of data.
+
+ The following code constructs a QBitArray containing 200 bits
+ initialized to false (0):
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 0
+
+ To initialize the bits to true, either pass \c true as second
+ argument to the constructor, or call fill() later on.
+
+ QBitArray uses 0-based indexes, just like C++ arrays. To access
+ the bit at a particular index position, you can use operator[]().
+ On non-const bit arrays, operator[]() returns a reference to a
+ bit that can be used on the left side of an assignment. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 1
+
+ For technical reasons, it is more efficient to use testBit() and
+ setBit() to access bits in the array than operator[](). For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 2
+
+ QBitArray supports \c{&} (\link operator&() AND\endlink), \c{|}
+ (\link operator|() OR\endlink), \c{^} (\link operator^()
+ XOR\endlink), \c{~} (\link operator~() NOT\endlink), as well as
+ \c{&=}, \c{|=}, and \c{^=}. These operators work in the same way
+ as the built-in C++ bitwise operators of the same name. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 3
+
+ For historical reasons, QBitArray distinguishes between a null
+ bit array and an empty bit array. A \e null bit array is a bit
+ array that is initialized using QBitArray's default constructor.
+ An \e empty bit array is any bit array with size 0. A null bit
+ array is always empty, but an empty bit array isn't necessarily
+ null:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 4
+
+ All functions except isNull() treat null bit arrays the same as
+ empty bit arrays; for example, QBitArray() compares equal to
+ QBitArray(0). We recommend that you always use isEmpty() and
+ avoid isNull().
+
+ \sa QByteArray, QVector
+*/
+
+/*! \fn QBitArray::QBitArray()
+
+ Constructs an empty bit array.
+
+ \sa isEmpty()
+*/
+
+/*!
+ 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)
+{
+ if (!size) {
+ d.resize(0);
+ return;
+ }
+ d.resize(1 + (size+7)/8);
+ uchar* c = reinterpret_cast<uchar*>(d.data());
+ memset(c, value ? 0xff : 0, d.size());
+ *c = d.size()*8 - size;
+ if (value && size && size % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
+}
+
+/*! \fn int QBitArray::size() const
+
+ Returns the number of bits stored in the bit array.
+
+ \sa resize()
+*/
+
+/*! \fn int QBitArray::count() const
+
+ Same as size().
+*/
+
+/*!
+ If \a on is true, this function returns the number of
+ 1-bits stored in the bit array; otherwise the number
+ of 0-bits is returned.
+*/
+int QBitArray::count(bool on) const
+{
+ int numBits = 0;
+ int len = size();
+#if 0
+ for (int i = 0; i < len; ++i)
+ numBits += testBit(i);
+#else
+ // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
+ while (len >= 32) {
+ quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24);
+ quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ len -= 32;
+ bits += 4;
+ numBits += int(c);
+ }
+ while (len >= 24) {
+ quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16);
+ quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ len -= 24;
+ bits += 3;
+ numBits += int(c);
+ }
+ while (len >= 0) {
+ if (bits[len / 8] & (1 << ((len - 1) & 7)))
+ ++numBits;
+ --len;
+ }
+#endif
+ return on ? numBits : size() - numBits;
+}
+
+/*!
+ Resizes the bit array to \a size bits.
+
+ If \a size is greater than the current size, the bit array is
+ extended to make it \a size bits with the extra bits added to the
+ end. The new bits are initialized to false (0).
+
+ If \a size is less than the current size, bits are removed from
+ the end.
+
+ \sa size()
+*/
+void QBitArray::resize(int size)
+{
+ if (!size) {
+ 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 % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
+ *c = d.size()*8 - size;
+ }
+}
+
+/*! \fn bool QBitArray::isEmpty() const
+
+ Returns true if this bit array has size 0; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn bool QBitArray::isNull() const
+
+ Returns true if this bit array is null; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 5
+
+ Qt makes a distinction between null bit arrays and empty bit
+ arrays for historical reasons. For most applications, what
+ matters is whether or not a bit array contains any data,
+ and this can be determined using isEmpty().
+
+ \sa isEmpty()
+*/
+
+/*! \fn bool QBitArray::fill(bool value, int size = -1)
+
+ Sets every bit in the bit array to \a value, returning true if successful;
+ otherwise returns false. If \a size is different from -1 (the default),
+ the bit array is resized to \a size beforehand.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 6
+
+ \sa resize()
+*/
+
+/*!
+ \overload
+
+ Sets bits at index positions \a begin up to and excluding \a end
+ to \a value.
+
+ \a begin and \a end must be a valid index position in the bit
+ array (i.e., 0 <= \a begin <= size() and 0 <= \a end <= size()).
+*/
+
+void QBitArray::fill(bool value, int begin, int end)
+{
+ while (begin < end && begin & 0x7)
+ setBit(begin++, value);
+ int len = end - begin;
+ if (len <= 0)
+ return;
+ int s = len & ~0x7;
+ uchar *c = reinterpret_cast<uchar*>(d.data());
+ memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
+ begin += s;
+ while (begin < end)
+ setBit(begin++, value);
+}
+
+/*! \fn bool QBitArray::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QBitArray::detach()
+
+ \internal
+*/
+
+/*! \fn void QBitArray::clear()
+
+ Clears the contents of the bit array and makes it empty.
+
+ \sa resize(), isEmpty()
+*/
+
+/*! \fn void QBitArray::truncate(int pos)
+
+ Truncates the bit array at index position \a pos.
+
+ If \a pos is beyond the end of the array, nothing happens.
+
+ \sa resize()
+*/
+
+/*! \fn bool QBitArray::toggleBit(int 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
+ it was unset).
+
+ If the previous value was 0, the new value will be 1. If the
+ previous value was 1, the new value will be 0.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::testBit(int i) const
+
+ Returns true if the bit at index position \a i is 1; otherwise
+ returns false.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::setBit(int i)
+
+ Sets the bit at index position \a i to 1.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa clearBit(), toggleBit()
+*/
+
+/*! \fn void QBitArray::setBit(int i, bool value)
+
+ \overload
+
+ Sets the bit at index position \a i to \a value.
+*/
+
+/*! \fn void QBitArray::clearBit(int i)
+
+ Sets the bit at index position \a i to 0.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), toggleBit()
+*/
+
+/*! \fn bool QBitArray::at(int i) const
+
+ Returns the value of the bit at index position \a i.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa operator[]()
+*/
+
+/*! \fn QBitRef QBitArray::operator[](int i)
+
+ Returns the bit at index position \a i as a modifiable reference.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 7
+
+ The return value is of type QBitRef, a helper class for QBitArray.
+ When you get an object of type QBitRef, you can assign to
+ it, and the assignment will apply to the bit in the QBitArray
+ from which you got the reference.
+
+ The functions testBit(), setBit(), and clearBit() are slightly
+ faster.
+
+ \sa at(), testBit(), setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::operator[](int i) const
+
+ \overload
+*/
+
+/*! \fn bool QBitArray::operator[](uint i)
+
+ \overload
+*/
+
+/*! \fn bool QBitArray::operator[](uint i) const
+
+ \overload
+*/
+
+/*! \fn QBitArray::QBitArray(const QBitArray &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QBitArray is
+ \l{implicitly shared}. This makes returning a QBitArray from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other)
+
+ Assigns \a other to this bit array and returns a reference to
+ this bit array.
+*/
+
+/*! \fn void QBitArray::swap(QBitArray &other)
+ \since 4.8
+
+ Swaps bit array \a other with this bit array. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QBitArray::operator==(const QBitArray &other) const
+
+ Returns true if \a other is equal to this bit array; otherwise
+ returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QBitArray::operator!=(const QBitArray &other) const
+
+ Returns true if \a other is not equal to this bit array;
+ otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ 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.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 8
+
+ \sa operator&(), operator|=(), operator^=(), operator~()
+*/
+
+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;
+}
+
+/*!
+ 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.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 9
+
+ \sa operator|(), operator&=(), operator^=(), operator~()
+*/
+
+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;
+}
+
+/*!
+ 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.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 10
+
+ \sa operator^(), operator&=(), operator|=(), operator~()
+*/
+
+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;
+}
+
+/*!
+ Returns a bit array that contains the inverted bits of this bit
+ array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 11
+
+ \sa operator&(), operator|(), operator^()
+*/
+
+QBitArray QBitArray::operator~() const
+{
+ 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;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the AND of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 12
+
+ \sa QBitArray::operator&=(), operator|(), operator^()
+*/
+
+QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp &= a2;
+ return tmp;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the OR of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 13
+
+ \sa QBitArray::operator|=(), operator&(), operator^()
+*/
+
+QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp |= a2;
+ return tmp;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the XOR of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 14
+
+ \sa QBitArray::operator^=(), operator&(), operator|()
+*/
+
+QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp ^= a2;
+ return tmp;
+}
+
+/*!
+ \class QBitRef
+ \reentrant
+ \brief The QBitRef class is an internal class, used with QBitArray.
+
+ \internal
+
+ The QBitRef is required by the indexing [] operator on bit arrays.
+ It is not for use in any other context.
+*/
+
+/*! \fn QBitRef::QBitRef (QBitArray& a, int i)
+
+ Constructs a reference to element \a i in the QBitArray \a a.
+ This is what QBitArray::operator[] constructs its return value
+ with.
+*/
+
+/*! \fn QBitRef::operator bool() const
+
+ Returns the value referenced by the QBitRef.
+*/
+
+/*! \fn bool QBitRef::operator!() const
+
+ \internal
+*/
+
+/*! \fn QBitRef& QBitRef::operator= (const QBitRef& v)
+
+ Sets the value referenced by the QBitRef to that referenced by
+ QBitRef \a v.
+*/
+
+/*! \fn QBitRef& QBitRef::operator= (bool v)
+ \overload
+
+ Sets the value referenced by the QBitRef to \a v.
+*/
+
+
+/*****************************************************************************
+ QBitArray stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QBitArray
+
+ Writes bit array \a ba to stream \a out.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
+{
+ quint32 len = ba.size();
+ out << len;
+ if (len > 0)
+ out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
+ return out;
+}
+
+/*!
+ \relates QBitArray
+
+ Reads a bit array into \a ba from stream \a in.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator>>(QDataStream &in, QBitArray &ba)
+{
+ ba.clear();
+ quint32 len;
+ in >> len;
+ if (len == 0) {
+ ba.clear();
+ return in;
+ }
+
+ const quint32 Step = 8 * 1024 * 1024;
+ quint32 totalBytes = (len + 7) / 8;
+ quint32 allocated = 0;
+
+ while (allocated < totalBytes) {
+ int blockSize = qMin(Step, totalBytes - allocated);
+ ba.d.resize(allocated + blockSize + 1);
+ if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadPastEnd);
+ return in;
+ }
+ allocated += blockSize;
+ }
+
+ int paddingMask = ~((0x1 << (len & 0x7)) - 1);
+ if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadCorruptData);
+ return in;
+ }
+
+ *ba.d.data() = ba.d.size() * 8 - len;
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn DataPtr &QBitArray::data_ptr()
+ \internal
+*/
+
+/*!
+ \typedef QBitArray::DataPtr
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
new file mode 100644
index 0000000000..cec338c394
--- /dev/null
+++ b/src/corelib/tools/qbitarray.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBITARRAY_H
+#define QBITARRAY_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QBitRef;
+class Q_CORE_EXPORT QBitArray
+{
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
+ friend Q_CORE_EXPORT uint qHash(const QBitArray &key);
+ QByteArray d;
+
+public:
+ inline QBitArray() {}
+ 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; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QBitArray &operator=(QBitArray &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QBitArray &other) { qSwap(d, 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;
+ // ### Qt 5: Store the number of set bits separately
+
+ inline bool isEmpty() const { return d.isEmpty(); }
+ inline bool isNull() const { return d.isNull(); }
+
+ void resize(int 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;
+
+ inline bool operator==(const QBitArray& a) const { return d == a.d; }
+ inline bool operator!=(const QBitArray& a) const { return d != a.d; }
+
+ inline bool fill(bool val, int size = -1);
+ void fill(bool val, int first, int last);
+
+ inline void truncate(int pos) { if (pos < size()) resize(pos); }
+
+public:
+ typedef QByteArray::DataPtr DataPtr;
+ inline DataPtr &data_ptr() { 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(i >= 0 && i < size());
+ return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; }
+
+inline void QBitArray::setBit(int i)
+{ Q_ASSERT(i >= 0 && i < size());
+ *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= uchar(1 << (i & 7)); }
+
+inline void QBitArray::clearBit(int i)
+{ Q_ASSERT(i >= 0 && i < 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(i >= 0 && i < 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); }
+
+class Q_CORE_EXPORT QBitRef
+{
+private:
+ QBitArray& a;
+ int i;
+ inline QBitRef(QBitArray& array, int 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; }
+};
+
+inline QBitRef QBitArray::operator[](int 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 &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
+#endif
+
+Q_DECLARE_TYPEINFO(QBitArray, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QBitArray)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBITARRAY_H
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
new file mode 100644
index 0000000000..1c9b6541e3
--- /dev/null
+++ b/src/corelib/tools/qbytearray.cpp
@@ -0,0 +1,4394 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbytearray.h"
+#include "qbytearraymatcher.h"
+#include "qtools_p.h"
+#include "qstring.h"
+#include "qlist.h"
+#include "qlocale.h"
+#include "qlocale_p.h"
+#include "qscopedpointer.h"
+#include <qdatastream.h>
+
+#ifndef QT_NO_COMPRESS
+#include <zlib.h>
+#endif
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define IS_RAW_DATA(d) ((d)->data != (d)->array)
+
+QT_BEGIN_NAMESPACE
+
+
+int qFindByteArray(
+ const char *haystack0, int haystackLen, int from,
+ const char *needle0, int needleLen);
+
+
+int qAllocMore(int alloc, int extra)
+{
+ if (alloc == 0 && extra == 0)
+ return 0;
+ const int page = 1 << 12;
+ int nalloc;
+ alloc += extra;
+ if (alloc < 1<<6) {
+ nalloc = (1<<3) + ((alloc >>3) << 3);
+ } else {
+ // don't do anything if the loop will overflow signed int.
+ if (alloc >= INT_MAX/2)
+ return INT_MAX;
+ nalloc = (alloc < page) ? 1 << 3 : page;
+ while (nalloc < alloc) {
+ if (nalloc <= 0)
+ return INT_MAX;
+ nalloc *= 2;
+ }
+ }
+ return nalloc - extra;
+}
+
+/*****************************************************************************
+ Safe and portable C string functions; extensions to standard string.h
+ *****************************************************************************/
+
+/*! \relates QByteArray
+
+ Returns a duplicate string.
+
+ Allocates space for a copy of \a src, copies it, and returns a
+ pointer to the copy. If \a src is 0, it immediately returns 0.
+
+ Ownership is passed to the caller, so the returned string must be
+ deleted using \c delete[].
+*/
+
+char *qstrdup(const char *src)
+{
+ if (!src)
+ return 0;
+ char *dst = new char[strlen(src) + 1];
+ return qstrcpy(dst, src);
+}
+
+/*! \relates QByteArray
+
+ Copies all the characters up to and including the '\\0' from \a
+ src into \a dst and returns a pointer to \a dst. If \a src is 0,
+ it immediately returns 0.
+
+ This function assumes that \a dst is large enough to hold the
+ contents of \a src.
+
+ \sa qstrncpy()
+*/
+
+char *qstrcpy(char *dst, const char *src)
+{
+ if (!src)
+ return 0;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ int len = qstrlen(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)
+ return dst;
+ return 0;
+#else
+ return strcpy(dst, src);
+#endif
+}
+
+/*! \relates QByteArray
+
+ 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 0, returns 0 immediately.
+
+ This function assumes that \a dst is at least \a len characters
+ long.
+
+ \note When compiling with Visual C++ compiler version 14.00
+ (Visual C++ 2005) or later, internally the function strncpy_s
+ will be used.
+
+ \sa qstrcpy()
+*/
+
+char *qstrncpy(char *dst, const char *src, uint len)
+{
+ if (!src || !dst)
+ return 0;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ strncpy_s(dst, len, src, len-1);
+#else
+ strncpy(dst, src, len);
+#endif
+ if (len > 0)
+ dst[len-1] = '\0';
+ return dst;
+}
+
+/*! \fn uint qstrlen(const char *str)
+ \relates QByteArray
+
+ A safe \c strlen() function.
+
+ Returns the number of characters that precede the terminating '\\0',
+ or 0 if \a str is 0.
+
+ \sa qstrnlen()
+*/
+
+/*! \fn uint qstrnlen(const char *str, uint maxlen)
+ \relates QByteArray
+ \since 4.2
+
+ A safe \c strnlen() function.
+
+ Returns the number of characters that precede the terminating '\\0', but
+ at most \a maxlen. If \a str is 0, returns 0.
+
+ \sa qstrlen()
+*/
+
+/*!
+ \relates QByteArray
+
+ A safe \c strcmp() function.
+
+ Compares \a str1 and \a str2. Returns a negative value if \a str1
+ is less than \a str2, 0 if \a str1 is equal to \a str2 or a
+ positive value if \a str1 is greater than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns an arbitrary non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+int qstrcmp(const char *str1, const char *str2)
+{
+ return (str1 && str2) ? strcmp(str1, str2)
+ : (str1 ? 1 : (str2 ? -1 : 0));
+}
+
+/*! \fn int qstrncmp(const char *str1, const char *str2, uint len);
+
+ \relates QByteArray
+
+ A safe \c strncmp() function.
+
+ Compares at most \a len bytes of \a str1 and \a str2.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a
+ str1 is equal to \a str2 or a positive value if \a str1 is greater
+ than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+
+/*! \relates QByteArray
+
+ A safe \c stricmp() function.
+
+ Compares \a str1 and \a str2 ignoring the case of the
+ characters. The encoding of the strings is assumed to be Latin-1.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a
+ str1 is equal to \a str2 or a positive value if \a str1 is greater
+ than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+
+int qstricmp(const char *str1, const char *str2)
+{
+ register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
+ register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ int res;
+ uchar c;
+ if (!s1 || !s2)
+ return s1 ? 1 : (s2 ? -1 : 0);
+ for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++)
+ if (!c) // strings are equal
+ break;
+ return res;
+}
+
+/*! \relates QByteArray
+
+ A safe \c strnicmp() function.
+
+ Compares at most \a len bytes of \a str1 and \a str2 ignoring the
+ case of the characters. The encoding of the strings is assumed to
+ be Latin-1.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a str1
+ is equal to \a str2 or a positive value if \a str1 is greater than \a
+ str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons}
+*/
+
+int qstrnicmp(const char *str1, const char *str2, uint len)
+{
+ register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
+ register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ int res;
+ uchar c;
+ if (!s1 || !s2)
+ return s1 ? 1 : (s2 ? -1 : 0);
+ for (; len--; s1++, s2++) {
+ if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)))
+ return res;
+ if (!c) // strings are equal
+ break;
+ }
+ return 0;
+}
+
+/*!
+ \internal
+ */
+int qstrcmp(const QByteArray &str1, const char *str2)
+{
+ if (!str2)
+ return str1.isEmpty() ? 0 : +1;
+
+ const char *str1data = str1.constData();
+ const char *str1end = str1data + str1.length();
+ for ( ; str1data < str1end && *str2; ++str1data, ++str2) {
+ register int diff = int(uchar(*str1data)) - uchar(*str2);
+ if (diff)
+ // found a difference
+ return diff;
+ }
+
+ // 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;
+}
+
+/*!
+ \internal
+ */
+int qstrcmp(const QByteArray &str1, const QByteArray &str2)
+{
+ int l1 = str1.length();
+ int l2 = str2.length();
+ int ret = memcmp(str1, str2, 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;
+}
+
+// the CRC table below is created by the following piece of code
+#if 0
+static void createCRC16Table() // build CRC16 lookup table
+{
+ register unsigned int i;
+ register unsigned int j;
+ unsigned short crc_tbl[16];
+ unsigned int v0, v1, v2, v3;
+ for (i = 0; i < 16; i++) {
+ v0 = i & 1;
+ v1 = (i >> 1) & 1;
+ v2 = (i >> 2) & 1;
+ v3 = (i >> 3) & 1;
+ j = 0;
+#undef SET_BIT
+#define SET_BIT(x, b, v) (x) |= (v) << (b)
+ SET_BIT(j, 0, v0);
+ SET_BIT(j, 7, v0);
+ SET_BIT(j, 12, v0);
+ SET_BIT(j, 1, v1);
+ SET_BIT(j, 8, v1);
+ SET_BIT(j, 13, v1);
+ SET_BIT(j, 2, v2);
+ SET_BIT(j, 9, v2);
+ SET_BIT(j, 14, v2);
+ SET_BIT(j, 3, v3);
+ SET_BIT(j, 10, v3);
+ SET_BIT(j, 15, v3);
+ crc_tbl[i] = j;
+ }
+ printf("static const quint16 crc_tbl[16] = {\n");
+ for (int i = 0; i < 16; i +=4)
+ printf(" 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n", crc_tbl[i], crc_tbl[i+1], crc_tbl[i+2], crc_tbl[i+3]);
+ printf("};\n");
+}
+#endif
+
+static const quint16 crc_tbl[16] = {
+ 0x0000, 0x1081, 0x2102, 0x3183,
+ 0x4204, 0x5285, 0x6306, 0x7387,
+ 0x8408, 0x9489, 0xa50a, 0xb58b,
+ 0xc60c, 0xd68d, 0xe70e, 0xf78f
+};
+
+/*!
+ \relates QByteArray
+
+ Returns the CRC-16 checksum of the first \a len bytes of \a data.
+
+ The checksum is independent of the byte order (endianness).
+
+ \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)
+{
+ register quint16 crc = 0xffff;
+ uchar c;
+ const uchar *p = reinterpret_cast<const uchar *>(data);
+ while (len--) {
+ c = *p++;
+ crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
+ c >>= 4;
+ crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
+ }
+ return ~crc & 0xffff;
+}
+
+/*!
+ \fn QByteArray qCompress(const QByteArray& data, int compressionLevel)
+
+ \relates QByteArray
+
+ Compresses the \a data byte array and returns the compressed data
+ in a new byte array.
+
+ The \a compressionLevel parameter specifies how much compression
+ should be used. Valid values are between 0 and 9, with 9
+ corresponding to the greatest compression (i.e. smaller compressed
+ data) at the cost of using a slower algorithm. Smaller values (8,
+ 7, ..., 1) provide successively less compression at slightly
+ faster speeds. The value 0 corresponds to no compression at all.
+ The default value is -1, which specifies zlib's default
+ compression.
+
+ \sa qUncompress()
+*/
+
+/*! \relates QByteArray
+
+ \overload
+
+ Compresses the first \a nbytes of \a data and returns the
+ compressed data in a new byte array.
+*/
+
+#ifndef QT_NO_COMPRESS
+QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
+{
+ if (nbytes == 0) {
+ return QByteArray(4, '\0');
+ }
+ if (!data) {
+ qWarning("qCompress: Data is null");
+ return QByteArray();
+ }
+ 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, (uchar*)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;
+ }
+ } while (res == Z_BUF_ERROR);
+
+ return bazip;
+}
+#endif
+
+/*!
+ \fn QByteArray qUncompress(const QByteArray &data)
+
+ \relates QByteArray
+
+ Uncompresses the \a data byte array and returns a new byte array
+ with the uncompressed data.
+
+ Returns an empty QByteArray if the input data was corrupt.
+
+ This function will uncompress data compressed with qCompress()
+ from this and any earlier Qt version, back to Qt 3.1 when this
+ feature was added.
+
+ \bold{Note:} If you want to use this function to uncompress external
+ 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.
+
+ \sa qCompress()
+*/
+
+/*! \relates QByteArray
+
+ \overload
+
+ Uncompresses the first \a nbytes of \a data and returns a new byte
+ array with the uncompressed data.
+*/
+
+#ifndef QT_NO_COMPRESS
+QByteArray qUncompress(const uchar* data, int 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 = (data[0] << 24) | (data[1] << 16) |
+ (data[2] << 8) | (data[3] );
+ ulong len = qMax(expectedSize, 1ul);
+ QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
+
+ forever {
+ ulong alloc = len;
+ if (len >= (1 << 31) - sizeof(QByteArray::Data)) {
+ //QByteArray does not support that huge size anyway.
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+ }
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc));
+ if (!p) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
+ }
+ d.take(); // realloc was successful
+ d.reset(p);
+
+ int res = ::uncompress((uchar*)d->array, &len,
+ (uchar*)data+4, nbytes-4);
+
+ switch (res) {
+ case Z_OK:
+ if (len != alloc) {
+ if (len >= (1 << 31) - sizeof(QByteArray::Data)) {
+ //QByteArray does not support that huge size anyway.
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+ }
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len));
+ if (!p) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
+ }
+ d.take(); // realloc was successful
+ d.reset(p);
+ }
+ d->ref = 1;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ d->array[len] = 0;
+
+ return QByteArray(d.take(), 0, 0);
+
+ case Z_MEM_ERROR:
+ qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
+ return QByteArray();
+
+ case Z_BUF_ERROR:
+ len *= 2;
+ continue;
+
+ case Z_DATA_ERROR:
+ qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
+ return QByteArray();
+ }
+ }
+}
+#endif
+
+static inline bool qIsUpper(char c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+static inline char qToLower(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A' + 'a';
+ else
+ return c;
+}
+
+QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_null.array, {0} };
+QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_empty.array, {0} };
+
+/*!
+ \class QByteArray
+ \brief The QByteArray class provides an array of bytes.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ \reentrant
+
+ 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
+ scenes, it always ensures that the data is followed by a '\\0'
+ terminator, and uses \l{implicit sharing} (copy-on-write) to
+ reduce memory usage and avoid needless copying of data.
+
+ In addition to QByteArray, Qt also provides the QString class to
+ store string data. For most purposes, QString is the class you
+ want to use. It stores 16-bit Unicode characters, making it easy
+ to store non-ASCII/non-Latin-1 characters in your application.
+ Furthermore, QString is used throughout in the Qt API. The two
+ main cases where QByteArray is appropriate are when you need to
+ store raw binary data, and when memory conservation is critical
+ (e.g., with Qt for Embedded Linux).
+
+ One way to initialize a QByteArray is simply to pass a \c{const
+ char *} to its constructor. For example, the following code
+ creates a byte array of size 5 containing the data "Hello":
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 0
+
+ Although the size() is 5, the byte array also maintains an extra
+ '\\0' character at the end so that if a function is used that
+ asks for a pointer to the underlying data (e.g. a call to
+ data()), the data pointed to is guaranteed to be
+ '\\0'-terminated.
+
+ QByteArray makes a deep copy of the \c{const char *} 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 QByteArray::fromRawData() instead.)
+
+ Another approach is to set the size of the array using resize()
+ and to initialize the data byte per byte. QByteArray uses 0-based
+ indexes, just like C++ arrays. To access the byte at a particular
+ index position, you can use operator[](). On non-const byte
+ arrays, operator[]() returns a reference to a byte that can be
+ used on the left side of an assignment. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 1
+
+ For read-only access, an alternative syntax is to use at():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 2
+
+ 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().
+
+ A QByteArray can embed '\\0' bytes. The size() function always
+ returns the size of the whole array, including embedded '\\0'
+ bytes. If you want to obtain the length of the data up to and
+ excluding the first '\\0' character, call qstrlen() on the byte
+ array.
+
+ After a call to resize(), newly allocated bytes have undefined
+ values. To set all the bytes to a particular value, call fill().
+
+ To obtain a pointer to the actual character data, call data() or
+ constData(). These functions return a pointer to the beginning of the data.
+ The pointer is guaranteed to remain valid until a non-const function is
+ called on the QByteArray. It is also guaranteed that the data ends with a
+ '\\0' byte unless the QByteArray was created from a \l{fromRawData()}{raw
+ data}. This '\\0' byte is automatically provided by QByteArray and is not
+ counted in size().
+
+ QByteArray provides the following basic functions for modifying
+ the byte data: append(), prepend(), insert(), replace(), and
+ remove(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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.
+
+ 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
+ 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.
+
+ A frequent requirement is to remove whitespace characters from a
+ byte array ('\\n', '\\t', ' ', etc.). If you want to remove
+ whitespace from both ends of a QByteArray, use trimmed(). If you
+ want to remove whitespace from both ends and replace multiple
+ consecutive whitespaces with a single space character within the
+ byte array, use simplified().
+
+ If you want to find all occurrences of a particular character or
+ substring in a QByteArray, use indexOf() or lastIndexOf(). 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's a typical loop that finds all occurrences of a
+ particular substring:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 4
+
+ If you simply want to check whether a QByteArray contains a
+ particular character or substring, use contains(). If you want to
+ find out how many times a particular character or substring
+ occurs in the byte array, use count(). If you want to replace all
+ occurrences of a particular value with another, use one of the
+ two-parameter replace() overloads.
+
+ QByteArrays can be compared using overloaded operators such as
+ operator<(), operator<=(), operator==(), operator>=(), and so on.
+ The comparison is based exclusively on the numeric values
+ of the characters and is very fast, but is not what a human would
+ expect. QString::localeAwareCompare() is a better choice for
+ sorting user-interface strings.
+
+ For historical reasons, QByteArray distinguishes between a null
+ byte array and an empty byte array. A \e null byte array is a
+ byte array that is initialized using QByteArray's default
+ constructor or by passing (const char *)0 to the constructor. An
+ \e empty byte array is any byte array with size 0. A null byte
+ array is always empty, but an empty byte array isn't necessarily
+ null:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 5
+
+ All functions except isNull() treat null byte arrays the same as
+ empty byte arrays. For example, data() returns a pointer to a
+ '\\0' character for a null byte array (\e not a null pointer),
+ and QByteArray() compares equal to QByteArray(""). We recommend
+ that you always use isEmpty() and avoid isNull().
+
+ \section1 Notes on Locale
+
+ \section2 Number-String Conversions
+
+ Functions that perform conversions between numeric data types and
+ strings are performed in the C locale, irrespective of the user's
+ locale settings. Use QString to perform locale-aware conversions
+ between numbers and strings.
+
+ \section2 8-bit Character Comparisons
+
+ In QByteArray, the notion of uppercase and lowercase and of which
+ character is greater than or less than another character is
+ locale dependent. This affects functions that support a case
+ insensitive option or that compare or lowercase or uppercase
+ their arguments. Case insensitive operations and comparisons will
+ be accurate if both strings contain only ASCII characters. (If \c
+ $LC_CTYPE is set, most Unix systems do "the right thing".)
+ Functions that this affects include contains(), indexOf(),
+ lastIndexOf(), operator<(), operator<=(), operator>(),
+ operator>=(), toLower() and toUpper().
+
+ This issue does not apply to QStrings since they represent
+ characters using Unicode.
+
+ \sa QString, QBitArray
+*/
+
+/*! \fn QByteArray::iterator QByteArray::begin()
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::begin() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::constBegin() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::iterator QByteArray::end()
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::end() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::constEnd() const
+
+ \internal
+*/
+
+/*! \fn void QByteArray::push_back(const QByteArray &other)
+
+ This function is provided for STL compatibility. It is equivalent
+ to append(\a other).
+*/
+
+/*! \fn void QByteArray::push_back(const char *str)
+
+ \overload
+
+ Same as append(\a str).
+*/
+
+/*! \fn void QByteArray::push_back(char ch)
+
+ \overload
+
+ Same as append(\a ch).
+*/
+
+/*! \fn void QByteArray::push_front(const QByteArray &other)
+
+ This function is provided for STL compatibility. It is equivalent
+ to prepend(\a other).
+*/
+
+/*! \fn void QByteArray::push_front(const char *str)
+
+ \overload
+
+ Same as prepend(\a str).
+*/
+
+/*! \fn void QByteArray::push_front(char ch)
+
+ \overload
+
+ Same as prepend(\a ch).
+*/
+
+/*! \fn QByteArray::QByteArray(const QByteArray &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QByteArray is
+ \l{implicitly shared}. This makes returning a QByteArray from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), taking \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QByteArray::~QByteArray()
+ Destroys the byte array.
+*/
+
+/*!
+ Assigns \a other to this byte array and returns a reference to
+ this byte array.
+*/
+QByteArray &QByteArray::operator=(const QByteArray & other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = other.d;
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Assigns \a str to this byte array.
+*/
+
+QByteArray &QByteArray::operator=(const char *str)
+{
+ Data *x;
+ if (!str) {
+ x = &shared_null;
+ } else if (!*str) {
+ x = &shared_empty;
+ } else {
+ int len = qstrlen(str);
+ if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
+ realloc(len);
+ x = d;
+ memcpy(x->data, str, len + 1); // include null terminator
+ x->size = len;
+ }
+ x->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ return *this;
+}
+
+/*! \fn void QByteArray::swap(QByteArray &other)
+ \since 4.8
+
+ Swaps byte array \a other with this byte array. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn int QByteArray::size() const
+
+ Returns the number of bytes in this byte array.
+
+ The last byte in the byte array is at position size() - 1. In addition,
+ QByteArray ensures that the byte at position size() is always '\\0', so
+ that 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 null-termination character then QByteArray doesn't add it
+ automaticall unless the \l{deep copy} is created.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 6
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QByteArray::isEmpty() const
+
+ Returns true if the byte array has size 0; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 7
+
+ \sa size()
+*/
+
+/*! \fn int QByteArray::capacity() const
+
+ Returns the maximum number of bytes that can be stored in the
+ byte array without forcing a reallocation.
+
+ 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 know how many
+ bytes are in the byte array, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QByteArray::reserve(int size)
+
+ 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
+ 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.
+
+ 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().
+
+ \sa squeeze(), capacity()
+*/
+
+/*! \fn void QByteArray::squeeze()
+
+ Releases any memory not required to store the array's data.
+
+ 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.
+
+ \sa reserve(), capacity()
+*/
+
+/*! \fn QByteArray::operator const char *() const
+ \fn QByteArray::operator const void *() 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 '\\0'-terminated. The pointer remains valid as long
+ as the array isn't reallocated or destroyed.
+
+ This operator is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_BYTEARRAY when you compile your applications.
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa constData()
+*/
+
+/*!
+ \macro QT_NO_CAST_FROM_BYTEARRAY
+ \relates QByteArray
+
+ Disables automatic conversions from QByteArray to
+ const char * or const void *.
+
+ \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII
+*/
+
+/*! \fn char *QByteArray::data()
+
+ Returns a pointer to the data stored in the byte array. The
+ pointer can be used to access and modify the bytes that compose
+ the array. The data is '\\0'-terminated, i.e. the number of
+ bytes in the returned character string is size() + 1 for the
+ '\\0' terminator.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_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.
+
+ This function is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ The following example makes a copy of the char* returned by
+ data(), but it will corrupt the heap and cause a crash because it
+ does not allocate a byte for the '\\0' at the end:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 46
+
+ This one allocates the correct amount of space:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 47
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const char *QByteArray::data() const
+
+ \overload
+*/
+
+/*! \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
+ '\\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.
+
+ This function is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa data(), operator[](), fromRawData()
+*/
+
+/*! \fn void QByteArray::detach()
+
+ \internal
+*/
+
+/*! \fn bool QByteArray::isDetached() const
+
+ \internal
+*/
+
+/*! \fn bool QByteArray::isSharedWith(const QByteArray &other) const
+
+ \internal
+*/
+
+/*! \fn char QByteArray::at(int i) const
+
+ Returns the character at index position \a i in the byte array.
+
+ \a i must be a valid index position in the byte array (i.e., 0 <=
+ \a i < size()).
+
+ \sa operator[]()
+*/
+
+/*! \fn QByteRef QByteArray::operator[](int i)
+
+ Returns the byte at index position \a i as a modifiable reference.
+
+ If an assignment is made beyond the end of the byte array, the
+ array is extended with resize() before the assignment takes
+ place.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 9
+
+ The return value is of type QByteRef, a helper class for
+ QByteArray. When you get an object of type QByteRef, you can use
+ it as if it were a char &. If you assign to it, the assignment
+ will apply to the character in the QByteArray from which you got
+ the reference.
+
+ \sa at()
+*/
+
+/*! \fn char QByteArray::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn QByteRef QByteArray::operator[](uint i)
+
+ \overload
+*/
+
+/*! \fn char QByteArray::operator[](uint i) const
+
+ \overload
+*/
+
+/*! \fn QBool QByteArray::contains(const QByteArray &ba) const
+
+ Returns true if the byte array contains an occurrence of the byte
+ array \a ba; otherwise returns false.
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn QBool QByteArray::contains(const char *str) const
+
+ \overload
+
+ Returns true if the byte array contains the string \a str;
+ otherwise returns false.
+*/
+
+/*! \fn QBool QByteArray::contains(char ch) const
+
+ \overload
+
+ Returns true if the byte array contains the character \a ch;
+ otherwise returns false.
+*/
+
+/*!
+
+ Truncates the byte array at index position \a pos.
+
+ If \a pos is beyond the end of the array, nothing happens.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 10
+
+ \sa chop(), resize(), left()
+*/
+void QByteArray::truncate(int pos)
+{
+ if (pos < d->size)
+ resize(pos);
+}
+
+/*!
+
+ Removes \a n bytes from the end of the byte array.
+
+ If \a n is greater than size(), the result is an empty byte
+ array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 11
+
+ \sa truncate(), resize(), left()
+*/
+
+void QByteArray::chop(int n)
+{
+ if (n > 0)
+ resize(d->size - n);
+}
+
+
+/*! \fn QByteArray &QByteArray::operator+=(const QByteArray &ba)
+
+ Appends the byte array \a ba onto the end of this byte array and
+ returns a reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 12
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this 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 \e this is not an empty QByteArray, 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.
+
+ \sa append(), prepend()
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(const QString &str)
+
+ \overload
+
+ Appends the string \a str onto the end of this byte array and
+ returns a reference to this byte array. The Unicode data is
+ converted into 8-bit characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ operator can lead to loss of information. You can disable this
+ operator by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(const char *str)
+
+ \overload
+
+ Appends the string \a str onto the end of this byte array and
+ returns a reference to this byte array.
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(char ch)
+
+ \overload
+
+ Appends the character \a ch onto the end of this byte array and
+ returns a reference to this byte array.
+*/
+
+/*! \fn int QByteArray::length() const
+
+ Same as size().
+*/
+
+/*! \fn bool QByteArray::isNull() const
+
+ Returns true if this byte array is null; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 13
+
+ Qt makes a distinction between null byte arrays and empty byte
+ arrays for historical reasons. For most applications, what
+ matters is whether or not a byte array contains any data,
+ and this can be determined using isEmpty().
+
+ \sa isEmpty()
+*/
+
+/*! \fn QByteArray::QByteArray()
+
+ Constructs an empty byte array.
+
+ \sa isEmpty()
+*/
+
+/*! \fn QByteArray::QByteArray(const char *str)
+
+ Constructs a byte array initialized with the string \a str.
+
+ QByteArray makes a deep copy of the string data.
+*/
+
+QByteArray::QByteArray(const char *str)
+{
+ if (!str) {
+ d = &shared_null;
+ } else if (!*str) {
+ d = &shared_empty;
+ } else {
+ int len = qstrlen(str);
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
+ Q_CHECK_PTR(d);
+ d->ref = 0;;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ memcpy(d->array, str, len+1); // include null terminator
+ }
+ d->ref.ref();
+}
+
+/*!
+ Constructs a byte array containing the first \a size bytes of
+ array \a data.
+
+ If \a data is 0, a null byte array is constructed.
+
+ QByteArray makes a deep copy of the string data.
+
+ \sa fromRawData()
+*/
+
+QByteArray::QByteArray(const char *data, int size)
+{
+ if (!data) {
+ d = &shared_null;
+ } else if (size <= 0) {
+ d = &shared_empty;
+ } else {
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ memcpy(d->array, data, size);
+ d->array[size] = '\0';
+ }
+ d->ref.ref();
+}
+
+/*!
+ Constructs a byte array of size \a size with every byte set to
+ character \a ch.
+
+ \sa fill()
+*/
+
+QByteArray::QByteArray(int size, char ch)
+{
+ if (size <= 0) {
+ d = &shared_null;
+ } else {
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+ memset(d->array, ch, size);
+ }
+ d->ref.ref();
+}
+
+/*!
+ \internal
+
+ Constructs a byte array of size \a size with uninitialized contents.
+*/
+
+QByteArray::QByteArray(int size, Qt::Initialization)
+{
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
+/*!
+ Sets the size of the byte array to \a size bytes.
+
+ If \a size is greater than the current size, the byte array is
+ 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.
+
+ \sa size(), truncate()
+*/
+
+void QByteArray::resize(int size)
+{
+ if (size <= 0) {
+ Data *x = &shared_empty;
+ x->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ } else if (d == &shared_null) {
+ //
+ // Optimize the idiom:
+ // QByteArray a;
+ // a.resize(sz);
+ // ...
+ // which is used in place of the Qt 3 idiom:
+ // QByteArray a(sz);
+ //
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(x);
+ x->ref = 1;
+ x->alloc = x->size = size;
+ x->data = x->array;
+ x->array[size] = '\0';
+ (void) d->ref.deref(); // cannot be 0, x points to shared_null
+ d = x;
+ } else {
+ if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
+ realloc(qAllocMore(size, sizeof(Data)));
+ if (d->alloc >= size) {
+ d->size = size;
+ if (d->data == d->array) {
+ d->array[size] = '\0';
+ }
+ }
+ }
+}
+
+/*!
+ Sets every byte in the byte array to character \a ch. If \a size
+ is different from -1 (the default), the byte array is resized to
+ size \a size beforehand.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 14
+
+ \sa resize()
+*/
+
+QByteArray &QByteArray::fill(char ch, int size)
+{
+ resize(size < 0 ? d->size : size);
+ if (d->size)
+ memset(d->data, ch, d->size);
+ return *this;
+}
+
+void QByteArray::realloc(int alloc)
+{
+ if (d->ref != 1 || d->data != d->array) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
+ Q_CHECK_PTR(x);
+ x->size = qMin(alloc, d->size);
+ ::memcpy(x->array, d->data, x->size);
+ x->array[x->size] = '\0';
+ x->ref = 1;
+ x->alloc = alloc;
+ x->data = x->array;
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ } else {
+ Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
+ Q_CHECK_PTR(x);
+ x->alloc = alloc;
+ x->data = x->array;
+ d = x;
+ }
+}
+
+void QByteArray::expand(int i)
+{
+ resize(qMax(i + 1, d->size));
+}
+
+/*!
+ \internal
+ Return a QByteArray that is sure to be NUL-terminated.
+
+ 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
+{
+ // is this fromRawData?
+ if (d->data == d->array)
+ return *this; // no, then we're sure we're zero terminated
+
+ QByteArray copy(*this);
+ copy.detach();
+ return copy;
+}
+
+/*!
+ Prepends the byte array \a ba to this byte array and returns a
+ reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 15
+
+ This is the same as insert(0, \a ba).
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this 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 \e this is not an empty QByteArray, a deep copy of the data is
+ performed, taking \l{linear time}.
+
+ \sa append(), insert()
+*/
+
+QByteArray &QByteArray::prepend(const QByteArray &ba)
+{
+ if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ *this = ba;
+ } else if (ba.d != &shared_null) {
+ QByteArray tmp = *this;
+ *this = ba;
+ append(tmp);
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Prepends the string \a str to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(const char *str)
+{
+ return prepend(str, qstrlen(str));
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Prepends \a len bytes of the string \a str to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(const char *str, int len)
+{
+ if (str) {
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memmove(d->data+len, d->data, d->size);
+ memcpy(d->data, str, len);
+ d->size += len;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Prepends the character \a ch to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(char ch)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(qAllocMore(d->size + 1, sizeof(Data)));
+ 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.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 16
+
+ This is the same as insert(size(), \a ba).
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this 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 \e this is not an empty QByteArray, 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.
+
+ \sa operator+=(), prepend(), insert()
+*/
+
+QByteArray &QByteArray::append(const QByteArray &ba)
+{
+ if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ *this = ba;
+ } else if (ba.d != &shared_null) {
+ if (d->ref != 1 || d->size + ba.d->size > d->alloc)
+ realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
+ memcpy(d->data + d->size, ba.d->data, ba.d->size);
+ d->size += ba.d->size;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*! \fn QByteArray &QByteArray::append(const QString &str)
+
+ \overload
+
+ Appends the string \a str to this byte array. The Unicode data is
+ converted into 8-bit characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*!
+ \overload
+
+ Appends the string \a str to this byte array.
+*/
+
+QByteArray& QByteArray::append(const char *str)
+{
+ if (str) {
+ int len = qstrlen(str);
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memcpy(d->data + d->size, str, len + 1); // include null terminator
+ d->size += len;
+ }
+ return *this;
+}
+
+/*!
+ \overload append()
+
+ Appends the first \a len characters of the string \a str to this byte
+ array and returns a reference to this byte array.
+
+ If \a len is negative, the length of the string will be determined
+ automatically using qstrlen(). If \a len is zero or \a str is
+ null, nothing is appended to the byte 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->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memcpy(d->data + d->size, str, len); // include null terminator
+ d->size += len;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Appends the character \a ch to this byte array.
+*/
+
+QByteArray& QByteArray::append(char ch)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(qAllocMore(d->size + 1, sizeof(Data)));
+ d->data[d->size++] = 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.
+*/
+static inline QByteArray &qbytearray_insert(QByteArray *ba,
+ int pos, const char *arr, int len)
+{
+ Q_ASSERT(pos >= 0);
+
+ if (pos < 0 || len <= 0 || arr == 0)
+ 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;
+}
+
+/*!
+ Inserts the byte array \a ba at index position \a i and returns a
+ reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 17
+
+ \sa append(), prepend(), replace(), remove()
+*/
+
+QByteArray &QByteArray::insert(int i, const QByteArray &ba)
+{
+ QByteArray copy(ba);
+ return qbytearray_insert(this, i, copy.d->data, copy.d->size);
+}
+
+/*!
+ \fn QByteArray &QByteArray::insert(int i, const QString &str)
+
+ \overload
+
+ Inserts the string \a str at index position \a i in the byte
+ array. The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*!
+ \overload
+
+ Inserts the string \a str at position \a i in the byte array.
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+*/
+
+QByteArray &QByteArray::insert(int i, const char *str)
+{
+ return qbytearray_insert(this, i, str, qstrlen(str));
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Inserts \a len bytes of the string \a str at position
+ \a i in the byte array.
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+*/
+
+QByteArray &QByteArray::insert(int i, const char *str, int len)
+{
+ return qbytearray_insert(this, i, str, len);
+}
+
+/*!
+ \overload
+
+ Inserts character \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().
+*/
+
+QByteArray &QByteArray::insert(int i, char ch)
+{
+ return qbytearray_insert(this, i, &ch, 1);
+}
+
+/*!
+ Removes \a len bytes from the array, starting at index position \a
+ pos, and returns a reference to the array.
+
+ If \a pos is out of range, nothing happens. If \a pos is valid,
+ but \a pos + \a len is larger than the size of the array, the
+ array is truncated at position \a pos.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 18
+
+ \sa insert(), replace()
+*/
+
+QByteArray &QByteArray::remove(int pos, int len)
+{
+ if (len <= 0 || pos >= d->size || pos < 0)
+ return *this;
+ detach();
+ if (pos + len >= d->size) {
+ resize(pos);
+ } else {
+ memmove(d->data + pos, d->data + pos + len, d->size - pos - len);
+ resize(d->size - len);
+ }
+ return *this;
+}
+
+/*!
+ Replaces \a len bytes from index position \a pos with the byte
+ array \a after, and returns a reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 19
+
+ \sa insert(), remove()
+*/
+
+QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
+{
+ if (len == after.d->size && (pos + len <= d->size)) {
+ detach();
+ memmove(d->data + pos, after.d->data, len*sizeof(char));
+ return *this;
+ } else {
+ QByteArray copy(after);
+ // ### optimize me
+ remove(pos, len);
+ return insert(pos, copy);
+ }
+}
+
+/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after)
+
+ \overload
+
+ Replaces \a len bytes from index position \a pos with the zero 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)
+
+ \overload
+
+ Replaces \a len bytes from index position \a pos with \a alen bytes
+ from the string \a after. \a after is allowed to have '\0' characters.
+
+ \since 4.7
+*/
+QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
+{
+ if (len == alen && (pos + len <= d->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)
+
+/*!
+ \overload
+
+ Replaces every occurrence of the byte array \a before with the
+ byte array \a after.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 20
+*/
+
+QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after)
+{
+ if (isNull() || before.d == after.d)
+ return *this;
+
+ QByteArray aft = after;
+ if (after.d == d)
+ aft.detach();
+
+ return replace(before.constData(), before.size(), aft.constData(), aft.size());
+}
+
+/*!
+ \fn QByteArray &QByteArray::replace(const char *before, const QByteArray &after)
+ \overload
+
+ Replaces every occurrence of the string \a before with the
+ byte array \a after.
+*/
+
+QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
+{
+ QByteArray aft = after;
+ if (after.d == d)
+ aft.detach();
+
+ return replace(c, qstrlen(c), aft.constData(), aft.size());
+}
+
+/*!
+ \fn QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
+ \overload
+
+ Replaces every occurrence of the string \a before with the string \a after.
+ Since the sizes of the strings are given by \a bsize and \a asize, they
+ may contain zero characters and do not need to be zero-terminated.
+*/
+
+QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
+{
+ if (isNull() || (before == after && bsize == asize))
+ return *this;
+
+ // protect against before or after being part of this
+ const char *a = after;
+ const char *b = before;
+ if (after >= d->data && after < d->data + d->size) {
+ char *copy = (char *)malloc(asize);
+ Q_CHECK_PTR(copy);
+ memcpy(copy, after, asize);
+ a = copy;
+ }
+ if (before >= d->data && before < d->data + d->size) {
+ char *copy = (char *)malloc(bsize);
+ Q_CHECK_PTR(copy);
+ memcpy(copy, before, bsize);
+ b = copy;
+ }
+
+ QByteArrayMatcher matcher(before, bsize);
+ int index = 0;
+ int len = d->size;
+ char *d = data();
+
+ if (bsize == asize) {
+ if (bsize) {
+ while ((index = matcher.indexIn(*this, index)) != -1) {
+ memcpy(d + index, after, asize);
+ index += bsize;
+ }
+ }
+ } else if (asize < bsize) {
+ uint to = 0;
+ uint movestart = 0;
+ uint num = 0;
+ while ((index = matcher.indexIn(*this, index)) != -1) {
+ if (num) {
+ int msize = index - movestart;
+ if (msize > 0) {
+ memmove(d + to, d + movestart, msize);
+ to += msize;
+ }
+ } else {
+ to = index;
+ }
+ if (asize) {
+ memcpy(d + to, after, asize);
+ to += asize;
+ }
+ index += bsize;
+ movestart = index;
+ num++;
+ }
+ if (num) {
+ int msize = len - movestart;
+ if (msize > 0)
+ memmove(d + to, d + movestart, msize);
+ resize(len - num*(bsize-asize));
+ }
+ } else {
+ // the most complex case. We don't want to lose performance by doing repeated
+ // copies and reallocs of the string.
+ while (index != -1) {
+ uint indices[4096];
+ uint pos = 0;
+ while(pos < 4095) {
+ index = matcher.indexIn(*this, index);
+ if (index == -1)
+ break;
+ indices[pos++] = index;
+ index += bsize;
+ // avoid infinite loop
+ if (!bsize)
+ index++;
+ }
+ if (!pos)
+ break;
+
+ // we have a table of replacement positions, use them for fast replacing
+ int 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;
+ if (newlen > len) {
+ resize(newlen);
+ len = newlen;
+ }
+ d = this->d->data;
+
+ while(pos) {
+ pos--;
+ int movestart = indices[pos] + bsize;
+ int insertstart = indices[pos] + pos*(asize-bsize);
+ int moveto = insertstart + asize;
+ memmove(d + moveto, d + movestart, (moveend - movestart));
+ if (asize)
+ memcpy(d + insertstart, after, asize);
+ moveend = movestart - bsize;
+ }
+ }
+ }
+
+ if (a != after)
+ ::free((char *)a);
+ if (b != before)
+ ::free((char *)b);
+
+
+ return *this;
+}
+
+
+/*!
+ \fn QByteArray &QByteArray::replace(const QByteArray &before, const char *after)
+ \overload
+
+ Replaces every occurrence of the byte array \a before with the
+ string \a after.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const QString &before, const QByteArray &after)
+
+ \overload
+
+ Replaces every occurrence of the string \a before with the byte
+ array \a after. The Unicode data is converted into 8-bit
+ characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const QString &before, const char *after)
+ \overload
+
+ Replaces every occurrence of the string \a before with the string
+ \a after.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const char *before, const char *after)
+
+ \overload
+
+ Replaces every occurrence of the string \a before with the string
+ \a after.
+*/
+
+/*!
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ byte array \a after.
+*/
+
+QByteArray &QByteArray::replace(char before, const QByteArray &after)
+{
+ char b[2] = { before, '\0' };
+ QByteArray cb = fromRawData(b, 1);
+ return replace(cb, after);
+}
+
+/*! \fn QByteArray &QByteArray::replace(char before, const QString &after)
+
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ string \a after. The Unicode data is converted into 8-bit
+ characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(char before, const char *after)
+
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ string \a after.
+*/
+
+/*!
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ character \a after.
+*/
+
+QByteArray &QByteArray::replace(char before, char after)
+{
+ if (d->size) {
+ char *i = data();
+ char *e = i + d->size;
+ for (; i != e; ++i)
+ if (*i == before)
+ * i = after;
+ }
+ return *this;
+}
+
+/*!
+ Splits the byte array into subarrays wherever \a sep occurs, and
+ returns the list of those arrays. If \a sep does not match
+ anywhere in the byte array, split() returns a single-element list
+ containing this byte array.
+*/
+
+QList<QByteArray> QByteArray::split(char sep) const
+{
+ QList<QByteArray> list;
+ int start = 0;
+ int end;
+ while ((end = indexOf(sep, start)) != -1) {
+ list.append(mid(start, end - start));
+ start = end + 1;
+ }
+ list.append(mid(start));
+ return list;
+}
+
+/*!
+ \since 4.5
+
+ Returns a copy of this byte array repeated the specified number of \a times.
+
+ If \a times is less than 1, an empty byte array is returned.
+
+ Example:
+
+ \code
+ QByteArray ba("ab");
+ ba.repeated(4); // returns "abababab"
+ \endcode
+*/
+QByteArray QByteArray::repeated(int times) const
+{
+ if (d->size == 0)
+ return *this;
+
+ if (times <= 1) {
+ if (times == 1)
+ return *this;
+ return QByteArray();
+ }
+
+ const int resultSize = times * d->size;
+
+ QByteArray result;
+ result.reserve(resultSize);
+ if (result.d->alloc != resultSize)
+ return QByteArray(); // not enough memory
+
+ memcpy(result.d->data, d->data, d->size);
+
+ int sizeSoFar = d->size;
+ char *end = result.d->data + sizeSoFar;
+
+ const int halfResultSize = resultSize >> 1;
+ while (sizeSoFar <= halfResultSize) {
+ memcpy(end, result.d->data, sizeSoFar);
+ end += sizeSoFar;
+ sizeSoFar <<= 1;
+ }
+ memcpy(end, result.d->data, resultSize - sizeSoFar);
+ result.d->data[resultSize] = '\0';
+ result.d->size = resultSize;
+ return result;
+}
+
+#define REHASH(a) \
+ if (ol_minus_1 < sizeof(uint) * CHAR_BIT) \
+ hashHaystack -= (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 doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 21
+
+ \sa lastIndexOf(), contains(), count()
+*/
+
+int QByteArray::indexOf(const QByteArray &ba, int from) const
+{
+ const int ol = ba.d->size;
+ if (ol == 0)
+ return from;
+ if (ol == 1)
+ return indexOf(*ba.d->data, from);
+
+ const int l = d->size;
+ if (from > d->size || ol + from > l)
+ return -1;
+
+ return qFindByteArray(d->data, d->size, from, ba.d->data, ol);
+}
+
+/*! \fn int QByteArray::indexOf(const QString &str, int from) const
+
+ \overload
+
+ Returns the index position of the first occurrence of the string
+ \a str in the byte array, searching forward from index position
+ \a from. Returns -1 if \a str could not be found.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn int QByteArray::indexOf(const char *str, int from) const
+
+ \overload
+
+ Returns the index position of the first occurrence of the 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);
+
+ const int l = d->size;
+ if (from > d->size || ol + from > l)
+ return -1;
+ if (ol == 0)
+ return from;
+
+ return qFindByteArray(d->data, d->size, from, c, ol);
+}
+
+/*!
+ \overload
+
+ Returns the index position of the first occurrence of the
+ character \a ch in the byte array, searching forward from index
+ position \a from. Returns -1 if \a ch could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 22
+
+ \sa lastIndexOf(), contains()
+*/
+
+int QByteArray::indexOf(char ch, int from) const
+{
+ if (from < 0)
+ from = qMax(from + d->size, 0);
+ if (from < d->size) {
+ const char *n = d->data + from - 1;
+ const char *e = d->data + d->size;
+ while (++n != e)
+ if (*n == ch)
+ return n - d->data;
+ }
+ return -1;
+}
+
+
+static int lastIndexOfHelper(const char *haystack, int l, const char *needle, int ol, int from)
+{
+ int delta = l - ol;
+ if (from < 0)
+ from = delta;
+ if (from < 0 || from > l)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ const char *end = haystack;
+ haystack += from;
+ const uint ol_minus_1 = ol - 1;
+ const char *n = needle + ol_minus_1;
+ const char *h = haystack + ol_minus_1;
+ uint hashNeedle = 0, hashHaystack = 0;
+ int idx;
+ for (idx = 0; idx < ol; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + *(n-idx));
+ hashHaystack = ((hashHaystack<<1) + *(h-idx));
+ }
+ hashHaystack -= *haystack;
+ while (haystack >= end) {
+ hashHaystack += *haystack;
+ if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(*(haystack + ol));
+ }
+ return -1;
+
+}
+
+/*!
+ \fn int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+
+ 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. Returns -1 if \a ba could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 23
+
+ \sa indexOf(), contains(), count()
+*/
+
+int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+{
+ const int ol = ba.d->size;
+ if (ol == 1)
+ return lastIndexOf(*ba.d->data, from);
+
+ return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from);
+}
+
+/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const
+
+ \overload
+
+ Returns the index position of the last occurrence of the 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 (size() - 1) byte. Returns -1 if \a str could not be found.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn int QByteArray::lastIndexOf(const char *str, int from) const
+ \overload
+
+ Returns the index position of the last occurrence of the 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 (size() - 1) byte. Returns -1 if \a str could not be found.
+*/
+int QByteArray::lastIndexOf(const char *str, int from) const
+{
+ const int ol = qstrlen(str);
+ if (ol == 1)
+ return lastIndexOf(*str, from);
+
+ return lastIndexOfHelper(d->data, d->size, str, ol, from);
+}
+
+/*!
+ \overload
+
+ Returns the index position of the last occurrence of character \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 (size() - 1) byte. Returns -1 if \a ch could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 24
+
+ \sa indexOf(), contains()
+*/
+
+int QByteArray::lastIndexOf(char ch, int from) const
+{
+ if (from < 0)
+ from += d->size;
+ else if (from > d->size)
+ from = d->size-1;
+ if (from >= 0) {
+ const char *b = d->data;
+ const char *n = d->data + from + 1;
+ while (n-- != b)
+ if (*n == ch)
+ return n - b;
+ }
+ return -1;
+}
+
+/*!
+ Returns the number of (potentially overlapping) occurrences of
+ byte array \a ba in this byte array.
+
+ \sa contains(), indexOf()
+*/
+
+int QByteArray::count(const QByteArray &ba) const
+{
+ int num = 0;
+ int i = -1;
+ if (d->size > 500 && ba.d->size > 5) {
+ QByteArrayMatcher matcher(ba);
+ while ((i = matcher.indexIn(*this, i + 1)) != -1)
+ ++num;
+ } else {
+ while ((i = indexOf(ba, i + 1)) != -1)
+ ++num;
+ }
+ return num;
+}
+
+/*!
+ \overload
+
+ Returns the number of (potentially overlapping) occurrences of
+ string \a str in the byte array.
+*/
+
+int QByteArray::count(const char *str) const
+{
+ return count(fromRawData(str, qstrlen(str)));
+}
+
+/*!
+ \overload
+
+ Returns the number of occurrences of character \a ch in the byte
+ array.
+
+ \sa contains(), indexOf()
+*/
+
+int QByteArray::count(char ch) const
+{
+ int num = 0;
+ const char *i = d->data + d->size;
+ const char *b = d->data;
+ while (i != b)
+ if (*--i == ch)
+ ++num;
+ return num;
+}
+
+/*! \fn int QByteArray::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*!
+ Returns true if this byte array starts with byte array \a ba;
+ otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 25
+
+ \sa endsWith(), left()
+*/
+bool QByteArray::startsWith(const QByteArray &ba) const
+{
+ if (d == ba.d || ba.d->size == 0)
+ return true;
+ if (d->size < ba.d->size)
+ return false;
+ return memcmp(d->data, ba.d->data, ba.d->size) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array starts with string \a str;
+ otherwise returns false.
+*/
+bool QByteArray::startsWith(const char *str) const
+{
+ if (!str || !*str)
+ return true;
+ int len = qstrlen(str);
+ if (d->size < len)
+ return false;
+ return qstrncmp(d->data, str, len) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array starts with character \a ch;
+ otherwise returns false.
+*/
+bool QByteArray::startsWith(char ch) const
+{
+ if (d->size == 0)
+ return false;
+ return d->data[0] == ch;
+}
+
+/*!
+ Returns true if this byte array ends with byte array \a ba;
+ otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 26
+
+ \sa startsWith(), right()
+*/
+bool QByteArray::endsWith(const QByteArray &ba) const
+{
+ if (d == ba.d || ba.d->size == 0)
+ return true;
+ if (d->size < ba.d->size)
+ return false;
+ return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array ends with string \a str; otherwise
+ returns false.
+*/
+bool QByteArray::endsWith(const char *str) const
+{
+ if (!str || !*str)
+ return true;
+ int len = qstrlen(str);
+ if (d->size < len)
+ return false;
+ return qstrncmp(d->data + d->size - len, str, len) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array ends with character \a ch;
+ otherwise returns false.
+*/
+bool QByteArray::endsWith(char ch) const
+{
+ if (d->size == 0)
+ return false;
+ return d->data[d->size - 1] == ch;
+}
+
+/*!
+ Returns a byte array that contains the leftmost \a len bytes of
+ this byte array.
+
+ The entire byte array is returned if \a len is greater than
+ size().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 27
+
+ \sa right(), mid(), startsWith(), truncate()
+*/
+
+QByteArray QByteArray::left(int len) const
+{
+ if (len >= d->size)
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(d->data, len);
+}
+
+/*!
+ Returns a byte array that contains the rightmost \a len bytes of
+ this byte array.
+
+ The entire byte array is returned if \a len is greater than
+ size().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 28
+
+ \sa endsWith(), left(), mid()
+*/
+
+QByteArray QByteArray::right(int len) const
+{
+ if (len >= d->size)
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(d->data + d->size - len, len);
+}
+
+/*!
+ Returns a byte array containing \a len bytes from this byte array,
+ starting at position \a pos.
+
+ 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 doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 29
+
+ \sa left(), right()
+*/
+
+QByteArray QByteArray::mid(int pos, int len) const
+{
+ if (d == &shared_null || d == &shared_empty || pos >= d->size)
+ return QByteArray();
+ if (len < 0)
+ len = d->size - pos;
+ if (pos < 0) {
+ len += pos;
+ pos = 0;
+ }
+ if (len + pos > d->size)
+ len = d->size - pos;
+ if (pos == 0 && len == d->size)
+ return *this;
+ return QByteArray(d->data + pos, len);
+}
+
+/*!
+ Returns a lowercase copy of the byte array. The bytearray is
+ interpreted as a Latin-1 encoded string.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 30
+
+ \sa toUpper(), {8-bit Character Comparisons}
+*/
+QByteArray QByteArray::toLower() const
+{
+ QByteArray s(*this);
+ register uchar *p = reinterpret_cast<uchar *>(s.data());
+ if (p) {
+ while (*p) {
+ *p = QChar::toLower((ushort)*p);
+ p++;
+ }
+ }
+ return s;
+}
+
+/*!
+ Returns an uppercase copy of the byte array. The bytearray is
+ interpreted as a Latin-1 encoded string.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 31
+
+ \sa toLower(), {8-bit Character Comparisons}
+*/
+
+QByteArray QByteArray::toUpper() const
+{
+ QByteArray s(*this);
+ register uchar *p = reinterpret_cast<uchar *>(s.data());
+ if (p) {
+ while (*p) {
+ *p = QChar::toUpper((ushort)*p);
+ p++;
+ }
+ }
+ return s;
+}
+
+/*! \fn void QByteArray::clear()
+
+ Clears the contents of the byte array and makes it empty.
+
+ \sa resize(), isEmpty()
+*/
+
+void QByteArray::clear()
+{
+ if (!d->ref.deref())
+ qFree(d);
+ d = &shared_null;
+ d->ref.ref();
+}
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+
+/*! \relates QByteArray
+
+ Writes byte array \a ba to the stream \a out and returns a reference
+ to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
+{
+ if (ba.isNull() && out.version() >= 6) {
+ out << (quint32)0xffffffff;
+ return out;
+ }
+ return out.writeBytes(ba, ba.size());
+}
+
+/*! \relates QByteArray
+
+ Reads a byte array into \a ba from the stream \a in and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QByteArray &ba)
+{
+ ba.clear();
+ quint32 len;
+ in >> len;
+ if (len == 0xffffffff)
+ return in;
+
+ const quint32 Step = 1024 * 1024;
+ quint32 allocated = 0;
+
+ do {
+ int blockSize = qMin(Step, len - allocated);
+ ba.resize(allocated + blockSize);
+ if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadPastEnd);
+ return in;
+ }
+ allocated += blockSize;
+ } while (allocated < len);
+
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*! \fn bool QByteArray::operator==(const QString &str) const
+
+ Returns true if this byte array is equal to string \a str;
+ otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator!=(const QString &str) const
+
+ Returns true if this byte array is not equal to string \a str;
+ otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator<(const QString &str) const
+
+ Returns true if this byte array is lexically less than string \a
+ str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator>(const QString &str) const
+
+ Returns true if this byte array is lexically greater than string
+ \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator<=(const QString &str) const
+
+ Returns true if this byte array is lexically less than or equal
+ to string \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator>=(const QString &str) const
+
+ Returns true if this byte array is greater than or equal to string
+ \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ 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::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool operator==(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator==(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is equal to string \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator==(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is not equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is not equal to string \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is not equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator<(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn inline bool operator<(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than string
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically less than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than or equal
+ to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than or equal
+ to string \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically less than or equal
+ to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than byte
+ array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than string
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically greater than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than or
+ equal to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than or
+ equal to string \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically greater than or
+ equal to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and byte array \a a2.
+
+ \sa QByteArray::operator+=()
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and string \a a2.
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, char a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and character \a a2.
+*/
+
+/*! \fn const QByteArray operator+(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating string
+ \a a1 and byte array \a a2.
+*/
+
+/*! \fn const QByteArray operator+(char a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating character
+ \a a1 and byte array \a a2.
+*/
+
+/*!
+ Returns a byte array that has whitespace removed from the start
+ and the end, and which has each sequence of internal whitespace
+ replaced with a single space.
+
+ Whitespace means any character for which the standard C++
+ isspace() function returns true. This includes the ASCII
+ characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 32
+
+ \sa trimmed()
+*/
+QByteArray QByteArray::simplified() const
+{
+ if (d->size == 0)
+ return *this;
+ QByteArray result(d->size, Qt::Uninitialized);
+ const char *from = d->data;
+ const char *fromend = from + d->size;
+ int outc=0;
+ char *to = result.d->data;
+ for (;;) {
+ while (from!=fromend && isspace(uchar(*from)))
+ from++;
+ while (from!=fromend && !isspace(uchar(*from)))
+ to[outc++] = *from++;
+ if (from!=fromend)
+ to[outc++] = ' ';
+ else
+ break;
+ }
+ if (outc > 0 && to[outc-1] == ' ')
+ outc--;
+ result.resize(outc);
+ return result;
+}
+
+/*!
+ Returns a byte array that has whitespace removed from the start
+ and the end.
+
+ Whitespace means any character for which the standard C++
+ isspace() function returns true. This includes the ASCII
+ characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 33
+
+ Unlike simplified(), trimmed() leaves internal whitespace alone.
+
+ \sa simplified()
+*/
+QByteArray QByteArray::trimmed() const
+{
+ if (d->size == 0)
+ return *this;
+ const char *s = d->data;
+ if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
+ return *this;
+ int start = 0;
+ int end = d->size - 1;
+ while (start<=end && isspace(uchar(s[start]))) // skip white space from start
+ start++;
+ if (start <= end) { // only white space
+ while (end && isspace(uchar(s[end]))) // skip white space from end
+ end--;
+ }
+ int l = end - start + 1;
+ if (l <= 0) {
+ shared_empty.ref.ref();
+ return QByteArray(&shared_empty, 0, 0);
+ }
+ return QByteArray(s+start, l);
+}
+
+/*!
+ Returns a byte array of size \a width that contains this byte
+ array padded by the \a fill character.
+
+ If \a truncate is false and the size() of the byte array is more
+ than \a width, then the returned byte array is a copy of this byte
+ array.
+
+ If \a truncate is true and the size() of the byte array is more
+ than \a width, then any bytes in a copy of the byte array
+ after position \a width are removed, and the copy is returned.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 34
+
+ \sa rightJustified()
+*/
+
+QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
+{
+ QByteArray result;
+ int len = d->size;
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ if (len)
+ memcpy(result.d->data, d->data, len);
+ memset(result.d->data+len, fill, padlen);
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+/*!
+ Returns a byte array of size \a width that contains the \a fill
+ character followed by this byte array.
+
+ If \a truncate is false and the size of the byte array is more
+ than \a width, then the returned byte array is a copy of this byte
+ array.
+
+ If \a truncate is true and the size of the byte array is more
+ than \a width, then the resulting byte array is truncated at
+ position \a width.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 35
+
+ \sa leftJustified()
+*/
+
+QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
+{
+ QByteArray result;
+ int len = d->size;
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ if (len)
+ memcpy(result.d->data+padlen, data(), len);
+ memset(result.d->data, fill, padlen);
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+bool QByteArray::isNull() const { return d == &shared_null; }
+
+
+/*!
+ Returns the byte array converted to a \c {long long} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+qlonglong QByteArray::toLongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QByteArray::toLongLong: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+
+ return QLocalePrivate::bytearrayToLongLong(nulTerminated().constData(), base, ok);
+}
+
+/*!
+ Returns the byte array 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.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+qulonglong QByteArray::toULongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QByteArray::toULongLong: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+
+ return QLocalePrivate::bytearrayToUnsLongLong(nulTerminated().constData(), base, ok);
+}
+
+
+/*!
+ Returns the byte array converted to an \c int using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 36
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+int QByteArray::toInt(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < INT_MIN || v > INT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return int(v);
+}
+
+/*!
+ Returns the byte array converted to an \c {unsigned int} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+uint QByteArray::toUInt(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > UINT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return uint(v);
+}
+
+/*!
+ \since 4.1
+
+ Returns the byte array converted to a \c long int using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 37
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+long QByteArray::toLong(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < LONG_MIN || v > LONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return long(v);
+}
+
+/*!
+ \since 4.1
+
+ Returns the byte array converted to an \c {unsigned long int} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+ulong QByteArray::toULong(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > ULONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return ulong(v);
+}
+
+/*!
+ Returns the byte array converted to a \c short using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+short QByteArray::toShort(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < SHRT_MIN || v > SHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return short(v);
+}
+
+/*!
+ Returns the byte array converted to an \c {unsigned short} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ 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; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+ushort QByteArray::toUShort(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > USHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return ushort(v);
+}
+
+
+/*!
+ Returns the byte array converted to a \c double value.
+
+ Returns 0.0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 38
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+double QByteArray::toDouble(bool *ok) const
+{
+ return QLocalePrivate::bytearrayToDouble(nulTerminated().constData(), ok);
+}
+
+/*!
+ Returns the byte array converted to a \c float value.
+
+ Returns 0.0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+float QByteArray::toFloat(bool *ok) const
+{
+ return float(toDouble(ok));
+}
+
+/*!
+ Returns a copy of the byte array, encoded as Base64.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 39
+
+ The algorithm used to encode Base64-encoded data is defined in \l{RFC 2045}.
+
+ \sa fromBase64()
+*/
+QByteArray QByteArray::toBase64() const
+{
+ const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+ "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
+ const char padchar = '=';
+ int padlen = 0;
+
+ QByteArray tmp((d->size * 4) / 3 + 3, Qt::Uninitialized);
+
+ int i = 0;
+ char *out = tmp.data();
+ while (i < d->size) {
+ int chunk = 0;
+ chunk |= int(uchar(d->data[i++])) << 16;
+ if (i == d->size) {
+ padlen = 2;
+ } else {
+ chunk |= int(uchar(d->data[i++])) << 8;
+ if (i == d->size) padlen = 1;
+ else chunk |= int(uchar(d->data[i++]));
+ }
+
+ int j = (chunk & 0x00fc0000) >> 18;
+ int k = (chunk & 0x0003f000) >> 12;
+ int l = (chunk & 0x00000fc0) >> 6;
+ int m = (chunk & 0x0000003f);
+ *out++ = alphabet[j];
+ *out++ = alphabet[k];
+ if (padlen > 1) *out++ = padchar;
+ else *out++ = alphabet[l];
+ if (padlen > 0) *out++ = padchar;
+ else *out++ = alphabet[m];
+ }
+
+ tmp.truncate(out - tmp.data());
+ return tmp;
+}
+
+/*!
+ \fn QByteArray &QByteArray::setNum(int n, int base)
+
+ Sets the byte array to the printed value of \a n in base \a base (10
+ by default) and returns a reference to the byte array. The \a base can
+ be any value between 2 and 36.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 40
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa number(), toInt()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(uint n, int base)
+ \overload
+
+ \sa toUInt()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(short n, int base)
+ \overload
+
+ \sa toShort()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(ushort n, int base)
+ \overload
+
+ \sa toUShort()
+*/
+
+/*!
+ \overload
+
+ \sa toLongLong()
+*/
+
+QByteArray &QByteArray::setNum(qlonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->longLongToString(n, -1, base).toLatin1();
+ return *this;
+}
+
+/*!
+ \overload
+
+ \sa toULongLong()
+*/
+
+QByteArray &QByteArray::setNum(qulonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->unsLongLongToString(n, -1, base).toLatin1();
+ return *this;
+}
+
+/*!
+ \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 \i Format \i Meaning
+ \row \i \c e \i format as [-]9.9e[+|-]999
+ \row \i \c E \i format as [-]9.9E[+|-]999
+ \row \i \c f \i format as [-]9.9
+ \row \i \c g \i use \c e or \c f format, whichever is the most concise
+ \row \i \c G \i 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).
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toDouble()
+*/
+
+QByteArray &QByteArray::setNum(double n, char f, int prec)
+{
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ uint flags = 0;
+
+ if (qIsUpper(f))
+ flags = QLocalePrivate::CapitalEorX;
+ f = qToLower(f);
+
+ switch (f) {
+ case 'f':
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case 'e':
+ form = QLocalePrivate::DFExponent;
+ break;
+ case 'g':
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ default:
+#if defined(QT_CHECK_RANGE)
+ qWarning("QByteArray::setNum: Invalid format char '%c'", f);
+#endif
+ break;
+ }
+
+ QLocale locale(QLocale::C);
+ *this = locale.d()->doubleToString(n, prec, form, -1, flags).toLatin1();
+ return *this;
+}
+
+/*!
+ \fn QByteArray &QByteArray::setNum(float n, char f, int prec)
+ \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.
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toFloat()
+*/
+
+/*!
+ Returns a byte array containing the string equivalent of the
+ number \a n to base \a base (10 by default). The \a base can be
+ any value between 2 and 36.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 41
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa setNum(), toInt()
+*/
+QByteArray QByteArray::number(int n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toUInt()
+*/
+QByteArray QByteArray::number(uint n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toLongLong()
+*/
+QByteArray QByteArray::number(qlonglong n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toULongLong()
+*/
+QByteArray QByteArray::number(qulonglong n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ 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 \i Format \i Meaning
+ \row \i \c e \i format as [-]9.9e[+|-]999
+ \row \i \c E \i format as [-]9.9E[+|-]999
+ \row \i \c f \i format as [-]9.9
+ \row \i \c g \i use \c e or \c f format, whichever is the most concise
+ \row \i \c G \i 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).
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 42
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toDouble()
+*/
+QByteArray QByteArray::number(double n, char f, int prec)
+{
+ QByteArray s;
+ s.setNum(n, f, prec);
+ return s;
+}
+
+/*!
+ 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
+ will not be deleted or modified as long as this QByteArray and any
+ copies of it exist that have not been modified. In other words,
+ because QByteArray is an \l{implicitly shared} class and the
+ instance returned by this function contains the \a data pointer,
+ the caller must not delete \a data or modify it directly as long
+ as the returned QByteArray and any copies exist. However,
+ QByteArray does not take ownership of \a data, so the QByteArray
+ destructor will never delete the raw \a data, even when the
+ last QByteArray referring to \a data is destroyed.
+
+ A subsequent attempt to modify the contents of the returned
+ QByteArray or any copy made from it will cause it to create a deep
+ copy of the \a data array before doing the modification. This
+ ensures that the raw \a data array itself will never be modified
+ by QByteArray.
+
+ Here is an example of how to read data using a QDataStream on raw
+ data in memory without copying the raw data into a QByteArray:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 43
+
+ \warning A byte array created with fromRawData() is \e not
+ null-terminated, unless the raw data contains a 0 character at
+ position \a size. While that does not matter for QDataStream or
+ functions like indexOf(), passing the byte array to a function
+ accepting a \c{const char *} expected to be '\\0'-terminated will
+ fail.
+
+ \sa setRawData(), data(), constData()
+*/
+
+QByteArray QByteArray::fromRawData(const char *data, int size)
+{
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
+ if (data) {
+ x->data = const_cast<char *>(data);
+ } else {
+ x->data = x->array;
+ size = 0;
+ }
+ x->ref = 1;
+ x->alloc = x->size = size;
+ *x->array = '\0';
+ return QByteArray(x, 0, 0);
+}
+
+/*!
+ \since 4.7
+
+ Resets the QByteArray to use 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
+ will not be deleted or modified as long as this QByteArray and any
+ copies of it exist that have not been modified.
+
+ This function can be used instead of fromRawData() to re-use
+ existings QByteArray objects to save memory re-allocations.
+
+ \sa fromRawData(), data(), constData()
+*/
+QByteArray &QByteArray::setRawData(const char *data, uint size)
+{
+ if (d->ref != 1 || d->alloc) {
+ *this = fromRawData(data, size);
+ } else {
+ if (data) {
+ d->data = const_cast<char *>(data);
+ } else {
+ d->data = d->array;
+ size = 0;
+ }
+ d->alloc = d->size = size;
+ *d->array = '\0';
+ }
+ return *this;
+}
+
+/*!
+ Returns a decoded copy of the Base64 array \a base64. Input is not checked
+ for validity; invalid characters in the input are skipped, enabling the
+ decoding process to continue with subsequent characters.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 44
+
+ The algorithm used to decode Base64-encoded data is defined in \l{RFC 2045}.
+
+ \sa toBase64()
+*/
+QByteArray QByteArray::fromBase64(const QByteArray &base64)
+{
+ unsigned int buf = 0;
+ int nbits = 0;
+ QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized);
+
+ int offset = 0;
+ for (int i = 0; i < base64.size(); ++i) {
+ int ch = base64.at(i);
+ int d;
+
+ if (ch >= 'A' && ch <= 'Z')
+ d = ch - 'A';
+ else if (ch >= 'a' && ch <= 'z')
+ d = ch - 'a' + 26;
+ else if (ch >= '0' && ch <= '9')
+ d = ch - '0' + 52;
+ else if (ch == '+')
+ d = 62;
+ else if (ch == '/')
+ d = 63;
+ else
+ d = -1;
+
+ if (d != -1) {
+ buf = (buf << 6) | d;
+ nbits += 6;
+ if (nbits >= 8) {
+ nbits -= 8;
+ tmp[offset++] = buf >> nbits;
+ buf &= (1 << nbits) - 1;
+ }
+ }
+ }
+
+ tmp.truncate(offset);
+ return tmp;
+}
+
+/*!
+ 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:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 45
+
+ \sa toHex()
+*/
+QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
+{
+ QByteArray res((hexEncoded.size() + 1)/ 2, Qt::Uninitialized);
+ uchar *result = (uchar *)res.data() + res.size();
+
+ bool odd_digit = true;
+ for (int i = hexEncoded.size() - 1; i >= 0; --i) {
+ int ch = hexEncoded.at(i);
+ int tmp;
+ if (ch >= '0' && ch <= '9')
+ tmp = ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ tmp = ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F')
+ tmp = ch - 'A' + 10;
+ else
+ continue;
+ if (odd_digit) {
+ --result;
+ *result = tmp;
+ odd_digit = false;
+ } else {
+ *result |= tmp << 4;
+ odd_digit = true;
+ }
+ }
+
+ res.remove(0, result - (const uchar *)res.constData());
+ return res;
+}
+
+/*!
+ Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
+ the letters a-f.
+
+ \sa fromHex()
+*/
+QByteArray QByteArray::toHex() const
+{
+ QByteArray hex(d->size * 2, Qt::Uninitialized);
+ char *hexData = hex.data();
+ const uchar *data = (const uchar *)d->data;
+ for (int i = 0; i < d->size; ++i) {
+ int j = (data[i] >> 4) & 0xf;
+ if (j <= 9)
+ hexData[i*2] = (j + '0');
+ else
+ hexData[i*2] = (j + 'a' - 10);
+ j = data[i] & 0xf;
+ if (j <= 9)
+ hexData[i*2+1] = (j + '0');
+ else
+ hexData[i*2+1] = (j + 'a' - 10);
+ }
+ return hex;
+}
+
+static void q_fromPercentEncoding(QByteArray *ba, char percent)
+{
+ if (ba->isEmpty())
+ return;
+
+ char *data = ba->data();
+ const char *inputPtr = data;
+
+ int i = 0;
+ int len = ba->count();
+ int outlen = 0;
+ int a, b;
+ char c;
+ while (i < len) {
+ c = inputPtr[i];
+ if (c == percent && i + 2 < len) {
+ a = inputPtr[++i];
+ b = inputPtr[++i];
+
+ if (a >= '0' && a <= '9') a -= '0';
+ else if (a >= 'a' && a <= 'f') a = a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F') a = a - 'A' + 10;
+
+ if (b >= '0' && b <= '9') b -= '0';
+ else if (b >= 'a' && b <= 'f') b = b - 'a' + 10;
+ else if (b >= 'A' && b <= 'F') b = b - 'A' + 10;
+
+ *data++ = (char)((a << 4) | b);
+ } else {
+ *data++ = c;
+ }
+
+ ++i;
+ ++outlen;
+ }
+
+ if (outlen != len)
+ ba->truncate(outlen);
+}
+
+void q_fromPercentEncoding(QByteArray *ba)
+{
+ q_fromPercentEncoding(ba, '%');
+}
+
+/*!
+ \since 4.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 '=').
+
+ For example:
+ \code
+ QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33");
+ text.data(); // returns "Qt is great!"
+ \endcode
+
+ \sa toPercentEncoding(), QUrl::fromPercentEncoding()
+*/
+QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent)
+{
+ if (input.isNull())
+ return QByteArray(); // preserve null
+ if (input.isEmpty())
+ return QByteArray(input.data(), 0);
+
+ QByteArray tmp = input;
+ q_fromPercentEncoding(&tmp, percent);
+ return tmp;
+}
+
+static inline bool q_strchr(const char str[], char chr)
+{
+ if (!str) return false;
+
+ const char *ptr = str;
+ char c;
+ while ((c = *ptr++))
+ if (c == chr)
+ return true;
+ return false;
+}
+
+static inline char toHexHelper(char c)
+{
+ static const char hexnumbers[] = "0123456789ABCDEF";
+ return hexnumbers[c & 0xf];
+}
+
+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 = 0;
+ 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++] = toHexHelper((c & 0xf0) >> 4);
+ output[length++] = toHexHelper(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, 0, '%');
+}
+
+/*!
+ \since 4.4
+
+ Returns a URI/URL-style percent-encoded copy of this byte array. The
+ \a percent parameter allows you to override the default '%'
+ character for another.
+
+ By default, this function will encode all characters that are not
+ one of the following:
+
+ ALPHA ("a" to "z" and "A" to "Z") / DIGIT (0 to 9) / "-" / "." / "_" / "~"
+
+ To prevent characters from being encoded pass them to \a
+ exclude. To force characters to be encoded pass them to \a
+ include. The \a percent character is always encoded.
+
+ Example:
+
+ \code
+ QByteArray text = "{a fishy string?}";
+ QByteArray ba = text.toPercentEncoding("{}", "s");
+ qDebug(ba.constData());
+ // prints "{a fi%73hy %73tring%3F}"
+ \endcode
+
+ The hex encoding uses the numbers 0-9 and the uppercase letters A-F.
+
+ \sa fromPercentEncoding(), QUrl::toPercentEncoding()
+*/
+QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteArray &include,
+ char percent) const
+{
+ if (isNull())
+ return QByteArray(); // preserve null
+ 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;
+
+ QByteArray result = *this;
+ q_toPercentEncoding(&result, exclude.nulTerminated().constData(), include2.nulTerminated().constData(), percent);
+
+ return result;
+}
+
+/*! \typedef QByteArray::ConstIterator
+ \internal
+*/
+
+/*! \typedef QByteArray::Iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::const_iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::const_reference
+ \internal
+*/
+
+/*! \typedef QByteArray::reference
+ \internal
+*/
+
+/*! \typedef QByteArray::value_type
+ \internal
+ */
+
+/*!
+ \fn QByteArray::QByteArray(int size)
+
+ Use QByteArray(int, char) instead.
+*/
+
+
+/*!
+ \fn QByteArray QByteArray::leftJustify(uint width, char fill, bool truncate) const
+
+ Use leftJustified() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::rightJustify(uint width, char fill, bool truncate) const
+
+ Use rightJustified() instead.
+*/
+
+/*!
+ \fn QByteArray& QByteArray::duplicate(const QByteArray& a)
+
+ \oldcode
+ QByteArray bdata;
+ bdata.duplicate(original);
+ \newcode
+ QByteArray bdata;
+ bdata = original;
+ \endcode
+
+ \note QByteArray uses implicit sharing so if you modify a copy, only the
+ copy is changed.
+*/
+
+/*!
+ \fn QByteArray& QByteArray::duplicate(const char *a, uint n)
+
+ \overload
+
+ \oldcode
+ QByteArray bdata;
+ bdata.duplicate(ptr, size);
+ \newcode
+ QByteArray bdata;
+ bdata = QByteArray(ptr, size);
+ \endcode
+
+ \note QByteArray uses implicit sharing so if you modify a copy, only the
+ copy is changed.
+*/
+
+/*!
+ \fn void QByteArray::resetRawData(const char *data, uint n)
+
+ Use clear() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::lower() const
+
+ Use toLower() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::upper() const
+
+ Use toUpper() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::stripWhiteSpace() const
+
+ Use trimmed() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::simplifyWhiteSpace() const
+
+ Use simplified() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(char c, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const char *c, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const QByteArray &ba, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(char c, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const char *c, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const QByteArray &ba, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const QString &s, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const QString &s, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn DataPtr &QByteArray::data_ptr()
+ \internal
+*/
+
+/*!
+ \typedef QByteArray::DataPtr
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
new file mode 100644
index 0000000000..0627b4e568
--- /dev/null
+++ b/src/corelib/tools/qbytearray.h
@@ -0,0 +1,622 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEARRAY_H
+#define QBYTEARRAY_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qnamespace.h>
+
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef truncate
+#error qbytearray.h must be included before any header file that defines truncate
+#endif
+
+#if defined(Q_CC_GNU) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
+//There is a bug in GCC 4.0 that tries to instantiate template of annonymous enum
+# ifdef QT_USE_FAST_OPERATOR_PLUS
+# undef QT_USE_FAST_OPERATOR_PLUS
+# endif
+# ifdef QT_USE_FAST_CONCATENATION
+# undef QT_USE_FAST_CONCATENATION
+# endif
+#endif
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*****************************************************************************
+ 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));
+}
+Q_CORE_EXPORT int qstricmp(const char *, const char *);
+Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len);
+
+// 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, ...);
+
+#ifdef QT3_SUPPORT
+inline QT3_SUPPORT void *qmemmove(void *dst, const void *src, uint len)
+{ return memmove(dst, src, len); }
+inline QT3_SUPPORT uint cstrlen(const char *str)
+{ return uint(strlen(str)); }
+inline QT3_SUPPORT char *cstrcpy(char *dst, const char *src)
+{ return qstrcpy(dst,src); }
+inline QT3_SUPPORT int cstrcmp(const char *str1, const char *str2)
+{ return strcmp(str1,str2); }
+inline QT3_SUPPORT int cstrncmp(const char *str1, const char *str2, uint len)
+{ return strncmp(str1,str2,len); }
+#endif
+
+// qChecksum: Internet checksum
+
+Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len);
+
+class QByteRef;
+class QString;
+class QDataStream;
+template <typename T> class QList;
+
+class Q_CORE_EXPORT QByteArray
+{
+private:
+ struct Data {
+ QBasicAtomicInt ref;
+ int alloc, size;
+ // ### Qt 5.0: We need to add the missing capacity bit
+ // (like other tool classes have), to maintain the
+ // reserved memory on resize.
+ char *data;
+ char array[1];
+ };
+
+public:
+ inline QByteArray();
+ QByteArray(const char *);
+ QByteArray(const char *, int size);
+ QByteArray(int size, char c);
+ QByteArray(int size, Qt::Initialization);
+ inline QByteArray(const QByteArray &);
+ inline ~QByteArray();
+
+ QByteArray &operator=(const QByteArray &);
+ QByteArray &operator=(const char *str);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QByteArray &operator=(QByteArray &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QByteArray &other) { qSwap(d, other.d); }
+
+ inline int size() const;
+ bool isEmpty() const;
+ void resize(int size);
+
+ QByteArray &fill(char c, int size = -1);
+
+ int capacity() const;
+ void reserve(int size);
+ void squeeze();
+
+#ifndef QT_NO_CAST_FROM_BYTEARRAY
+ operator const char *() const;
+ operator const void *() const;
+#endif
+ char *data();
+ const char *data() const;
+ inline const char *constData() const;
+ inline void detach();
+ bool isDetached() const;
+ inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
+ void clear();
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const char at(int i) const;
+ const char operator[](int i) const;
+ const char operator[](uint i) const;
+#else
+ char at(int i) const;
+ char operator[](int i) const;
+ char operator[](uint i) const;
+#endif
+ QByteRef operator[](int i);
+ QByteRef operator[](uint i);
+
+ 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;
+
+ QBool contains(char c) const;
+ QBool contains(const char *a) const;
+ QBool contains(const QByteArray &a) const;
+ int count(char c) const;
+ int count(const char *a) const;
+ int count(const QByteArray &a) const;
+
+ QByteArray left(int len) const;
+ QByteArray right(int len) const;
+ QByteArray mid(int index, int len = -1) const;
+
+ 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;
+
+ void truncate(int pos);
+ void chop(int n);
+
+ QByteArray toLower() const;
+ QByteArray toUpper() const;
+
+ QByteArray trimmed() const;
+ QByteArray simplified() const;
+ QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const;
+ QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QByteArray leftJustify(uint width, char aFill = ' ', bool aTruncate = false) const
+ { return leftJustified(int(width), aFill, aTruncate); }
+ inline QT3_SUPPORT QByteArray rightJustify(uint width, char aFill = ' ', bool aTruncate = false) const
+ { return rightJustified(int(width), aFill, aTruncate); }
+#endif
+
+ QByteArray &prepend(char c);
+ QByteArray &prepend(const char *s);
+ QByteArray &prepend(const char *s, int len);
+ QByteArray &prepend(const QByteArray &a);
+ QByteArray &append(char c);
+ QByteArray &append(const char *s);
+ QByteArray &append(const char *s, int len);
+ QByteArray &append(const QByteArray &a);
+ QByteArray &insert(int i, 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);
+ QByteArray &replace(char before, const char *after);
+ QByteArray &replace(char before, const QByteArray &after);
+ 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);
+ QByteArray &replace(const QByteArray &before, const char *after);
+ QByteArray &replace(const char *before, const QByteArray &after);
+ QByteArray &replace(char before, char after);
+ QByteArray &operator+=(char c);
+ QByteArray &operator+=(const char *s);
+ QByteArray &operator+=(const QByteArray &a);
+
+ QList<QByteArray> split(char sep) const;
+
+ QByteArray repeated(int times) const;
+
+#ifndef QT_NO_CAST_TO_ASCII
+ QT_ASCII_CAST_WARN QByteArray &append(const QString &s);
+ QT_ASCII_CAST_WARN QByteArray &insert(int i, const QString &s);
+ QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const char *after);
+ QT_ASCII_CAST_WARN QByteArray &replace(char c, const QString &after);
+ QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const QByteArray &after);
+
+ QT_ASCII_CAST_WARN QByteArray &operator+=(const QString &s);
+ QT_ASCII_CAST_WARN int indexOf(const QString &s, int from = 0) const;
+ QT_ASCII_CAST_WARN int lastIndexOf(const QString &s, int from = -1) const;
+#endif
+#ifndef QT_NO_CAST_FROM_ASCII
+ inline QT_ASCII_CAST_WARN bool operator==(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator!=(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator<(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator<=(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>=(const QString &s2) const;
+#endif
+
+ short toShort(bool *ok = 0, int base = 10) const;
+ ushort toUShort(bool *ok = 0, int base = 10) const;
+ int toInt(bool *ok = 0, int base = 10) const;
+ uint toUInt(bool *ok = 0, int base = 10) const;
+ long toLong(bool *ok = 0, int base = 10) const;
+ ulong toULong(bool *ok = 0, int base = 10) const;
+ qlonglong toLongLong(bool *ok = 0, int base = 10) const;
+ qulonglong toULongLong(bool *ok = 0, int base = 10) const;
+ float toFloat(bool *ok = 0) const;
+ double toDouble(bool *ok = 0) const;
+ QByteArray toBase64() const;
+ QByteArray toHex() const;
+ QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(),
+ const QByteArray &include = QByteArray(),
+ char percent = '%') const;
+
+ QByteArray &setNum(short, int base = 10);
+ QByteArray &setNum(ushort, int base = 10);
+ QByteArray &setNum(int, int base = 10);
+ QByteArray &setNum(uint, int base = 10);
+ QByteArray &setNum(qlonglong, int base = 10);
+ QByteArray &setNum(qulonglong, int base = 10);
+ 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 5: use an int
+
+ static QByteArray number(int, int base = 10);
+ static QByteArray number(uint, int base = 10);
+ static QByteArray number(qlonglong, int base = 10);
+ static QByteArray number(qulonglong, int base = 10);
+ static QByteArray number(double, char f = 'g', int prec = 6);
+ static QByteArray fromRawData(const char *, int size);
+ static QByteArray fromBase64(const QByteArray &base64);
+ static QByteArray fromHex(const QByteArray &hexEncoded);
+ static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
+
+
+ typedef char *iterator;
+ typedef const char *const_iterator;
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ iterator begin();
+ const_iterator begin() const;
+ const_iterator constBegin() const;
+ iterator end();
+ const_iterator end() const;
+ const_iterator constEnd() const;
+
+ // stl compatibility
+ typedef const char & const_reference;
+ typedef char & reference;
+ typedef char value_type;
+ void push_back(char c);
+ void push_back(const char *c);
+ void push_back(const QByteArray &a);
+ void push_front(char c);
+ void push_front(const char *c);
+ void push_front(const QByteArray &a);
+
+ inline int count() const { return d->size; }
+ int length() const { return d->size; }
+ bool isNull() const;
+
+ // compatibility
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QByteArray(int size);
+ inline QT3_SUPPORT QByteArray& duplicate(const QByteArray& a) { *this = a; return *this; }
+ inline QT3_SUPPORT QByteArray& duplicate(const char *a, uint n)
+ { *this = QByteArray(a, n); return *this; }
+ inline QT3_SUPPORT void resetRawData(const char *, uint) { clear(); }
+ inline QT3_SUPPORT QByteArray lower() const { return toLower(); }
+ inline QT3_SUPPORT QByteArray upper() const { return toUpper(); }
+ inline QT3_SUPPORT QByteArray stripWhiteSpace() const { return trimmed(); }
+ inline QT3_SUPPORT QByteArray simplifyWhiteSpace() const { return simplified(); }
+ inline QT3_SUPPORT int find(char c, int from = 0) const { return indexOf(c, from); }
+ inline QT3_SUPPORT int find(const char *c, int from = 0) const { return indexOf(c, from); }
+ inline QT3_SUPPORT int find(const QByteArray &ba, int from = 0) const { return indexOf(ba, from); }
+ inline QT3_SUPPORT int findRev(char c, int from = -1) const { return lastIndexOf(c, from); }
+ inline QT3_SUPPORT int findRev(const char *c, int from = -1) const { return lastIndexOf(c, from); }
+ inline QT3_SUPPORT int findRev(const QByteArray &ba, int from = -1) const { return lastIndexOf(ba, from); }
+#ifndef QT_NO_CAST_TO_ASCII
+ QT3_SUPPORT int find(const QString &s, int from = 0) const;
+ QT3_SUPPORT int findRev(const QString &s, int from = -1) const;
+#endif
+#endif
+
+private:
+ operator QNoImplicitBoolCast() const;
+ static Data shared_null;
+ static Data shared_empty;
+ Data *d;
+ QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
+ void realloc(int alloc);
+ void expand(int i);
+ QByteArray nulTerminated() const;
+
+ friend class QByteRef;
+ friend class QString;
+ friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes);
+public:
+ typedef Data * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+inline QByteArray::QByteArray(): d(&shared_null) { d->ref.ref(); }
+inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); }
+inline int QByteArray::size() const
+{ return d->size; }
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+inline const char QByteArray::at(int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const char QByteArray::operator[](int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const char QByteArray::operator[](uint i) const
+{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+#else
+inline char QByteArray::at(int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline char QByteArray::operator[](int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline char QByteArray::operator[](uint i) const
+{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+#endif
+
+inline bool QByteArray::isEmpty() const
+{ return d->size == 0; }
+#ifndef QT_NO_CAST_FROM_BYTEARRAY
+inline QByteArray::operator const char *() const
+{ return d->data; }
+inline QByteArray::operator const void *() const
+{ return d->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; }
+inline void QByteArray::detach()
+{ if (d->ref != 1 || d->data != d->array) realloc(d->size); }
+inline bool QByteArray::isDetached() const
+{ return d->ref == 1; }
+inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
+{ d->ref.ref(); }
+#ifdef QT3_SUPPORT
+inline QByteArray::QByteArray(int aSize) : d(&shared_null)
+{ d->ref.ref(); if (aSize > 0) fill('\0', aSize); }
+#endif
+
+inline int QByteArray::capacity() const
+{ return d->alloc; }
+
+inline void QByteArray::reserve(int asize)
+{ if (d->ref != 1 || asize > d->alloc) realloc(asize); }
+
+inline void QByteArray::squeeze()
+{ if (d->size < d->alloc) realloc(d->size); }
+
+class Q_CORE_EXPORT QByteRef {
+ QByteArray &a;
+ int i;
+ inline QByteRef(QByteArray &array, int idx)
+ : a(array),i(idx) {}
+ friend class QByteArray;
+public:
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline operator const char() const
+ { return i < a.d->size ? a.d->data[i] : char(0); }
+#else
+ inline operator char() const
+ { return i < a.d->size ? a.d->data[i] : char(0); }
+#endif
+ inline QByteRef &operator=(char c)
+ { if (i >= a.d->size) a.expand(i); else a.detach();
+ a.d->data[i] = c; return *this; }
+ inline QByteRef &operator=(const QByteRef &c)
+ { if (i >= a.d->size) a.expand(i); else a.detach();
+ a.d->data[i] = c.a.d->data[c.i]; return *this; }
+ inline bool operator==(char c) const
+ { return a.d->data[i] == c; }
+ inline bool operator!=(char c) const
+ { return a.d->data[i] != c; }
+ inline bool operator>(char c) const
+ { return a.d->data[i] > c; }
+ inline bool operator>=(char c) const
+ { return a.d->data[i] >= c; }
+ inline bool operator<(char c) const
+ { return a.d->data[i] < c; }
+ inline bool operator<=(char c) const
+ { return a.d->data[i] <= c; }
+};
+
+inline QByteRef QByteArray::operator[](int i)
+{ Q_ASSERT(i >= 0); return QByteRef(*this, i); }
+inline QByteRef QByteArray::operator[](uint i)
+{ return QByteRef(*this, i); }
+inline QByteArray::iterator QByteArray::begin()
+{ detach(); return d->data; }
+inline QByteArray::const_iterator QByteArray::begin() const
+{ return d->data; }
+inline QByteArray::const_iterator QByteArray::constBegin() const
+{ return d->data; }
+inline QByteArray::iterator QByteArray::end()
+{ detach(); return d->data + d->size; }
+inline QByteArray::const_iterator QByteArray::end() const
+{ return d->data + d->size; }
+inline QByteArray::const_iterator QByteArray::constEnd() const
+{ return d->data + d->size; }
+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 QBool QByteArray::contains(const QByteArray &a) const
+{ return QBool(indexOf(a) != -1); }
+inline QBool QByteArray::contains(char c) const
+{ return QBool(indexOf(c) != -1); }
+inline bool operator==(const QByteArray &a1, const QByteArray &a2)
+{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); }
+inline bool operator==(const QByteArray &a1, const char *a2)
+{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); }
+inline bool operator==(const char *a1, const QByteArray &a2)
+{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); }
+inline bool operator!=(const QByteArray &a1, const QByteArray &a2)
+{ return !(a1==a2); }
+inline bool operator!=(const QByteArray &a1, const char *a2)
+{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); }
+inline bool operator!=(const char *a1, const QByteArray &a2)
+{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); }
+inline bool operator<(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) < 0; }
+ inline bool operator<(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) < 0; }
+inline bool operator<(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) < 0; }
+inline bool operator<=(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator<=(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator<=(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator>(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>=(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) >= 0; }
+inline bool operator>=(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) >= 0; }
+inline bool operator>=(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) >= 0; }
+#ifndef QT_USE_FAST_OPERATOR_PLUS
+# ifndef QT_USE_FAST_CONCATENATION
+inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const QByteArray &a1, const char *a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const QByteArray &a1, char a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const char *a1, const QByteArray &a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(char a1, const QByteArray &a2)
+{ return QByteArray(&a1, 1) += a2; }
+# endif // QT_USE_FAST_CONCATENATION
+#endif // QT_USE_FAST_OPERATOR_PLUS
+inline QBool QByteArray::contains(const char *c) const
+{ return QBool(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 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 setNum(qlonglong(n), base); }
+inline QByteArray &QByteArray::setNum(uint n, int base)
+{ return setNum(qulonglong(n), base); }
+inline QByteArray &QByteArray::setNum(float n, char f, int prec)
+{ return setNum(double(n),f,prec); }
+
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+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);
+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)
+{ return qUncompress(reinterpret_cast<const uchar*>(data.constData()), data.size()); }
+#endif
+
+Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QByteArray)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#ifdef QT_USE_FAST_CONCATENATION
+#include <QtCore/qstring.h>
+#endif
+
+#endif // QBYTEARRAY_H
diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp
new file mode 100644
index 0000000000..bc99760ddc
--- /dev/null
+++ b/src/corelib/tools/qbytearraymatcher.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbytearraymatcher.h"
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline void bm_init_skiptable(const uchar *cc, int len, uchar *skiptable)
+{
+ int l = qMin(len, 255);
+ memset(skiptable, l, 256*sizeof(uchar));
+ cc += len - l;
+ while (l--)
+ skiptable[*cc++] = l;
+}
+
+static inline int bm_find(const uchar *cc, int l, int index, const uchar *puc, uint pl,
+ const uchar *skiptable)
+{
+ if (pl == 0)
+ return index > l ? -1 : index;
+ const uint pl_minus_one = pl - 1;
+
+ register const uchar *current = cc + index + pl_minus_one;
+ const uchar *end = cc + l;
+ while (current < end) {
+ uint skip = skiptable[*current];
+ if (!skip) {
+ // possible match
+ while (skip < pl) {
+ if (*(current - skip) != puc[pl_minus_one - skip])
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) // we have a match
+ return (current - cc) - skip + 1;
+
+ // 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[*(current - skip)] == pl)
+ skip = pl - skip;
+ else
+ skip = 1;
+ }
+ if (current > end - skip)
+ break;
+ current += skip;
+ }
+ return -1; // not found
+}
+
+/*! \class QByteArrayMatcher
+ \brief The QByteArrayMatcher class holds a sequence of bytes that
+ can be quickly matched in a byte array.
+
+ \ingroup tools
+ \ingroup string-processing
+
+ This class is useful when you have a sequence of bytes that you
+ want to repeatedly match against some byte arrays (perhaps in a
+ loop), or when you want to search for the same sequence of bytes
+ multiple times in the same byte array. Using a matcher object and
+ indexIn() is faster than matching a plain QByteArray with
+ QByteArray::indexOf() if repeated matching takes place. This
+ class offers no benefit if you are doing one-off byte array
+ matches.
+
+ Create the QByteArrayMatcher with the QByteArray you want to
+ search for. Then call indexIn() on the QByteArray that you want to
+ search.
+
+ \sa QByteArray, QStringMatcher
+*/
+
+/*!
+ Constructs an empty byte array matcher that won't match anything.
+ Call setPattern() to give it a pattern to match.
+*/
+QByteArrayMatcher::QByteArrayMatcher()
+ : d(0)
+{
+ p.p = 0;
+ p.l = 0;
+ qMemSet(p.q_skiptable, 0, sizeof(p.q_skiptable));
+}
+
+/*!
+ 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(0)
+{
+ p.p = reinterpret_cast<const uchar *>(pattern);
+ p.l = length;
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Constructs a byte array matcher that will search for \a pattern.
+ Call indexIn() to perform a search.
+*/
+QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern)
+ : d(0), q_pattern(pattern)
+{
+ p.p = reinterpret_cast<const uchar *>(pattern.constData());
+ p.l = pattern.size();
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Copies the \a other byte array matcher to this byte array matcher.
+*/
+QByteArrayMatcher::QByteArrayMatcher(const QByteArrayMatcher &other)
+ : d(0)
+{
+ operator=(other);
+}
+
+/*!
+ Destroys the byte array matcher.
+*/
+QByteArrayMatcher::~QByteArrayMatcher()
+{
+}
+
+/*!
+ Assigns the \a other byte array matcher to this byte array matcher.
+*/
+QByteArrayMatcher &QByteArrayMatcher::operator=(const QByteArrayMatcher &other)
+{
+ q_pattern = other.q_pattern;
+ memcpy(&p, &other.p, sizeof(p));
+ return *this;
+}
+
+/*!
+ Sets the byte array that this byte array matcher will search for
+ to \a pattern.
+
+ \sa pattern(), indexIn()
+*/
+void QByteArrayMatcher::setPattern(const QByteArray &pattern)
+{
+ q_pattern = pattern;
+ p.p = reinterpret_cast<const uchar *>(pattern.constData());
+ p.l = pattern.size();
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ 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.
+*/
+int QByteArrayMatcher::indexIn(const QByteArray &ba, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find(reinterpret_cast<const uchar *>(ba.constData()), ba.size(), 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.
+*/
+int QByteArrayMatcher::indexIn(const char *str, int len, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find(reinterpret_cast<const uchar *>(str), len, from,
+ p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ \fn QByteArray QByteArrayMatcher::pattern() const
+
+ Returns the byte array pattern that this byte array matcher will
+ search for.
+
+ \sa setPattern()
+*/
+
+
+static int findChar(const char *str, int len, char ch, int from)
+{
+ const uchar *s = (const uchar *)str;
+ uchar c = (uchar)ch;
+ if (from < 0)
+ from = qMax(from + len, 0);
+ if (from < len) {
+ const uchar *n = s + from - 1;
+ const uchar *e = s + len;
+ while (++n != e)
+ if (*n == c)
+ return n - s;
+ }
+ return -1;
+}
+
+/*! \internal
+ */
+static int qFindByteArrayBoyerMoore(
+ const char *haystack, int haystackLen, int haystackOffset,
+ const char *needle, int needleLen)
+{
+ uchar skiptable[256];
+ bm_init_skiptable((const uchar *)needle, needleLen, skiptable);
+ if (haystackOffset < 0)
+ haystackOffset = 0;
+ return bm_find((const uchar *)haystack, haystackLen, haystackOffset,
+ (const uchar *)needle, needleLen, skiptable);
+}
+
+#define REHASH(a) \
+ if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \
+ hashHaystack -= (a) << sl_minus_1; \
+ hashHaystack <<= 1
+
+/*! \internal
+ */
+int qFindByteArray(
+ const char *haystack0, int haystackLen, int from,
+ const char *needle, int needleLen)
+{
+ const int l = haystackLen;
+ const int sl = needleLen;
+ if (from < 0)
+ from += l;
+ if (uint(sl + from) > (uint)l)
+ return -1;
+ if (!sl)
+ return from;
+ if (!l)
+ return -1;
+
+ if (sl == 1)
+ return findChar(haystack0, haystackLen, needle[0], from);
+
+ /*
+ We use the Boyer-Moore algorithm in cases where the overhead
+ for the skip table should pay off, otherwise we use a simple
+ hash function.
+ */
+ if (l > 500 && sl > 5)
+ return qFindByteArrayBoyerMoore(haystack0, haystackLen, from,
+ needle, needleLen);
+
+ /*
+ We use some hashing for efficiency's sake. Instead of
+ comparing strings, we compare the hash value of str with that
+ of a part of this QString. Only if that matches, we call memcmp().
+ */
+ const char *haystack = haystack0 + from;
+ const char *end = haystack0 + (l - sl);
+ const uint sl_minus_1 = sl - 1;
+ uint hashNeedle = 0, hashHaystack = 0;
+ int idx;
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + needle[idx]);
+ hashHaystack = ((hashHaystack<<1) + haystack[idx]);
+ }
+ hashHaystack -= *(haystack + sl_minus_1);
+
+ while (haystack <= end) {
+ hashHaystack += *(haystack + sl_minus_1);
+ if (hashHaystack == hashNeedle && *needle == *haystack
+ && memcmp(needle, haystack, sl) == 0)
+ return haystack - haystack0;
+
+ REHASH(*haystack);
+ ++haystack;
+ }
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h
new file mode 100644
index 0000000000..444089a00a
--- /dev/null
+++ b/src/corelib/tools/qbytearraymatcher.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEARRAYMATCHER_H
+#define QBYTEARRAYMATCHER_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArrayMatcherPrivate;
+
+class Q_CORE_EXPORT QByteArrayMatcher
+{
+public:
+ QByteArrayMatcher();
+ explicit QByteArrayMatcher(const QByteArray &pattern);
+ explicit QByteArrayMatcher(const char *pattern, int length);
+ QByteArrayMatcher(const QByteArrayMatcher &other);
+ ~QByteArrayMatcher();
+
+ QByteArrayMatcher &operator=(const QByteArrayMatcher &other);
+
+ 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;
+ inline QByteArray pattern() const
+ {
+ if (q_pattern.isNull())
+ return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
+ return q_pattern;
+ }
+
+private:
+ QByteArrayMatcherPrivate *d;
+ QByteArray q_pattern;
+#ifdef Q_CC_RVCT
+// explicitly allow anonymous unions for RVCT to prevent compiler warnings
+# pragma push
+# pragma anon_unions
+#endif
+ struct Data {
+ uchar q_skiptable[256];
+ const uchar *p;
+ int l;
+ };
+ union {
+ uint dummy[256];
+ Data p;
+ };
+#ifdef Q_CC_RVCT
+# pragma pop
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBYTEARRAYMATCHER_H
diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h
new file mode 100644
index 0000000000..45c576d2e9
--- /dev/null
+++ b/src/corelib/tools/qbytedata_p.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEDATA_H
+#define QBYTEDATA_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 <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+// this class handles a list of QByteArrays. It is a variant of QRingBuffer
+// that avoid malloc/realloc/memcpy.
+class QByteDataBuffer
+{
+private:
+ QList<QByteArray> buffers;
+ qint64 bufferCompleteSize;
+public:
+ QByteDataBuffer() : bufferCompleteSize(0)
+ {
+ }
+
+ ~QByteDataBuffer()
+ {
+ clear();
+ }
+
+ inline void append(QByteDataBuffer& other)
+ {
+ if (other.isEmpty())
+ return;
+
+ buffers.append(other.buffers);
+ bufferCompleteSize += other.byteAmount();
+ }
+
+
+ inline void append(const QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.append(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ inline void prepend(QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.prepend(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ // return the first QByteData. User of this function has to qFree() its .data!
+ // preferably use this function to read data.
+ inline QByteArray read()
+ {
+ bufferCompleteSize -= buffers.first().size();
+ return buffers.takeFirst();
+ }
+
+ // return everything. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray readAll()
+ {
+ return read(byteAmount());
+ }
+
+ // return amount. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray read(qint64 amount)
+ {
+ amount = qMin(byteAmount(), amount);
+ QByteArray byteData;
+ byteData.resize(amount);
+ read(byteData.data(), byteData.size());
+ return byteData;
+ }
+
+ // return amount bytes. User of this function has to qFree() its .data!
+ // avoid to use this, it will memcpy.
+ qint64 read(char* dst, qint64 amount)
+ {
+ amount = qMin(amount, byteAmount());
+ qint64 originalAmount = amount;
+ char *writeDst = dst;
+
+ while (amount > 0) {
+ QByteArray first = buffers.takeFirst();
+ if (amount >= first.size()) {
+ // take it completely
+ bufferCompleteSize -= first.size();
+ amount -= first.size();
+ memcpy(writeDst, first.constData(), first.size());
+ writeDst += first.size();
+ first.clear();
+ } else {
+ // take a part of it & it is the last one to take
+ bufferCompleteSize -= amount;
+ memcpy(writeDst, first.constData(), amount);
+
+ qint64 newFirstSize = first.size() - amount;
+ QByteArray newFirstData;
+ newFirstData.resize(newFirstSize);
+ memcpy(newFirstData.data(), first.constData() + amount, newFirstSize);
+ buffers.prepend(newFirstData);
+
+ amount = 0;
+ first.clear();
+ }
+ }
+
+ return originalAmount;
+ }
+
+ inline char getChar()
+ {
+ char c;
+ read(&c, 1);
+ return c;
+ }
+
+ inline void clear()
+ {
+ buffers.clear();
+ bufferCompleteSize = 0;
+ }
+
+ // The byte count of all QByteArrays
+ inline qint64 byteAmount() const
+ {
+ return bufferCompleteSize;
+ }
+
+ // the number of QByteArrays
+ inline qint64 bufferCount() const
+ {
+ return buffers.length();
+ }
+
+ inline bool isEmpty() const
+ {
+ return byteAmount() == 0;
+ }
+
+ inline qint64 sizeNextBlock() const
+ {
+ if(buffers.isEmpty())
+ return 0;
+ else
+ return buffers.first().size();
+ }
+
+ inline QByteArray& operator[](int i)
+ {
+ return buffers[i];
+ }
+
+ inline bool canReadLine() const {
+ for (int i = 0; i < buffers.length(); i++)
+ if (buffers.at(i).contains('\n'))
+ return true;
+ return false;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QBYTEDATA_H
diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h
new file mode 100644
index 0000000000..7f6b86919f
--- /dev/null
+++ b/src/corelib/tools/qcache.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCACHE_H
+#define QCACHE_H
+
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class Key, class T>
+class QCache
+{
+ struct Node {
+ inline Node() : keyPtr(0) {}
+ inline Node(T *data, int cost)
+ : keyPtr(0), t(data), c(cost), p(0), n(0) {}
+ const Key *keyPtr; T *t; int c; Node *p,*n;
+ };
+ Node *f, *l;
+ QHash<Key, Node> hash;
+ void *unused; // ### Qt5: remove
+ int mx, total;
+
+ inline void unlink(Node &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ if (f == &n) f = n.n;
+ total -= n.c;
+ T *obj = n.t;
+ hash.remove(*n.keyPtr);
+ delete obj;
+ }
+ inline T *relink(const Key &key) {
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
+ return 0;
+
+ Node &n = *i;
+ if (f != &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ n.p = 0;
+ n.n = f;
+ f->p = &n;
+ f = &n;
+ }
+ return n.t;
+ }
+
+ Q_DISABLE_COPY(QCache)
+
+public:
+ inline explicit QCache(int maxCost = 100);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QCache(int maxCost, int /* dummy */)
+ : f(0), l(0), mx(maxCost), total(0) {}
+#endif
+ inline ~QCache() { clear(); }
+
+ inline int maxCost() const { return mx; }
+ void setMaxCost(int m);
+ inline int totalCost() const { return total; }
+
+ inline int size() const { return hash.size(); }
+ inline int count() const { return hash.size(); }
+ inline bool isEmpty() const { return hash.isEmpty(); }
+ inline QList<Key> keys() const { return hash.keys(); }
+
+ void clear();
+
+ bool insert(const Key &key, T *object, int cost = 1);
+ T *object(const Key &key) const;
+ inline bool contains(const Key &key) const { return hash.contains(key); }
+ T *operator[](const Key &key) const;
+
+ bool remove(const Key &key);
+ T *take(const Key &key);
+
+private:
+ void trim(int m);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT T *find(const Key &key) const { return object(key); }
+#endif
+
+};
+
+template <class Key, class T>
+inline QCache<Key, T>::QCache(int amaxCost)
+ : f(0), l(0), unused(0), mx(amaxCost), total(0) {}
+
+template <class Key, class T>
+inline void QCache<Key,T>::clear()
+{ while (f) { delete f->t; f = f->n; }
+ hash.clear(); l = 0; total = 0; }
+
+template <class Key, class T>
+inline void QCache<Key,T>::setMaxCost(int m)
+{ mx = m; trim(mx); }
+
+template <class Key, class T>
+inline T *QCache<Key,T>::object(const Key &key) const
+{ return const_cast<QCache<Key,T>*>(this)->relink(key); }
+
+template <class Key, class T>
+inline T *QCache<Key,T>::operator[](const Key &key) const
+{ return object(key); }
+
+template <class Key, class T>
+inline bool QCache<Key,T>::remove(const Key &key)
+{
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) {
+ return false;
+ } else {
+ unlink(*i);
+ return true;
+ }
+}
+
+template <class Key, class T>
+inline T *QCache<Key,T>::take(const Key &key)
+{
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (i == hash.end())
+ return 0;
+
+ Node &n = *i;
+ T *t = n.t;
+ n.t = 0;
+ unlink(n);
+ return t;
+}
+
+template <class Key, class T>
+bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
+{
+ remove(akey);
+ if (acost > mx) {
+ delete aobject;
+ return false;
+ }
+ trim(mx - acost);
+ Node sn(aobject, acost);
+ typename QHash<Key, Node>::iterator i = hash.insert(akey, sn);
+ total += acost;
+ Node *n = &i.value();
+ n->keyPtr = &i.key();
+ if (f) f->p = n;
+ n->n = f;
+ f = n;
+ if (!l) l = f;
+ return true;
+}
+
+template <class Key, class T>
+void QCache<Key,T>::trim(int m)
+{
+ Node *n = l;
+ while (n && total > m) {
+ Node *u = n;
+ n = n->p;
+ if (qIsDetached(*u->t))
+ unlink(*u);
+ }
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCACHE_H
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
new file mode 100644
index 0000000000..9e12c92c1c
--- /dev/null
+++ b/src/corelib/tools/qcache.qdoc
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QCache
+ \brief The QCache class is a template class that provides a cache.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QCache\<Key, T\> defines a cache that stores objects of type T
+ associated with keys of type Key. For example, here's the
+ definition of a cache that stores objects of type Employee
+ associated with an integer key:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 0
+
+ Here's how to insert an object in the cache:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 1
+
+ The advantage of using QCache over some other key-based data
+ structure (such as QMap or QHash) is that QCache automatically
+ takes ownership of the objects that are inserted into the cache and
+ deletes them to make room for new objects, if necessary. When
+ inserting an object into the cache, you can specify a \e{cost},
+ which should bear some approximate relationship to the amount of
+ memory taken by the object. When the sum of all objects' costs
+ (totalCost()) exceeds the cache's limit (maxCost()), QCache starts
+ deleting objects in the cache to keep under the limit, starting with
+ less recently accessed objects.
+
+ By default, QCache's maxCost() is 100. You can specify a
+ different value in the QCache constructor:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 2
+
+ Each time you call insert(), you can specify a cost as third
+ argument (after the key and a pointer to the object to insert).
+ After the call, the inserted object is owned by the QCache, which
+ may delete it at any time to make room for other objects.
+
+ To look up objects in the cache, use object() or
+ operator[](). This function looks up an object by its key, and
+ returns either a pointer to the cached object (which is owned by
+ the cache) or 0.
+
+ If you want to remove an object from the cache for a particular key,
+ call remove(). This will also delete the object. If you want to
+ remove an object from the cache without the QCache deleting it, use
+ take().
+
+ \sa QPixmapCache, QHash, QMap
+*/
+
+/*! \fn QCache::QCache(int maxCost = 100)
+
+ Constructs a cache whose contents will never have a total cost
+ greater than \a maxCost.
+*/
+
+/*! \fn QCache::~QCache()
+
+ Destroys the cache. Deletes all the objects in the cache.
+*/
+
+/*! \fn int QCache::maxCost() const
+
+ Returns the maximum allowed total cost of the cache.
+
+ \sa setMaxCost(), totalCost()
+*/
+
+/*! \fn void QCache::setMaxCost(int 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
+ deleted immediately.
+
+ \sa maxCost(), totalCost()
+*/
+
+/*! \fn int QCache::totalCost() const
+
+ Returns the total cost of the objects in the cache.
+
+ This value is normally below maxCost(), but QCache makes an
+ exception for Qt's \l{implicitly shared} classes. If a cached
+ object shares its internal data with another instance, QCache may
+ keep the object lying around, possibly contributing to making
+ totalCost() larger than maxCost().
+
+ \sa setMaxCost()
+*/
+
+/*! \fn int QCache::size() const
+
+ Returns the number of objects in the cache.
+
+ \sa isEmpty()
+*/
+
+/*! \fn int QCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn bool QCache::isEmpty() const
+
+ Returns true if the cache contains no objects; otherwise
+ returns false.
+
+ \sa size()
+*/
+
+/*! \fn QList<Key> QCache::keys() const
+
+ Returns a list of the keys in the cache.
+*/
+
+/*! \fn void QCache::clear();
+
+ Deletes all the objects in the cache.
+
+ \sa remove(), take()
+*/
+
+
+/*! \fn bool QCache::insert(const Key &key, T *object, int 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
+ the cache will be removed.
+
+ After this call, \a object is owned by the QCache and may be
+ deleted at any time. In particular, if \a cost is greater than
+ maxCost(), the object will be deleted immediately.
+
+ The function returns true if the object was inserted into the
+ cache; otherwise it returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::object(const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+
+ \sa take(), remove()
+*/
+
+/*! \fn bool QCache::contains(const Key &key) const
+
+ Returns true if the cache contains an object associated with key \a
+ key; otherwise returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::operator[](const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ This is the same as object().
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+*/
+
+/*! \fn bool QCache::remove(const Key &key)
+
+ Deletes the object associated with key \a key. Returns true if the
+ object was found in the cache; otherwise returns false.
+
+ \sa take(), clear()
+*/
+
+/*! \fn T *QCache::take(const Key &key)
+
+ Takes the object associated with key \a key out of the cache
+ without deleting it. Returns a pointer to the object taken out, or
+ 0 if the key does not exist in the cache.
+
+ The ownership of the returned object is passed to the caller.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QCache::QCache(int maxCost, int dummy)
+
+ Use QCache(int) instead.
+*/
+
+/*!
+ \fn T *QCache::find(const Key &key) const
+
+ Use object() instead.
+*/
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
new file mode 100644
index 0000000000..a9030074b3
--- /dev/null
+++ b/src/corelib/tools/qchar.cpp
@@ -0,0 +1,1654 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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
+#include "qchar.h"
+
+#include "qdatastream.h"
+#include "qtextcodec.h"
+
+#include "qunicodetables_p.h"
+#include "qunicodetables.cpp"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+# ifdef QT_NO_TEXTCODEC
+# define QT_NO_CODEC_FOR_C_STRINGS
+# endif
+#endif
+
+#define FLAG(x) (1 << (x))
+
+/*!
+ \class QLatin1Char
+ \brief The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
+
+ \ingroup string-processing
+
+ This class is only useful to avoid the codec for C strings business
+ in the QChar(ch) constructor. You can avoid it by writing
+ QChar(ch, 0).
+
+ \sa QChar, QLatin1String, QString
+*/
+
+/*!
+ \fn const char QLatin1Char::toLatin1() const
+
+ Converts a Latin-1 character to an 8-bit ASCII representation of
+ the character.
+*/
+
+/*!
+ \fn const ushort QLatin1Char::unicode() const
+
+ Converts a Latin-1 character to an 16-bit-encoded Unicode representation
+ of the character.
+*/
+
+/*!
+ \fn QLatin1Char::QLatin1Char(char c)
+
+ Constructs a Latin-1 character for \a c. This constructor should be
+ used when the encoding of the input character is known to be Latin-1.
+*/
+
+/*!
+ \class QChar
+ \brief The QChar class provides a 16-bit Unicode character.
+
+ \ingroup string-processing
+ \reentrant
+
+ 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
+ it like a \c{unsigned short}.
+
+ QChar provides a full complement of testing/classification
+ functions, converting to and from other formats, converting from
+ composed to decomposed Unicode, and trying to compare and
+ case-convert if you ask it to.
+
+ The classification functions include functions like those in the
+ standard C++ header \<cctype\> (formerly \<ctype.h\>), but
+ operating on the full range of Unicode characters. They all
+ return true if the character is a certain type of character;
+ otherwise they return false. These classification functions are
+ isNull() (returns true if the character is '\\0'), isPrint()
+ (true if the character is any sort of printable character,
+ including whitespace), isPunct() (any sort of punctation),
+ isMark() (Unicode Mark), isLetter() (a letter), isNumber() (any
+ sort of numeric character, not just 0-9), isLetterOrNumber(), and
+ isDigit() (decimal digits). All of these are wrappers around
+ category() which return the Unicode-defined category of each
+ character.
+
+ QChar also provides direction(), which indicates the "natural"
+ writing direction of this character. The joining() function
+ indicates how the character joins with its neighbors (needed
+ mostly for Arabic) and finally hasMirrored(), which indicates
+ whether the character needs to be mirrored when it is printed in
+ its "unnatural" writing direction.
+
+ Composed Unicode characters (like \aring) can be converted to
+ decomposed Unicode ("a" followed by "ring above") by using
+ decomposition().
+
+ In Unicode, comparison is not necessarily possible and case
+ conversion is very difficult at best. Unicode, covering the
+ "entire" world, also includes most of the world's case and
+ sorting problems. operator==() and friends will do comparison
+ based purely on the numeric Unicode value (code point) of the
+ characters, and toUpper() and toLower() will do case changes when
+ the character has a well-defined uppercase/lowercase equivalent.
+ For locale-dependent comparisons, use
+ QString::localeAwareCompare().
+
+ The conversion functions include unicode() (to a scalar),
+ toLatin1() (to scalar, but converts all non-Latin-1 characters to
+ 0), row() (gives the Unicode row), cell() (gives the Unicode
+ cell), digitValue() (gives the integer value of any of the
+ numerous digit characters), and a host of constructors.
+
+ QChar provides constructors and cast operators that make it easy
+ to convert to and from traditional 8-bit \c{char}s. If you
+ defined \c QT_NO_CAST_FROM_ASCII and \c QT_NO_CAST_TO_ASCII, as
+ explained in the QString documentation, you will need to
+ explicitly call fromAscii() or fromLatin1(), or use QLatin1Char,
+ to construct a QChar from an 8-bit \c char, and you will need to
+ call toAscii() or toLatin1() to get the 8-bit value back.
+
+ \sa QString, Unicode, QLatin1Char
+*/
+
+/*!
+ \enum QChar::UnicodeVersion
+
+ Specifies which version of the \l{http://www.unicode.org/}{Unicode standard}
+ introduced a certain character.
+
+ \value Unicode_1_1 Version 1.1
+ \value Unicode_2_0 Version 2.0
+ \value Unicode_2_1_2 Version 2.1.2
+ \value Unicode_3_0 Version 3.0
+ \value Unicode_3_1 Version 3.1
+ \value Unicode_3_2 Version 3.2
+ \value Unicode_4_0 Version 4.0
+ \value Unicode_4_1 Version 4.1
+ \value Unicode_5_0 Version 5.0
+ \value Unicode_Unassigned The value is not assigned to any character
+ in version 5.0 of Unicode.
+
+ \sa unicodeVersion()
+*/
+
+/*!
+ \enum QChar::Category
+
+ This enum maps the Unicode character categories.
+
+ The following characters are normative in Unicode:
+
+ \value Mark_NonSpacing Unicode class name Mn
+
+ \value Mark_SpacingCombining Unicode class name Mc
+
+ \value Mark_Enclosing Unicode class name Me
+
+ \value Number_DecimalDigit Unicode class name Nd
+
+ \value Number_Letter Unicode class name Nl
+
+ \value Number_Other Unicode class name No
+
+ \value Separator_Space Unicode class name Zs
+
+ \value Separator_Line Unicode class name Zl
+
+ \value Separator_Paragraph Unicode class name Zp
+
+ \value Other_Control Unicode class name Cc
+
+ \value Other_Format Unicode class name Cf
+
+ \value Other_Surrogate Unicode class name Cs
+
+ \value Other_PrivateUse Unicode class name Co
+
+ \value Other_NotAssigned Unicode class name Cn
+
+
+ The following categories are informative in Unicode:
+
+ \value Letter_Uppercase Unicode class name Lu
+
+ \value Letter_Lowercase Unicode class name Ll
+
+ \value Letter_Titlecase Unicode class name Lt
+
+ \value Letter_Modifier Unicode class name Lm
+
+ \value Letter_Other Unicode class name Lo
+
+ \value Punctuation_Connector Unicode class name Pc
+
+ \value Punctuation_Dash Unicode class name Pd
+
+ \value Punctuation_Open Unicode class name Ps
+
+ \value Punctuation_Close Unicode class name Pe
+
+ \value Punctuation_InitialQuote Unicode class name Pi
+
+ \value Punctuation_FinalQuote Unicode class name Pf
+
+ \value Punctuation_Other Unicode class name Po
+
+ \value Symbol_Math Unicode class name Sm
+
+ \value Symbol_Currency Unicode class name Sc
+
+ \value Symbol_Modifier Unicode class name Sk
+
+ \value Symbol_Other Unicode class name So
+
+ \value NoCategory Qt cannot find an appropriate category for the character.
+
+ \omitvalue Punctuation_Dask
+
+ \sa category()
+*/
+
+/*!
+ \enum QChar::Direction
+
+ This enum type defines the Unicode direction attributes. See the
+ \l{http://www.unicode.org/}{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.
+
+ \value DirAL
+ \value DirAN
+ \value DirB
+ \value DirBN
+ \value DirCS
+ \value DirEN
+ \value DirES
+ \value DirET
+ \value DirL
+ \value DirLRE
+ \value DirLRO
+ \value DirNSM
+ \value DirON
+ \value DirPDF
+ \value DirR
+ \value DirRLE
+ \value DirRLO
+ \value DirS
+ \value DirWS
+
+ \sa direction()
+*/
+
+/*!
+ \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.
+
+ \value NoDecomposition
+ \value Canonical
+ \value Circle
+ \value Compat
+ \value Final
+ \value Font
+ \value Fraction
+ \value Initial
+ \value Isolated
+ \value Medial
+ \value Narrow
+ \value NoBreak
+ \value Small
+ \value Square
+ \value Sub
+ \value Super
+ \value Vertical
+ \value Wide
+
+ \omitvalue Single
+
+ \sa decomposition()
+*/
+
+/*!
+ \enum QChar::Joining
+
+ 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()
+*/
+
+/*!
+ \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.
+
+ \value Combining_Above
+ \value Combining_AboveAttached
+ \value Combining_AboveLeft
+ \value Combining_AboveLeftAttached
+ \value Combining_AboveRight
+ \value Combining_AboveRightAttached
+ \value Combining_Below
+ \value Combining_BelowAttached
+ \value Combining_BelowLeft
+ \value Combining_BelowLeftAttached
+ \value Combining_BelowRight
+ \value Combining_BelowRightAttached
+ \value Combining_DoubleAbove
+ \value Combining_DoubleBelow
+ \value Combining_IotaSubscript
+ \value Combining_Left
+ \value Combining_LeftAttached
+ \value Combining_Right
+ \value Combining_RightAttached
+*/
+
+/*!
+ \enum QChar::SpecialCharacter
+
+ \value Null A QChar with this value isNull().
+ \value Nbsp Non-breaking space.
+ \value ReplacementCharacter The character shown when a font has no glyph
+ for a certain codepoint. A special question mark character is often
+ used. Codecs use this codepoint when input data cannot be
+ represented in Unicode.
+ \value ObjectReplacementCharacter Used to represent an object such as an
+ image when such objects cannot be presented.
+ \value ByteOrderMark
+ \value ByteOrderSwapped
+ \value ParagraphSeparator
+ \value LineSeparator
+
+ \omitvalue null
+ \omitvalue replacement
+ \omitvalue byteOrderMark
+ \omitvalue byteOrderSwapped
+ \omitvalue nbsp
+*/
+
+/*!
+ \fn void QChar::setCell(uchar cell)
+ \internal
+*/
+
+/*!
+ \fn void QChar::setRow(uchar row)
+ \internal
+*/
+
+/*!
+ \fn QChar::QChar()
+
+ Constructs a null QChar ('\\0').
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QChar::QChar(QLatin1Char ch)
+
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+*/
+
+/*!
+ \fn QChar::QChar(SpecialCharacter ch)
+
+ Constructs a QChar for the predefined character value \a ch.
+*/
+
+/*!
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a
+ ch.
+*/
+QChar::QChar(char ch)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ ucs = QTextCodec::codecForCStrings()->toUnicode(&ch, 1).at(0).unicode();
+ else
+#endif
+ ucs = uchar(ch);
+}
+
+/*!
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+*/
+QChar::QChar(uchar ch)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings()) {
+ // #####
+ char c = char(ch);
+ ucs = QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode();
+ } else
+#endif
+ ucs = ch;
+}
+
+/*!
+ \fn QChar::QChar(uchar cell, uchar row)
+
+ Constructs a QChar for Unicode cell \a cell in row \a row.
+
+ \sa cell(), row()
+*/
+
+/*!
+ \fn QChar::QChar(ushort code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(short code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(uint code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(int code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn bool QChar::isNull() const
+
+ Returns true if the character is the Unicode character 0x0000
+ ('\\0'); otherwise returns false.
+*/
+
+/*!
+ \fn uchar QChar::cell() const
+
+ Returns the cell (least significant byte) of the Unicode
+ character.
+
+ \sa row()
+*/
+
+/*!
+ \fn uchar QChar::row() const
+
+ Returns the row (most significant byte) of the Unicode character.
+
+ \sa cell()
+*/
+
+/*!
+ Returns true if the character is a printable character; otherwise
+ returns false. This is any character not of category Cc or Cn.
+
+ Note that this gives no indication of whether the character is
+ available in a particular font.
+*/
+bool QChar::isPrint() const
+{
+ const int test = FLAG(Other_Control) |
+ FLAG(Other_NotAssigned);
+ return !(FLAG(qGetProp(ucs)->category) & test);
+}
+
+/*!
+ Returns true if the character is a separator character
+ (Separator_* categories); otherwise returns false.
+*/
+bool QChar::isSpace() const
+{
+ if(ucs >= 9 && ucs <=13)
+ return true;
+ const int test = FLAG(Separator_Space) |
+ FLAG(Separator_Line) |
+ FLAG(Separator_Paragraph);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a mark (Mark_* categories);
+ otherwise returns false.
+
+ See QChar::Category for more information regarding marks.
+*/
+bool QChar::isMark() const
+{
+ const int test = FLAG(Mark_NonSpacing) |
+ FLAG(Mark_SpacingCombining) |
+ FLAG(Mark_Enclosing);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a punctuation mark (Punctuation_*
+ categories); otherwise returns false.
+*/
+bool QChar::isPunct() const
+{
+ const int test = FLAG(Punctuation_Connector) |
+ FLAG(Punctuation_Dash) |
+ FLAG(Punctuation_Open) |
+ FLAG(Punctuation_Close) |
+ FLAG(Punctuation_InitialQuote) |
+ FLAG(Punctuation_FinalQuote) |
+ FLAG(Punctuation_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a letter (Letter_* categories);
+ otherwise returns false.
+*/
+bool QChar::isLetter() const
+{
+ const int test = FLAG(Letter_Uppercase) |
+ FLAG(Letter_Lowercase) |
+ FLAG(Letter_Titlecase) |
+ FLAG(Letter_Modifier) |
+ FLAG(Letter_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a number (Number_* categories,
+ not just 0-9); otherwise returns false.
+
+ \sa isDigit()
+*/
+bool QChar::isNumber() const
+{
+ const int test = FLAG(Number_DecimalDigit) |
+ FLAG(Number_Letter) |
+ FLAG(Number_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a letter or number (Letter_* or
+ Number_* categories); otherwise returns false.
+*/
+bool QChar::isLetterOrNumber() const
+{
+ const int test = FLAG(Letter_Uppercase) |
+ FLAG(Letter_Lowercase) |
+ FLAG(Letter_Titlecase) |
+ FLAG(Letter_Modifier) |
+ FLAG(Letter_Other) |
+ FLAG(Number_DecimalDigit) |
+ FLAG(Number_Letter) |
+ FLAG(Number_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+
+/*!
+ Returns true if the character is a decimal digit
+ (Number_DecimalDigit); otherwise returns false.
+*/
+bool QChar::isDigit() const
+{
+ return (qGetProp(ucs)->category == Number_DecimalDigit);
+}
+
+
+/*!
+ Returns true if the character is a symbol (Symbol_* categories);
+ otherwise returns false.
+*/
+bool QChar::isSymbol() const
+{
+ const int test = FLAG(Symbol_Math) |
+ FLAG(Symbol_Currency) |
+ FLAG(Symbol_Modifier) |
+ FLAG(Symbol_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ \fn bool QChar::isHighSurrogate() const
+
+ Returns true if the QChar is the high part of a utf16 surrogate
+ (ie. if its code point is between 0xd800 and 0xdbff, inclusive).
+*/
+
+/*!
+ \fn bool QChar::isLowSurrogate() const
+
+ Returns true if the QChar is the low part of a utf16 surrogate
+ (ie. if its code point is between 0xdc00 and 0xdfff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::isHighSurrogate(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ is the high part of a utf16 surrogate
+ (ie. if its code point is between 0xd800 and 0xdbff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::isLowSurrogate(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ is the low part of a utf16 surrogate
+ (ie. if its code point is between 0xdc00 and 0xdfff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::requiresSurrogates(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ can be split into the high and low parts of a utf16 surrogate
+ (ie. if its code point is greater than or equals to 0x10000).
+*/
+
+/*!
+ \fn static uint QChar::surrogateToUcs4(ushort high, ushort low)
+
+ Converts a UTF16 surrogate pair with the given \a high and \a low values
+ to its UCS-4 code point.
+*/
+
+/*!
+ \fn static uint QChar::surrogateToUcs4(QChar high, QChar low)
+
+ Converts a utf16 surrogate pair (\a high, \a low) to its ucs4 code point.
+*/
+
+/*!
+ \fn static ushort QChar::highSurrogate(uint ucs4)
+
+ Returns the high surrogate value of a ucs4 code point.
+ The returned result is undefined if \a ucs4 is smaller than 0x10000.
+*/
+
+/*!
+ \fn static ushort QChar::lowSurrogate(uint ucs4)
+
+ Returns the low surrogate value of a ucs4 code point.
+ The returned result is undefined if \a ucs4 is smaller than 0x10000.
+*/
+
+/*!
+ Returns the numeric value of the digit, or -1 if the character is
+ not a digit.
+*/
+int QChar::digitValue() const
+{
+ return qGetProp(ucs)->digitValue;
+}
+
+/*!
+ \overload
+ Returns the numeric value of the digit, specified by the UCS-2-encoded
+ character, \a ucs2, or -1 if the character is not a digit.
+*/
+int QChar::digitValue(ushort ucs2)
+{
+ return qGetProp(ucs2)->digitValue;
+}
+
+/*!
+ \overload
+ Returns the numeric value of the digit specified by the UCS-4-encoded
+ character, \a ucs4, or -1 if the character is not a digit.
+*/
+int QChar::digitValue(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ return qGetProp(ucs4)->digitValue;
+}
+
+/*!
+ Returns the character's category.
+*/
+QChar::Category QChar::category() const
+{
+ return (QChar::Category) qGetProp(ucs)->category;
+}
+
+/*!
+ \overload
+ \since 4.3
+ Returns the category of the UCS-4-encoded character specified by \a ucs4.
+*/
+QChar::Category QChar::category(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::NoCategory;
+ return (QChar::Category) qGetProp(ucs4)->category;
+}
+
+/*!
+ \overload
+ Returns the category of the UCS-2-encoded character specified by \a ucs2.
+*/
+QChar::Category QChar::category(ushort ucs2)
+{
+ return (QChar::Category) qGetProp(ucs2)->category;
+}
+
+
+/*!
+ Returns the character's direction.
+*/
+QChar::Direction QChar::direction() const
+{
+ return (QChar::Direction) qGetProp(ucs)->direction;
+}
+
+/*!
+ \overload
+ Returns the direction of the UCS-4-encoded character specified by \a ucs4.
+*/
+QChar::Direction QChar::direction(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::DirL;
+ return (QChar::Direction) qGetProp(ucs4)->direction;
+}
+
+/*!
+ \overload
+ Returns the direction of the UCS-2-encoded character specified by \a ucs2.
+*/
+QChar::Direction QChar::direction(ushort ucs2)
+{
+ return (QChar::Direction) qGetProp(ucs2)->direction;
+}
+
+/*!
+ Returns information about the joining properties of the character
+ (needed for certain languages such as Arabic).
+*/
+QChar::Joining QChar::joining() const
+{
+ return (QChar::Joining) qGetProp(ucs)->joining;
+}
+
+/*!
+ \overload
+ Returns information about the joining properties of the UCS-4-encoded
+ character specified by \a ucs4 (needed for certain languages such as
+ Arabic).
+*/
+QChar::Joining QChar::joining(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::OtherJoining;
+ return (QChar::Joining) qGetProp(ucs4)->joining;
+}
+
+/*!
+ \overload
+ Returns information about the joining properties of the UCS-2-encoded
+ character specified by \a ucs2 (needed for certain languages such as
+ Arabic).
+*/
+QChar::Joining QChar::joining(ushort ucs2)
+{
+ return (QChar::Joining) qGetProp(ucs2)->joining;
+}
+
+
+/*!
+ Returns true if the character should be reversed if the text
+ direction is reversed; otherwise returns false.
+
+ Same as (ch.mirroredChar() != ch).
+
+ \sa mirroredChar()
+*/
+bool QChar::hasMirrored() const
+{
+ return qGetProp(ucs)->mirrorDiff != 0;
+}
+
+/*!
+ \fn bool QChar::isLower() const
+
+ Returns true if the character is a lowercase letter, i.e.
+ category() is Letter_Lowercase.
+
+ \sa isUpper(), toLower(), toUpper()
+*/
+
+/*!
+ \fn bool QChar::isUpper() const
+
+ Returns true if the character is an uppercase letter, i.e.
+ category() is Letter_Uppercase.
+
+ \sa isLower(), toUpper(), toLower()
+*/
+
+/*!
+ \fn bool QChar::isTitleCase() const
+ \since 4.3
+
+ Returns true if the character is a titlecase letter, i.e.
+ category() is Letter_Titlecase.
+
+ \sa isLower(), toUpper(), toLower(), toTitleCase()
+*/
+
+/*!
+ Returns the mirrored character if this character is a mirrored
+ character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+QChar QChar::mirroredChar() const
+{
+ return ucs + qGetProp(ucs)->mirrorDiff;
+}
+
+/*!
+ \overload
+ Returns the mirrored character if the UCS-4-encoded character specified
+ by \a ucs4 is a mirrored character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+uint QChar::mirroredChar(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ return ucs4 + qGetProp(ucs4)->mirrorDiff;
+}
+
+/*!
+ \overload
+ Returns the mirrored character if the UCS-2-encoded character specified
+ by \a ucs2 is a mirrored character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+ushort QChar::mirroredChar(ushort ucs2)
+{
+ return ucs2 + qGetProp(ucs2)->mirrorDiff;
+}
+
+
+enum {
+ Hangul_SBase = 0xac00,
+ Hangul_LBase = 0x1100,
+ Hangul_VBase = 0x1161,
+ Hangul_TBase = 0x11a7,
+ Hangul_SCount = 11172,
+ Hangul_LCount = 19,
+ Hangul_VCount = 21,
+ Hangul_TCount = 28,
+ Hangul_NCount = 21*28
+};
+
+// 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)
+{
+ *length = 0;
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount) {
+ int 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;
+ *tag = QChar::Canonical;
+ return buffer;
+ }
+
+ const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4);
+ if (index == 0xffff)
+ return 0;
+ const unsigned short *decomposition = uc_decomposition_map+index;
+ *tag = (*decomposition) & 0xff;
+ *length = (*decomposition) >> 8;
+ return decomposition+1;
+}
+
+/*!
+ Decomposes a character into its parts. Returns an empty string if
+ no decomposition exists.
+*/
+QString QChar::decomposition() const
+{
+ return decomposition(ucs);
+}
+
+/*!
+ \overload
+ Decomposes the UCS-4-encoded character specified by \a ucs4 into its
+ constituent parts. Returns an empty string if no decomposition exists.
+*/
+QString QChar::decomposition(uint ucs4)
+{
+ unsigned short buffer[3];
+ int length;
+ int tag;
+ const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer);
+ return QString::fromUtf16(d, length);
+}
+
+/*!
+ Returns the tag defining the composition of the character. Returns
+ QChar::Single if no decomposition exists.
+*/
+QChar::Decomposition QChar::decompositionTag() const
+{
+ return decompositionTag(ucs);
+}
+
+/*!
+ \overload
+ Returns the tag defining the composition of the UCS-4-encoded character
+ specified by \a ucs4. Returns QChar::Single if no decomposition exists.
+*/
+QChar::Decomposition QChar::decompositionTag(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::NoDecomposition;
+ const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4);
+ if (index == 0xffff)
+ return QChar::NoDecomposition;
+ return (QChar::Decomposition)(uc_decomposition_map[index] & 0xff);
+}
+
+/*!
+ Returns the combining class for the character as defined in the
+ Unicode standard. This is mainly useful as a positioning hint for
+ marks attached to a base character.
+
+ The Qt text rendering engine uses this information to correctly
+ position non-spacing marks around a base character.
+*/
+unsigned char QChar::combiningClass() const
+{
+ return (unsigned char) qGetProp(ucs)->combiningClass;
+}
+
+/*!
+ \overload
+ Returns the combining class for the UCS-4-encoded character specified by
+ \a ucs4, as defined in the Unicode standard.
+*/
+unsigned char QChar::combiningClass(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ return (unsigned char) qGetProp(ucs4)->combiningClass;
+}
+
+/*!
+ \overload
+ Returns the combining class for the UCS-2-encoded character specified by
+ \a ucs2, as defined in the Unicode standard.
+*/
+unsigned char QChar::combiningClass(ushort ucs2)
+{
+ return (unsigned char) qGetProp(ucs2)->combiningClass;
+}
+
+/*!
+ Returns the Unicode version that introduced this character.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion() const
+{
+ return (QChar::UnicodeVersion) qGetProp(ucs)->unicodeVersion;
+}
+
+/*!
+ \overload
+ Returns the Unicode version that introduced the character specified in
+ its UCS-4-encoded form as \a ucs4.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::Unicode_Unassigned;
+ return (QChar::UnicodeVersion) qGetProp(ucs4)->unicodeVersion;
+}
+
+/*!
+ \overload
+ Returns the Unicode version that introduced the character specified in
+ its UCS-2-encoded form as \a ucs2.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2)
+{
+ return (QChar::UnicodeVersion) qGetProp(ucs2)->unicodeVersion;
+}
+
+/*!
+ \since 4.8
+
+ Returns the most recent supported Unicode version.
+*/
+QChar::UnicodeVersion QChar::currentUnicodeVersion()
+{
+ return UNICODE_DATA_VERSION;
+}
+
+/*!
+ Returns the lowercase equivalent if the character is uppercase or titlecase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toLower() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->lowerCaseSpecial)
+ return ucs + p->lowerCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the lowercase equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is uppercase or titlecase; otherwise returns
+ the character itself.
+*/
+uint QChar::toLower(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->lowerCaseSpecial)
+ return ucs4 + p->lowerCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the lowercase equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is uppercase or titlecase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toLower(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->lowerCaseSpecial)
+ return ucs2 + p->lowerCaseDiff;
+ return ucs2;
+}
+
+/*!
+ Returns the uppercase equivalent if the character is lowercase or titlecase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toUpper() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->upperCaseSpecial)
+ return ucs + p->upperCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the uppercase equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is lowercase or titlecase; otherwise returns
+ the character itself.
+*/
+uint QChar::toUpper(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->upperCaseSpecial)
+ return ucs4 + p->upperCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the uppercase equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is lowercase or titlecase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toUpper(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->upperCaseSpecial)
+ return ucs2 + p->upperCaseDiff;
+ return ucs2;
+}
+
+/*!
+ Returns the title case equivalent if the character is lowercase or uppercase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toTitleCase() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->titleCaseSpecial)
+ return ucs + p->titleCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the title case equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is lowercase or uppercase; otherwise returns
+ the character itself.
+*/
+uint QChar::toTitleCase(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->titleCaseSpecial)
+ return ucs4 + p->titleCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the title case equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is lowercase or uppercase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toTitleCase(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->titleCaseSpecial)
+ return ucs2 + p->titleCaseDiff;
+ return ucs2;
+}
+
+
+static inline uint foldCase(const ushort *ch, const ushort *start)
+{
+ uint c = *ch;
+ if (QChar(c).isLowSurrogate() && ch > start && QChar(*(ch - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(ch - 1), c);
+ return *ch + qGetProp(c)->caseFoldDiff;
+}
+
+static inline uint foldCase(uint ch, uint &last)
+{
+ uint c = ch;
+ if (QChar(c).isLowSurrogate() && QChar(last).isHighSurrogate())
+ c = QChar::surrogateToUcs4(last, c);
+ last = ch;
+ return ch + qGetProp(c)->caseFoldDiff;
+}
+
+static inline ushort foldCase(ushort ch)
+{
+ return ch + qGetProp(ch)->caseFoldDiff;
+}
+
+/*!
+ Returns the case folded equivalent of the character. For most Unicode characters this
+ is the same as toLowerCase().
+*/
+QChar QChar::toCaseFolded() const
+{
+ return ucs + qGetProp(ucs)->caseFoldDiff;
+}
+
+/*!
+ \overload
+ Returns the case folded equivalent of the UCS-4-encoded character specified
+ by \a ucs4. For most Unicode characters this is the same as toLowerCase().
+*/
+uint QChar::toCaseFolded(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ return ucs4 + qGetProp(ucs4)->caseFoldDiff;
+}
+
+/*!
+ \overload
+ Returns the case folded equivalent of the UCS-2-encoded character specified
+ by \a ucs2. For most Unicode characters this is the same as toLowerCase().
+*/
+ushort QChar::toCaseFolded(ushort ucs2)
+{
+ return ucs2 + qGetProp(ucs2)->caseFoldDiff;
+}
+
+
+/*!
+ \fn char QChar::latin1() const
+
+ Use toLatin1() instead.
+*/
+
+/*!
+ \fn char QChar::ascii() const
+
+ Use toAscii() instead.
+*/
+
+/*!
+ \fn char QChar::toLatin1() const
+
+ Returns the Latin-1 character equivalent to the QChar, or 0. This
+ is mainly useful for non-internationalized software.
+
+ \sa toAscii(), unicode(), QTextCodec::codecForCStrings()
+*/
+
+/*!
+ \fn char QChar::toAscii() const
+ Returns the character value of the QChar obtained using the current
+ codec used to read C strings, or 0 if the character is not representable
+ using this codec. The default codec handles Latin-1 encoded text,
+ but this can be changed to assist developers writing source code using
+ other encodings.
+
+ 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.
+
+ \sa toLatin1(), unicode(), QTextCodec::codecForCStrings()
+*/
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+const char QChar::toAscii() const
+#else
+char QChar::toAscii() const
+#endif
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ return QTextCodec::codecForCStrings()->fromUnicode(QString(*this)).at(0);
+#endif
+ return ucs > 0xff ? 0 : char(ucs);
+}
+
+/*!
+ \fn QChar QChar::fromLatin1(char c)
+
+ Converts the Latin-1 character \a c to its equivalent QChar. This
+ is mainly useful for non-internationalized software.
+
+ \sa fromAscii(), unicode(), QTextCodec::codecForCStrings()
+*/
+
+/*!
+ Converts the ASCII character \a c to its equivalent QChar. This
+ is mainly useful for non-internationalized software.
+
+ An alternative is to use QLatin1Char.
+
+ \sa fromLatin1(), unicode(), QTextCodec::codecForCStrings()
+*/
+QChar QChar::fromAscii(char c)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ return QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode();
+#endif
+ return QChar(ushort((uchar)c));
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QChar
+
+ Writes the char \a chr to the stream \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator<<(QDataStream &out, const QChar &chr)
+{
+ out << quint16(chr.unicode());
+ return out;
+}
+
+/*!
+ \relates QChar
+
+ Reads a char from the stream \a in into char \a chr.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator>>(QDataStream &in, QChar &chr)
+{
+ quint16 u;
+ in >> u;
+ chr.unicode() = ushort(u);
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn ushort & QChar::unicode()
+
+ Returns a reference to the numeric Unicode value of the QChar.
+*/
+
+/*!
+ \fn ushort QChar::unicode() const
+
+ \overload
+*/
+
+/*****************************************************************************
+ Documentation of QChar related functions
+ *****************************************************************************/
+
+/*!
+ \fn bool operator==(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if \a c1 and \a c2 are the same Unicode character;
+ otherwise returns false.
+*/
+
+/*!
+ \fn int operator!=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if \a c1 and \a c2 are not the same Unicode
+ character; otherwise returns false.
+*/
+
+/*!
+ \fn int operator<=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is less than
+ or equal to that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator>=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is greater than
+ or equal to that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator<(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is less than
+ that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator>(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is greater than
+ that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn bool QChar::mirrored() const
+
+ Use hasMirrored() instead.
+*/
+
+/*!
+ \fn QChar QChar::lower() const
+
+ Use toLower() instead.
+*/
+
+/*!
+ \fn QChar QChar::upper() const
+
+ Use toUpper() instead.
+*/
+
+/*!
+ \fn bool QChar::networkOrdered()
+
+ See if QSysInfo::ByteOrder == QSysInfo::BigEndian instead.
+*/
+
+
+// ---------------------------------------------------------------------------
+
+
+static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from)
+{
+ unsigned short buffer[3];
+
+ QString &s = *str;
+
+ const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data());
+ const unsigned short *uc = utf16 + s.length();
+ while (uc != utf16 + from) {
+ uint ucs4 = *(--uc);
+ if (QChar(ucs4).isLowSurrogate() && uc != utf16) {
+ ushort high = *(uc - 1);
+ if (QChar(high).isHighSurrogate()) {
+ --uc;
+ ucs4 = QChar::surrogateToUcs4(high, ucs4);
+ }
+ }
+ if (QChar::unicodeVersion(ucs4) > version)
+ continue;
+ int length;
+ int tag;
+ const unsigned short *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);
+ // since the insert invalidates the pointers and we do decomposition recursive
+ utf16 = reinterpret_cast<unsigned short *>(s.data());
+ uc = utf16 + pos + length;
+ }
+}
+
+
+struct UCS2Pair {
+ ushort u1;
+ ushort u2;
+};
+
+inline bool operator<(ushort u1, const UCS2Pair &ligature)
+{ return u1 < ligature.u1; }
+inline bool operator<(const UCS2Pair &ligature, ushort u1)
+{ return ligature.u1 < u1; }
+
+static ushort ligatureHelper(ushort u1, ushort u2)
+{
+ // hangul L-V pair
+ int LIndex = u1 - Hangul_LBase;
+ if (0 <= LIndex && LIndex < Hangul_LCount) {
+ int VIndex = u2 - Hangul_VBase;
+ if (0 <= VIndex && VIndex < Hangul_VCount)
+ return Hangul_SBase + (LIndex * Hangul_VCount + VIndex) * Hangul_TCount;
+ }
+
+ // hangul LV-T pair
+ int SIndex = u1 - Hangul_SBase;
+ if (0 <= SIndex && SIndex < Hangul_SCount && (SIndex % Hangul_TCount) == 0) {
+ int TIndex = u2 - Hangul_TBase;
+ if (0 <= TIndex && TIndex <= Hangul_TCount)
+ return u1 + TIndex;
+ }
+
+ const unsigned short index = GET_LIGATURE_INDEX(u2);
+ if (index == 0xffff)
+ return 0;
+ const unsigned short *ligatures = uc_ligature_map+index;
+ ushort length = *ligatures++;
+ {
+ const UCS2Pair *data = reinterpret_cast<const UCS2Pair *>(ligatures);
+ const UCS2Pair *r = qBinaryFind(data, data + length, u1);
+ if (r != data + length)
+ return r->u2;
+ }
+
+ return 0;
+}
+
+static void composeHelper(QString *str, int from)
+{
+ QString &s = *str;
+
+ if (s.length() - from < 2)
+ return;
+
+ // the loop can partly ignore high Unicode as all ligatures are in the BMP
+ int starter = 0;
+ int lastCombining = 0;
+ int pos = from;
+ while (pos < s.length()) {
+ uint uc = s.at(pos).unicode();
+ if (QChar(uc).isHighSurrogate() && pos < s.length()-1) {
+ ushort low = s.at(pos+1).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ uc = QChar::surrogateToUcs4(uc, low);
+ ++pos;
+ }
+ }
+ int combining = QChar::combiningClass(uc);
+ if (starter == pos - 1 || combining > lastCombining) {
+ // allowed to form ligature with S
+ QChar ligature = ligatureHelper(s.at(starter).unicode(), uc);
+ if (ligature.unicode()) {
+ s[starter] = ligature;
+ s.remove(pos, 1);
+ continue;
+ }
+ }
+ if (!combining)
+ starter = pos;
+ lastCombining = combining;
+ ++pos;
+ }
+}
+
+
+static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from)
+{
+ QString &s = *str;
+ const int l = s.length()-1;
+ int pos = from;
+ while (pos < l) {
+ int p2 = pos+1;
+ uint u1 = s.at(pos).unicode();
+ if (QChar(u1).isHighSurrogate()) {
+ ushort low = s.at(p2).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ u1 = QChar::surrogateToUcs4(u1, low);
+ if (p2 >= l)
+ break;
+ ++p2;
+ }
+ }
+ uint u2 = s.at(p2).unicode();
+ if (QChar(u2).isHighSurrogate() && p2 < l) {
+ ushort low = s.at(p2+1).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ u2 = QChar::surrogateToUcs4(u2, low);
+ ++p2;
+ }
+ }
+
+ ushort c2 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u2);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c2 = p->combiningClass;
+ }
+ if (c2 == 0) {
+ pos = p2+1;
+ continue;
+ }
+
+ ushort c1 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u1);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c1 = p->combiningClass;
+ }
+
+ if (c1 > c2) {
+ QChar *uc = s.data();
+ int p = pos;
+ // exchange characters
+ if (!QChar::requiresSurrogates(u2)) {
+ uc[p++] = u2;
+ } else {
+ uc[p++] = QChar::highSurrogate(u2);
+ uc[p++] = QChar::lowSurrogate(u2);
+ }
+ if (!QChar::requiresSurrogates(u1)) {
+ uc[p++] = u1;
+ } else {
+ uc[p++] = QChar::highSurrogate(u1);
+ uc[p++] = QChar::lowSurrogate(u1);
+ }
+ if (pos > 0)
+ --pos;
+ if (pos > 0 && s.at(pos).isLowSurrogate())
+ --pos;
+ } else {
+ ++pos;
+ if (QChar::requiresSurrogates(u1))
+ ++pos;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
new file mode 100644
index 0000000000..508053671c
--- /dev/null
+++ b/src/corelib/tools/qchar.h
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCHAR_H
+#define QCHAR_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QString;
+
+struct QLatin1Char
+{
+public:
+ inline explicit QLatin1Char(char c) : ch(c) {}
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline const char toLatin1() const { return ch; }
+ inline const ushort unicode() const { return ushort(uchar(ch)); }
+#else
+ inline char toLatin1() const { return ch; }
+ inline ushort unicode() const { return ushort(uchar(ch)); }
+#endif
+
+private:
+ char ch;
+};
+
+
+class Q_CORE_EXPORT QChar {
+public:
+ QChar();
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(char c);
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(uchar c);
+#endif
+ QChar(QLatin1Char ch);
+ QChar(uchar c, uchar r);
+ inline QChar(ushort rc) : ucs(rc){}
+ QChar(short rc);
+ QChar(uint rc);
+ QChar(int rc);
+ enum SpecialCharacter {
+ Null = 0x0000,
+ Nbsp = 0x00a0,
+ ReplacementCharacter = 0xfffd,
+ ObjectReplacementCharacter = 0xfffc,
+ ByteOrderMark = 0xfeff,
+ ByteOrderSwapped = 0xfffe,
+#ifdef QT3_SUPPORT
+ null = Null,
+ replacement = ReplacementCharacter,
+ byteOrderMark = ByteOrderMark,
+ byteOrderSwapped = ByteOrderSwapped,
+ nbsp = Nbsp,
+#endif
+ ParagraphSeparator = 0x2029,
+ LineSeparator = 0x2028
+ };
+ QChar(SpecialCharacter sc);
+
+ // Unicode information
+
+ enum Category
+ {
+ NoCategory, // ### Qt 5: replace with Other_NotAssigned
+
+ Mark_NonSpacing, // Mn
+ Mark_SpacingCombining, // Mc
+ Mark_Enclosing, // Me
+
+ Number_DecimalDigit, // Nd
+ Number_Letter, // Nl
+ Number_Other, // No
+
+ Separator_Space, // Zs
+ Separator_Line, // Zl
+ Separator_Paragraph, // Zp
+
+ Other_Control, // Cc
+ Other_Format, // Cf
+ Other_Surrogate, // Cs
+ Other_PrivateUse, // Co
+ Other_NotAssigned, // Cn
+
+ Letter_Uppercase, // Lu
+ Letter_Lowercase, // Ll
+ Letter_Titlecase, // Lt
+ Letter_Modifier, // Lm
+ Letter_Other, // Lo
+
+ Punctuation_Connector, // Pc
+ Punctuation_Dash, // Pd
+ Punctuation_Open, // Ps
+ Punctuation_Close, // Pe
+ Punctuation_InitialQuote, // Pi
+ Punctuation_FinalQuote, // Pf
+ Punctuation_Other, // Po
+
+ Symbol_Math, // Sm
+ Symbol_Currency, // Sc
+ Symbol_Modifier, // Sk
+ Symbol_Other, // So
+
+ Punctuation_Dask = Punctuation_Dash // ### Qt 5: remove
+ };
+
+ enum Direction
+ {
+ DirL, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON,
+ DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN
+ };
+
+ enum Decomposition
+ {
+ NoDecomposition,
+ Canonical,
+ Font,
+ NoBreak,
+ Initial,
+ Medial,
+ Final,
+ Isolated,
+ Circle,
+ Super,
+ Sub,
+ Vertical,
+ Wide,
+ Narrow,
+ Small,
+ Square,
+ Compat,
+ Fraction
+
+#ifdef QT3_SUPPORT
+ , Single = NoDecomposition
+#endif
+ };
+
+ enum Joining
+ {
+ OtherJoining, Dual, Right, Center
+ };
+
+ enum CombiningClass
+ {
+ Combining_BelowLeftAttached = 200,
+ Combining_BelowAttached = 202,
+ Combining_BelowRightAttached = 204,
+ Combining_LeftAttached = 208,
+ Combining_RightAttached = 210,
+ Combining_AboveLeftAttached = 212,
+ Combining_AboveAttached = 214,
+ Combining_AboveRightAttached = 216,
+
+ Combining_BelowLeft = 218,
+ Combining_Below = 220,
+ Combining_BelowRight = 222,
+ Combining_Left = 224,
+ Combining_Right = 226,
+ Combining_AboveLeft = 228,
+ Combining_Above = 230,
+ Combining_AboveRight = 232,
+
+ Combining_DoubleBelow = 233,
+ Combining_DoubleAbove = 234,
+ Combining_IotaSubscript = 240
+ };
+
+ enum UnicodeVersion {
+ Unicode_Unassigned, // ### Qt 5: assign with some constantly big value
+ Unicode_1_1,
+ Unicode_2_0,
+ Unicode_2_1_2,
+ Unicode_3_0,
+ Unicode_3_1,
+ Unicode_3_2,
+ Unicode_4_0,
+ Unicode_4_1,
+ Unicode_5_0
+ };
+ // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO
+
+ Category category() const;
+ Direction direction() const;
+ Joining joining() const;
+ bool hasMirrored() const;
+ unsigned char combiningClass() const;
+
+ QChar mirroredChar() const;
+ QString decomposition() const;
+ Decomposition decompositionTag() const;
+
+ int digitValue() const;
+ QChar toLower() const;
+ QChar toUpper() const;
+ QChar toTitleCase() const;
+ QChar toCaseFolded() const;
+
+ UnicodeVersion unicodeVersion() const;
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const char toAscii() const;
+ inline const char toLatin1() const;
+ inline const ushort unicode() const { return ucs; }
+#else
+ char toAscii() const;
+ inline char toLatin1() const;
+ inline ushort unicode() const { return ucs; }
+#endif
+#ifdef Q_NO_PACKED_REFERENCE
+ inline ushort &unicode() { return const_cast<ushort&>(ucs); }
+#else
+ inline ushort &unicode() { return ucs; }
+#endif
+
+ static QChar fromAscii(char c);
+ static QChar fromLatin1(char c);
+
+ inline bool isNull() const { return ucs == 0; }
+ bool isPrint() const;
+ bool isPunct() const;
+ bool isSpace() const;
+ bool isMark() const;
+ bool isLetter() const;
+ bool isNumber() const;
+ bool isLetterOrNumber() const;
+ bool isDigit() const;
+ bool isSymbol() const;
+ inline bool isLower() const { return category() == Letter_Lowercase; }
+ inline bool isUpper() const { return category() == Letter_Uppercase; }
+ inline bool isTitleCase() const { return category() == Letter_Titlecase; }
+
+ inline bool isHighSurrogate() const {
+ return ((ucs & 0xfc00) == 0xd800);
+ }
+ inline bool isLowSurrogate() const {
+ return ((ucs & 0xfc00) == 0xdc00);
+ }
+
+ inline uchar cell() const { return uchar(ucs & 0xff); }
+ inline uchar row() const { return uchar((ucs>>8)&0xff); }
+ inline void setCell(uchar cell);
+ inline void setRow(uchar row);
+
+ static inline bool isHighSurrogate(uint ucs4) {
+ return ((ucs4 & 0xfffffc00) == 0xd800);
+ }
+ static inline bool isLowSurrogate(uint ucs4) {
+ return ((ucs4 & 0xfffffc00) == 0xdc00);
+ }
+ static inline bool requiresSurrogates(uint ucs4) {
+ return (ucs4 >= 0x10000);
+ }
+ static inline uint surrogateToUcs4(ushort high, ushort low) {
+ return (uint(high)<<10) + low - 0x35fdc00;
+ }
+ static inline uint surrogateToUcs4(QChar high, QChar low) {
+ return (uint(high.ucs)<<10) + low.ucs - 0x35fdc00;
+ }
+ static inline ushort highSurrogate(uint ucs4) {
+ return ushort((ucs4>>10) + 0xd7c0);
+ }
+ static inline ushort lowSurrogate(uint ucs4) {
+ return ushort(ucs4%0x400 + 0xdc00);
+ }
+
+ static Category QT_FASTCALL category(uint ucs4);
+ static Category QT_FASTCALL category(ushort ucs2);
+ static Direction QT_FASTCALL direction(uint ucs4);
+ static Direction QT_FASTCALL direction(ushort ucs2);
+ static Joining QT_FASTCALL joining(uint ucs4);
+ static Joining QT_FASTCALL joining(ushort ucs2);
+ static unsigned char QT_FASTCALL combiningClass(uint ucs4);
+ static unsigned char QT_FASTCALL combiningClass(ushort ucs2);
+
+ static uint QT_FASTCALL mirroredChar(uint ucs4);
+ static ushort QT_FASTCALL mirroredChar(ushort ucs2);
+ static Decomposition QT_FASTCALL decompositionTag(uint ucs4);
+
+ static int QT_FASTCALL digitValue(uint ucs4);
+ static int QT_FASTCALL digitValue(ushort ucs2);
+ static uint QT_FASTCALL toLower(uint ucs4);
+ static ushort QT_FASTCALL toLower(ushort ucs2);
+ static uint QT_FASTCALL toUpper(uint ucs4);
+ static ushort QT_FASTCALL toUpper(ushort ucs2);
+ static uint QT_FASTCALL toTitleCase(uint ucs4);
+ static ushort QT_FASTCALL toTitleCase(ushort ucs2);
+ static uint QT_FASTCALL toCaseFolded(uint ucs4);
+ static ushort QT_FASTCALL toCaseFolded(ushort ucs2);
+
+ static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4);
+ static UnicodeVersion QT_FASTCALL unicodeVersion(ushort ucs2);
+
+ static UnicodeVersion QT_FASTCALL currentUnicodeVersion();
+
+ static QString QT_FASTCALL decomposition(uint ucs4);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool mirrored() const { return hasMirrored(); }
+ inline QT3_SUPPORT QChar lower() const { return toLower(); }
+ inline QT3_SUPPORT QChar upper() const { return toUpper(); }
+ static inline QT3_SUPPORT bool networkOrdered() {
+ return QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ }
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline QT3_SUPPORT const char latin1() const { return toLatin1(); }
+ inline QT3_SUPPORT const char ascii() const { return toAscii(); }
+#else
+ inline QT3_SUPPORT char latin1() const { return toLatin1(); }
+ inline QT3_SUPPORT char ascii() const { return toAscii(); }
+#endif
+#endif
+
+private:
+#ifdef QT_NO_CAST_FROM_ASCII
+ QChar(char c);
+ QChar(uchar c);
+#endif
+ ushort ucs;
+};
+
+Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE);
+
+inline QChar::QChar() : ucs(0) {}
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
+#else
+inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
+#endif
+inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); }
+
+inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){}
+inline QChar::QChar(short rc) : ucs(ushort(rc)){}
+inline QChar::QChar(uint rc) : ucs(ushort(rc & 0xffff)){}
+inline QChar::QChar(int rc) : ucs(ushort(rc & 0xffff)){}
+inline QChar::QChar(SpecialCharacter s) : ucs(ushort(s)) {}
+inline QChar::QChar(QLatin1Char ch) : ucs(ch.unicode()) {}
+
+inline void QChar::setCell(uchar acell)
+{ ucs = ushort((ucs & 0xff00) + acell); }
+inline void QChar::setRow(uchar arow)
+{ ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); }
+
+inline bool operator==(QChar c1, QChar c2) { return c1.unicode() == c2.unicode(); }
+inline bool operator!=(QChar c1, QChar c2) { return c1.unicode() != c2.unicode(); }
+inline bool operator<=(QChar c1, QChar c2) { return c1.unicode() <= c2.unicode(); }
+inline bool operator>=(QChar c1, QChar c2) { return c1.unicode() >= c2.unicode(); }
+inline bool operator<(QChar c1, QChar c2) { return c1.unicode() < c2.unicode(); }
+inline bool operator>(QChar c1, QChar c2) { return c1.unicode() > c2.unicode(); }
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QChar &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCHAR_H
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
new file mode 100644
index 0000000000..28f8a6f1a3
--- /dev/null
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTAINERFWD_H
+#define QCONTAINERFWD_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class Key, class T> class QCache;
+template <class Key, class T> class QHash;
+template <class T> class QLinkedList;
+template <class T> class QList;
+template <class Key, class T> class QMap;
+template <class Key, class T> class QMultiHash;
+template <class Key, class T> class QMultiMap;
+template <class T1, class T2> struct QPair;
+template <class T> class QQueue;
+template <class T> class QSet;
+template <class T> class QStack;
+template<class T, int Prealloc = 256> class QVarLengthArray;
+template <class T> class QVector;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCONTAINERFWD_H
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
new file mode 100644
index 0000000000..8e1c4c49a2
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontiguouscache.h"
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+#include <QDebug>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+void QContiguousCacheData::dump() const
+{
+ qDebug() << "capacity:" << alloc;
+ qDebug() << "count:" << count;
+ qDebug() << "start:" << start;
+ qDebug() << "offset:" << offset;
+}
+#endif
+
+QContiguousCacheData *QContiguousCacheData::allocate(int size, int alignment)
+{
+ return static_cast<QContiguousCacheData *>(qMallocAligned(size, alignment));
+}
+
+void QContiguousCacheData::free(QContiguousCacheData *data)
+{
+ qFreeAligned(data);
+}
+
+/*! \class QContiguousCache
+ \brief The QContiguousCache class is a template class that provides a contiguous cache.
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+ \since 4.6
+
+ The QContiguousCache class provides an efficient way of caching items for
+ display in a user interface view. Unlike QCache, it adds a restriction
+ that elements within the cache are contiguous. This has the advantage
+ of matching how user interface views most commonly request data, as
+ a set of rows localized around the current scrolled position. This
+ restriction allows the cache to consume less memory and processor
+ cycles than QCache. The QContiguousCache class also can provide
+ an upper bound on memory usage via setCapacity().
+
+ The simplest way of using a contiguous cache is to use the append()
+ and prepend().
+
+\code
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while(row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while(row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+\endcode
+
+ If the cache is full then the item at the opposite end of the cache from
+ where the new item is appended or prepended will be removed.
+
+ This usage can be further optimized by using the insert() function
+ in the case where the requested row is a long way from the currently cached
+ items. If there is a gap between where the new item is inserted and the currently
+ cached items then the existing cached items are first removed to retain
+ the contiguous nature of the cache. Hence it is important to take some care then
+ when using insert() in order to avoid unwanted clearing of the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Calling prepend() such that the first index would become less
+ than 0 or append() such that the last index would become greater
+ than INT_MAX can result in the indexes of the cache being invalid.
+ When the cache indexes are invalid it is important to call
+ normalizeIndexes() before calling any of containsIndex(), firstIndex(),
+ lastIndex(), at() or \l{QContiguousCache::operator[]()}{operator[]()}.
+ Calling these functions when the cache has invalid indexes will result in
+ undefined behavior. The indexes can be checked by using areIndexesValid()
+
+ In most cases the indexes will not exceed 0 to INT_MAX, and
+ normalizeIndexes() will not need to be used.
+
+ See the \l{Contiguous Cache Example}{Contiguous Cache} example.
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(int capacity)
+
+ Constructs a cache with the given \a capacity.
+
+ \sa setCapacity()
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QContiguousCache is
+ \l{implicitly shared}. This makes returning a QContiguousCache from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QContiguousCache::~QContiguousCache()
+
+ Destroys the cache.
+*/
+
+/*! \fn void QContiguousCache::detach()
+ \internal
+*/
+
+/*! \fn bool QContiguousCache::isDetached() const
+ \internal
+*/
+
+/*! \fn void QContiguousCache::setSharable(bool sharable)
+ \internal
+*/
+
+/*! \typedef QContiguousCache::value_type
+ \internal
+ */
+
+/*! \typedef QContiguousCache::pointer
+ \internal
+ */
+
+/*! \typedef QContiguousCache::const_pointer
+ \internal
+ */
+
+/*! \typedef QContiguousCache::reference
+ \internal
+ */
+
+/*! \typedef QContiguousCache::const_reference
+ \internal
+ */
+
+/*! \typedef QContiguousCache::difference_type
+ \internal
+ */
+
+/*! \typedef QContiguousCache::size_type
+ \internal
+ */
+
+/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
+
+ Assigns \a other to this cache and returns a reference to this cache.
+*/
+
+/*! \fn void QContiguousCache::swap(QContiguousCache<T> &other)
+ \since 4.8
+
+ Swaps cache \a other with this cache. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is equal to this cache; otherwise returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is not equal to this cache; otherwise
+ returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QContiguousCache::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
+ items will cause items farthest from the added item to be removed.
+
+ \sa setCapacity(), size()
+*/
+
+/*! \fn int QContiguousCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn int QContiguousCache::size() const
+
+ Returns the number of items contained within the cache.
+
+ \sa capacity()
+*/
+
+/*! \fn bool QContiguousCache::isEmpty() const
+
+ Returns true if no items are stored within the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn bool QContiguousCache::isFull() const
+
+ Returns true if the number of items stored within the cache is equal
+ to the capacity of the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn int QContiguousCache::available() const
+
+ Returns the number of items that can be added to the cache before it becomes full.
+
+ \sa size(), capacity(), isFull()
+*/
+
+/*! \fn void QContiguousCache::clear()
+
+ Removes all items from the cache. The capacity is unchanged.
+*/
+
+/*! \fn void QContiguousCache::setCapacity(int 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
+ items to the cache, if the cache is already full then the item farthest from
+ the added item will be removed.
+
+ If the given \a size is smaller than the current count of items in the cache
+ then only the last \a size items from the cache will remain.
+
+ \sa capacity(), isFull()
+*/
+
+/*! \fn const T &QContiguousCache::at(int 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()).
+
+ The indexes in the cache refer to the number of positions the item is from the
+ first item appended into the cache. That is to say a cache with a capacity of
+ 100, that has had 150 items appended will have a valid index range of
+ 50 to 149. This allows inserting and retrieving items into the cache based
+ on a theoretical infinite list
+
+ \sa firstIndex(), lastIndex(), insert(), operator[]()
+*/
+
+/*! \fn T &QContiguousCache::operator[](int 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
+ then it will first insert an empty item at that position.
+
+ In most cases it is better to use either at() or insert().
+
+ \note This non-const overload of operator[] requires QContiguousCache
+ to make a deep copy. Use at() for read-only access to a non-const
+ QContiguousCache.
+
+ \sa insert(), at()
+*/
+
+/*! \fn const T &QContiguousCache::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn void QContiguousCache::append(const T &value)
+
+ Inserts \a value at the end of the cache. If the cache is already full
+ the item at the start of the cache will be removed.
+
+ \sa prepend(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::prepend(const T &value)
+
+ Inserts \a value at the start of the cache. If the cache is already full
+ the item at the end of the cache will be removed.
+
+ \sa append(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::insert(int 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
+ lastIndex() or one less than firstIndex() it is the equivalent to an append()
+ or a prepend().
+
+ If the given index \a i is not within the current range of the cache nor adjacent
+ to the bounds of the cache's index range, the cache is first cleared before
+ inserting the item. At this point the cache will have a size of 1. It is
+ worthwhile taking effort to insert items in an order that starts adjacent
+ to the current index range for the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Inserting outside of this range has undefined behavior.
+
+
+ \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
+*/
+
+/*! \fn bool QContiguousCache::containsIndex(int i) const
+
+ Returns true if the cache's index range includes the given index \a i.
+
+ \sa firstIndex(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::firstIndex() const
+
+ Returns the first valid index in the cache. The index will be invalid if the
+ cache is empty.
+
+ \sa capacity(), size(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::lastIndex() const
+
+ Returns the last valid index in the cache. The index will be invalid if the cache is empty.
+
+ \sa capacity(), size(), firstIndex()
+*/
+
+
+/*! \fn T &QContiguousCache::first()
+
+ Returns a reference to the first item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn T &QContiguousCache::last()
+
+ Returns a reference to the last item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QContiguousCache::first() const
+
+ \overload
+*/
+
+/*! \fn const T& QContiguousCache::last() const
+
+ \overload
+*/
+
+/*! \fn void QContiguousCache::removeFirst()
+
+ Removes the first item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeLast()
+*/
+
+/*! \fn void QContiguousCache::removeLast()
+
+ Removes the last item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeFirst()
+
+ Removes the first item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeFirst() is more efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeLast()
+
+ Removes the last item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeLast() is more efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QContiguousCache::normalizeIndexes()
+
+ Moves the first index and last index of the cache
+ such that they point to valid indexes. The function does not modify
+ the contents of the cache or the ordering of elements within the cache.
+
+ It is provided so that index overflows can be corrected when using the
+ cache as a circular buffer.
+
+ \code
+ QContiguousCache<int> cache(10);
+ cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+ cache.append(2); // cache contains two values but does not have valid indexes.
+ cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+ \endcode
+
+ \sa areIndexesValid(), append(), prepend()
+*/
+
+/*! \fn bool QContiguousCache::areIndexesValid() const
+
+ Returns whether the indexes for items stored in the cache are valid.
+ Indexes can become invalid if items are appended after the index position
+ INT_MAX or prepended before the index position 0. This is only expected
+ to occur in very long lived circular buffer style usage of the
+ contiguous cache. Indexes can be made valid again by calling
+ normalizeIndexs().
+
+ \sa normalizeIndexes(), append(), prepend()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
new file mode 100644
index 0000000000..7880c2e411
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTIGUOUSCACHE_H
+#define QCONTIGUOUSCACHE_H
+
+#include <QtCore/qatomic.h>
+#include <limits.h>
+#include <new>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#undef QT_QCONTIGUOUSCACHE_DEBUG
+QT_MODULE(Core)
+
+
+struct Q_CORE_EXPORT QContiguousCacheData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+ uint reserved : 31;
+
+ // total is 24 bytes (HP-UX aCC: 40 bytes)
+ // the next entry is already aligned to 8 bytes
+ // there will be an 8 byte gap here if T requires 16-byte alignment
+ // (such as long double on 64-bit platforms, __int128, __float128)
+
+ static QContiguousCacheData *allocate(int size, int alignment);
+ static void free(QContiguousCacheData *data);
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const;
+#endif
+};
+
+template <typename T>
+struct QContiguousCacheTypedData: private QContiguousCacheData
+{
+ // private inheritance to avoid aliasing warningss
+ T array[1];
+
+ static inline void free(QContiguousCacheTypedData *data) { QContiguousCacheData::free(data); }
+};
+
+template<typename T>
+class QContiguousCache {
+ typedef QContiguousCacheTypedData<T> Data;
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; };
+public:
+ // STL compatibility
+ 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 int size_type;
+
+ explicit QContiguousCache(int capacity = 0);
+ QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+
+ inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(p); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+
+ QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QContiguousCache<T> &other) { qSwap(d, other.d); }
+ bool operator==(const QContiguousCache<T> &other) const;
+ inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ inline int capacity() const {return d->alloc; }
+ inline int count() const { return d->count; }
+ inline int size() const { return d->count; }
+
+ inline bool isEmpty() const { return d->count == 0; }
+ inline bool isFull() const { return d->count == d->alloc; }
+ inline int available() const { return d->alloc - d->count; }
+
+ void clear();
+ void setCapacity(int size);
+
+ const T &at(int pos) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+
+ void append(const T &value);
+ void prepend(const T &value);
+ void insert(int pos, const T &value);
+
+ inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; }
+ inline int firstIndex() const { return d->offset; }
+ inline int lastIndex() const { return d->offset + d->count - 1; }
+
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return p->array[d->start]; }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return p->array[(d->start + d->count -1) % d->alloc]; }
+ inline T &first() { Q_ASSERT(!isEmpty()); detach(); return p->array[d->start]; }
+ inline T &last() { Q_ASSERT(!isEmpty()); detach(); return p->array[(d->start + d->count -1) % d->alloc]; }
+
+ void removeFirst();
+ T takeFirst();
+ void removeLast();
+ T takeLast();
+
+ inline bool areIndexesValid() const
+ { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; }
+
+ inline void normalizeIndexes() { d->offset = d->start; }
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const { p->dump(); }
+#endif
+private:
+ void detach_helper();
+
+ QContiguousCacheData *malloc(int aalloc);
+ void free(Data *x);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+ int alignOfTypedData() const
+ {
+#ifdef Q_ALIGNOF
+ return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+#else
+ return 0;
+#endif
+ }
+};
+
+template <typename T>
+void QContiguousCache<T>::detach_helper()
+{
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+
+ x.d = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->count = d->count;
+ x.d->start = d->start;
+ x.d->offset = d->offset;
+ x.d->alloc = d->alloc;
+ x.d->sharable = true;
+ x.d->reserved = 0;
+
+ T *dest = x.p->array + x.d->start;
+ T *src = p->array + d->start;
+ int oldcount = x.d->count;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ dest++;
+ if (dest == x.p->array + x.d->alloc)
+ dest = x.p->array;
+ src++;
+ if (src == p->array + d->alloc)
+ src = p->array;
+ }
+
+ if (!d->ref.deref())
+ free(p);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::setCapacity(int asize)
+{
+ if (asize == d->alloc)
+ return;
+ detach();
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+ x.d = malloc(asize);
+ x.d->alloc = asize;
+ x.d->count = qMin(d->count, asize);
+ x.d->offset = d->offset + d->count - x.d->count;
+ if(asize)
+ x.d->start = x.d->offset % x.d->alloc;
+ else
+ x.d->start = 0;
+
+ int oldcount = x.d->count;
+ if(oldcount)
+ {
+ T *dest = x.p->array + (x.d->start + x.d->count-1) % x.d->alloc;
+ T *src = p->array + (d->start + d->count-1) % d->alloc;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ if (dest == x.p->array)
+ dest = x.p->array + x.d->alloc;
+ dest--;
+ if (src == p->array)
+ src = p->array + d->alloc;
+ src--;
+ }
+ }
+ /* free old */
+ free(p);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::clear()
+{
+ if (d->ref == 1) {
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = p->array + d->start;
+ T * e = p->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = p->array;
+ }
+ }
+ d->count = d->start = d->offset = 0;
+ } else {
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+ x.d = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->alloc = d->alloc;
+ x.d->count = x.d->start = x.d->offset = 0;
+ x.d->sharable = true;
+ if (!d->ref.deref()) free(p);
+ d = x.d;
+ }
+}
+
+template <typename T>
+inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
+{
+ return QContiguousCacheData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
+}
+
+template <typename T>
+QContiguousCache<T>::QContiguousCache(int cap)
+{
+ d = malloc(cap);
+ d->ref = 1;
+ d->alloc = cap;
+ d->count = d->start = d->offset = 0;
+ d->sharable = true;
+}
+
+template <typename T>
+QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = other.d;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+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 (int i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+}
+
+template <typename T>
+void QContiguousCache<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = p->array + d->start;
+ T * e = p->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = p->array;
+ }
+ }
+ x->free(x);
+}
+template <typename T>
+void QContiguousCache<T>::append(const T &value)
+{
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ if (d->count == d->alloc)
+ (p->array + (d->start+d->count) % d->alloc)->~T();
+ new (p->array + (d->start+d->count) % d->alloc) T(value);
+ } else {
+ p->array[(d->start+d->count) % d->alloc] = value;
+ }
+
+ if (d->count == d->alloc) {
+ d->start++;
+ d->start %= d->alloc;
+ d->offset++;
+ } else {
+ d->count++;
+ }
+}
+
+template<typename T>
+void QContiguousCache<T>::prepend(const T &value)
+{
+ detach();
+ if (d->start)
+ d->start--;
+ else
+ d->start = d->alloc-1;
+ d->offset--;
+
+ if (d->count != d->alloc)
+ d->count++;
+ else
+ if (d->count == d->alloc)
+ (p->array + d->start)->~T();
+
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->start) T(value);
+ else
+ p->array[d->start] = value;
+}
+
+template<typename T>
+void QContiguousCache<T>::insert(int pos, const T &value)
+{
+ Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+ detach();
+ if (containsIndex(pos)) {
+ if(QTypeInfo<T>::isComplex)
+ new (p->array + pos % d->alloc) T(value);
+ else
+ p->array[pos % d->alloc] = value;
+ } else if (pos == d->offset-1)
+ prepend(value);
+ else if (pos == d->offset+d->count)
+ append(value);
+ else {
+ // we don't leave gaps.
+ clear();
+ d->offset = pos;
+ d->start = pos % d->alloc;
+ d->count = 1;
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->start) T(value);
+ else
+ p->array[d->start] = value;
+ }
+}
+
+template <typename T>
+inline const T &QContiguousCache<T>::at(int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
+template <typename T>
+inline const T &QContiguousCache<T>::operator[](int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
+
+template <typename T>
+inline T &QContiguousCache<T>::operator[](int pos)
+{
+ detach();
+ if (!containsIndex(pos))
+ insert(pos, T());
+ return p->array[pos % d->alloc];
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeFirst()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (p->array + d->start)->~T();
+ d->start = (d->start + 1) % d->alloc;
+ d->offset++;
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeLast()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (p->array + (d->start + d->count) % d->alloc)->~T();
+}
+
+template <typename T>
+inline T QContiguousCache<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+
+template <typename T>
+inline T QContiguousCache<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
new file mode 100644
index 0000000000..630e390563
--- /dev/null
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcryptographichash.h>
+
+#ifdef Q_OS_SYMBIAN
+#define _MD5_H_ // Needed to disable system header
+#endif
+
+#include "../../3rdparty/md5/md5.h"
+#include "../../3rdparty/md5/md5.cpp"
+#include "../../3rdparty/md4/md4.h"
+#include "../../3rdparty/md4/md4.cpp"
+#include "../../3rdparty/sha1/sha1.cpp"
+
+
+QT_BEGIN_NAMESPACE
+
+class QCryptographicHashPrivate
+{
+public:
+ QCryptographicHash::Algorithm method;
+ union {
+ MD5Context md5Context;
+ md4_context md4Context;
+ Sha1State sha1Context;
+ };
+ QByteArray result;
+};
+
+/*!
+ \class QCryptographicHash
+
+ \brief The QCryptographicHash class provides a way to generate cryptographic hashes.
+
+ \since 4.3
+
+ \ingroup tools
+ \reentrant
+
+ QCryptographicHash can be used to generate cryptographic hashes of binary or text data.
+
+ Currently MD4, MD5, and SHA-1 are supported.
+*/
+
+/*!
+ \enum QCryptographicHash::Algorithm
+
+ \value Md4 Generate an MD4 hash sum
+ \value Md5 Generate an MD5 hash sum
+ \value Sha1 Generate an SHA1 hash sum
+*/
+
+/*!
+ 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->method = method;
+ reset();
+}
+
+/*!
+ Destroys the object.
+*/
+QCryptographicHash::~QCryptographicHash()
+{
+ delete d;
+}
+
+/*!
+ Resets the object.
+*/
+void QCryptographicHash::reset()
+{
+ switch (d->method) {
+ case Md4:
+ md4_init(&d->md4Context);
+ break;
+ case Md5:
+ MD5Init(&d->md5Context);
+ break;
+ case Sha1:
+ sha1InitState(&d->sha1Context);
+ break;
+ }
+ d->result.clear();
+}
+
+/*!
+ Adds the first \a length chars of \a data to the cryptographic
+ hash.
+*/
+void QCryptographicHash::addData(const char *data, int length)
+{
+ switch (d->method) {
+ case Md4:
+ md4_update(&d->md4Context, (const unsigned char *)data, length);
+ break;
+ case Md5:
+ MD5Update(&d->md5Context, (const unsigned char *)data, length);
+ break;
+ case Sha1:
+ sha1Update(&d->sha1Context, (const unsigned char *)data, length);
+ break;
+ }
+ d->result.clear();
+}
+
+/*!
+ \overload addData()
+*/
+void QCryptographicHash::addData(const QByteArray &data)
+{
+ addData(data.constData(), data.length());
+}
+
+/*!
+ Returns the final hash value.
+
+ \sa QByteArray::toHex()
+*/
+QByteArray QCryptographicHash::result() const
+{
+ if (!d->result.isEmpty())
+ return d->result;
+
+ switch (d->method) {
+ 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());
+ break;
+ }
+ case Sha1: {
+ Sha1State copy = d->sha1Context;
+ d->result.resize(20);
+ sha1FinalizeState(&copy);
+ sha1ToHash(&copy, (unsigned char *)d->result.data());
+ }
+ }
+ return d->result;
+}
+
+/*!
+ Returns the hash of \a data using \a method.
+*/
+QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
+{
+ QCryptographicHash hash(method);
+ hash.addData(data);
+ return hash.result();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h
new file mode 100644
index 0000000000..8506961882
--- /dev/null
+++ b/src/corelib/tools/qcryptographichash.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCRYPTOGRAPHICSHASH_H
+#define QCRYPTOGRAPHICSHASH_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QCryptographicHashPrivate;
+
+class Q_CORE_EXPORT QCryptographicHash
+{
+public:
+ enum Algorithm {
+ Md4,
+ Md5,
+ Sha1
+ };
+
+ QCryptographicHash(Algorithm method);
+ ~QCryptographicHash();
+
+ void reset();
+
+ void addData(const char *data, int length);
+ void addData(const QByteArray &data);
+
+ QByteArray result() const;
+
+ static QByteArray hash(const QByteArray &data, Algorithm method);
+private:
+ Q_DISABLE_COPY(QCryptographicHash)
+ QCryptographicHashPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
new file mode 100644
index 0000000000..a3a8884374
--- /dev/null
+++ b/src/corelib/tools/qdatetime.cpp
@@ -0,0 +1,5881 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "private/qdatetime_p.h"
+
+#include "qdatastream.h"
+#include "qset.h"
+#include "qlocale.h"
+#include "qdatetime.h"
+#include "qregexp.h"
+#include "qdebug.h"
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+#include <qt_windows.h>
+#endif
+#ifndef Q_WS_WIN
+#include <locale.h>
+#endif
+
+#include <time.h>
+#if defined(Q_OS_WINCE)
+#include "qfunctions_wince.h"
+#endif
+
+//#define QDATETIMEPARSER_DEBUG
+#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
+# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
+# define QDTPDEBUGN qDebug
+#else
+# define QDTPDEBUG if (false) qDebug()
+# define QDTPDEBUGN if (false) qDebug
+#endif
+
+#if defined(Q_WS_MAC)
+#include <private/qcore_mac_p.h>
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+#include <e32std.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ FIRST_YEAR = -4713,
+ FIRST_MONTH = 1,
+ FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid
+ SECS_PER_DAY = 86400,
+ MSECS_PER_DAY = 86400000,
+ SECS_PER_HOUR = 3600,
+ MSECS_PER_HOUR = 3600000,
+ SECS_PER_MIN = 60,
+ MSECS_PER_MIN = 60000,
+ JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromGregorianDate(1970, 1, 1)
+};
+
+static inline QDate fixedDate(int y, int m, int d)
+{
+ QDate result(y, m, 1);
+ result.setDate(y, m, qMin(d, result.daysInMonth()));
+ return result;
+}
+
+static inline uint julianDayFromGregorianDate(int year, int month, int day)
+{
+ // Gregorian calendar starting from October 15, 1582
+ // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
+ return (1461 * (year + 4800 + (month - 14) / 12)) / 4
+ + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
+ - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
+ + day - 32075;
+}
+
+static uint julianDayFromDate(int year, int month, int day)
+{
+ if (year < 0)
+ ++year;
+
+ if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
+ return julianDayFromGregorianDate(year, month, day);
+ } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
+ // Julian calendar until October 4, 1582
+ // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
+ int a = (14 - month) / 12;
+ return (153 * (month + (12 * a) - 3) + 2) / 5
+ + (1461 * (year + 4800 - a)) / 4
+ + day - 32083;
+ } else {
+ // the day following October 4, 1582 is October 15, 1582
+ return 0;
+ }
+}
+
+static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
+{
+ int y, m, d;
+
+ if (julianDay >= 2299161) {
+ // Gregorian calendar starting from October 15, 1582
+ // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
+ qulonglong ell, n, i, j;
+ ell = qulonglong(julianDay) + 68569;
+ n = (4 * ell) / 146097;
+ ell = ell - (146097 * n + 3) / 4;
+ i = (4000 * (ell + 1)) / 1461001;
+ ell = ell - (1461 * i) / 4 + 31;
+ j = (80 * ell) / 2447;
+ d = ell - (2447 * j) / 80;
+ ell = j / 11;
+ m = j + 2 - (12 * ell);
+ y = 100 * (n - 49) + i + ell;
+ } else {
+ // Julian calendar until October 4, 1582
+ // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
+ julianDay += 32082;
+ int dd = (4 * julianDay + 3) / 1461;
+ int ee = julianDay - (1461 * dd) / 4;
+ int mm = ((5 * ee) + 2) / 153;
+ d = ee - (153 * mm + 2) / 5 + 1;
+ m = mm + 3 - 12 * (mm / 10);
+ y = dd - 4800 + (mm / 10);
+ if (y <= 0)
+ --y;
+ }
+ if (year)
+ *year = y;
+ if (month)
+ *month = m;
+ if (day)
+ *day = d;
+}
+
+
+static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+#ifndef QT_NO_TEXTDATE
+static const char * const qt_shortMonthNames[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+#endif
+#ifndef QT_NO_DATESTRING
+static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
+#endif
+
+/*****************************************************************************
+ QDate member functions
+ *****************************************************************************/
+
+/*!
+ \since 4.5
+
+ \enum QDate::MonthNameType
+
+ This enum describes the types of the string representation used
+ for the month name.
+
+ \value DateFormat This type of name can be used for date-to-string formatting.
+ \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
+ Usually standalone names are represented in singular forms with
+ capitalized first letter.
+*/
+
+/*!
+ \class QDate
+ \reentrant
+ \brief The QDate class provides date functions.
+
+
+ A QDate object contains a calendar date, i.e. year, month, and day
+ numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
+ Gregorian and Julian Calendars} for dates prior to 15 October
+ 1582). It can read the current date from the system clock. It
+ provides functions for comparing dates, and for manipulating
+ dates. For example, it is possible to add and subtract days,
+ months, and years to dates.
+
+ A QDate object is typically created either by giving the year,
+ month, and day numbers explicitly. Note that QDate interprets two
+ digit years as is, i.e., years 0 - 99. A QDate can also be
+ constructed with the static function currentDate(), which creates
+ a QDate object containing the system clock's date. An explicit
+ date can also be set using setDate(). The fromString() function
+ returns a QDate given a string and a date format which is used to
+ interpret the date within the string.
+
+ The year(), month(), and day() functions provide access to the
+ year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
+ functions are provided. The same information is provided in
+ textual format by the toString(), shortDayName(), longDayName(),
+ shortMonthName(), and longMonthName() functions.
+
+ QDate provides a full set of operators to compare two QDate
+ objects where smaller means earlier, and larger means later.
+
+ You can increment (or decrement) a date by a given number of days
+ using addDays(). Similarly you can use addMonths() and addYears().
+ The daysTo() function returns the number of days between two
+ dates.
+
+ The daysInMonth() and daysInYear() functions return how many days
+ there are in this date's month and year, respectively. The
+ isLeapYear() function indicates whether a date is in a leap year.
+
+ \section1
+
+ \target QDate G and J
+ \section2 Use of Gregorian and Julian Calendars
+
+ QDate uses the Gregorian calendar in all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, the Julian calendar is used. This means there is a
+ 10-day gap in the internal calendar between the 4th and the 15th
+ of October 1582. When you use QDateTime for dates in that epoch,
+ the day after 4 October 1582 is 15 October 1582, and the dates in
+ the gap are invalid.
+
+ The Julian to Gregorian changeover date used here is the date when
+ the Gregorian calendar was first introduced, by Pope Gregory
+ XIII. That change was not universally accepted and some localities
+ only executed it at a later date (if at all). QDateTime
+ doesn't take any of these historical facts into account. If an
+ application must support a locale-specific dating system, it must
+ do so on its own, remembering to convert the dates using the
+ Julian day.
+
+ \section2 No Year 0
+
+ There is no year 0. Dates in that year are considered invalid. The
+ year -1 is the year "1 before Christ" or "1 before current era."
+ The day before 0001-01-01 is December 31st, 1 BCE.
+
+ \section2 Range of Valid Dates
+
+ The range of valid dates is from January 2nd, 4713 BCE, to
+ sometime in the year 11 million CE. The Julian Day returned by
+ QDate::toJulianDay() is a number in the contiguous range from 1 to
+ \e{overflow}, even across QDateTime's "date holes". It is suitable
+ for use in applications that must convert a QDateTime to a date in
+ another calendar system, e.g., Hebrew, Islamic or Chinese.
+
+ \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
+*/
+
+/*!
+ \fn QDate::QDate()
+
+ Constructs a null date. Null dates are invalid.
+
+ \sa isNull(), isValid()
+*/
+
+/*!
+ Constructs a date with year \a y, month \a m and day \a d.
+
+ If the specified date is invalid, the date is not set and
+ isValid() returns false. A date before 2 January 4713 B.C. is
+ considered invalid.
+
+ \warning Years 0 to 99 are interpreted as is, i.e., years
+ 0-99.
+
+ \sa isValid()
+*/
+
+QDate::QDate(int y, int m, int d)
+{
+ setDate(y, m, d);
+}
+
+
+/*!
+ \fn bool QDate::isNull() const
+
+ Returns true if the date is null; otherwise returns false. A null
+ date is invalid.
+
+ \note The behavior of this function is equivalent to isValid().
+
+ \sa isValid()
+*/
+
+
+/*!
+ Returns true if this date is valid; otherwise returns false.
+
+ \sa isNull()
+*/
+
+bool QDate::isValid() const
+{
+ return !isNull();
+}
+
+
+/*!
+ Returns the year of this date. Negative numbers indicate years
+ before 1 A.D. = 1 C.E., such that year -44 is 44 B.C.
+
+ \sa month(), day()
+*/
+
+int QDate::year() const
+{
+ int y;
+ getDateFromJulianDay(jd, &y, 0, 0);
+ return y;
+}
+
+/*!
+ Returns the number corresponding to the month of this date, using
+ the following convention:
+
+ \list
+ \i 1 = "January"
+ \i 2 = "February"
+ \i 3 = "March"
+ \i 4 = "April"
+ \i 5 = "May"
+ \i 6 = "June"
+ \i 7 = "July"
+ \i 8 = "August"
+ \i 9 = "September"
+ \i 10 = "October"
+ \i 11 = "November"
+ \i 12 = "December"
+ \endlist
+
+ \sa year(), day()
+*/
+
+int QDate::month() const
+{
+ int m;
+ getDateFromJulianDay(jd, 0, &m, 0);
+ return m;
+}
+
+/*!
+ Returns the day of the month (1 to 31) of this date.
+
+ \sa year(), month(), dayOfWeek()
+*/
+
+int QDate::day() const
+{
+ int d;
+ getDateFromJulianDay(jd, 0, 0, &d);
+ return d;
+}
+
+/*!
+ Returns the weekday (1 to 7) for this date.
+
+ \sa day(), dayOfYear(), Qt::DayOfWeek
+*/
+
+int QDate::dayOfWeek() const
+{
+ return (jd % 7) + 1;
+}
+
+/*!
+ Returns the day of the year (1 to 365 or 366 on leap years) for
+ this date.
+
+ \sa day(), dayOfWeek()
+*/
+
+int QDate::dayOfYear() const
+{
+ return jd - julianDayFromDate(year(), 1, 1) + 1;
+}
+
+/*!
+ Returns the number of days in the month (28 to 31) for this date.
+
+ \sa day(), daysInYear()
+*/
+
+int QDate::daysInMonth() const
+{
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ if (m == 2 && isLeapYear(y))
+ return 29;
+ else
+ return monthDays[m];
+}
+
+/*!
+ Returns the number of days in the year (365 or 366) for this date.
+
+ \sa day(), daysInMonth()
+*/
+
+int QDate::daysInYear() const
+{
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ return isLeapYear(y) ? 366 : 365;
+}
+
+/*!
+ Returns the week number (1 to 53), and stores the year in
+ *\a{yearNumber} unless \a yearNumber is null (the default).
+
+ Returns 0 if the date is invalid.
+
+ In accordance with ISO 8601, weeks start on Monday and the first
+ Thursday of a year is always in week 1 of that year. Most years
+ have 52 weeks, but some have 53.
+
+ *\a{yearNumber} is not always the same as year(). For example, 1
+ January 2000 has week number 52 in the year 1999, and 31 December
+ 2002 has week number 1 in the year 2003.
+
+ \legalese
+ Copyright (c) 1989 The Regents of the University of California.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms are permitted
+ provided that the above copyright notice and this paragraph are
+ duplicated in all such forms and that any documentation,
+ advertising materials, and other materials related to such
+ distribution and use acknowledge that the software was developed
+ by the University of California, Berkeley. The name of the
+ University may not be used to endorse or promote products derived
+ from this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ \sa isValid()
+*/
+
+int QDate::weekNumber(int *yearNumber) const
+{
+ if (!isValid())
+ return 0;
+
+ int year = QDate::year();
+ int yday = dayOfYear() - 1;
+ int wday = dayOfWeek();
+ if (wday == 7)
+ wday = 0;
+ int w;
+
+ for (;;) {
+ int len;
+ int bot;
+ int top;
+
+ len = isLeapYear(year) ? 366 : 365;
+ /*
+ ** What yday (-3 ... 3) does
+ ** the ISO year begin on?
+ */
+ bot = ((yday + 11 - wday) % 7) - 3;
+ /*
+ ** What yday does the NEXT
+ ** ISO year begin on?
+ */
+ top = bot - (len % 7);
+ if (top < -3)
+ top += 7;
+ top += len;
+ if (yday >= top) {
+ ++year;
+ w = 1;
+ break;
+ }
+ if (yday >= bot) {
+ w = 1 + ((yday - bot) / 7);
+ break;
+ }
+ --year;
+ yday += isLeapYear(year) ? 366 : 365;
+ }
+ if (yearNumber != 0)
+ *yearNumber = year;
+ return w;
+}
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \since 4.5
+
+ Returns the short name of the \a month for the representation specified
+ by \a type.
+
+ The months are enumerated using the following convention:
+
+ \list
+ \i 1 = "Jan"
+ \i 2 = "Feb"
+ \i 3 = "Mar"
+ \i 4 = "Apr"
+ \i 5 = "May"
+ \i 6 = "Jun"
+ \i 7 = "Jul"
+ \i 8 = "Aug"
+ \i 9 = "Sep"
+ \i 10 = "Oct"
+ \i 11 = "Nov"
+ \i 12 = "Dec"
+ \endlist
+
+ The month names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), longMonthName(), shortDayName(), longDayName()
+*/
+
+QString QDate::shortMonthName(int month, QDate::MonthNameType type)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the short version of the name of the \a month. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), longMonthName(), shortDayName(), longDayName()
+ */
+
+QString QDate::shortMonthName(int month)
+{
+ return shortMonthName(month, QDate::DateFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the long name of the \a month for the representation specified
+ by \a type.
+
+ The months are enumerated using the following convention:
+
+ \list
+ \i 1 = "January"
+ \i 2 = "February"
+ \i 3 = "March"
+ \i 4 = "April"
+ \i 5 = "May"
+ \i 6 = "June"
+ \i 7 = "July"
+ \i 8 = "August"
+ \i 9 = "September"
+ \i 10 = "October"
+ \i 11 = "November"
+ \i 12 = "December"
+ \endlist
+
+ The month names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortMonthName(), shortDayName(), longDayName()
+*/
+
+QString QDate::longMonthName(int month, MonthNameType type)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the long version of the name of the \a month. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), shortMonthName(), shortDayName(), longDayName()
+ */
+
+QString QDate::longMonthName(int month)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ return QLocale::system().monthName(month, QLocale::LongFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the short name of the \a weekday for the representation specified
+ by \a type.
+
+ The days are enumerated using the following convention:
+
+ \list
+ \i 1 = "Mon"
+ \i 2 = "Tue"
+ \i 3 = "Wed"
+ \i 4 = "Thu"
+ \i 5 = "Fri"
+ \i 6 = "Sat"
+ \i 7 = "Sun"
+ \endlist
+
+ The day names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortMonthName(), longMonthName(), longDayName()
+*/
+
+QString QDate::shortDayName(int weekday, MonthNameType type)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the short version of the name of the \a weekday. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), longDayName(), shortMonthName(), longMonthName()
+ */
+
+QString QDate::shortDayName(int weekday)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ return QLocale::system().dayName(weekday, QLocale::ShortFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the long name of the \a weekday for the representation specified
+ by \a type.
+
+ The days are enumerated using the following convention:
+
+ \list
+ \i 1 = "Monday"
+ \i 2 = "Tuesday"
+ \i 3 = "Wednesday"
+ \i 4 = "Thursday"
+ \i 5 = "Friday"
+ \i 6 = "Saturday"
+ \i 7 = "Sunday"
+ \endlist
+
+ The day names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortDayName(), shortMonthName(), longMonthName()
+*/
+
+QString QDate::longDayName(int weekday, MonthNameType type)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
+ default:
+ break;
+ }
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+}
+
+/*!
+ Returns the long version of the name of the \a weekday. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), shortDayName(), shortMonthName(), longMonthName()
+ */
+
+QString QDate::longDayName(int weekday)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+}
+#endif //QT_NO_TEXTDATE
+
+#ifndef QT_NO_DATESTRING
+
+/*!
+ \fn QString QDate::toString(Qt::DateFormat format) const
+
+ \overload
+
+ Returns the date as a string. The \a format parameter determines
+ the format of the string.
+
+ If the \a format is Qt::TextDate, the string is formatted in
+ the default way. QDate::shortDayName() and QDate::shortMonthName()
+ are used to generate the string, so the day and month names will
+ be localized names. An example of this formatting is
+ "Sat May 20 1995".
+
+ 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-DD, where YYYY is the
+ year, MM is the month of the year (between 01 and 12), and DD is
+ the day of the month between 01 and 31.
+
+ If the \a format is Qt::SystemLocaleShortDate or
+ Qt::SystemLocaleLongDate, the string format depends on the locale
+ settings of the system. Identical to calling
+ QLocale::system().toString(date, QLocale::ShortFormat) or
+ QLocale::system().toString(date, QLocale::LongFormat).
+
+ If the \a format is Qt::DefaultLocaleShortDate or
+ Qt::DefaultLocaleLongDate, the string format depends on the
+ default application locale. This is the locale set with
+ QLocale::setDefault(), or the system locale if no default locale
+ has been set. Identical to calling QLocale().toString(date,
+ QLocale::ShortFormat) or QLocale().toString(date,
+ QLocale::LongFormat).
+
+ If the date is invalid, an empty string will be returned.
+
+ \warning The Qt::ISODate format is only valid for years in the
+ range 0 to 9999. This restriction may apply to locale-aware
+ formats as well, depending on the locale settings.
+
+ \sa shortDayName(), shortMonthName()
+*/
+QString QDate::toString(Qt::DateFormat f) const
+{
+ if (!isValid())
+ return QString();
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ switch (f) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ default:
+#ifndef QT_NO_TEXTDATE
+ case Qt::TextDate:
+ {
+ return QString::fromLatin1("%0 %1 %2 %3")
+ .arg(shortDayName(dayOfWeek()))
+ .arg(shortMonthName(m))
+ .arg(d)
+ .arg(y);
+ }
+#endif
+ case Qt::ISODate:
+ {
+ if (year() < 0 || year() > 9999)
+ return QString();
+ QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
+ QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
+ return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
+ }
+ }
+}
+
+/*!
+ Returns the date as a string. The \a format parameter determines
+ the format of the result string.
+
+ These expressions may be used:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1 to 12)
+ \row \i MM \i the month as number with a leading zero (01 to 12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00 to 99)
+ \row \i yyyy \i the year as four digit number. If the year is negative,
+ a minus sign is prepended in addition.
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assuming that the QDate is the 20 July
+ 1969):
+
+ \table
+ \header \o Format \o Result
+ \row \o dd.MM.yyyy \o 20.07.1969
+ \row \o ddd MMMM d yy \o Sun July 20 69
+ \row \o 'The day is' dddd \o The day is Sunday
+ \endtable
+
+ If the datetime is invalid, an empty string will be returned.
+
+ \warning The Qt::ISODate format is only valid for years in the
+ range 0 to 9999. This restriction may apply to locale-aware
+ formats as well, depending on the locale settings.
+
+ \sa QDateTime::toString() QTime::toString()
+
+*/
+QString QDate::toString(const QString& format) const
+{
+ if (year() > 9999)
+ return QString();
+ return fmtDateTime(format, 0, this);
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+ \obsolete
+
+ Sets the date's year \a y, month \a m, and day \a d.
+
+ If \a y is in the range 0 to 99, it is interpreted as 1900 to
+ 1999.
+
+ Use setDate() instead.
+*/
+
+bool QDate::setYMD(int y, int m, int d)
+{
+ if (uint(y) <= 99)
+ y += 1900;
+ return setDate(y, m, d);
+}
+
+/*!
+ \since 4.2
+
+ Sets the date's \a year, \a month, and \a day. Returns true if
+ the date is valid; otherwise returns false.
+
+ If the specified date is invalid, the QDate object is set to be
+ invalid. Any date before 2 January 4713 B.C. is considered
+ invalid.
+
+ \sa isValid()
+*/
+bool QDate::setDate(int year, int month, int day)
+{
+ if (!isValid(year, month, day)) {
+ jd = 0;
+ } else {
+ jd = julianDayFromDate(year, month, day);
+ }
+ return jd != 0;
+}
+
+/*!
+ \since 4.5
+
+ Extracts the date's year, month, and day, and assigns them to
+ *\a year, *\a month, and *\a day. The pointers may be null.
+
+ \sa year(), month(), day(), isValid()
+*/
+void QDate::getDate(int *year, int *month, int *day)
+{
+ getDateFromJulianDay(jd, year, month, day);
+}
+
+/*!
+ Returns a QDate object containing a date \a ndays later than the
+ date of this object (or earlier if \a ndays is negative).
+
+ \sa addMonths() addYears() daysTo()
+*/
+
+QDate QDate::addDays(int ndays) const
+{
+ QDate d;
+ // this is basically "d.jd = jd + ndays" with checks for integer overflow
+ if (ndays >= 0)
+ d.jd = (jd + ndays >= jd) ? jd + ndays : 0;
+ else
+ d.jd = (jd + ndays < jd) ? jd + ndays : 0;
+ return d;
+}
+
+/*!
+ Returns a QDate object containing a date \a nmonths later than the
+ date of this object (or earlier if \a nmonths is negative).
+
+ \note If the ending day/month combination does not exist in the
+ resulting month/year, this function will return a date that is the
+ latest valid date.
+
+ \warning QDate has a date hole around the days introducing the
+ Gregorian calendar (the days 5 to 14 October 1582, inclusive, do
+ not exist). If the calculation ends in one of those days, QDate
+ will return either October 4 or October 15.
+
+ \sa addDays() addYears()
+*/
+
+QDate QDate::addMonths(int nmonths) const
+{
+ if (!isValid())
+ return QDate();
+ if (!nmonths)
+ return *this;
+
+ int old_y, y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ old_y = y;
+
+ bool increasing = nmonths > 0;
+
+ while (nmonths != 0) {
+ if (nmonths < 0 && nmonths + 12 <= 0) {
+ y--;
+ nmonths+=12;
+ } else if (nmonths < 0) {
+ m+= nmonths;
+ nmonths = 0;
+ if (m <= 0) {
+ --y;
+ m += 12;
+ }
+ } else if (nmonths - 12 >= 0) {
+ y++;
+ nmonths -= 12;
+ } else if (m == 12) {
+ y++;
+ m = 0;
+ } else {
+ m += nmonths;
+ nmonths = 0;
+ if (m > 12) {
+ ++y;
+ m -= 12;
+ }
+ }
+ }
+
+ // was there a sign change?
+ if ((old_y > 0 && y <= 0) ||
+ (old_y < 0 && y >= 0))
+ // yes, adjust the date by +1 or -1 years
+ y += increasing ? +1 : -1;
+
+ // did we end up in the Gregorian/Julian conversion hole?
+ if (y == 1582 && m == 10 && d > 4 && d < 15)
+ d = increasing ? 15 : 4;
+
+ return fixedDate(y, m, d);
+}
+
+/*!
+ Returns a QDate object containing a date \a nyears later than the
+ date of this object (or earlier if \a nyears is negative).
+
+ \note If the ending day/month combination does not exist in the
+ resulting year (i.e., if the date was Feb 29 and the final year is
+ not a leap year), this function will return a date that is the
+ latest valid date (that is, Feb 28).
+
+ \sa addDays(), addMonths()
+*/
+
+QDate QDate::addYears(int nyears) const
+{
+ if (!isValid())
+ return QDate();
+
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+
+ int old_y = y;
+ y += nyears;
+
+ // was there a sign change?
+ if ((old_y > 0 && y <= 0) ||
+ (old_y < 0 && y >= 0))
+ // yes, adjust the date by +1 or -1 years
+ y += nyears > 0 ? +1 : -1;
+
+ return fixedDate(y, m, d);
+}
+
+/*!
+ Returns the number of days from this date to \a d (which is
+ negative if \a d is earlier than this date).
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0
+
+ \sa addDays()
+*/
+
+int QDate::daysTo(const QDate &d) const
+{
+ return d.jd - jd;
+}
+
+
+/*!
+ \fn bool QDate::operator==(const QDate &d) const
+
+ Returns true if this date is equal to \a d; otherwise returns
+ false.
+
+*/
+
+/*!
+ \fn bool QDate::operator!=(const QDate &d) const
+
+ Returns true if this date is different from \a d; otherwise
+ returns false.
+*/
+
+/*!
+ \fn bool QDate::operator<(const QDate &d) const
+
+ Returns true if this date is earlier than \a d; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QDate::operator<=(const QDate &d) const
+
+ Returns true if this date is earlier than or equal to \a d;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QDate::operator>(const QDate &d) const
+
+ Returns true if this date is later than \a d; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QDate::operator>=(const QDate &d) const
+
+ Returns true if this date is later than or equal to \a d;
+ otherwise returns false.
+*/
+
+/*!
+ \fn QDate::currentDate()
+ Returns the current date, as reported by the system clock.
+
+ \sa QTime::currentTime(), QDateTime::currentDateTime()
+*/
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \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.
+
+ Note for Qt::TextDate: It is recommended that you use the
+ English short month names (e.g. "Jan"). Although localized month
+ names can also be used, they depend on the user's locale settings.
+*/
+QDate QDate::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty())
+ return QDate();
+
+ switch (f) {
+ case Qt::ISODate:
+ {
+ int year(s.mid(0, 4).toInt());
+ int month(s.mid(5, 2).toInt());
+ int day(s.mid(8, 2).toInt());
+ if (year && month && day)
+ return QDate(year, month, day);
+ }
+ break;
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ default:
+#ifndef QT_NO_TEXTDATE
+ case Qt::TextDate: {
+ QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ if (parts.count() != 4) {
+ return QDate();
+ }
+
+ QString monthName = parts.at(1);
+ int month = -1;
+ // Assume that English monthnames are the default
+ for (int i = 0; i < 12; ++i) {
+ if (monthName == QLatin1String(qt_shortMonthNames[i])) {
+ month = i + 1;
+ break;
+ }
+ }
+ // If English names can't be found, search the localized ones
+ if (month == -1) {
+ for (int i = 1; i <= 12; ++i) {
+ if (monthName == QDate::shortMonthName(i)) {
+ month = i;
+ break;
+ }
+ }
+ }
+ if (month < 1 || month > 12) {
+ return QDate();
+ }
+
+ bool ok;
+ int day = parts.at(2).toInt(&ok);
+ if (!ok) {
+ return QDate();
+ }
+
+ int year = parts.at(3).toInt(&ok);
+ if (!ok) {
+ return QDate();
+ }
+
+ return QDate(year, month, day);
+ }
+#else
+ break;
+#endif
+ }
+ return QDate();
+}
+
+/*!
+ \fn QDate::fromString(const QString &string, const QString &format)
+
+ Returns the QDate represented by the \a string, using the \a
+ format given, or an invalid date if the string cannot be parsed.
+
+ These expressions may be used for the format:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i The day as a number without a leading zero (1 to 31)
+ \row \i dd \i The day as a number with a leading zero (01 to 31)
+ \row \i ddd
+ \i The abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i The long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i The month as a number without a leading zero (1 to 12)
+ \row \i MM \i The month as a number with a leading zero (01 to 12)
+ \row \i MMM
+ \i The abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i The long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i The year as two digit number (00 to 99)
+ \row \i yyyy \i The year as four digit number. If the year is negative,
+ a minus sign is prepended in addition.
+ \endtable
+
+ All other input characters will be treated as text. Any sequence
+ of characters that are enclosed in single quotes will also be
+ treated as text and will not be used as an expression. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 1
+
+ If the format is not satisfied, an invalid QDate is returned. The
+ expressions that don't expect leading zeroes (d, M) will be
+ greedy. This means that they will use two digits even if this
+ will put them outside the accepted range of values and leaves too
+ few digits for other sections. For example, the following format
+ string could have meant January 30 but the M will grab two
+ digits, resulting in an invalid date:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2
+
+ For any field that is not represented in the format the following
+ defaults are used:
+
+ \table
+ \header \i Field \i Default value
+ \row \i Year \i 1900
+ \row \i Month \i 1
+ \row \i Day \i 1
+ \endtable
+
+ The following examples demonstrate the default values:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3
+
+ \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(),
+ QDateTime::toString(), QTime::toString()
+*/
+
+QDate QDate::fromString(const QString &string, const QString &format)
+{
+ QDate date;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
+ if (dt.parseFormat(format))
+ dt.fromString(string, &date, 0);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return date;
+}
+#endif // QT_NO_DATESTRING
+
+/*!
+ \overload
+
+ Returns true if the specified date (\a year, \a month, and \a
+ day) is valid; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4
+
+ \sa isNull(), setDate()
+*/
+
+bool QDate::isValid(int year, int month, int day)
+{
+ if (year < FIRST_YEAR
+ || (year == FIRST_YEAR &&
+ (month < FIRST_MONTH
+ || (month == FIRST_MONTH && day < FIRST_DAY)))
+ || year == 0) // there is no year 0 in the Julian calendar
+ return false;
+
+ // passage from Julian to Gregorian calendar
+ if (year == 1582 && month == 10 && day > 4 && day < 15)
+ return 0;
+
+ return (day > 0 && month > 0 && month <= 12) &&
+ (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
+}
+
+/*!
+ \fn bool QDate::isLeapYear(int year)
+
+ Returns true if the specified \a year is a leap year; otherwise
+ returns false.
+*/
+
+bool QDate::isLeapYear(int y)
+{
+ if (y < 1582) {
+ if ( y < 1) { // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years
+ ++y;
+ }
+ return y % 4 == 0;
+ } else {
+ return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
+ }
+}
+
+/*!
+ \internal
+
+ This function has a confusing name and shouldn't be part of the
+ API anyway, since we have toJulian() and fromJulian().
+ ### Qt 5: remove it
+*/
+uint QDate::gregorianToJulian(int y, int m, int d)
+{
+ return julianDayFromDate(y, m, d);
+}
+
+/*!
+ \internal
+
+ This function has a confusing name and shouldn't be part of the
+ API anyway, since we have toJulian() and fromJulian().
+ ### Qt 5: remove it
+*/
+void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
+{
+ getDateFromJulianDay(jd, &y, &m, &d);
+}
+
+/*! \fn static QDate QDate::fromJulianDay(int jd)
+
+ Converts the Julian day \a jd to a QDate.
+
+ \sa toJulianDay()
+*/
+
+/*! \fn int QDate::toJulianDay() const
+
+ Converts the date to a Julian day.
+
+ \sa fromJulianDay()
+*/
+
+/*****************************************************************************
+ QTime member functions
+ *****************************************************************************/
+
+/*!
+ \class QTime
+ \reentrant
+
+ \brief The QTime class provides clock time functions.
+
+
+ A QTime object contains a clock time, i.e. the number of hours,
+ minutes, seconds, and milliseconds since midnight. It can read the
+ current time from the system clock and measure a span of elapsed
+ time. It provides functions for comparing times and for
+ manipulating a time by adding a number of milliseconds.
+
+ QTime uses the 24-hour clock format; it has no concept of AM/PM.
+ Unlike QDateTime, QTime knows nothing about time zones or
+ daylight savings time (DST).
+
+ A QTime object is typically created either by giving the number
+ of hours, minutes, seconds, and milliseconds explicitly, or by
+ using the static function currentTime(), which creates a QTime
+ object that contains the system's local time. Note that the
+ accuracy depends on the accuracy of the underlying operating
+ system; not all systems provide 1-millisecond accuracy.
+
+ The hour(), minute(), second(), and msec() functions provide
+ access to the number of hours, minutes, seconds, and milliseconds
+ of the time. The same information is provided in textual format by
+ the toString() function.
+
+ QTime provides a full set of operators to compare two QTime
+ objects. One time is considered smaller than another if it is
+ earlier than the other.
+
+ The time a given number of seconds or milliseconds later than a
+ given time can be found using the addSecs() or addMSecs()
+ functions. Correspondingly, the number of seconds or milliseconds
+ between two times can be found using secsTo() or msecsTo().
+
+ QTime can be used to measure a span of elapsed time using the
+ start(), restart(), and elapsed() functions.
+
+ \sa QDate, QDateTime
+*/
+
+/*!
+ \fn QTime::QTime()
+
+ Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
+ (i.e., midnight) object, except that isNull() returns true and isValid()
+ returns false.
+
+ \sa isNull(), isValid()
+*/
+
+/*!
+ Constructs a time with hour \a h, minute \a m, seconds \a s and
+ milliseconds \a ms.
+
+ \a h must be in the range 0 to 23, \a m and \a s must be in the
+ range 0 to 59, and \a ms must be in the range 0 to 999.
+
+ \sa isValid()
+*/
+
+QTime::QTime(int h, int m, int s, int ms)
+{
+ setHMS(h, m, s, ms);
+}
+
+
+/*!
+ \fn bool QTime::isNull() const
+
+ Returns true if the time is null (i.e., the QTime object was
+ constructed using the default constructor); otherwise returns
+ false. A null time is also an invalid time.
+
+ \sa isValid()
+*/
+
+/*!
+ Returns true if the time is valid; otherwise returns false. For example,
+ the time 23:30:55.746 is valid, but 24:12:30 is invalid.
+
+ \sa isNull()
+*/
+
+bool QTime::isValid() const
+{
+ return mds > NullTime && mds < MSECS_PER_DAY;
+}
+
+
+/*!
+ Returns the hour part (0 to 23) of the time.
+
+ \sa minute(), second(), msec()
+*/
+
+int QTime::hour() const
+{
+ return ds() / MSECS_PER_HOUR;
+}
+
+/*!
+ Returns the minute part (0 to 59) of the time.
+
+ \sa hour(), second(), msec()
+*/
+
+int QTime::minute() const
+{
+ return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
+}
+
+/*!
+ Returns the second part (0 to 59) of the time.
+
+ \sa hour(), minute(), msec()
+*/
+
+int QTime::second() const
+{
+ return (ds() / 1000)%SECS_PER_MIN;
+}
+
+/*!
+ Returns the millisecond part (0 to 999) of the time.
+
+ \sa hour(), minute(), second()
+*/
+
+int QTime::msec() const
+{
+ return ds() % 1000;
+}
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \overload
+
+ Returns the time as a string. Milliseconds are not included. The
+ \a format parameter determines the format of the string.
+
+ If \a format is Qt::TextDate, the string format is HH:MM:SS; e.g. 1
+ second before midnight would be "23:59:59".
+
+ If \a format is Qt::ISODate, the string format corresponds to the
+ ISO 8601 extended specification for representations of dates,
+ which is also HH:MM:SS. (However, contrary to ISO 8601, dates
+ before 15 October 1582 are handled as Julian dates, not Gregorian
+ dates. See \l{QDate G and J} {Use of Gregorian and Julian
+ Calendars}. This might change in a future version of Qt.)
+
+ If the \a format is Qt::SystemLocaleShortDate or
+ Qt::SystemLocaleLongDate, the string format depends on the locale
+ settings of the system. Identical to calling
+ QLocale::system().toString(time, QLocale::ShortFormat) or
+ QLocale::system().toString(time, QLocale::LongFormat).
+
+ If the \a format is Qt::DefaultLocaleShortDate or
+ Qt::DefaultLocaleLongDate, the string format depends on the
+ default application locale. This is the locale set with
+ QLocale::setDefault(), or the system locale if no default locale
+ has been set. Identical to calling QLocale().toString(time,
+ QLocale::ShortFormat) or QLocale().toString(time,
+ QLocale::LongFormat).
+
+ If the time is invalid, an empty string will be returned.
+*/
+
+QString QTime::toString(Qt::DateFormat format) const
+{
+ if (!isValid())
+ return QString();
+
+ switch (format) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+
+ default:
+ case Qt::ISODate:
+ case Qt::TextDate:
+ return QString::fromLatin1("%1:%2:%3")
+ .arg(hour(), 2, 10, QLatin1Char('0'))
+ .arg(minute(), 2, 10, QLatin1Char('0'))
+ .arg(second(), 2, 10, QLatin1Char('0'));
+ }
+}
+
+/*!
+ Returns the time as a string. The \a format parameter determines
+ the format of the result string.
+
+ These expressions may be used:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i H
+ \i the hour without a leading zero (0 to 23, even with AM/PM display)
+ \row \i HH
+ \i the hour with a leading zero (00 to 23, even with AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP or A
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap or a
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \row \i t \i the timezone (for example "CEST")
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assuming that the QTime is 14:13:09.042)
+
+ \table
+ \header \i Format \i Result
+ \row \i hh:mm:ss.zzz \i 14:13:09.042
+ \row \i h:m:s ap \i 2:13:9 pm
+ \row \i H:m:s a \i 14:13:9 pm
+ \endtable
+
+ If the datetime is invalid, an empty string will be returned.
+ If \a format is empty, the default format "hh:mm:ss" is used.
+
+ \sa QDate::toString() QDateTime::toString()
+*/
+QString QTime::toString(const QString& format) const
+{
+ return fmtDateTime(format, this, 0);
+}
+#endif //QT_NO_DATESTRING
+/*!
+ Sets the time to hour \a h, minute \a m, seconds \a s and
+ milliseconds \a ms.
+
+ \a h must be in the range 0 to 23, \a m and \a s must be in the
+ range 0 to 59, and \a ms must be in the range 0 to 999.
+ Returns true if the set time is valid; otherwise returns false.
+
+ \sa isValid()
+*/
+
+bool QTime::setHMS(int h, int m, int s, int ms)
+{
+#if defined(Q_OS_WINCE)
+ startTick = NullTime;
+#endif
+ if (!isValid(h,m,s,ms)) {
+ mds = NullTime; // make this invalid
+ return false;
+ }
+ mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
+ return true;
+}
+
+/*!
+ Returns a QTime object containing a time \a s seconds later
+ than the time of this object (or earlier if \a s is negative).
+
+ Note that the time will wrap if it passes midnight.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5
+
+ \sa addMSecs(), secsTo(), QDateTime::addSecs()
+*/
+
+QTime QTime::addSecs(int s) const
+{
+ return addMSecs(s * 1000);
+}
+
+/*!
+ Returns the number of seconds from this time to \a t.
+ If \a t is earlier than this time, the number of seconds returned
+ is negative.
+
+ Because QTime measures time within a day and there are 86400
+ seconds in a day, the result is always between -86400 and 86400.
+
+ secsTo() does not take into account any milliseconds.
+
+ \sa addSecs(), QDateTime::secsTo()
+*/
+
+int QTime::secsTo(const QTime &t) const
+{
+ return (t.ds() - ds()) / 1000;
+}
+
+/*!
+ Returns a QTime object containing a time \a ms milliseconds later
+ than the time of this object (or earlier if \a ms is negative).
+
+ Note that the time will wrap if it passes midnight. See addSecs()
+ for an example.
+
+ \sa addSecs(), msecsTo(), QDateTime::addMSecs()
+*/
+
+QTime QTime::addMSecs(int ms) const
+{
+ QTime t;
+ if (ms < 0) {
+ // % not well-defined for -ve, but / is.
+ 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 defined(Q_OS_WINCE)
+ if (startTick > NullTime)
+ t.startTick = (startTick + ms) % MSECS_PER_DAY;
+#endif
+ return t;
+}
+
+/*!
+ Returns the number of milliseconds from this time to \a t.
+ If \a t is earlier than this time, the number of milliseconds returned
+ is negative.
+
+ Because QTime measures time within a day and there are 86400
+ seconds in a day, the result is always between -86400000 and
+ 86400000 ms.
+
+ \sa secsTo(), addMSecs(), QDateTime::msecsTo()
+*/
+
+int QTime::msecsTo(const QTime &t) const
+{
+#if defined(Q_OS_WINCE)
+ // GetLocalTime() for Windows CE has no milliseconds resolution
+ if (t.startTick > NullTime && startTick > NullTime)
+ return t.startTick - startTick;
+ else
+#endif
+ return t.ds() - ds();
+}
+
+
+/*!
+ \fn bool QTime::operator==(const QTime &t) const
+
+ Returns true if this time is equal to \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator!=(const QTime &t) const
+
+ Returns true if this time is different from \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator<(const QTime &t) const
+
+ Returns true if this time is earlier than \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator<=(const QTime &t) const
+
+ Returns true if this time is earlier than or equal to \a t;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator>(const QTime &t) const
+
+ Returns true if this time is later than \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator>=(const QTime &t) const
+
+ Returns true if this time is later than or equal to \a t;
+ otherwise returns false.
+*/
+
+/*!
+ \fn QTime::currentTime()
+
+ Returns the current time as reported by the system clock.
+
+ Note that the accuracy depends on the accuracy of the underlying
+ operating system; not all systems provide 1-millisecond accuracy.
+*/
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \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.
+
+ Note that fromString() uses a "C" locale encoded string to convert
+ milliseconds to a float value. If the default locale is not "C",
+ this may result in two conversion attempts (if the conversion
+ fails for the default locale). This should be considered an
+ implementation detail.
+*/
+QTime QTime::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty()) {
+ QTime t;
+ t.mds = NullTime;
+ return t;
+ }
+
+ switch (f) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ default:
+ {
+ bool ok = true;
+ const int hour(s.mid(0, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const int minute(s.mid(3, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const int second(s.mid(6, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
+ const float msec(msec_s.toFloat(&ok));
+ if (!ok)
+ return QTime(hour, minute, second, 0);
+ return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
+ }
+ }
+}
+
+/*!
+ \fn 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.
+
+ These expressions may be used for the format:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
+ \row \i ap
+ \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
+ \endtable
+
+ All other input characters will be treated as text. Any sequence
+ of characters that are enclosed in single quotes will also be
+ treated as text and not be used as an expression.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 6
+
+ 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
+ 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
+ in an invalid time:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7
+
+ Any field that is not represented in the format will be set to zero.
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8
+
+ \sa QDateTime::fromString() QDate::fromString() QDate::toString()
+ QDateTime::toString() QTime::toString()
+*/
+
+QTime QTime::fromString(const QString &string, const QString &format)
+{
+ QTime time;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
+ if (dt.parseFormat(format))
+ dt.fromString(string, 0, &time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return time;
+}
+
+#endif // QT_NO_DATESTRING
+
+
+/*!
+ \overload
+
+ Returns true if the specified time is valid; otherwise returns
+ false.
+
+ The time is valid if \a h is in the range 0 to 23, \a m and
+ \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 9
+*/
+
+bool QTime::isValid(int h, int m, int s, int ms)
+{
+ return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
+}
+
+
+/*!
+ Sets this time to the current time. This is practical for timing:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 10
+
+ \sa restart(), elapsed(), currentTime()
+*/
+
+void QTime::start()
+{
+ *this = currentTime();
+}
+
+/*!
+ Sets this time to the current time and returns the number of
+ milliseconds that have elapsed since the last time start() or
+ restart() was called.
+
+ This function is guaranteed to be atomic and is thus very handy
+ for repeated measurements. Call start() to start the first
+ measurement, and restart() for each later measurement.
+
+ Note that the counter wraps to zero 24 hours after the last call
+ to start() or restart().
+
+ \warning If the system's clock setting has been changed since the
+ last time start() or restart() was called, the result is
+ undefined. This can happen when daylight savings time is turned on
+ or off.
+
+ \sa start(), elapsed(), currentTime()
+*/
+
+int QTime::restart()
+{
+ QTime t = currentTime();
+ int n = msecsTo(t);
+ if (n < 0) // passed midnight
+ n += 86400*1000;
+ *this = t;
+ return n;
+}
+
+/*!
+ Returns the number of milliseconds that have elapsed since the
+ last time start() or restart() was called.
+
+ Note that the counter wraps to zero 24 hours after the last call
+ to start() or restart.
+
+ Note that the accuracy depends on the accuracy of the underlying
+ operating system; not all systems provide 1-millisecond accuracy.
+
+ \warning If the system's clock setting has been changed since the
+ last time start() or restart() was called, the result is
+ undefined. This can happen when daylight savings time is turned on
+ or off.
+
+ \sa start(), restart()
+*/
+
+int QTime::elapsed() const
+{
+ int n = msecsTo(currentTime());
+ if (n < 0) // passed midnight
+ n += 86400 * 1000;
+ return n;
+}
+
+
+/*****************************************************************************
+ QDateTime member functions
+ *****************************************************************************/
+
+/*!
+ \class QDateTime
+ \reentrant
+ \brief The QDateTime class provides date and time functions.
+
+
+ A QDateTime object contains a calendar date and a clock time (a
+ "datetime"). It is a combination 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.
+
+ A QDateTime object is typically created either by giving a date
+ and time explicitly in the constructor, or by using the static
+ function currentDateTime() that returns a QDateTime object set
+ to the system clock's time. The date and time can be changed with
+ setDate() and setTime(). A datetime can also be set using the
+ setTime_t() function that takes a POSIX-standard "number of
+ seconds since 00:00:00 on January 1, 1970" value. The fromString()
+ function returns a QDateTime, given a string and a date format
+ used to interpret the date within the string.
+
+ The date() and time() functions provide access to the date and
+ time parts of the datetime. The same information is provided in
+ textual format by the toString() function.
+
+ QDateTime provides a full set of operators to compare two
+ QDateTime objects where smaller means earlier and larger means
+ later.
+
+ You can increment (or decrement) a datetime by a given number of
+ milliseconds using addMSecs(), seconds using addSecs(), or days
+ using addDays(). Similarly you can use addMonths() and addYears().
+ The daysTo() function returns the number of days between two datetimes,
+ secsTo() returns the number of seconds between two datetimes, and
+ msecsTo() returns the number of milliseconds between two datetimes.
+
+ QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
+ as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
+ QDateTime expressed as local time; use toUTC() to convert it to
+ UTC. You can also use timeSpec() to find out if a QDateTime
+ object stores a UTC time or a local time. Operations such as
+ addSecs() and secsTo() are aware of daylight saving time (DST).
+
+ \note QDateTime does not account for leap seconds.
+
+ \section1
+
+ \target QDateTime G and J
+ \section2 Use of Gregorian and Julian Calendars
+
+ QDate uses the Gregorian calendar in all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, the Julian calendar is used. This means there is a
+ 10-day gap in the internal calendar between the 4th and the 15th
+ of October 1582. When you use QDateTime for dates in that epoch,
+ the day after 4 October 1582 is 15 October 1582, and the dates in
+ the gap are invalid.
+
+ The Julian to Gregorian changeover date used here is the date when
+ the Gregorian calendar was first introduced, by Pope Gregory
+ XIII. That change was not universally accepted and some localities
+ only executed it at a later date (if at all). QDateTime
+ doesn't take any of these historical facts into account. If an
+ application must support a locale-specific dating system, it must
+ do so on its own, remembering to convert the dates using the
+ Julian day.
+
+ \section2 No Year 0
+
+ There is no year 0. Dates in that year are considered invalid. The
+ year -1 is the year "1 before Christ" or "1 before current era."
+ The day before 0001-01-01 is December 31st, 1 BCE.
+
+ \section2 Range of Valid Dates
+
+ The range of valid dates is from January 2nd, 4713 BCE, to
+ sometime in the year 11 million CE. The Julian Day returned by
+ QDate::toJulianDay() is a number in the contiguous range from 1 to
+ \e{overflow}, even across QDateTime's "date holes". It is suitable
+ for use in applications that must convert a QDateTime to a date in
+ another calendar system, e.g., Hebrew, Islamic or Chinese.
+
+ The Gregorian calendar was introduced in different places around
+ the world on different dates. QDateTime uses QDate to store the
+ date, so it uses the Gregorian calendar for all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, QDateTime uses the Julian calendar. This means
+ there is a 10-day gap in the QDateTime calendar between the 4th
+ and the 15th of October 1582. When you use QDateTime for dates in
+ that epoch, the day after 4 October 1582 is 15 October 1582, and
+ the dates in the gap are invalid.
+
+ \section2
+ Use of System Timezone
+
+ QDateTime uses the system's time zone information to determine the
+ offset of local time from UTC. If the system is not configured
+ correctly or not up-to-date, QDateTime will give wrong results as
+ well.
+
+ \section2 Daylight Savings Time (DST)
+
+ QDateTime takes into account the system's time zone information
+ when dealing with DST. On modern Unix systems, this means it
+ applies the correct historical DST data whenever possible. On
+ Windows and Windows CE, where the system doesn't support
+ historical DST data, historical accuracy is not maintained with
+ respect to DST.
+
+ 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 falling
+ outside that range, QDateTime makes a \e{best guess} using the
+ rules for year 1970 or 2037, but we can't guarantee accuracy. This
+ means QDateTime doesn't take into account changes in a locale's
+ time zone before 1970, even if the system's time zone database
+ supports that information.
+
+ \sa QDate QTime QDateTimeEdit
+*/
+
+/*!
+ Constructs a null datetime (i.e. null date and null time). A null
+ datetime is invalid, since the date is invalid.
+
+ \sa isValid()
+*/
+QDateTime::QDateTime()
+ : d(new QDateTimePrivate)
+{
+}
+
+
+/*!
+ Constructs a datetime with the given \a date, a valid
+ time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
+*/
+
+QDateTime::QDateTime(const QDate &date)
+ : d(new QDateTimePrivate)
+{
+ d->date = date;
+ d->time = QTime(0, 0, 0);
+}
+
+/*!
+ Constructs a datetime with the given \a date and \a time, using
+ the time specification defined by \a spec.
+
+ If \a date is valid and \a time is not, the time will be set to midnight.
+*/
+
+QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
+ : d(new QDateTimePrivate)
+{
+ d->date = date;
+ d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
+ d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
+}
+
+/*!
+ Constructs a copy of the \a other datetime.
+*/
+
+QDateTime::QDateTime(const QDateTime &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Destroys the datetime.
+*/
+QDateTime::~QDateTime()
+{
+}
+
+/*!
+ Makes a copy of the \a other datetime and returns a reference to the
+ copy.
+*/
+
+QDateTime &QDateTime::operator=(const QDateTime &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if both the date and the time are null; otherwise
+ returns false. A null datetime is invalid.
+
+ \sa QDate::isNull(), QTime::isNull(), isValid()
+*/
+
+bool QDateTime::isNull() const
+{
+ return d->date.isNull() && d->time.isNull();
+}
+
+/*!
+ Returns true if both the date and the time are valid; otherwise
+ returns false.
+
+ \sa QDate::isValid(), QTime::isValid()
+*/
+
+bool QDateTime::isValid() const
+{
+ return d->date.isValid() && d->time.isValid();
+}
+
+/*!
+ Returns the date part of the datetime.
+
+ \sa setDate(), time(), timeSpec()
+*/
+
+QDate QDateTime::date() const
+{
+ return d->date;
+}
+
+/*!
+ Returns the time part of the datetime.
+
+ \sa setTime(), date(), timeSpec()
+*/
+
+QTime QDateTime::time() const
+{
+ return d->time;
+}
+
+/*!
+ Returns the time specification of the datetime.
+
+ \sa setTimeSpec(), date(), time(), Qt::TimeSpec
+*/
+
+Qt::TimeSpec QDateTime::timeSpec() const
+{
+ switch(d->spec)
+ {
+ case QDateTimePrivate::UTC:
+ return Qt::UTC;
+ case QDateTimePrivate::OffsetFromUTC:
+ return Qt::OffsetFromUTC;
+ default:
+ return Qt::LocalTime;
+ }
+}
+
+/*!
+ Sets the date part of this datetime to \a date.
+ If no time is set, it is set to midnight.
+
+ \sa date(), setTime(), setTimeSpec()
+*/
+
+void QDateTime::setDate(const QDate &date)
+{
+ detach();
+ d->date = date;
+ if (d->spec == QDateTimePrivate::LocalStandard
+ || d->spec == QDateTimePrivate::LocalDST)
+ d->spec = QDateTimePrivate::LocalUnknown;
+ if (date.isValid() && !d->time.isValid())
+ d->time = QTime(0, 0, 0);
+}
+
+/*!
+ Sets the time part of this datetime to \a time.
+
+ \sa time(), setDate(), setTimeSpec()
+*/
+
+void QDateTime::setTime(const QTime &time)
+{
+ detach();
+ if (d->spec == QDateTimePrivate::LocalStandard
+ || d->spec == QDateTimePrivate::LocalDST)
+ d->spec = QDateTimePrivate::LocalUnknown;
+ d->time = time;
+}
+
+/*!
+ Sets the time specification used in this datetime to \a spec.
+
+ \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec
+*/
+
+void QDateTime::setTimeSpec(Qt::TimeSpec spec)
+{
+ detach();
+
+ switch(spec)
+ {
+ case Qt::UTC:
+ d->spec = QDateTimePrivate::UTC;
+ break;
+ case Qt::OffsetFromUTC:
+ d->spec = QDateTimePrivate::OffsetFromUTC;
+ break;
+ default:
+ d->spec = QDateTimePrivate::LocalUnknown;
+ break;
+ }
+}
+
+qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
+{
+ qint64 days = jd - JULIAN_DAY_FOR_EPOCH;
+ qint64 retval = (days * MSECS_PER_DAY) + msecs;
+ return retval;
+}
+
+/*!
+ \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).
+
+ On systems that do not support time zones, this function will
+ behave as if local time were Qt::UTC.
+
+ The behavior for this function is undefined if the datetime stored in
+ this object is not valid. However, for all valid dates, this function
+ returns a unique value.
+
+ \sa toTime_t(), setMSecsSinceEpoch()
+*/
+qint64 QDateTime::toMSecsSinceEpoch() const
+{
+ QDate utcDate;
+ QTime utcTime;
+ d->getUTC(utcDate, utcTime);
+
+ return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds());
+}
+
+/*!
+ Returns the datetime as the number of seconds that have passed
+ since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
+
+ On systems that do not support time zones, this function will
+ behave as if local time were Qt::UTC.
+
+ \note This function returns a 32-bit unsigned integer, so it does not
+ support dates before 1970, but it does support dates after
+ 2038-01-19T03:14:06, which may not be valid time_t values. Be careful
+ when passing those time_t values to system functions, which could
+ interpret them as negative dates.
+
+ If the date is outside the range 1970-01-01T00:00:00 to
+ 2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
+ (i.e., 0xFFFFFFFF).
+
+ To get an extended range, use toMSecsSinceEpoch().
+
+ \sa toMSecsSinceEpoch(), setTime_t()
+*/
+
+uint QDateTime::toTime_t() const
+{
+ qint64 retval = toMSecsSinceEpoch() / 1000;
+ if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
+ return uint(-1);
+ return uint(retval);
+}
+
+/*!
+ \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.
+
+ 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 toMSecsSinceEpoch(), setTime_t()
+*/
+void QDateTime::setMSecsSinceEpoch(qint64 msecs)
+{
+ detach();
+
+ QDateTimePrivate::Spec oldSpec = d->spec;
+
+ int ddays = msecs / MSECS_PER_DAY;
+ msecs %= MSECS_PER_DAY;
+ if (msecs < 0) {
+ // negative
+ --ddays;
+ msecs += MSECS_PER_DAY;
+ }
+
+ d->date = QDate(1970, 1, 1).addDays(ddays);
+ d->time = QTime().addMSecs(msecs);
+ d->spec = QDateTimePrivate::UTC;
+
+ if (oldSpec != QDateTimePrivate::UTC)
+ d->spec = d->getLocal(d->date, d->time);
+}
+
+/*!
+ \fn void QDateTime::setTime_t(uint seconds)
+
+ Sets the date and time given the number of \a seconds that have
+ passed since 1970-01-01T00:00:00, Coordinated Universal Time
+ (Qt::UTC). On systems that do not support time zones this function
+ will behave as if local time were Qt::UTC.
+
+ \sa toTime_t()
+*/
+
+void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
+{
+ detach();
+
+ QDateTimePrivate::Spec oldSpec = d->spec;
+
+ d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
+ d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
+ d->spec = QDateTimePrivate::UTC;
+
+ if (oldSpec != QDateTimePrivate::UTC)
+ d->spec = d->getLocal(d->date, d->time);
+}
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \fn QString QDateTime::toString(Qt::DateFormat format) const
+
+ \overload
+
+ Returns the datetime as a string in the \a format given.
+
+ If the \a format is Qt::TextDate, the string is formatted in
+ the default way. QDate::shortDayName(), QDate::shortMonthName(),
+ and QTime::toString() are used to generate the string, so the
+ day and month names will be localized names. An example of this
+ formatting is "Wed May 20 03:40:13 1998".
+
+ 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.
+
+ If the \a format is Qt::SystemLocaleShortDate or
+ Qt::SystemLocaleLongDate, the string format depends on the locale
+ settings of the system. Identical to calling
+ QLocale::system().toString(datetime, QLocale::ShortFormat) or
+ QLocale::system().toString(datetime, QLocale::LongFormat).
+
+ If the \a format is Qt::DefaultLocaleShortDate or
+ Qt::DefaultLocaleLongDate, the string format depends on the
+ default application locale. This is the locale set with
+ QLocale::setDefault(), or the system locale if no default locale
+ has been set. Identical to calling QLocale().toString(datetime,
+ QLocale::ShortFormat) or QLocale().toString(datetime,
+ QLocale::LongFormat).
+
+ If the datetime is invalid, an empty string will be returned.
+
+ \warning The Qt::ISODate format is only valid for years in the
+ range 0 to 9999. This restriction may apply to locale-aware
+ formats as well, depending on the locale settings.
+
+ \sa QDate::toString() QTime::toString() Qt::DateFormat
+*/
+
+QString QDateTime::toString(Qt::DateFormat f) const
+{
+ QString buf;
+ if (!isValid())
+ return buf;
+
+ if (f == Qt::ISODate) {
+ buf = d->date.toString(Qt::ISODate);
+ if (buf.isEmpty())
+ return QString(); // failed to convert
+ buf += QLatin1Char('T');
+ buf += d->time.toString(Qt::ISODate);
+ }
+#ifndef QT_NO_TEXTDATE
+ else if (f == Qt::TextDate) {
+#ifndef Q_WS_WIN
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += d->date.shortMonthName(d->date.month());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+#else
+ wchar_t out[255];
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
+ QString winstr = QString::fromWCharArray(out);
+ switch (winstr.toInt()) {
+ case 1:
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+ buf += QLatin1String(". ");
+ buf += d->date.shortMonthName(d->date.month());
+ break;
+ default:
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += d->date.shortMonthName(d->date.month());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+ }
+#endif
+ buf += QLatin1Char(' ');
+ buf += d->time.toString();
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.year());
+ }
+#endif
+ else {
+ buf = d->date.toString(f);
+ if (buf.isEmpty())
+ return QString(); // failed to convert
+ buf += QLatin1Char(' ');
+ buf += d->time.toString(f);
+ }
+
+ return buf;
+}
+
+/*!
+ Returns the datetime as a string. The \a format parameter
+ determines the format of the result string.
+
+ These expressions may be used for the date:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i the year as four digit number
+ \endtable
+
+ These expressions may be used for the time:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assumed that the QDateTime is 21 May 2001
+ 14:13:09):
+
+ \table
+ \header \i Format \i Result
+ \row \i dd.MM.yyyy \i 21.05.2001
+ \row \i ddd MMMM d yy \i Tue May 21 01
+ \row \i hh:mm:ss.zzz \i 14:13:09.042
+ \row \i h:m:s ap \i 2:13:9 pm
+ \endtable
+
+ If the datetime is invalid, an empty string will be returned.
+
+ \sa QDate::toString() QTime::toString()
+*/
+QString QDateTime::toString(const QString& format) const
+{
+ return fmtDateTime(format, &d->time, &d->date);
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+ Returns a QDateTime object containing a datetime \a ndays days
+ later than the datetime of this object (or earlier if \a ndays is
+ negative).
+
+ \sa daysTo(), addMonths(), addYears(), addSecs()
+*/
+
+QDateTime QDateTime::addDays(int ndays) const
+{
+ return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a nmonths months
+ later than the datetime of this object (or earlier if \a nmonths
+ is negative).
+
+ \sa daysTo(), addDays(), addYears(), addSecs()
+*/
+
+QDateTime QDateTime::addMonths(int nmonths) const
+{
+ return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a nyears years
+ later than the datetime of this object (or earlier if \a nyears is
+ negative).
+
+ \sa daysTo(), addDays(), addMonths(), addSecs()
+*/
+
+QDateTime QDateTime::addYears(int nyears) const
+{
+ return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
+}
+
+QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
+{
+ QDate utcDate;
+ QTime utcTime;
+ dt.d->getUTC(utcDate, utcTime);
+
+ addMSecs(utcDate, utcTime, msecs);
+
+ return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
+}
+
+/*!
+ Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that
+ utcDate and utcTime are adjusted to UTC.
+
+ \since 4.5
+ \internal
+ */
+void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
+{
+ uint dd = utcDate.jd;
+ int tt = utcTime.ds();
+ int sign = 1;
+ if (msecs < 0) {
+ msecs = -msecs;
+ sign = -1;
+ }
+ if (msecs >= int(MSECS_PER_DAY)) {
+ dd += sign * (msecs / MSECS_PER_DAY);
+ msecs %= MSECS_PER_DAY;
+ }
+
+ tt += sign * msecs;
+ if (tt < 0) {
+ tt = MSECS_PER_DAY - tt - 1;
+ dd -= tt / MSECS_PER_DAY;
+ tt = tt % MSECS_PER_DAY;
+ tt = MSECS_PER_DAY - tt - 1;
+ } else if (tt >= int(MSECS_PER_DAY)) {
+ dd += tt / MSECS_PER_DAY;
+ tt = tt % MSECS_PER_DAY;
+ }
+
+ utcDate.jd = dd;
+ utcTime.mds = tt;
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a s seconds
+ later than the datetime of this object (or earlier if \a s is
+ negative).
+
+ \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
+*/
+
+QDateTime QDateTime::addSecs(int s) const
+{
+ return d->addMSecs(*this, qint64(s) * 1000);
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a msecs miliseconds
+ later than the datetime of this object (or earlier if \a msecs is
+ negative).
+
+ \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
+*/
+QDateTime QDateTime::addMSecs(qint64 msecs) const
+{
+ return d->addMSecs(*this, msecs);
+}
+
+/*!
+ Returns the number of days from this datetime to the \a other
+ datetime. If the \a other datetime is earlier than this datetime,
+ the value returned is negative.
+
+ \sa addDays(), secsTo(), msecsTo()
+*/
+
+int QDateTime::daysTo(const QDateTime &other) const
+{
+ return d->date.daysTo(other.d->date);
+}
+
+/*!
+ Returns the number of seconds from this datetime to the \a other
+ datetime. If the \a other datetime is earlier than this datetime,
+ the value returned is negative.
+
+ Before performing the comparison, the two datetimes are converted
+ to Qt::UTC to ensure that the result is correct if one of the two
+ datetimes has daylight saving time (DST) and the other doesn't.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11
+
+ \sa addSecs(), daysTo(), QTime::secsTo()
+*/
+
+int QDateTime::secsTo(const QDateTime &other) const
+{
+ QDate date1, date2;
+ QTime time1, time2;
+
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+
+ return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
+}
+
+/*!
+ Returns the number of milliseconds from this datetime to the \a other
+ datetime. If the \a other datetime is earlier than this datetime,
+ the value returned is negative.
+
+ Before performing the comparison, the two datetimes are converted
+ to Qt::UTC to ensure that the result is correct if one of the two
+ datetimes has daylight saving time (DST) and the other doesn't.
+
+ \sa addMSecs(), daysTo(), QTime::msecsTo()
+*/
+
+qint64 QDateTime::msecsTo(const QDateTime &other) const
+{
+ QDate selfDate;
+ QDate otherDate;
+ QTime selfTime;
+ QTime otherTime;
+
+ d->getUTC(selfDate, selfTime);
+ other.d->getUTC(otherDate, otherTime);
+
+ return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY))
+ + static_cast<qint64>(selfTime.msecsTo(otherTime));
+}
+
+
+/*!
+ \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const
+
+ Returns a copy of this datetime configured to use the given time
+ \a specification.
+
+ \sa timeSpec(), toUTC(), toLocalTime()
+*/
+
+QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
+{
+ if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
+ return *this;
+
+ QDateTime ret;
+ if (spec == Qt::UTC) {
+ d->getUTC(ret.d->date, ret.d->time);
+ ret.d->spec = QDateTimePrivate::UTC;
+ } else {
+ ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
+ }
+ return ret;
+}
+
+/*!
+ Returns true if this datetime is equal to the \a other datetime;
+ otherwise returns false.
+
+ \sa operator!=()
+*/
+
+bool QDateTime::operator==(const QDateTime &other) const
+{
+ if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
+ return d->time == other.d->time && d->date == other.d->date;
+ else {
+ QDate date1, date2;
+ QTime time1, time2;
+
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+ return time1 == time2 && date1 == date2;
+ }
+}
+
+/*!
+ \fn bool QDateTime::operator!=(const QDateTime &other) const
+
+ Returns true if this datetime is different from the \a other
+ datetime; otherwise returns false.
+
+ Two datetimes are different if either the date, the time, or the
+ time zone components are different.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns true if this datetime is earlier than the \a other
+ datetime; otherwise returns false.
+*/
+
+bool QDateTime::operator<(const QDateTime &other) const
+{
+ if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) {
+ if (d->date != other.d->date)
+ return d->date < other.d->date;
+ return d->time < other.d->time;
+ } else {
+ QDate date1, date2;
+ QTime time1, time2;
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+ if (date1 != date2)
+ return date1 < date2;
+ return time1 < time2;
+ }
+}
+
+/*!
+ \fn bool QDateTime::operator<=(const QDateTime &other) const
+
+ Returns true if this datetime is earlier than or equal to the
+ \a other datetime; otherwise returns false.
+*/
+
+/*!
+ \fn bool QDateTime::operator>(const QDateTime &other) const
+
+ Returns true if this datetime is later than the \a other datetime;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QDateTime::operator>=(const QDateTime &other) const
+
+ Returns true if this datetime is later than or equal to the
+ \a other datetime; otherwise returns false.
+*/
+
+/*!
+ \fn QDateTime QDateTime::currentDateTime()
+ Returns the current datetime, as reported by the system clock, in
+ the local time zone.
+
+ \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
+*/
+
+/*!
+ \fn QDateTime QDateTime::currentDateTimeUtc()
+ \since 4.7
+ Returns the current datetime, as reported by the system clock, in
+ UTC.
+
+ \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
+*/
+
+/*!
+ \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.
+
+ \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
+*/
+
+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;
+}
+
+#if defined(Q_OS_WIN)
+QDate QDate::currentDate()
+{
+ QDate d;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetLocalTime(&st);
+ d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
+ return d;
+}
+
+QTime QTime::currentTime()
+{
+ QTime ct;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetLocalTime(&st);
+ ct.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+#if defined(Q_OS_WINCE)
+ ct.startTick = GetTickCount() % MSECS_PER_DAY;
+#endif
+ return ct;
+}
+
+QDateTime QDateTime::currentDateTime()
+{
+ QDate d;
+ QTime t;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetLocalTime(&st);
+ d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
+ t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+ return QDateTime(d, t);
+}
+
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ QDate d;
+ QTime t;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetSystemTime(&st);
+ d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
+ t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+ return QDateTime(d, t, Qt::UTC);
+}
+
+qint64 QDateTime::currentMSecsSinceEpoch()
+{
+ QDate d;
+ QTime t;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetSystemTime(&st);
+
+ return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
+ qint64(julianDayFromGregorianDate(st.wYear, st.wMonth, st.wDay)
+ - julianDayFromGregorianDate(1970, 1, 1)) * Q_INT64_C(86400000);
+}
+
+#elif defined(Q_OS_SYMBIAN)
+QDate QDate::currentDate()
+{
+ QDate d;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1 );
+ return d;
+}
+
+QTime QTime::currentTime()
+{
+ QTime ct;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
+ localDateTime.Second(), localDateTime.MicroSecond() / 1000);
+ return ct;
+}
+
+QDateTime QDateTime::currentDateTime()
+{
+ QDate d;
+ QTime ct;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1);
+ ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
+ localDateTime.Second(), localDateTime.MicroSecond() / 1000);
+ return QDateTime(d, ct);
+}
+
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ QDate d;
+ QTime ct;
+ TTime gmTime;
+ gmTime.UniversalTime();
+ TDateTime gmtDateTime = gmTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(gmtDateTime.Year(), gmtDateTime.Month() + 1, gmtDateTime.Day() + 1);
+ ct.mds = msecsFromDecomposed(gmtDateTime.Hour(), gmtDateTime.Minute(),
+ gmtDateTime.Second(), gmtDateTime.MicroSecond() / 1000);
+ return QDateTime(d, ct, Qt::UTC);
+}
+
+qint64 QDateTime::currentMSecsSinceEpoch()
+{
+ QDate d;
+ QTime ct;
+ TTime gmTime;
+ gmTime.UniversalTime();
+ TDateTime gmtDateTime = gmTime.DateTime();
+
+ // according to the documentation, the value is:
+ // "a date and time as a number of microseconds since midnight, January 1st, 0 AD nominal Gregorian"
+ qint64 value = gmTime.Int64();
+
+ // whereas 1970-01-01T00:00:00 is (in the same representation):
+ // ((1970 * 365) + (1970 / 4) - (1970 / 100) + (1970 / 400) - 13) * 86400 * 1000000
+ static const qint64 unixEpoch = Q_INT64_C(0xdcddb30f2f8000);
+
+ return (value - unixEpoch) / 1000;
+}
+
+#elif defined(Q_OS_UNIX)
+QDate QDate::currentDate()
+{
+ QDate d;
+ // posix compliant system
+ time_t ltime;
+ time(&ltime);
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
+
+ d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ return d;
+}
+
+QTime QTime::currentTime()
+{
+ QTime ct;
+ // posix compliant system
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif
+ Q_CHECK_PTR(t);
+
+ ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+ return ct;
+}
+
+QDateTime QDateTime::currentDateTime()
+{
+ // posix compliant system
+ // we have milliseconds
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif
+
+ QDateTime dt;
+ dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+
+ dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST :
+ t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard :
+ QDateTimePrivate::LocalUnknown;
+ return dt;
+}
+
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ // posix compliant system
+ // we have milliseconds
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ struct tm res;
+ t = gmtime_r(&ltime, &res);
+#else
+ t = gmtime(&ltime);
+#endif
+
+ QDateTime dt;
+ dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+
+ dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ dt.d->spec = QDateTimePrivate::UTC;
+ return dt;
+}
+
+qint64 QDateTime::currentMSecsSinceEpoch()
+{
+ // posix compliant system
+ // we have milliseconds
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
+}
+
+#else
+#error "What system is this?"
+#endif
+
+/*!
+ \since 4.2
+
+ Returns a datetime whose date and time are the number of \a seconds
+ that have passed since 1970-01-01T00:00:00, Coordinated Universal
+ Time (Qt::UTC). On systems that do not support time zones, the time
+ will be set as if local time were Qt::UTC.
+
+ \sa toTime_t(), setTime_t()
+*/
+QDateTime QDateTime::fromTime_t(uint seconds)
+{
+ QDateTime d;
+ d.setTime_t(seconds);
+ return d;
+}
+
+/*!
+ \since 4.7
+
+ 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). On systems that do not support time zones, the time
+ will be set as if local time were Qt::UTC.
+
+ 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 toTime_t(), setTime_t()
+*/
+QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
+{
+ QDateTime d;
+ d.setMSecsSinceEpoch(msecs);
+ return d;
+}
+
+/*!
+ \since 4.4
+ \internal
+
+ Sets the offset from UTC to \a seconds, and also sets timeSpec() to
+ Qt::OffsetFromUTC.
+
+ The maximum and minimum offset is 14 positive or negative hours. If
+ \a seconds is larger or smaller than that, the result is undefined.
+
+ 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the
+ timeSpec() will be set to Qt::UTC. Hence the UTC offset always
+ relates to UTC, and can never relate to local time.
+
+ \sa isValid(), utcOffset()
+ */
+void QDateTime::setUtcOffset(int seconds)
+{
+ detach();
+
+ /* The motivation to also setting d->spec is to ensure that the QDateTime
+ * instance stay in well-defined states all the time, instead of that
+ * we instruct the user to ensure it. */
+ if(seconds == 0)
+ d->spec = QDateTimePrivate::UTC;
+ else
+ d->spec = QDateTimePrivate::OffsetFromUTC;
+
+ /* Even if seconds is 0 we assign it to utcOffset. */
+ d->utcOffset = seconds;
+}
+
+/*!
+ \since 4.4
+ \internal
+
+ Returns the UTC offset in seconds. If the timeSpec() isn't
+ Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC
+ offset the return value of this function cannot be used to determine
+ whether a utcOffset() is used or is valid, timeSpec() must be
+ checked.
+
+ Likewise, if this QDateTime() is invalid or if timeSpec() isn't
+ Qt::OffsetFromUTC, 0 is returned.
+
+ The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC.
+
+ \sa isValid(), setUtcOffset()
+ */
+int QDateTime::utcOffset() const
+{
+ if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC)
+ return d->utcOffset;
+ else
+ return 0;
+}
+
+#ifndef QT_NO_DATESTRING
+
+static int fromShortMonthName(const QString &monthName)
+{
+ // Assume that English monthnames are the default
+ for (int i = 0; i < 12; ++i) {
+ if (monthName == QLatin1String(qt_shortMonthNames[i]))
+ return i + 1;
+ }
+ // If English names can't be found, search the localized ones
+ for (int i = 1; i <= 12; ++i) {
+ if (monthName == QDate::shortMonthName(i))
+ return i;
+ }
+ return -1;
+}
+
+/*!
+ \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.
+
+ Note for Qt::TextDate: It is recommended that you use the
+ English short month names (e.g. "Jan"). Although localized month
+ names can also be used, they depend on the user's locale settings.
+*/
+QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty()) {
+ return QDateTime();
+ }
+
+ switch (f) {
+ case Qt::ISODate: {
+ QString tmp = s;
+ Qt::TimeSpec ts = Qt::LocalTime;
+ const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate);
+ if (tmp.size() == 10)
+ return QDateTime(date);
+
+ tmp = tmp.mid(11);
+
+ // Recognize UTC specifications
+ if (tmp.endsWith(QLatin1Char('Z'))) {
+ ts = Qt::UTC;
+ tmp.chop(1);
+ }
+
+ // Recognize timezone specifications
+ QRegExp rx(QLatin1String("[+-]"));
+ if (tmp.contains(rx)) {
+ int idx = tmp.indexOf(rx);
+ QString tmp2 = tmp.mid(idx);
+ tmp = tmp.left(idx);
+ bool ok = true;
+ int ntzhour = 1;
+ int ntzminute = 3;
+ if ( tmp2.indexOf(QLatin1Char(':')) == 3 )
+ ntzminute = 4;
+ const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok));
+ const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok));
+ QTime tzt(tzhour, tzminute);
+ int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60;
+ if ( utcOffset != 0 ) {
+ ts = Qt::OffsetFromUTC;
+ QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts);
+ dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) );
+ return dt;
+ }
+ }
+ return QDateTime(date, QTime::fromString(tmp, Qt::ISODate), ts);
+ }
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+#if !defined(QT_NO_TEXTDATE)
+ case Qt::TextDate: {
+ QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ if ((parts.count() < 5) || (parts.count() > 6)) {
+ return QDateTime();
+ }
+
+ // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
+ int month = -1, day = -1;
+ bool ok;
+
+ month = fromShortMonthName(parts.at(1));
+ if (month != -1) {
+ day = parts.at(2).toInt(&ok);
+ if (!ok)
+ day = -1;
+ }
+
+ if (month == -1 || day == -1) {
+ // first variant failed, lets try the other
+ month = fromShortMonthName(parts.at(2));
+ if (month != -1) {
+ QString dayStr = parts.at(1);
+ if (dayStr.endsWith(QLatin1Char('.'))) {
+ dayStr.chop(1);
+ day = dayStr.toInt(&ok);
+ if (!ok)
+ day = -1;
+ } else {
+ day = -1;
+ }
+ }
+ }
+
+ if (month == -1 || day == -1) {
+ // both variants failed, give up
+ return QDateTime();
+ }
+
+ int year;
+ QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
+ if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
+ year = parts.at(4).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ } else {
+ timeParts = parts.at(4).split(QLatin1Char(':'));
+ if ((timeParts.count() != 3) && (timeParts.count() != 2))
+ return QDateTime();
+ year = parts.at(3).toInt(&ok);
+ if (!ok)
+ 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 = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
+ if (!ok) {
+ return QDateTime();
+ }
+
+ QDate date(year, month, day);
+ QTime time(hour, minute, second);
+
+ if (parts.count() == 5)
+ return QDateTime(date, time, Qt::LocalTime);
+
+ QString tz = parts.at(5);
+ if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
+ return QDateTime();
+ QDateTime dt(date, time, Qt::UTC);
+ if (tz.length() > 3) {
+ int tzoffset = 0;
+ QChar sign = tz.at(3);
+ if ((sign != QLatin1Char('+'))
+ && (sign != QLatin1Char('-'))) {
+ return QDateTime();
+ }
+ int tzhour = tz.mid(4, 2).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ int tzminute = tz.mid(6).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ tzoffset = (tzhour*60 + tzminute) * 60;
+ if (sign == QLatin1Char('-'))
+ tzoffset = -tzoffset;
+ dt.setUtcOffset(tzoffset);
+ }
+ return dt.toLocalTime();
+ }
+#endif //QT_NO_TEXTDATE
+ }
+
+ return QDateTime();
+}
+
+/*!
+ \fn QDateTime::fromString(const QString &string, const QString &format)
+
+ Returns the QDateTime represented by the \a string, using the \a
+ format given, or an invalid datetime if the string cannot be parsed.
+
+ These expressions may be used for the date part of the format string:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i the year as four digit number
+ \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.
+
+ These expressions may be used for the time part of the format string:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i H
+ \i the hour without a leading zero (0 to 23, even with AM/PM display)
+ \row \i HH
+ \i the hour with a leading zero (00 to 23, even with AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP or A
+ \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
+ \row \i ap or a
+ \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
+ \endtable
+
+ All other input characters will be treated as text. Any sequence
+ of characters that are enclosed in singlequotes will also be
+ treated as text and not be used as an expression.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 12
+
+ If the format is not satisfied an invalid QDateTime is returned.
+ 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
+ put them outside the range and/or leave too few digits for other
+ sections.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13
+
+ This could have meant 1 January 00:30.00 but the M will grab
+ two digits.
+
+ For any field that is not represented in the format the following
+ defaults are used:
+
+ \table
+ \header \i Field \i Default value
+ \row \i Year \i 1900
+ \row \i Month \i 1 (January)
+ \row \i Day \i 1
+ \row \i Hour \i 0
+ \row \i Minute \i 0
+ \row \i Second \i 0
+ \endtable
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14
+
+ \sa QDate::fromString() QTime::fromString() QDate::toString()
+ QDateTime::toString() QTime::toString()
+*/
+
+QDateTime QDateTime::fromString(const QString &string, const QString &format)
+{
+#ifndef QT_BOOTSTRAPPED
+ QTime time;
+ QDate date;
+
+ QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
+ if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
+ return QDateTime(date, time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return QDateTime(QDate(), QTime(-1, -1, -1));
+}
+
+#endif // QT_NO_DATESTRING
+/*!
+ \fn QDateTime QDateTime::toLocalTime() const
+
+ Returns a datetime containing the date and time information in
+ this datetime, but specified using the Qt::LocalTime definition.
+
+ \sa toTimeSpec()
+*/
+
+/*!
+ \fn QDateTime QDateTime::toUTC() const
+
+ Returns a datetime containing the date and time information in
+ this datetime, but specified using the Qt::UTC definition.
+
+ \sa toTimeSpec()
+*/
+
+/*! \internal
+ */
+void QDateTime::detach()
+{
+ d.detach();
+}
+
+/*****************************************************************************
+ Date/time stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QDate
+
+ Writes the \a date to stream \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &out, const QDate &date)
+{
+ return out << (quint32)(date.jd);
+}
+
+/*!
+ \relates QDate
+
+ Reads a date from stream \a in into the \a date.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QDate &date)
+{
+ quint32 jd;
+ in >> jd;
+ date.jd = jd;
+ return in;
+}
+
+/*!
+ \relates QTime
+
+ Writes \a time to stream \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &out, const QTime &time)
+{
+ return out << quint32(time.mds);
+}
+
+/*!
+ \relates QTime
+
+ Reads a time from stream \a in into the given \a time.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QTime &time)
+{
+ quint32 ds;
+ in >> ds;
+ time.mds = int(ds);
+ return in;
+}
+
+/*!
+ \relates QDateTime
+
+ Writes \a dateTime to the \a out stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
+{
+ out << dateTime.d->date << dateTime.d->time;
+ if (out.version() >= 7)
+ out << (qint8)dateTime.d->spec;
+ return out;
+}
+
+/*!
+ \relates QDateTime
+
+ Reads a datetime from the stream \a in into \a dateTime.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
+{
+ dateTime.detach();
+
+ qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
+ in >> dateTime.d->date >> dateTime.d->time;
+ if (in.version() >= 7)
+ in >> ts;
+ dateTime.d->spec = (QDateTimePrivate::Spec)ts;
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+
+/*!
+ \fn QString QDate::monthName(int month)
+
+ Use shortMonthName() instead.
+*/
+
+/*!
+ \fn QString QDate::dayName(int weekday)
+
+ Use shortDayName() instead.
+*/
+
+/*!
+ \fn bool QDate::leapYear(int year)
+
+ Use isLeapYear() instead.
+*/
+
+/*!
+ \fn QDate QDate::currentDate(Qt::TimeSpec spec)
+
+ If \a spec is Qt::LocalTime, use the currentDate() overload that
+ takes no parameters instead; otherwise, use
+ QDateTime::currentDateTime().
+
+ \oldcode
+ QDate localDate = QDate::currentDate(Qt::LocalTime);
+ QDate utcDate = QDate::currentDate(Qt::UTC);
+ \newcode
+ QDate localDate = QDate::currentDate();
+ QDate utcDate = QDateTime::currentDateTime().toUTC().date();
+ \endcode
+
+ \sa QDateTime::toUTC()
+*/
+
+/*!
+ \fn QTime QTime::currentTime(Qt::TimeSpec specification)
+
+ Returns the current time for the given \a specification.
+
+ To replace uses of this function where the \a specification is Qt::LocalTime,
+ use the currentDate() overload that takes no parameters instead; otherwise,
+ use QDateTime::currentDateTime() and convert the result to a UTC measurement.
+
+ \oldcode
+ QTime localTime = QTime::currentTime(Qt::LocalTime);
+ QTime utcTime = QTime::currentTime(Qt::UTC);
+ \newcode
+ QTime localTime = QTime::currentTime();
+ QTime utcTime = QTimeTime::currentDateTime().toUTC().time();
+ \endcode
+
+ \sa QDateTime::toUTC()
+*/
+
+/*!
+ \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec)
+
+ Use the single-argument overload of setTime_t() instead.
+*/
+
+/*!
+ \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec)
+
+ Use the currentDateTime() overload that takes no parameters
+ instead.
+*/
+
+// checks if there is an unqoted 'AP' or 'ap' in the string
+static bool hasUnquotedAP(const QString &f)
+{
+ const QLatin1Char quote('\'');
+ bool inquote = false;
+ const int max = f.size();
+ for (int i=0; i<max; ++i) {
+ if (f.at(i) == quote) {
+ inquote = !inquote;
+ } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifndef QT_NO_DATESTRING
+/*****************************************************************************
+ Some static function used by QDate, QTime and QDateTime
+*****************************************************************************/
+
+// Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
+static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
+{
+ if (f.isEmpty())
+ return QString();
+
+ QString buf = f;
+ int removed = 0;
+
+ if (dt) {
+ if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
+ const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
+ if (hour12 && dt->hour() > 12)
+ buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
+ else if (hour12 && dt->hour() == 0)
+ buf = QLatin1String("12");
+ else
+ buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
+ const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
+ if (hour12 && dt->hour() > 12)
+ buf = QString::number(dt->hour() - 12);
+ else if (hour12 && dt->hour() == 0)
+ buf = QLatin1String("12");
+ else
+ buf = QString::number(dt->hour());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("mm"))) {
+ buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == (QLatin1Char('m'))) {
+ buf = QString::number(dt->minute());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("ss"))) {
+ buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('s')) {
+ buf = QString::number(dt->second());
+ } else if (f.startsWith(QLatin1String("zzz"))) {
+ buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
+ removed = 3;
+ } else if (f.at(0) == QLatin1Char('z')) {
+ buf = QString::number(dt->msec());
+ removed = 1;
+ } else if (f.at(0).toUpper() == QLatin1Char('A')) {
+ const bool upper = f.at(0) == QLatin1Char('A');
+ buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
+ if (upper)
+ buf = buf.toUpper();
+ if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
+ f.at(0).isUpper() == f.at(1).isUpper()) {
+ removed = 2;
+ } else {
+ removed = 1;
+ }
+ }
+ }
+
+ if (dd) {
+ if (f.startsWith(QLatin1String("dddd"))) {
+ buf = dd->longDayName(dd->dayOfWeek());
+ removed = 4;
+ } else if (f.startsWith(QLatin1String("ddd"))) {
+ buf = dd->shortDayName(dd->dayOfWeek());
+ removed = 3;
+ } else if (f.startsWith(QLatin1String("dd"))) {
+ buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('d')) {
+ buf = QString::number(dd->day());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("MMMM"))) {
+ buf = dd->longMonthName(dd->month());
+ removed = 4;
+ } else if (f.startsWith(QLatin1String("MMM"))) {
+ buf = dd->shortMonthName(dd->month());
+ removed = 3;
+ } else if (f.startsWith(QLatin1String("MM"))) {
+ buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('M')) {
+ buf = QString::number(dd->month());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("yyyy"))) {
+ const int year = dd->year();
+ buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
+ if(year > 0)
+ removed = 4;
+ else
+ {
+ buf.prepend(QLatin1Char('-'));
+ removed = 5;
+ }
+
+ } else if (f.startsWith(QLatin1String("yy"))) {
+ buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
+ removed = 2;
+ }
+ }
+ if (removed == 0 || removed >= f.size()) {
+ return buf;
+ }
+
+ return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
+}
+
+// Parses the format string and uses getFmtString to get the values for the tokens. Ret
+static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
+{
+ const QLatin1Char quote('\'');
+ if (f.isEmpty())
+ return QString();
+ if (dt && !dt->isValid())
+ return QString();
+ if (dd && !dd->isValid())
+ return QString();
+
+ const bool ap = hasUnquotedAP(f);
+
+ QString buf;
+ QString frm;
+ QChar status(QLatin1Char('0'));
+
+ for (int i = 0; i < (int)f.length(); ++i) {
+ if (f.at(i) == quote) {
+ if (status == quote) {
+ if (i > 0 && f.at(i - 1) == quote)
+ buf += QLatin1Char('\'');
+ status = QLatin1Char('0');
+ } else {
+ if (!frm.isEmpty()) {
+ buf += getFmtString(frm, dt, dd, ap);
+ frm.clear();
+ }
+ status = quote;
+ }
+ } else if (status == quote) {
+ buf += f.at(i);
+ } else if (f.at(i) == status) {
+ if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p'))))
+ status = QLatin1Char('0');
+ frm += f.at(i);
+ } else {
+ buf += getFmtString(frm, dt, dd, ap);
+ frm.clear();
+ if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m'))
+ || (f.at(i) == QLatin1Char('H'))
+ || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) {
+ status = f.at(i);
+ frm += f.at(i);
+ } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) {
+ status = f.at(i);
+ frm += f.at(i);
+ } else if ((ap) && (f.at(i) == QLatin1Char('A'))) {
+ status = QLatin1Char('P');
+ frm += f.at(i);
+ } else if((ap) && (f.at(i) == QLatin1Char('a'))) {
+ status = QLatin1Char('p');
+ frm += f.at(i);
+ } else {
+ buf += f.at(i);
+ status = QLatin1Char('0');
+ }
+ }
+ }
+
+ buf += getFmtString(frm, dt, dd, ap);
+
+ return buf;
+}
+#endif // QT_NO_DATESTRING
+
+#ifdef Q_OS_WIN
+static const int LowerYear = 1980;
+#else
+static const int LowerYear = 1970;
+#endif
+static const int UpperYear = 2037;
+
+static QDate adjustDate(QDate date)
+{
+ QDate lowerLimit(LowerYear, 1, 2);
+ QDate upperLimit(UpperYear, 12, 30);
+
+ if (date > lowerLimit && date < upperLimit)
+ return date;
+
+ int month = date.month();
+ int day = date.day();
+
+ // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29
+ if (month == 2 && day == 29)
+ --day;
+
+ if (date < lowerLimit)
+ date.setDate(LowerYear, month, day);
+ else
+ date.setDate(UpperYear, month, day);
+
+ return date;
+}
+
+static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
+{
+ QDate fakeDate = adjustDate(date);
+
+ // won't overflow because of fakeDate
+ time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000;
+ tm *brokenDown = 0;
+
+#if defined(Q_OS_WINCE)
+ tm res;
+ FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC);
+ FILETIME resultTime;
+ FileTimeToLocalFileTime(&utcTime , &resultTime);
+ SYSTEMTIME sysTime;
+ FileTimeToSystemTime(&resultTime , &sysTime);
+
+ res.tm_sec = sysTime.wSecond;
+ res.tm_min = sysTime.wMinute;
+ res.tm_hour = sysTime.wHour;
+ res.tm_mday = sysTime.wDay;
+ res.tm_mon = sysTime.wMonth - 1;
+ res.tm_year = sysTime.wYear - 1900;
+ brokenDown = &res;
+#elif defined(Q_OS_SYMBIAN)
+ // months and days are zero index based
+ _LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = User::UTCOffset();
+ TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
+ TTime epochTTime;
+ TInt err = epochTTime.Set(KUnixEpoch);
+ tm res;
+ if(err == KErrNone) {
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = 0;
+ brokenDown = &res;
+ }
+#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ tm res;
+ brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ tm res;
+ if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
+ brokenDown = &res;
+#else
+ brokenDown = localtime(&secsSince1Jan1970UTC);
+#endif
+ if (!brokenDown) {
+ date = QDate(1970, 1, 1);
+ time = QTime();
+ return QDateTimePrivate::LocalUnknown;
+ } else {
+ int deltaDays = fakeDate.daysTo(date);
+ date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
+ time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
+ date = date.addDays(deltaDays);
+ if (brokenDown->tm_isdst > 0)
+ return QDateTimePrivate::LocalDST;
+ else if (brokenDown->tm_isdst < 0)
+ return QDateTimePrivate::LocalUnknown;
+ else
+ return QDateTimePrivate::LocalStandard;
+ }
+}
+
+static void localToUtc(QDate &date, QTime &time, int isdst)
+{
+ if (!date.isValid())
+ return;
+
+ QDate fakeDate = adjustDate(date);
+
+ tm localTM;
+ localTM.tm_sec = time.second();
+ localTM.tm_min = time.minute();
+ localTM.tm_hour = time.hour();
+ localTM.tm_mday = fakeDate.day();
+ localTM.tm_mon = fakeDate.month() - 1;
+ localTM.tm_year = fakeDate.year() - 1900;
+ localTM.tm_isdst = (int)isdst;
+#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+ time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000);
+#else
+#if defined(Q_OS_WIN)
+ _tzset();
+#endif
+ time_t secsSince1Jan1970UTC = mktime(&localTM);
+#endif
+ tm *brokenDown = 0;
+#if defined(Q_OS_WINCE)
+ tm res;
+ FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
+ SYSTEMTIME sysTime;
+ FileTimeToSystemTime(&localTime, &sysTime);
+ FILETIME resultTime;
+ LocalFileTimeToFileTime(&localTime , &resultTime);
+ FileTimeToSystemTime(&resultTime , &sysTime);
+ res.tm_sec = sysTime.wSecond;
+ res.tm_min = sysTime.wMinute;
+ res.tm_hour = sysTime.wHour;
+ res.tm_mday = sysTime.wDay;
+ res.tm_mon = sysTime.wMonth - 1;
+ res.tm_year = sysTime.wYear - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
+#elif defined(Q_OS_SYMBIAN)
+ // months and days are zero index based
+ _LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int());
+ TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
+ TTime epochTTime;
+ TInt err = epochTTime.Set(KUnixEpoch);
+ tm res;
+ if(err == KErrNone) {
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
+ }
+#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of gmtime() where available
+ tm res;
+ brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ tm res;
+ if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
+ brokenDown = &res;
+#else
+ brokenDown = gmtime(&secsSince1Jan1970UTC);
+#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
+ if (!brokenDown) {
+ date = QDate(1970, 1, 1);
+ time = QTime();
+ } else {
+ int deltaDays = fakeDate.daysTo(date);
+ date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
+ time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
+ date = date.addDays(deltaDays);
+ }
+}
+
+QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
+{
+ outDate = date;
+ outTime = time;
+ if (spec == QDateTimePrivate::UTC)
+ return utcToLocal(outDate, outTime);
+ return spec;
+}
+
+void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
+{
+ outDate = date;
+ outTime = time;
+ const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC;
+
+ if (spec != QDateTimePrivate::UTC && !isOffset)
+ localToUtc(outDate, outTime, (int)spec);
+
+ if (isOffset)
+ addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000));
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
+QDebug operator<<(QDebug dbg, const QDate &date)
+{
+ dbg.nospace() << "QDate(" << date.toString() << ')';
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const QTime &time)
+{
+ dbg.nospace() << "QTime(" << time.toString() << ')';
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const QDateTime &date)
+{
+ dbg.nospace() << "QDateTime(" << date.toString() << ')';
+ return dbg.space();
+}
+#endif
+
+#ifndef QT_BOOTSTRAPPED
+
+/*!
+ \internal
+ Gets the digit from a datetime. E.g.
+
+ QDateTime var(QDate(2004, 02, 02));
+ int digit = getDigit(var, Year);
+ // digit = 2004
+*/
+
+int QDateTimeParser::getDigit(const QDateTime &t, int index) const
+{
+ if (index < 0 || index >= sectionNodes.size()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
+ qPrintable(t.toString()), index);
+#else
+ qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
+#endif
+ return -1;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+ switch (node.type) {
+ case Hour24Section: case Hour12Section: return t.time().hour();
+ case MinuteSection: return t.time().minute();
+ case SecondSection: return t.time().second();
+ case MSecSection: return t.time().msec();
+ case YearSection2Digits:
+ case YearSection: return t.date().year();
+ case MonthSection: return t.date().month();
+ case DaySection: return t.date().day();
+ case DayOfWeekSection: return t.date().day();
+ case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
+
+ default: break;
+ }
+
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
+ qPrintable(t.toString()), index);
+#else
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
+#endif
+ return -1;
+}
+
+/*!
+ \internal
+ Sets a digit in a datetime. E.g.
+
+ QDateTime var(QDate(2004, 02, 02));
+ int digit = getDigit(var, Year);
+ // digit = 2004
+ setDigit(&var, Year, 2005);
+ digit = getDigit(var, Year);
+ // digit = 2005
+*/
+
+bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
+{
+ if (index < 0 || index >= sectionNodes.size()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
+ qPrintable(v.toString()), index, newVal);
+#else
+ qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
+#endif
+ return false;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+
+ int year, month, day, hour, minute, second, msec;
+ year = v.date().year();
+ month = v.date().month();
+ day = v.date().day();
+ hour = v.time().hour();
+ minute = v.time().minute();
+ second = v.time().second();
+ msec = v.time().msec();
+
+ switch (node.type) {
+ case Hour24Section: case Hour12Section: hour = newVal; break;
+ case MinuteSection: minute = newVal; break;
+ case SecondSection: second = newVal; break;
+ case MSecSection: msec = newVal; break;
+ case YearSection2Digits:
+ case YearSection: year = newVal; break;
+ case MonthSection: month = newVal; break;
+ case DaySection:
+ case DayOfWeekSection:
+ if (newVal > 31) {
+ // have to keep legacy behavior. setting the
+ // date to 32 should return false. Setting it
+ // to 31 for february should return true
+ return false;
+ }
+ day = newVal;
+ break;
+ case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
+ default:
+ qWarning("QDateTimeParser::setDigit() Internal error (%s)",
+ qPrintable(sectionName(node.type)));
+ break;
+ }
+
+ if (!(node.type & (DaySection|DayOfWeekSection))) {
+ if (day < cachedDay)
+ day = cachedDay;
+ const int max = QDate(year, month, 1).daysInMonth();
+ if (day > max) {
+ day = max;
+ }
+ }
+ if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
+ v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ return true;
+ }
+ return false;
+}
+
+
+
+/*!
+ \
+
+ Returns the absolute maximum for a section
+*/
+
+int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ case Hour24Section:
+ case Hour12Section: return 23; // this is special-cased in
+ // parseSection. We want it to be
+ // 23 for the stepBy case.
+ case MinuteSection:
+ case SecondSection: return 59;
+ case MSecSection: return 999;
+ case YearSection2Digits:
+ case YearSection: return 9999; // sectionMaxSize will prevent
+ // people from typing in a larger
+ // number in count == 2 sections.
+ // stepBy() will work on real years anyway
+ case MonthSection: return 12;
+ case DaySection:
+ case DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31;
+ case AmPmSection: return 1;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns the absolute minimum for a section
+*/
+
+int QDateTimeParser::absoluteMin(int s) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ case Hour24Section:
+ case Hour12Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection:
+ case YearSection2Digits:
+ case YearSection: return 0;
+ case MonthSection:
+ case DaySection:
+ case DayOfWeekSection: return 1;
+ case AmPmSection: return 0;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
+ qPrintable(sectionName(sn.type)), sn.type);
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns the sectionNode for the Section \a s.
+*/
+
+const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
+{
+ if (sectionIndex < 0) {
+ switch (sectionIndex) {
+ case FirstSectionIndex:
+ return first;
+ case LastSectionIndex:
+ return last;
+ case NoSectionIndex:
+ return none;
+ }
+ } else if (sectionIndex < sectionNodes.size()) {
+ return sectionNodes.at(sectionIndex);
+ }
+
+ qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
+ sectionIndex);
+ return none;
+}
+
+QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
+{
+ return sectionNode(sectionIndex).type;
+}
+
+
+/*!
+ \internal
+
+ Returns the starting position for section \a s.
+*/
+
+int QDateTimeParser::sectionPos(int sectionIndex) const
+{
+ return sectionPos(sectionNode(sectionIndex));
+}
+
+int QDateTimeParser::sectionPos(const SectionNode &sn) const
+{
+ switch (sn.type) {
+ case FirstSection: return 0;
+ case LastSection: return displayText().size() - 1;
+ default: break;
+ }
+ if (sn.pos == -1) {
+ qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
+ return -1;
+ }
+ return sn.pos;
+}
+
+
+/*!
+ \internal helper function for parseFormat. removes quotes that are
+ not escaped and removes the escaping on those that are escaped
+
+*/
+
+static QString unquote(const QString &str)
+{
+ const QChar quote(QLatin1Char('\''));
+ const QChar slash(QLatin1Char('\\'));
+ const QChar zero(QLatin1Char('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) {
+ status = quote;
+ } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+ ret[ret.size() - 1] = quote;
+ } else {
+ status = zero;
+ }
+ } else {
+ ret += str.at(i);
+ }
+ }
+ return ret;
+}
+/*!
+ \internal
+
+ Parses the format \a newFormat. If successful, returns true and
+ sets up the format. Else keeps the old format and returns false.
+
+*/
+
+static inline int countRepeat(const QString &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;
+}
+
+static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
+{
+ QString str(string.mid(from, size));
+ if (lastQuote >= from)
+ str = unquote(str);
+ list->append(str);
+}
+
+
+bool QDateTimeParser::parseFormat(const QString &newFormat)
+{
+ const QLatin1Char quote('\'');
+ const QLatin1Char slash('\\');
+ const QLatin1Char zero('0');
+ if (newFormat == displayFormat && !newFormat.isEmpty()) {
+ return true;
+ }
+
+ QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
+
+ QVector<SectionNode> newSectionNodes;
+ Sections newDisplay = 0;
+ QStringList newSeparators;
+ int i, index = 0;
+ int add = 0;
+ QChar 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) {
+ status = quote;
+ } else if (newFormat.at(i - 1) != slash) {
+ status = zero;
+ }
+ } else if (status != quote) {
+ const char sect = newFormat.at(i).toLatin1();
+ switch (sect) {
+ case 'H':
+ case 'h':
+ if (parserType != QVariant::Date) {
+ const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
+ const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2) };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= hour;
+ }
+ break;
+ case 'm':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2) };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MinuteSection;
+ }
+ break;
+ case 's':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2) };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= SecondSection;
+ }
+ break;
+
+ case 'z':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MSecSection;
+ }
+ break;
+ case 'A':
+ case 'a':
+ if (parserType != QVariant::Date) {
+ const bool cap = (sect == 'A');
+ const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ newDisplay |= AmPmSection;
+ if (i + 1 < newFormat.size()
+ && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
+ ++i;
+ }
+ index = i + 1;
+ }
+ break;
+ case 'y':
+ if (parserType != QVariant::Time) {
+ const int repeat = countRepeat(newFormat, i, 4);
+ if (repeat >= 2) {
+ const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
+ i - add, repeat == 4 ? 4 : 2 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= sn.type;
+ }
+ }
+ break;
+ case 'M':
+ if (parserType != QVariant::Time) {
+ const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4) };
+ newSectionNodes.append(sn);
+ newSeparators.append(unquote(newFormat.mid(index, i - index)));
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MonthSection;
+ }
+ break;
+ case 'd':
+ if (parserType != QVariant::Time) {
+ const int repeat = countRepeat(newFormat, i, 4);
+ const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= sn.type;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
+ return false;
+ }
+
+ if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
+ const int max = newSectionNodes.size();
+ for (int i=0; i<max; ++i) {
+ SectionNode &node = newSectionNodes[i];
+ if (node.type == Hour12Section)
+ node.type = Hour24Section;
+ }
+ }
+
+ if (index < newFormat.size()) {
+ appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
+ } else {
+ newSeparators.append(QString());
+ }
+
+ displayFormat = newFormat;
+ separators = newSeparators;
+ sectionNodes = newSectionNodes;
+ display = newDisplay;
+ last.pos = -1;
+
+// for (int i=0; i<sectionNodes.size(); ++i) {
+// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
+// }
+
+ QDTPDEBUG << newFormat << displayFormat;
+ QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Returns the size of section \a s.
+*/
+
+int QDateTimeParser::sectionSize(int sectionIndex) const
+{
+ if (sectionIndex < 0)
+ return 0;
+
+ if (sectionIndex >= sectionNodes.size()) {
+ qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
+ return -1;
+ }
+ if (sectionIndex == sectionNodes.size() - 1) {
+ return displayText().size() - sectionPos(sectionIndex) - separators.last().size();
+ } else {
+ return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
+ - separators.at(sectionIndex + 1).size();
+ }
+}
+
+
+int QDateTimeParser::sectionMaxSize(Section s, int count) const
+{
+#ifndef QT_NO_TEXTDATE
+ int mcount = 12;
+#endif
+
+ switch (s) {
+ case FirstSection:
+ case NoSection:
+ case LastSection: return 0;
+
+ case AmPmSection: {
+ const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
+ getAmPmText(PmText, LowerCase).size());
+ const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
+ getAmPmText(PmText, UpperCase).size());
+ return qMin(4, qMin(lowerMax, upperMax));
+ }
+
+ case Hour24Section:
+ case Hour12Section:
+ case MinuteSection:
+ case SecondSection:
+ case DaySection: return 2;
+ case DayOfWeekSection:
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ mcount = 7;
+ // fall through
+#endif
+ case MonthSection:
+ if (count <= 2)
+ return 2;
+
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ {
+ int ret = 0;
+ const QLocale l = locale();
+ for (int i=1; i<=mcount; ++i) {
+ const QString str = (s == MonthSection
+ ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
+ : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
+ ret = qMax(str.size(), ret);
+ }
+ return ret;
+ }
+#endif
+ case MSecSection: return 3;
+ case YearSection: return 4;
+ case YearSection2Digits: return 2;
+
+ case CalendarPopupSection:
+ case Internal:
+ case TimeSectionMask:
+ case DateSectionMask:
+ qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
+ sectionName(s).toLatin1().constData());
+
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ case CalendarPopupIndex:
+ // these cases can't happen
+ break;
+ }
+ return -1;
+}
+
+
+int QDateTimeParser::sectionMaxSize(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ return sectionMaxSize(sn.type, sn.count);
+}
+
+/*!
+ \internal
+
+ Returns the text of section \a s. This function operates on the
+ arg text rather than edit->text().
+*/
+
+
+QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
+{
+ const SectionNode &sn = sectionNode(sectionIndex);
+ switch (sn.type) {
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ return QString();
+ default: break;
+ }
+
+ return text.mid(index, sectionSize(sectionIndex));
+}
+
+QString QDateTimeParser::sectionText(int sectionIndex) const
+{
+ const SectionNode &sn = sectionNode(sectionIndex);
+ switch (sn.type) {
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ return QString();
+ default: break;
+ }
+
+ return displayText().mid(sn.pos, sectionSize(sectionIndex));
+}
+
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \internal:skipToNextSection
+
+ Parses the part of \a text that corresponds to \a s and returns
+ the value of that field. Sets *stateptr to the right state if
+ stateptr != 0.
+*/
+
+int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
+ QString &text, int &cursorPosition, int index,
+ State &state, int *usedptr) const
+{
+ state = Invalid;
+ int num = 0;
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if ((sn.type & Internal) == Internal) {
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ const int sectionmaxsize = sectionMaxSize(sectionIndex);
+ QString sectiontext = text.mid(index, sectionmaxsize);
+ int sectiontextSize = sectiontext.size();
+
+ QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
+ << "with text" << text << "and st" << sectiontext
+ << text.mid(index, sectionmaxsize)
+ << index;
+
+ int used = 0;
+ switch (sn.type) {
+ case AmPmSection: {
+ const int ampm = findAmPm(sectiontext, sectionIndex, &used);
+ switch (ampm) {
+ case AM: // sectiontext == AM
+ case PM: // sectiontext == PM
+ num = ampm;
+ state = Acceptable;
+ break;
+ case PossibleAM: // sectiontext => AM
+ case PossiblePM: // sectiontext => PM
+ num = ampm - 2;
+ state = Intermediate;
+ break;
+ case PossibleBoth: // sectiontext => AM|PM
+ num = 0;
+ state = Intermediate;
+ break;
+ case Neither:
+ state = Invalid;
+ QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
+ break;
+ default:
+ QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
+ break;
+ }
+ if (state != Invalid) {
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ }
+ break; }
+ case MonthSection:
+ case DayOfWeekSection:
+ if (sn.count >= 3) {
+ if (sn.type == MonthSection) {
+ int min = 1;
+ const QDate minDate = getMinimum().date();
+ if (currentValue.date().year() == minDate.year()) {
+ min = minDate.month();
+ }
+ num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
+ } else {
+ num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
+ }
+
+ if (num != -1) {
+ state = (used == sectiontext.size() ? Acceptable : Intermediate);
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ } else {
+ state = Intermediate;
+ }
+ break; }
+ // fall through
+ case DaySection:
+ case YearSection:
+ case YearSection2Digits:
+ case Hour12Section:
+ case Hour24Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection: {
+ if (sectiontextSize == 0) {
+ num = 0;
+ used = 0;
+ state = Intermediate;
+ } else {
+ const int absMax = absoluteMax(sectionIndex);
+ QLocale loc;
+ bool ok = true;
+ int last = -1;
+ used = -1;
+
+ QString digitsStr(sectiontext);
+ for (int i = 0; i < sectiontextSize; ++i) {
+ if (digitsStr.at(i).isSpace()) {
+ sectiontextSize = i;
+ break;
+ }
+ }
+
+ const int max = qMin(sectionmaxsize, sectiontextSize);
+ for (int digits = max; digits >= 1; --digits) {
+ digitsStr.truncate(digits);
+ int tmp = (int)loc.toUInt(digitsStr, &ok, 10);
+ if (ok && sn.type == Hour12Section) {
+ if (tmp > 12) {
+ tmp = -1;
+ ok = false;
+ } else if (tmp == 12) {
+ tmp = 0;
+ }
+ }
+ if (ok && tmp <= absMax) {
+ QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
+ last = tmp;
+ used = digits;
+ break;
+ }
+ }
+
+ if (last == -1) {
+ QChar first(sectiontext.at(0));
+ if (separators.at(sectionIndex + 1).startsWith(first)) {
+ used = 0;
+ state = Intermediate;
+ } else {
+ state = Invalid;
+ QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
+ }
+ } else {
+ num += last;
+ const FieldInfo fi = fieldInfo(sectionIndex);
+ const bool done = (used == sectionmaxsize);
+ if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
+ for (int i=used; i<sectionmaxsize; ++i) {
+ num *= 10;
+ }
+ }
+ const int absMin = absoluteMin(sectionIndex);
+ if (num < absMin) {
+ state = done ? Invalid : Intermediate;
+ if (done)
+ QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
+ } else if (num > absMax) {
+ state = Intermediate;
+ } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
+ if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
+ state = Acceptable;
+ const int missingZeroes = sectionmaxsize - digitsStr.size();
+ text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
+ used = sectionmaxsize;
+ cursorPosition += missingZeroes;
+ } else {
+ state = Intermediate;;
+ }
+ } else {
+ state = Acceptable;
+ }
+ }
+ }
+ break; }
+ default:
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ if (usedptr)
+ *usedptr = used;
+
+ return (state != Invalid ? num : -1);
+}
+#endif // QT_NO_TEXTDATE
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \internal
+*/
+
+QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
+ const QDateTime &currentValue, bool fixup) const
+{
+ const QDateTime minimum = getMinimum();
+ const QDateTime maximum = getMaximum();
+
+ State state = Acceptable;
+
+ QDateTime newCurrentValue;
+ int pos = 0;
+ bool conflicts = false;
+ const int sectionNodesCount = sectionNodes.size();
+
+ QDTPDEBUG << "parse" << input;
+ {
+ int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
+ getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
+ year2digits = year % 100;
+ hour = currentValue.time().hour();
+ hour12 = -1;
+ minute = currentValue.time().minute();
+ second = currentValue.time().second();
+ msec = currentValue.time().msec();
+ dayofweek = currentValue.date().dayOfWeek();
+
+ ampm = -1;
+ Sections isSet = NoSection;
+ int num;
+ State tmpstate;
+
+ for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
+ if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
+ QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
+ << "!=" << separators.at(index)
+ << index << pos << currentSectionIndex;
+ state = Invalid;
+ goto end;
+ }
+ pos += separators.at(index).size();
+ sectionNodes[index].pos = pos;
+ int *current = 0;
+ const SectionNode sn = sectionNodes.at(index);
+ int used;
+
+ num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
+ QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
+ << "pos" << pos << "used" << used << stateName(tmpstate);
+ if (fixup && tmpstate == Intermediate && used < sn.count) {
+ const FieldInfo fi = fieldInfo(index);
+ if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
+ const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
+ input.replace(pos, used, newText);
+ used = sn.count;
+ }
+ }
+ pos += qMax(0, used);
+
+ state = qMin<State>(state, tmpstate);
+ if (state == Intermediate && context == FromString) {
+ state = Invalid;
+ break;
+ }
+
+ QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
+ << pos << "state is" << stateName(state);
+
+
+ if (state != Invalid) {
+ switch (sn.type) {
+ case Hour24Section: current = &hour; break;
+ case Hour12Section: current = &hour12; break;
+ case MinuteSection: current = &minute; break;
+ case SecondSection: current = &second; break;
+ case MSecSection: current = &msec; break;
+ case YearSection: current = &year; break;
+ case YearSection2Digits: current = &year2digits; break;
+ case MonthSection: current = &month; break;
+ case DayOfWeekSection: current = &dayofweek; break;
+ case DaySection: current = &day; num = qMax<int>(1, num); break;
+ case AmPmSection: current = &ampm; break;
+ default:
+ qWarning("QDateTimeParser::parse Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ break;
+ }
+ if (!current) {
+ qWarning("QDateTimeParser::parse Internal error 2");
+ return StateNode();
+ }
+ if (isSet & sn.type && *current != num) {
+ QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
+ conflicts = true;
+ if (index != currentSectionIndex || num == -1) {
+ continue;
+ }
+ }
+ if (num != -1)
+ *current = num;
+ isSet |= sn.type;
+ }
+ }
+
+ if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
+ QDTPDEBUG << "invalid because" << input.mid(pos)
+ << "!=" << separators.last() << pos;
+ state = Invalid;
+ }
+
+ if (state != Invalid) {
+ if (parserType != QVariant::Time) {
+ if (year % 100 != year2digits) {
+ switch (isSet & (YearSection2Digits|YearSection)) {
+ case YearSection2Digits:
+ year = (year / 100) * 100;
+ year += year2digits;
+ break;
+ case ((uint)YearSection2Digits|(uint)YearSection): {
+ conflicts = true;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == YearSection2Digits) {
+ year = (year / 100) * 100;
+ year += year2digits;
+ }
+ break; }
+ default:
+ break;
+ }
+ }
+
+ const QDate date(year, month, day);
+ const int diff = dayofweek - date.dayOfWeek();
+ if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) {
+ conflicts = isSet & DaySection;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == DayOfWeekSection || currentSectionIndex == -1) {
+ // dayofweek should be preferred
+ day += diff;
+ if (day <= 0) {
+ day += 7;
+ } else if (day > date.daysInMonth()) {
+ day -= 7;
+ }
+ QDTPDEBUG << year << month << day << dayofweek
+ << diff << QDate(year, month, day).dayOfWeek();
+ }
+ }
+ bool needfixday = false;
+ if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSection)) {
+ cachedDay = day;
+ } else if (cachedDay > day) {
+ day = cachedDay;
+ needfixday = true;
+ }
+
+ if (!QDate::isValid(year, month, day)) {
+ if (day < 32) {
+ cachedDay = day;
+ }
+ if (day > 28 && QDate::isValid(year, month, 1)) {
+ needfixday = true;
+ }
+ }
+ if (needfixday) {
+ if (context == FromString) {
+ state = Invalid;
+ goto end;
+ }
+ if (state == Acceptable && fixday) {
+ day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
+
+ const QLocale loc = locale();
+ for (int i=0; i<sectionNodesCount; ++i) {
+ if (sectionType(i) & (DaySection|DayOfWeekSection)) {
+ input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
+ }
+ }
+ } else {
+ state = qMin(Intermediate, state);
+ }
+ }
+ }
+
+ if (parserType != QVariant::Date) {
+ 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) {
+ 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)) {
+ conflicts = true;
+ }
+ }
+
+ }
+
+ newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ QDTPDEBUG << year << month << day << hour << minute << second << msec;
+ }
+ QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
+ newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
+ stateName(state).toLatin1().constData());
+ }
+end:
+ if (newCurrentValue.isValid()) {
+ if (context != FromString && state != Invalid && newCurrentValue < minimum) {
+ const QLatin1Char space(' ');
+ if (newCurrentValue >= minimum)
+ qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
+ qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
+
+ bool done = false;
+ state = Invalid;
+ for (int i=0; i<sectionNodesCount && !done; ++i) {
+ const SectionNode &sn = sectionNodes.at(i);
+ QString t = sectionText(input, i, sn.pos).toLower();
+ if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
+ || t.contains(space)) {
+ switch (sn.type) {
+ case AmPmSection:
+ switch (findAmPm(t, i)) {
+ case AM:
+ case PM:
+ state = Acceptable;
+ done = true;
+ break;
+ case Neither:
+ state = Invalid;
+ done = true;
+ break;
+ case PossibleAM:
+ case PossiblePM:
+ case PossibleBoth: {
+ const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
+ if (copy >= minimum && copy <= maximum) {
+ state = Intermediate;
+ done = true;
+ }
+ break; }
+ }
+ case MonthSection:
+ if (sn.count >= 3) {
+ int tmp = newCurrentValue.date().month();
+ // I know the first possible month makes the date too early
+ while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
+ const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
+ if (copy >= minimum && copy <= maximum)
+ break; // break out of while
+ }
+ if (tmp == -1) {
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break;
+ }
+ // fallthrough
+ default: {
+ int toMin;
+ int toMax;
+
+ if (sn.type & TimeSectionMask) {
+ if (newCurrentValue.daysTo(minimum) != 0) {
+ break;
+ }
+ toMin = newCurrentValue.time().msecsTo(minimum.time());
+ if (newCurrentValue.daysTo(maximum) > 0) {
+ toMax = -1; // can't get to max
+ } else {
+ toMax = newCurrentValue.time().msecsTo(maximum.time());
+ }
+ } else {
+ toMin = newCurrentValue.daysTo(minimum);
+ toMax = newCurrentValue.daysTo(maximum);
+ }
+ const int maxChange = QDateTimeParser::maxChange(i);
+ if (toMin > maxChange) {
+ QDTPDEBUG << "invalid because toMin > maxChange" << toMin
+ << maxChange << t << newCurrentValue << minimum;
+ state = Invalid;
+ done = true;
+ break;
+ } else if (toMax > maxChange) {
+ toMax = -1; // can't get to max
+ }
+
+ const int min = getDigit(minimum, i);
+ if (min == -1) {
+ qWarning("QDateTimeParser::parse Internal error 4 (%s)",
+ qPrintable(sectionName(sn.type)));
+ state = Invalid;
+ done = true;
+ break;
+ }
+
+ int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
+ int pos = cursorPosition - sn.pos;
+ if (pos < 0 || pos >= t.size())
+ pos = -1;
+ if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
+ QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
+ << sectionName(sn.type) << "returned" << toMax << toMin << pos;
+ state = Invalid;
+ done = true;
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break; }
+ }
+ }
+ }
+ } else {
+ if (context == FromString) {
+ // optimization
+ Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
+ if (newCurrentValue.date().toJulianDay() > 4642999)
+ state = Invalid;
+ } else {
+ if (newCurrentValue > getMaximum())
+ state = Invalid;
+ }
+
+ QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
+ }
+ }
+ StateNode node;
+ node.input = input;
+ node.state = state;
+ node.conflicts = conflicts;
+ node.value = newCurrentValue.toTimeSpec(spec);
+ text = input;
+ return node;
+}
+#endif // QT_NO_DATESTRING
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \internal finds the first possible monthname that \a str1 can
+ match. Starting from \a index; str should already by lowered
+*/
+
+int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
+ QString *usedMonth, int *used) const
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if (sn.type != MonthSection) {
+ qWarning("QDateTimeParser::findMonth Internal error");
+ return -1;
+ }
+
+ QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
+ QLocale l = locale();
+
+ for (int month=startMonth; month<=12; ++month) {
+ QString str2 = l.monthName(month, type).toLower();
+
+ if (str1.startsWith(str2)) {
+ if (used) {
+ QDTPDEBUG << "used is set to" << str2.size();
+ *used = str2.size();
+ }
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+
+ return month;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+
+ QDTPDEBUG << "limit is" << limit << str1 << str2;
+ bool equal = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i)) {
+ equal = false;
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = month;
+ }
+ break;
+ }
+ }
+ if (equal) {
+ if (used)
+ *used = limit;
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+ return month;
+ }
+ }
+ if (usedMonth && bestMatch != -1)
+ *usedMonth = l.monthName(bestMatch, type);
+ }
+ if (used) {
+ QDTPDEBUG << "used is set to" << bestCount;
+ *used = bestCount;
+ }
+ return bestMatch;
+}
+
+int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if (!(sn.type & (DaySection|DayOfWeekSection))) {
+ qWarning("QDateTimeParser::findDay Internal error");
+ return -1;
+ }
+ const QLocale l = locale();
+ for (int day=startDay; day<=7; ++day) {
+ const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+
+ if (str1.startsWith(str2.toLower())) {
+ if (used)
+ *used = str2.size();
+ if (usedDay) {
+ *usedDay = str2;
+ }
+ return day;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+ bool found = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = day;
+ }
+ found = false;
+ break;
+ }
+
+ }
+ if (found) {
+ if (used)
+ *used = limit;
+ if (usedDay)
+ *usedDay = str2;
+
+ return day;
+ }
+ }
+ if (usedDay && bestMatch != -1) {
+ *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+ }
+ }
+ if (used)
+ *used = bestCount;
+
+ return bestMatch;
+}
+#endif // QT_NO_TEXTDATE
+
+/*!
+ \internal
+
+ returns
+ 0 if str == QDateTimeEdit::tr("AM")
+ 1 if str == QDateTimeEdit::tr("PM")
+ 2 if str can become QDateTimeEdit::tr("AM")
+ 3 if str can become QDateTimeEdit::tr("PM")
+ 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
+ -1 can't become anything sensible
+
+*/
+
+int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
+{
+ const SectionNode &s = sectionNode(index);
+ if (s.type != AmPmSection) {
+ qWarning("QDateTimeParser::findAmPm Internal error");
+ return -1;
+ }
+ if (used)
+ *used = str.size();
+ if (str.trimmed().isEmpty()) {
+ return PossibleBoth;
+ }
+ const QLatin1Char space(' ');
+ int size = sectionMaxSize(index);
+
+ enum {
+ amindex = 0,
+ 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[i].truncate(size);
+
+ QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
+
+ if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
+ str = ampm[amindex];
+ return AM;
+ } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
+ str = ampm[pmindex];
+ return PM;
+ } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
+ return Neither;
+ }
+ size = qMin(size, str.size());
+
+ bool broken[2] = {false, false};
+ for (int i=0; i<size; ++i) {
+ if (str.at(i) != 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)
+ << "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()
+ << "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()
+ << "in" << ampm[j] << "and got" << index;
+ }
+ if (index == -1) {
+ broken[j] = true;
+ if (broken[amindex] && broken[pmindex]) {
+ QDTPDEBUG << str << "didn't make it";
+ return Neither;
+ }
+ continue;
+ } else {
+ str[i] = ampm[j].at(index); // fix case
+ }
+ }
+ ampm[j].remove(index, 1);
+ }
+ }
+ }
+ }
+ if (!broken[pmindex] && !broken[amindex])
+ return PossibleBoth;
+ return (!broken[amindex] ? PossibleAM : PossiblePM);
+}
+
+/*!
+ \internal
+ Max number of units that can be changed by this section.
+*/
+
+int QDateTimeParser::maxChange(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ switch (sn.type) {
+ // Time. unit is msec
+ case MSecSection: return 999;
+ case SecondSection: return 59 * 1000;
+ case MinuteSection: return 59 * 60 * 1000;
+ case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
+
+ // Date. unit is day
+ case DayOfWeekSection: return 7;
+ case DaySection: return 30;
+ case MonthSection: return 365 - 31;
+ case YearSection: return 9999 * 365;
+ case YearSection2Digits: return 100 * 365;
+ default:
+ qWarning("QDateTimeParser::maxChange() Internal error (%s)",
+ qPrintable(sectionName(sectionType(index))));
+ }
+
+ return -1;
+}
+
+QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
+{
+ FieldInfo ret = 0;
+ const SectionNode &sn = sectionNode(index);
+ const Section s = sn.type;
+ switch (s) {
+ case MSecSection:
+ ret |= Fraction;
+ // fallthrough
+ case SecondSection:
+ case MinuteSection:
+ case Hour24Section:
+ case Hour12Section:
+ case YearSection:
+ case YearSection2Digits:
+ ret |= Numeric;
+ if (s != YearSection) {
+ ret |= AllowPartial;
+ }
+ if (sn.count != 1) {
+ ret |= FixedWidth;
+ }
+ break;
+ case MonthSection:
+ case DaySection:
+ switch (sn.count) {
+ case 2:
+ ret |= FixedWidth;
+ // fallthrough
+ case 1:
+ ret |= (Numeric|AllowPartial);
+ break;
+ }
+ break;
+ case DayOfWeekSection:
+ if (sn.count == 3)
+ ret |= FixedWidth;
+ break;
+ case AmPmSection:
+ ret |= FixedWidth;
+ break;
+ default:
+ qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
+ index, qPrintable(sectionName(sn.type)), sn.count);
+ break;
+ }
+ return ret;
+}
+
+/*!
+ \internal Get a number that str can become which is between min
+ and max or -1 if this is not possible.
+*/
+
+
+QString QDateTimeParser::sectionFormat(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ return sectionFormat(sn.type, sn.count);
+}
+
+QString QDateTimeParser::sectionFormat(Section s, int count) const
+{
+ QChar fillChar;
+ switch (s) {
+ 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 DayOfWeekSection:
+ case DaySection: fillChar = QLatin1Char('d'); break;
+ case MonthSection: fillChar = QLatin1Char('M'); break;
+ case YearSection2Digits:
+ case YearSection: fillChar = QLatin1Char('y'); break;
+ default:
+ qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
+ qPrintable(sectionName(s)));
+ return QString();
+ }
+ if (fillChar.isNull()) {
+ qWarning("QDateTimeParser::sectionFormat Internal error 2");
+ return QString();
+ }
+
+ QString str;
+ str.fill(fillChar, count);
+ return str;
+}
+
+
+/*! \internal Returns true if str can be modified to represent a
+ number that is within min and max.
+*/
+
+bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const
+{
+ if (str.isEmpty()) {
+ return true;
+ }
+ const int size = sectionMaxSize(index);
+ int val = (int)locale().toUInt(str);
+ const SectionNode &sn = sectionNode(index);
+ if (sn.type == YearSection2Digits) {
+ val += currentValue.date().year() - (currentValue.date().year() % 100);
+ }
+ if (val >= min && val <= max && str.size() == size) {
+ return true;
+ } else if (val > max) {
+ return false;
+ } else if (str.size() == size && val < min) {
+ return false;
+ }
+
+ const int len = size - str.size();
+ for (int i=0; i<len; ++i) {
+ for (int j=0; j<10; ++j) {
+ if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
+ return true;
+ } else if (insert >= 0) {
+ QString tmp = str;
+ tmp.insert(insert, QLatin1Char('0' + j));
+ if (potentialValue(tmp, min, max, index, currentValue, insert))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
+{
+ Q_ASSERT(current >= getMinimum() && current <= getMaximum());
+
+ const SectionNode &node = sectionNode(index);
+ Q_ASSERT(text.size() < sectionMaxSize(index));
+
+ const QDateTime maximum = getMaximum();
+ const QDateTime minimum = getMinimum();
+ QDateTime tmp = current;
+ int min = absoluteMin(index);
+ setDigit(tmp, index, min);
+ if (tmp < minimum) {
+ min = getDigit(minimum, index);
+ }
+
+ int max = absoluteMax(index, current);
+ setDigit(tmp, index, max);
+ if (tmp > maximum) {
+ max = getDigit(maximum, index);
+ }
+ int pos = cursorPosition() - node.pos;
+ if (pos < 0 || pos >= text.size())
+ pos = -1;
+
+ const bool potential = potentialValue(text, min, max, index, current, pos);
+ return !potential;
+
+ /* If the value potentially can become another valid entry we
+ * don't want to skip to the next. E.g. In a M field (month
+ * without leading 0 if you type 1 we don't want to autoskip but
+ * if you type 3 we do
+ */
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the section \a s.
+*/
+
+QString QDateTimeParser::sectionName(int s) const
+{
+ switch (s) {
+ case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
+ case QDateTimeParser::DaySection: return QLatin1String("DaySection");
+ case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection");
+ 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::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(s);
+ }
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the state \a s.
+*/
+
+QString QDateTimeParser::stateName(int 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);
+ }
+}
+
+#ifndef QT_NO_DATESTRING
+bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
+{
+ QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
+ QString text = t;
+ int copy = -1;
+ const StateNode tmp = parse(text, copy, val, false);
+ if (tmp.state != Acceptable || tmp.conflicts) {
+ return false;
+ }
+ if (time) {
+ const QTime t = tmp.value.time();
+ if (!t.isValid()) {
+ return false;
+ }
+ *time = t;
+ }
+
+ if (date) {
+ const QDate d = tmp.value.date();
+ if (!d.isValid()) {
+ return false;
+ }
+ *date = d;
+ }
+ return true;
+}
+#endif // QT_NO_DATESTRING
+
+QDateTime QDateTimeParser::getMinimum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
+}
+
+QDateTime QDateTimeParser::getMaximum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
+}
+
+QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
+{
+ if (ap == AmText) {
+ return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
+ } else {
+ return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
+ }
+}
+
+/*
+ \internal
+
+ I give arg2 preference because arg1 is always a QDateTime.
+*/
+
+bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
+{
+ return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
+}
+
+#ifdef Q_OS_SYMBIAN
+const static TTime UnixEpochOffset(I64LIT(0xdcddb30f2f8000));
+const static TInt64 MinimumMillisecondTime(KMinTInt64 / 1000);
+const static TInt64 MaximumMillisecondTime(KMaxTInt64 / 1000);
+QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time)
+{
+ TTimeIntervalMicroSeconds absolute = time.MicroSecondsFrom(UnixEpochOffset);
+
+ return QDateTime::fromMSecsSinceEpoch(absolute.Int64() / 1000);
+}
+
+TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime)
+{
+ qint64 absolute = datetime.toMSecsSinceEpoch();
+ if(absolute > MaximumMillisecondTime)
+ return TTime(KMaxTInt64);
+ if(absolute < MinimumMillisecondTime)
+ return TTime(KMinTInt64);
+ return TTime(absolute * 1000);
+}
+
+time_t qt_symbian_TTime_To_time_t(const TTime& time)
+{
+ TTimeIntervalSeconds interval;
+ TInt err = time.SecondsFrom(UnixEpochOffset, interval);
+ if (err || interval.Int() < 0)
+ return (time_t) 0;
+ return (time_t) interval.Int();
+}
+
+TTime qt_symbian_time_t_To_TTime(time_t time)
+{
+ return UnixEpochOffset + TTimeIntervalSeconds(time);
+}
+#endif //Q_OS_SYMBIAN
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
new file mode 100644
index 0000000000..432c906372
--- /dev/null
+++ b/src/corelib/tools/qdatetime.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATETIME_H
+#define QDATETIME_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QDate
+{
+public:
+ enum MonthNameType {
+ DateFormat = 0,
+ StandaloneFormat
+ };
+public:
+ QDate() { jd = 0; }
+ QDate(int y, int m, int d);
+
+ bool isNull() const { return jd == 0; }
+ bool isValid() const;
+
+ int year() const;
+ int month() const;
+ int day() const;
+ int dayOfWeek() const;
+ int dayOfYear() const;
+ int daysInMonth() const;
+ int daysInYear() const;
+ int weekNumber(int *yearNum = 0) const;
+
+#ifndef QT_NO_TEXTDATE
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QString monthName(int month) { return shortMonthName(month); }
+ static QT3_SUPPORT QString dayName(int weekday) { return shortDayName(weekday); }
+#endif
+ // ### Qt 5: merge these functions.
+ static QString shortMonthName(int month);
+ static QString shortMonthName(int month, MonthNameType type);
+ static QString shortDayName(int weekday);
+ static QString shortDayName(int weekday, MonthNameType type);
+ static QString longMonthName(int month);
+ static QString longMonthName(int month, MonthNameType type);
+ static QString longDayName(int weekday);
+ static QString longDayName(int weekday, MonthNameType type);
+#endif // QT_NO_TEXTDATE
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ bool setYMD(int y, int m, int d);
+ bool setDate(int year, int month, int day);
+
+ void getDate(int *year, int *month, int *day);
+
+ QDate addDays(int days) const;
+ QDate addMonths(int months) const;
+ QDate addYears(int years) const;
+ int daysTo(const QDate &) const;
+
+ bool operator==(const QDate &other) const { return jd == other.jd; }
+ bool operator!=(const QDate &other) const { return jd != other.jd; }
+ bool operator<(const QDate &other) const { return jd < other.jd; }
+ bool operator<=(const QDate &other) const { return jd <= other.jd; }
+ bool operator>(const QDate &other) const { return jd > other.jd; }
+ bool operator>=(const QDate &other) const { return jd >= other.jd; }
+
+ static QDate currentDate();
+#ifndef QT_NO_DATESTRING
+ static QDate fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
+ static QDate fromString(const QString &s, const QString &format);
+#endif
+ static bool isValid(int y, int m, int d);
+ static bool isLeapYear(int year);
+#ifdef QT3_SUPPORT
+ inline static QT3_SUPPORT bool leapYear(int year) { return isLeapYear(year); }
+#endif
+
+ // ### Qt 5: remove these two functions
+ static uint gregorianToJulian(int y, int m, int d);
+ static void julianToGregorian(uint jd, int &y, int &m, int &d);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QDate currentDate(Qt::TimeSpec spec);
+#endif
+
+ static inline QDate fromJulianDay(int jd) { QDate d; d.jd = jd; return d; }
+ inline int toJulianDay() const { return jd; }
+
+private:
+ uint jd;
+
+ friend class QDateTime;
+ friend class QDateTimePrivate;
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QDate, Q_MOVABLE_TYPE);
+
+class Q_CORE_EXPORT QTime
+{
+public:
+ QTime(): mds(NullTime)
+#if defined(Q_OS_WINCE)
+ , startTick(NullTime)
+#endif
+ {}
+ QTime(int h, int m, int s = 0, int ms = 0);
+
+ bool isNull() const { return mds == NullTime; }
+ bool isValid() const;
+
+ int hour() const;
+ int minute() const;
+ int second() const;
+ int msec() const;
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ bool setHMS(int h, int m, int s, int ms = 0);
+
+ QTime addSecs(int secs) const;
+ int secsTo(const QTime &) const;
+ QTime addMSecs(int ms) const;
+ int msecsTo(const QTime &) const;
+
+ bool operator==(const QTime &other) const { return mds == other.mds; }
+ bool operator!=(const QTime &other) const { return mds != other.mds; }
+ bool operator<(const QTime &other) const { return mds < other.mds; }
+ bool operator<=(const QTime &other) const { return mds <= other.mds; }
+ bool operator>(const QTime &other) const { return mds > other.mds; }
+ bool operator>=(const QTime &other) const { return mds >= other.mds; }
+
+ static QTime currentTime();
+#ifndef QT_NO_DATESTRING
+ static QTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
+ static QTime fromString(const QString &s, const QString &format);
+#endif
+ static bool isValid(int h, int m, int s, int ms = 0);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QTime currentTime(Qt::TimeSpec spec);
+#endif
+
+ void start();
+ int restart();
+ int elapsed() const;
+private:
+ enum TimeFlag { NullTime = -1 };
+ inline int ds() const { return mds == -1 ? 0 : mds; }
+ int mds;
+#if defined(Q_OS_WINCE)
+ int startTick;
+#endif
+
+ friend class QDateTime;
+ friend class QDateTimePrivate;
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QTime, Q_MOVABLE_TYPE);
+
+class QDateTimePrivate;
+
+class Q_CORE_EXPORT QDateTime
+{
+public:
+ QDateTime();
+ explicit QDateTime(const QDate &);
+ QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
+ QDateTime(const QDateTime &other);
+ ~QDateTime();
+
+ QDateTime &operator=(const QDateTime &other);
+
+ bool isNull() const;
+ bool isValid() const;
+
+ QDate date() const;
+ QTime time() const;
+ Qt::TimeSpec timeSpec() const;
+ qint64 toMSecsSinceEpoch() const;
+ uint toTime_t() const;
+ void setDate(const QDate &date);
+ void setTime(const QTime &time);
+ void setTimeSpec(Qt::TimeSpec spec);
+ void setMSecsSinceEpoch(qint64 msecs);
+ void setTime_t(uint secsSince1Jan1970UTC);
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ QDateTime addDays(int days) const;
+ QDateTime addMonths(int months) const;
+ QDateTime addYears(int years) const;
+ QDateTime addSecs(int secs) const;
+ QDateTime addMSecs(qint64 msecs) const;
+ QDateTime toTimeSpec(Qt::TimeSpec spec) const;
+ inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
+ inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); }
+ int daysTo(const QDateTime &) const;
+ int 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); }
+
+ void setUtcOffset(int seconds);
+ int utcOffset() const;
+
+ static QDateTime currentDateTime();
+ static QDateTime currentDateTimeUtc();
+#ifndef QT_NO_DATESTRING
+ static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
+ static QDateTime fromString(const QString &s, const QString &format);
+#endif
+ static QDateTime fromTime_t(uint secsSince1Jan1970UTC);
+ static QDateTime fromMSecsSinceEpoch(qint64 msecs);
+ static qint64 currentMSecsSinceEpoch();
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec) {
+ setTime_t(secsSince1Jan1970UTC);
+ if (spec == Qt::UTC)
+ *this = toUTC();
+ }
+ static inline QT3_SUPPORT QDateTime currentDateTime(Qt::TimeSpec spec) {
+ if (spec == Qt::LocalTime)
+ return currentDateTime();
+ else
+ return currentDateTime().toUTC();
+ }
+
+#endif
+
+private:
+ friend class QDateTimePrivate;
+ void detach();
+ QExplicitlySharedDataPointer<QDateTimePrivate> d;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QDateTime, Q_MOVABLE_TYPE);
+
+#ifdef QT3_SUPPORT
+inline QDate QDate::currentDate(Qt::TimeSpec spec)
+{
+ if (spec == Qt::LocalTime)
+ return currentDate();
+ else
+ return QDateTime::currentDateTime().toUTC().date();
+}
+
+inline QTime QTime::currentTime(Qt::TimeSpec spec)
+{
+ if (spec == Qt::LocalTime)
+ return currentTime();
+ else
+ return QDateTime::currentDateTime().toUTC().time();
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
+#endif // QT_NO_DATASTREAM
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QDate &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QTime &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDATETIME_H
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
new file mode 100644
index 0000000000..ad4055db51
--- /dev/null
+++ b/src/corelib/tools/qdatetime_p.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATETIME_P_H
+#define QDATETIME_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 "qplatformdefs.h"
+#include "QtCore/qatomic.h"
+#include "QtCore/qdatetime.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qlocale.h"
+#ifndef QT_BOOTSTRAPPED
+# include "QtCore/qvariant.h"
+#endif
+#include "QtCore/qvector.h"
+
+
+#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
+#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
+#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
+#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
+#define QDATETIMEEDIT_DATE_MAX QDate(7999, 12, 31)
+#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
+#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
+#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
+#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
+
+QT_BEGIN_NAMESPACE
+
+class QDateTimePrivate
+{
+public:
+ enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
+
+ QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {}
+ QDateTimePrivate(const QDateTimePrivate &other)
+ : date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
+ {}
+
+ QAtomicInt ref;
+ QDate date;
+ QTime time;
+ Spec spec;
+ /*!
+ \internal
+ \since 4.4
+
+ The offset in seconds. Applies only when timeSpec() is OffsetFromUTC.
+ */
+ int utcOffset;
+
+ Spec getLocal(QDate &outDate, QTime &outTime) const;
+ void getUTC(QDate &outDate, QTime &outTime) const;
+ static QDateTime addMSecs(const QDateTime &dt, qint64 msecs);
+ static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs);
+};
+
+#ifndef QT_BOOTSTRAPPED
+
+class Q_CORE_EXPORT QDateTimeParser
+{
+public:
+ enum Context {
+ FromString,
+ DateTimeEdit
+ };
+ QDateTimeParser(QVariant::Type t, Context ctx)
+ : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
+ fixday(false), spec(Qt::LocalTime), context(ctx)
+ {
+ defaultLocale = QLocale::system();
+ first.type = FirstSection;
+ first.pos = -1;
+ first.count = -1;
+ last.type = FirstSection;
+ last.pos = -1;
+ last.count = -1;
+ none.type = NoSection;
+ none.pos = -1;
+ none.count = -1;
+ }
+ virtual ~QDateTimeParser() {}
+ enum {
+ Neither = -1,
+ AM = 0,
+ PM = 1,
+ PossibleAM = 2,
+ PossiblePM = 3,
+ PossibleBoth = 4
+ };
+
+ enum Section {
+ NoSection = 0x00000,
+ AmPmSection = 0x00001,
+ MSecSection = 0x00002,
+ SecondSection = 0x00004,
+ MinuteSection = 0x00008,
+ Hour12Section = 0x00010,
+ Hour24Section = 0x00020,
+ TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section),
+ Internal = 0x10000,
+ DaySection = 0x00100,
+ MonthSection = 0x00200,
+ YearSection = 0x00400,
+ YearSection2Digits = 0x00800,
+ DayOfWeekSection = 0x01000,
+ DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSection),
+ FirstSection = 0x02000|Internal,
+ LastSection = 0x04000|Internal,
+ CalendarPopupSection = 0x08000|Internal,
+
+ NoSectionIndex = -1,
+ FirstSectionIndex = -2,
+ LastSectionIndex = -3,
+ CalendarPopupIndex = -4
+ }; // duplicated from qdatetimeedit.h
+ Q_DECLARE_FLAGS(Sections, Section)
+
+ struct SectionNode {
+ Section type;
+ mutable int pos;
+ int count;
+ };
+
+ enum State { // duplicated from QValidator
+ Invalid,
+ Intermediate,
+ Acceptable
+ };
+
+ struct StateNode {
+ StateNode() : state(Invalid), conflicts(false) {}
+ QString input;
+ State state;
+ bool conflicts;
+ QDateTime value;
+ };
+
+ enum AmPm {
+ AmText,
+ PmText
+ };
+
+ enum Case {
+ UpperCase,
+ LowerCase
+ };
+
+#ifndef QT_NO_DATESTRING
+ StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
+#endif
+ int sectionMaxSize(int index) const;
+ int sectionSize(int index) const;
+ int sectionMaxSize(Section s, int count) const;
+ int sectionPos(int index) const;
+ int sectionPos(const SectionNode &sn) const;
+
+ const SectionNode &sectionNode(int index) const;
+ Section sectionType(int index) const;
+ QString sectionText(int sectionIndex) const;
+ QString sectionText(const QString &text, int sectionIndex, int index) const;
+ int getDigit(const QDateTime &dt, int index) const;
+ bool setDigit(QDateTime &t, int index, int newval) const;
+ int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
+ int index, QDateTimeParser::State &state, int *used = 0) const;
+ int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
+ int absoluteMin(int index) const;
+ bool parseFormat(const QString &format);
+#ifndef QT_NO_DATESTRING
+ bool fromString(const QString &text, QDate *date, QTime *time) const;
+#endif
+
+#ifndef QT_NO_TEXTDATE
+ int findMonth(const QString &str1, int monthstart, int sectionIndex,
+ QString *monthName = 0, int *used = 0) const;
+ int findDay(const QString &str1, int intDaystart, int sectionIndex,
+ QString *dayName = 0, int *used = 0) const;
+#endif
+ int findAmPm(QString &str1, int index, int *used = 0) const;
+ int maxChange(int s) const;
+ bool potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const;
+ bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
+ QString sectionName(int s) const;
+ QString stateName(int s) const;
+
+ QString sectionFormat(int index) const;
+ QString sectionFormat(Section s, int count) const;
+
+ enum FieldInfoFlag {
+ Numeric = 0x01,
+ FixedWidth = 0x02,
+ AllowPartial = 0x04,
+ Fraction = 0x08
+ };
+ Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
+
+ FieldInfo fieldInfo(int index) const;
+
+ virtual QDateTime getMinimum() const;
+ virtual QDateTime getMaximum() const;
+ virtual int cursorPosition() const { return -1; }
+ virtual QString displayText() const { return text; }
+ virtual QString getAmPmText(AmPm ap, Case cs) const;
+ virtual QLocale locale() const { return defaultLocale; }
+
+ mutable int currentSectionIndex;
+ Sections display;
+ mutable int cachedDay;
+ mutable QString text;
+ QVector<SectionNode> sectionNodes;
+ SectionNode first, last, none, popup;
+ QStringList separators;
+ QString displayFormat;
+ QLocale defaultLocale;
+ QVariant::Type parserType;
+
+ bool fixday;
+
+ Qt::TimeSpec spec; // spec if used by QDateTimeEdit
+ Context context;
+};
+
+Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
+
+#ifdef Q_OS_SYMBIAN
+QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time);
+TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime);
+time_t qt_symbian_TTime_To_time_t(const TTime& time);
+TTime qt_symbian_time_t_To_TTime(time_t time);
+#endif //Q_OS_SYMBIAN
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
+
+#endif // QDATETIME_P_H
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
new file mode 100644
index 0000000000..7daf95abe1
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -0,0 +1,937 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+
+| *property* | *Used for type* |
+| period | QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| amplitude | QEasingCurve::{In,Out,InOut,OutIn}Bounce, QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| overshoot | QEasingCurve::{In,Out,InOut,OutIn}Back |
+
+*/
+
+
+
+
+/*!
+ \class QEasingCurve
+ \since 4.6
+ \ingroup animation
+ \brief The QEasingCurve class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how the speed of the interpolation
+ between 0 and 1 should be. Easing curves allow transitions from
+ one value to another to appear more natural than a simple constant speed would allow.
+ The QEasingCurve class is usually used in conjunction with the QVariantAnimation and
+ QPropertyAnimation classes but can be used on its own. It is usually used to accelerate
+ the interpolation from zero velocity (ease in) or decelerate to zero velocity (ease out).
+ Ease in and ease out can also be combined in the same easing curve.
+
+ To calculate the speed of the interpolation, the easing curve provides the function
+ valueForProgress(), where the \a progress argument specifies the progress of the
+ interpolation: 0 is the start value of the interpolation, 1 is the end value of the
+ interpolation. The returned value is the effective progress of the interpolation.
+ If the returned value is the same as the input value for all input values the easing
+ curve is a linear curve. This is the default behaviour.
+
+ For example,
+ \code
+ QEasingCurve easing(QEasingCurve::InOutQuad);
+
+ for(qreal t = 0.0; t < 1.0; t+=0.1)
+ qWarning() << "Effective progress" << t << " is
+ << easing.valueForProgress(t);
+ \endcode
+ will print the effective progress of the interpolation between 0 and 1.
+
+ When using a QPropertyAnimation, the associated easing curve will be used to control the
+ progress of the interpolation between startValue and endValue:
+ \code
+ QPropertyAnimation animation;
+ animation.setStartValue(0);
+ animation.setEndValue(1000);
+ animation.setDuration(1000);
+ animation.setEasingCurve(QEasingCurve::InOutQuad);
+ \endcode
+
+ The ability to set an amplitude, overshoot, or period depends on
+ the QEasingCurve type. Amplitude access is available to curves
+ that behave as springs such as elastic and bounce curves. Changing
+ the amplitude changes the height of the curve. Period access is
+ only available to elastic curves and setting a higher period slows
+ the rate of bounce. Only curves that have "boomerang" behaviors
+ such as the InBack, OutBack, InOutBack, and OutInBack have
+ overshoot settings. These curves will interpolate beyond the end
+ points and return to the end point, acting similar to a boomerang.
+
+ The \l{Easing Curves Example} contains samples of QEasingCurve
+ types and lets you change the curve settings.
+
+ */
+
+/*!
+ \enum QEasingCurve::Type
+
+ The type of easing curve.
+
+ \value Linear \inlineimage qeasingcurve-linear.png
+ \br
+ Easing curve for a linear (t) function:
+ velocity is constant.
+ \value InQuad \inlineimage qeasingcurve-inquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ accelerating from zero velocity.
+ \value OutQuad \inlineimage qeasingcurve-outquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ decelerating to zero velocity.
+ \value InOutQuad \inlineimage qeasingcurve-inoutquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuad \inlineimage qeasingcurve-outinquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ deceleration until halfway, then acceleration.
+ \value InCubic \inlineimage qeasingcurve-incubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ accelerating from zero velocity.
+ \value OutCubic \inlineimage qeasingcurve-outcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ decelerating to zero velocity.
+ \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCubic \inlineimage qeasingcurve-outincubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ deceleration until halfway, then acceleration.
+ \value InQuart \inlineimage qeasingcurve-inquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ accelerating from zero velocity.
+ \value OutQuart \inlineimage qeasingcurve-outquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ decelerating to zero velocity.
+ \value InOutQuart \inlineimage qeasingcurve-inoutquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuart \inlineimage qeasingcurve-outinquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ deceleration until halfway, then acceleration.
+ \value InQuint \inlineimage qeasingcurve-inquint.png
+ \br
+ Easing curve for a quintic (t^5) easing
+ in: accelerating from zero velocity.
+ \value OutQuint \inlineimage qeasingcurve-outquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ decelerating to zero velocity.
+ \value InOutQuint \inlineimage qeasingcurve-inoutquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuint \inlineimage qeasingcurve-outinquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ deceleration until halfway, then acceleration.
+ \value InSine \inlineimage qeasingcurve-insine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ accelerating from zero velocity.
+ \value OutSine \inlineimage qeasingcurve-outsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ decelerating from zero velocity.
+ \value InOutSine \inlineimage qeasingcurve-inoutsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInSine \inlineimage qeasingcurve-outinsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ deceleration until halfway, then acceleration.
+ \value InExpo \inlineimage qeasingcurve-inexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ accelerating from zero velocity.
+ \value OutExpo \inlineimage qeasingcurve-outexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ decelerating from zero velocity.
+ \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ acceleration until halfway, then deceleration.
+ \value OutInExpo \inlineimage qeasingcurve-outinexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ deceleration until halfway, then acceleration.
+ \value InCirc \inlineimage qeasingcurve-incirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ accelerating from zero velocity.
+ \value OutCirc \inlineimage qeasingcurve-outcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ decelerating from zero velocity.
+ \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCirc \inlineimage qeasingcurve-outincirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ deceleration until halfway, then acceleration.
+ \value InElastic \inlineimage qeasingcurve-inelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ accelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value OutElastic \inlineimage qeasingcurve-outelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ decelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ acceleration until halfway, then deceleration.
+ \value OutInElastic \inlineimage qeasingcurve-outinelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ deceleration until halfway, then acceleration.
+ \value InBack \inlineimage qeasingcurve-inback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in:
+ accelerating from zero velocity.
+ \value OutBack \inlineimage qeasingcurve-outback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing out:
+ decelerating to zero velocity.
+ \value InOutBack \inlineimage qeasingcurve-inoutback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBack \inlineimage qeasingcurve-outinback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBounce \inlineimage qeasingcurve-inbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function: accelerating
+ from zero velocity.
+ \value OutBounce \inlineimage qeasingcurve-outbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function: decelerating
+ from zero velocity.
+ \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBounce \inlineimage qeasingcurve-outinbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function easing out/in:
+ deceleration until halfway, then acceleration.
+ \omitvalue InCurve
+ \omitvalue OutCurve
+ \omitvalue SineCurve
+ \omitvalue CosineCurve
+ \value Custom This is returned if the user specified a custom curve type with
+ setCustomType(). Note that you cannot call setType() with this value,
+ but type() can return it.
+ \omitvalue NCurveTypes
+*/
+
+/*!
+ \typedef QEasingCurve::EasingFunction
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp 0
+*/
+
+#include "qeasingcurve.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#include <QtCore/qstring.h>
+#endif
+
+#ifndef QT_NO_DATASTREAM
+#include <QtCore/qdatastream.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static bool isConfigFunction(QEasingCurve::Type type)
+{
+ return type >= QEasingCurve::InElastic
+ && type <= QEasingCurve::OutInBounce;
+}
+
+class QEasingCurveFunction
+{
+public:
+ enum Type { In, Out, InOut, OutIn };
+
+ QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0,
+ qreal overshoot = 1.70158)
+ : _t(type), _p(period), _a(amplitude), _o(overshoot)
+ { }
+ virtual ~QEasingCurveFunction() {}
+ virtual qreal value(qreal t);
+ virtual QEasingCurveFunction *copy() const;
+ bool operator==(const QEasingCurveFunction& other);
+
+ Type _t;
+ qreal _p;
+ qreal _a;
+ qreal _o;
+};
+
+qreal QEasingCurveFunction::value(qreal t)
+{
+ return t;
+}
+
+QEasingCurveFunction *QEasingCurveFunction::copy() const
+{
+ return new QEasingCurveFunction(_t, _p, _a, _o);
+}
+
+bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other)
+{
+ return _t == other._t &&
+ qFuzzyCompare(_p, other._p) &&
+ qFuzzyCompare(_a, other._a) &&
+ qFuzzyCompare(_o, other._o);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "../../3rdparty/easing/easing.cpp"
+QT_END_INCLUDE_NAMESPACE
+
+class QEasingCurvePrivate
+{
+public:
+ QEasingCurvePrivate()
+ : type(QEasingCurve::Linear),
+ config(0),
+ func(&easeNone)
+ { }
+ ~QEasingCurvePrivate() { delete config; }
+ void setType_helper(QEasingCurve::Type);
+
+ QEasingCurve::Type type;
+ QEasingCurveFunction *config;
+ QEasingCurve::EasingFunction func;
+};
+
+struct ElasticEase : public QEasingCurveFunction
+{
+ ElasticEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ ElasticEase *rv = new ElasticEase(_t);
+ rv->_p = _p;
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal p = (_p < 0) ? qreal(0.3) : _p;
+ qreal a = (_a < 0) ? qreal(1.0) : _a;
+ switch(_t) {
+ case In:
+ return easeInElastic(t, a, p);
+ case Out:
+ return easeOutElastic(t, a, p);
+ case InOut:
+ return easeInOutElastic(t, a, p);
+ case OutIn:
+ return easeOutInElastic(t, a, p);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BounceEase : public QEasingCurveFunction
+{
+ BounceEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BounceEase *rv = new BounceEase(_t);
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal a = (_a < 0) ? qreal(1.0) : _a;
+ switch(_t) {
+ case In:
+ return easeInBounce(t, a);
+ case Out:
+ return easeOutBounce(t, a);
+ case InOut:
+ return easeInOutBounce(t, a);
+ case OutIn:
+ return easeOutInBounce(t, a);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BackEase : public QEasingCurveFunction
+{
+ BackEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0), qreal(1.70158))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BackEase *rv = new BackEase(_t);
+ rv->_o = _o;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal o = (_o < 0) ? qreal(1.70158) : _o;
+ switch(_t) {
+ case In:
+ return easeInBack(t, o);
+ case Out:
+ return easeOutBack(t, o);
+ case InOut:
+ return easeInOutBack(t, o);
+ case OutIn:
+ return easeOutInBack(t, o);
+ default:
+ return t;
+ }
+ }
+};
+
+static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
+{
+ switch(curve) {
+ case QEasingCurve::Linear:
+ return &easeNone;
+ case QEasingCurve::InQuad:
+ return &easeInQuad;
+ case QEasingCurve::OutQuad:
+ return &easeOutQuad;
+ case QEasingCurve::InOutQuad:
+ return &easeInOutQuad;
+ case QEasingCurve::OutInQuad:
+ return &easeOutInQuad;
+ case QEasingCurve::InCubic:
+ return &easeInCubic;
+ case QEasingCurve::OutCubic:
+ return &easeOutCubic;
+ case QEasingCurve::InOutCubic:
+ return &easeInOutCubic;
+ case QEasingCurve::OutInCubic:
+ return &easeOutInCubic;
+ case QEasingCurve::InQuart:
+ return &easeInQuart;
+ case QEasingCurve::OutQuart:
+ return &easeOutQuart;
+ case QEasingCurve::InOutQuart:
+ return &easeInOutQuart;
+ case QEasingCurve::OutInQuart:
+ return &easeOutInQuart;
+ case QEasingCurve::InQuint:
+ return &easeInQuint;
+ case QEasingCurve::OutQuint:
+ return &easeOutQuint;
+ case QEasingCurve::InOutQuint:
+ return &easeInOutQuint;
+ case QEasingCurve::OutInQuint:
+ return &easeOutInQuint;
+ case QEasingCurve::InSine:
+ return &easeInSine;
+ case QEasingCurve::OutSine:
+ return &easeOutSine;
+ case QEasingCurve::InOutSine:
+ return &easeInOutSine;
+ case QEasingCurve::OutInSine:
+ return &easeOutInSine;
+ case QEasingCurve::InExpo:
+ return &easeInExpo;
+ case QEasingCurve::OutExpo:
+ return &easeOutExpo;
+ case QEasingCurve::InOutExpo:
+ return &easeInOutExpo;
+ case QEasingCurve::OutInExpo:
+ return &easeOutInExpo;
+ case QEasingCurve::InCirc:
+ return &easeInCirc;
+ case QEasingCurve::OutCirc:
+ return &easeOutCirc;
+ case QEasingCurve::InOutCirc:
+ return &easeInOutCirc;
+ case QEasingCurve::OutInCirc:
+ return &easeOutInCirc;
+ // Internal for, compatibility with QTimeLine only ??
+ case QEasingCurve::InCurve:
+ return &easeInCurve;
+ case QEasingCurve::OutCurve:
+ return &easeOutCurve;
+ case QEasingCurve::SineCurve:
+ return &easeSineCurve;
+ case QEasingCurve::CosineCurve:
+ return &easeCosineCurve;
+ default:
+ return 0;
+ };
+}
+
+static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
+{
+ QEasingCurveFunction *curveFunc = 0;
+ switch(type) {
+ case QEasingCurve::InElastic:
+ curveFunc = new ElasticEase(ElasticEase::In);
+ break;
+ case QEasingCurve::OutElastic:
+ curveFunc = new ElasticEase(ElasticEase::Out);
+ break;
+ case QEasingCurve::InOutElastic:
+ curveFunc = new ElasticEase(ElasticEase::InOut);
+ break;
+ case QEasingCurve::OutInElastic:
+ curveFunc = new ElasticEase(ElasticEase::OutIn);
+ break;
+ case QEasingCurve::OutBounce:
+ curveFunc = new BounceEase(BounceEase::Out);
+ break;
+ case QEasingCurve::InBounce:
+ curveFunc = new BounceEase(BounceEase::In);
+ break;
+ case QEasingCurve::OutInBounce:
+ curveFunc = new BounceEase(BounceEase::OutIn);
+ break;
+ case QEasingCurve::InOutBounce:
+ curveFunc = new BounceEase(BounceEase::InOut);
+ break;
+ case QEasingCurve::InBack:
+ curveFunc = new BackEase(BackEase::In);
+ break;
+ case QEasingCurve::OutBack:
+ curveFunc = new BackEase(BackEase::Out);
+ break;
+ case QEasingCurve::InOutBack:
+ curveFunc = new BackEase(BackEase::InOut);
+ break;
+ case QEasingCurve::OutInBack:
+ curveFunc = new BackEase(BackEase::OutIn);
+ break;
+ default:
+ curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, qreal(0.3), qreal(1.0), qreal(1.70158));
+ }
+
+ return curveFunc;
+}
+
+/*!
+ Constructs an easing curve of the given \a type.
+ */
+QEasingCurve::QEasingCurve(Type type)
+ : d_ptr(new QEasingCurvePrivate)
+{
+ setType(type);
+}
+
+/*!
+ Construct a copy of \a other.
+ */
+QEasingCurve::QEasingCurve(const QEasingCurve &other)
+ : d_ptr(new QEasingCurvePrivate)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ *d_ptr = *other.d_ptr;
+ if (other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+}
+
+/*!
+ Destructor.
+ */
+
+QEasingCurve::~QEasingCurve()
+{
+ delete d_ptr;
+}
+
+/*!
+ Copy \a other.
+ */
+QEasingCurve &QEasingCurve::operator=(const QEasingCurve &other)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ if (d_ptr->config) {
+ delete d_ptr->config;
+ d_ptr->config = 0;
+ }
+
+ *d_ptr = *other.d_ptr;
+ if (other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+
+ return *this;
+}
+
+/*!
+ Compare this easing curve with \a other and returns true if they are
+ equal. It will also compare the properties of a curve.
+ */
+bool QEasingCurve::operator==(const QEasingCurve &other) const
+{
+ bool res = d_ptr->func == other.d_ptr->func
+ && d_ptr->type == other.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());
+ }
+ }
+ return res;
+}
+
+/*!
+ \fn bool QEasingCurve::operator!=(const QEasingCurve &other) const
+ Compare this easing curve with \a other and returns true if they are not equal.
+ It will also compare the properties of a curve.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns the amplitude. This is not applicable for all curve types.
+ It is only applicable for bounce and elastic curves (curves of type()
+ QEasingCurve::InBounce, QEasingCurve::OutBounce, QEasingCurve::InOutBounce,
+ QEasingCurve::OutInBounce, QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic).
+ */
+qreal QEasingCurve::amplitude() const
+{
+ return d_ptr->config ? d_ptr->config->_a : qreal(1.0);
+}
+
+/*!
+ Sets the amplitude to \a amplitude.
+
+ This will set the amplitude of the bounce or the amplitude of the
+ elastic "spring" effect. The higher the number, the higher the amplitude.
+ \sa amplitude()
+*/
+void QEasingCurve::setAmplitude(qreal amplitude)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_a = amplitude;
+}
+
+/*!
+ Returns the period. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic.
+ */
+qreal QEasingCurve::period() const
+{
+ return d_ptr->config ? d_ptr->config->_p : qreal(0.3);
+}
+
+/*!
+ Sets the period to \a period.
+ Setting a small period value will give a high frequency of the curve. A
+ large period will give it a small frequency.
+
+ \sa period()
+*/
+void QEasingCurve::setPeriod(qreal period)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_p = period;
+}
+
+/*!
+ Returns the overshoot. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InBack, QEasingCurve::OutBack,
+ QEasingCurve::InOutBack or QEasingCurve::OutInBack.
+ */
+qreal QEasingCurve::overshoot() const
+{
+ return d_ptr->config ? d_ptr->config->_o : qreal(1.70158) ;
+}
+
+/*!
+ Sets the overshoot to \a overshoot.
+
+ 0 produces no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent.
+
+ \sa overshoot()
+*/
+void QEasingCurve::setOvershoot(qreal overshoot)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_o = overshoot;
+}
+
+/*!
+ Returns the type of the easing curve.
+*/
+QEasingCurve::Type QEasingCurve::type() const
+{
+ return d_ptr->type;
+}
+
+void QEasingCurvePrivate::setType_helper(QEasingCurve::Type newType)
+{
+ qreal amp = -1.0;
+ qreal period = -1.0;
+ qreal overshoot = -1.0;
+
+ if (config) {
+ amp = config->_a;
+ period = config->_p;
+ overshoot = config->_o;
+ delete config;
+ config = 0;
+ }
+
+ if (isConfigFunction(newType) || (amp != -1.0) || (period != -1.0) || (overshoot != -1.0)) {
+ config = curveToFunctionObject(newType);
+ if (amp != -1.0)
+ config->_a = amp;
+ if (period != -1.0)
+ config->_p = period;
+ if (overshoot != -1.0)
+ config->_o = overshoot;
+ func = 0;
+ } else if (newType != QEasingCurve::Custom) {
+ func = curveToFunc(newType);
+ }
+ Q_ASSERT((func == 0) == (config != 0));
+ type = newType;
+}
+
+/*!
+ Sets the type of the easing curve to \a type.
+*/
+void QEasingCurve::setType(Type type)
+{
+ if (d_ptr->type == type)
+ return;
+ if (type < Linear || type >= NCurveTypes - 1) {
+ qWarning("QEasingCurve: Invalid curve type %d", type);
+ return;
+ }
+
+ d_ptr->setType_helper(type);
+}
+
+/*!
+ Sets a custom easing curve that is defined by the user in the function \a func.
+ The signature of the function is qreal myEasingFunction(qreal progress),
+ where \e progress and the return value is considered to be normalized between 0 and 1.
+ (In some cases the return value can be outside that range)
+ After calling this function type() will return QEasingCurve::Custom.
+ \a func cannot be zero.
+
+ \sa customType()
+ \sa valueForProgress()
+*/
+void QEasingCurve::setCustomType(EasingFunction func)
+{
+ if (!func) {
+ qWarning("Function pointer must not be null");
+ return;
+ }
+ d_ptr->func = func;
+ d_ptr->setType_helper(Custom);
+}
+
+/*!
+ Returns the function pointer to the custom easing curve.
+ If type() does not return QEasingCurve::Custom, this function
+ will return 0.
+*/
+QEasingCurve::EasingFunction QEasingCurve::customType() const
+{
+ return d_ptr->type == Custom ? d_ptr->func : 0;
+}
+
+/*!
+ Return the effective progress for the easing curve at \a progress.
+ While \a progress must be between 0 and 1, the returned effective progress
+ can be outside those bounds. For instance, QEasingCurve::InBack will
+ return negative values in the beginning of the function.
+ */
+qreal QEasingCurve::valueForProgress(qreal progress) const
+{
+ progress = qBound<qreal>(0, progress, 1);
+ if (d_ptr->func)
+ return d_ptr->func(progress);
+ else if (d_ptr->config)
+ return d_ptr->config->value(progress);
+ else
+ return progress;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QEasingCurve &item)
+{
+ debug << "type:" << item.d_ptr->type
+ << "func:" << item.d_ptr->func;
+ if (item.d_ptr->config) {
+ debug << QString::fromAscii("period:%1").arg(item.d_ptr->config->_p, 0, 'f', 20)
+ << QString::fromAscii("amp:%1").arg(item.d_ptr->config->_a, 0, 'f', 20)
+ << QString::fromAscii("overshoot:%1").arg(item.d_ptr->config->_o, 0, 'f', 20);
+ }
+ return debug;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QEasingCurve &easing)
+ \relates QEasingCurve
+
+ Writes the given \a easing curve to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QEasingCurve &easing)
+{
+ stream << quint8(easing.d_ptr->type);
+ stream << quint64(quintptr(easing.d_ptr->func));
+
+ bool hasConfig = easing.d_ptr->config;
+ stream << hasConfig;
+ if (hasConfig) {
+ stream << easing.d_ptr->config->_p;
+ stream << easing.d_ptr->config->_a;
+ stream << easing.d_ptr->config->_o;
+ }
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing)
+ \relates QQuaternion
+
+ Reads an easing curve from the given \a stream into the given \a
+ easing curve and returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing)
+{
+ QEasingCurve::Type type;
+ quint8 int_type;
+ stream >> int_type;
+ type = static_cast<QEasingCurve::Type>(int_type);
+ easing.setType(type);
+
+ quint64 ptr_func;
+ stream >> ptr_func;
+ easing.d_ptr->func = QEasingCurve::EasingFunction(quintptr(ptr_func));
+
+ bool hasConfig;
+ stream >> hasConfig;
+ if (hasConfig) {
+ QEasingCurveFunction *config = curveToFunctionObject(type);
+ stream >> config->_p;
+ stream >> config->_a;
+ stream >> config->_o;
+ easing.d_ptr->config = config;
+ }
+ return stream;
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
new file mode 100644
index 0000000000..b2cebb307f
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEASINGCURVE_H
+#define QEASINGCURVE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEasingCurvePrivate;
+class Q_CORE_EXPORT QEasingCurve
+{
+ Q_GADGET
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ Linear,
+ InQuad, OutQuad, InOutQuad, OutInQuad,
+ InCubic, OutCubic, InOutCubic, OutInCubic,
+ InQuart, OutQuart, InOutQuart, OutInQuart,
+ InQuint, OutQuint, InOutQuint, OutInQuint,
+ InSine, OutSine, InOutSine, OutInSine,
+ InExpo, OutExpo, InOutExpo, OutInExpo,
+ InCirc, OutCirc, InOutCirc, OutInCirc,
+ InElastic, OutElastic, InOutElastic, OutInElastic,
+ InBack, OutBack, InOutBack, OutInBack,
+ InBounce, OutBounce, InOutBounce, OutInBounce,
+ InCurve, OutCurve, SineCurve, CosineCurve,
+ Custom, NCurveTypes
+ };
+
+ QEasingCurve(Type type = Linear);
+ QEasingCurve(const QEasingCurve &other);
+ ~QEasingCurve();
+
+ QEasingCurve &operator=(const QEasingCurve &other);
+ bool operator==(const QEasingCurve &other) const;
+ inline bool operator!=(const QEasingCurve &other) const
+ { return !(this->operator==(other)); }
+
+ qreal amplitude() const;
+ void setAmplitude(qreal amplitude);
+
+ qreal period() const;
+ void setPeriod(qreal period);
+
+ qreal overshoot() const;
+ void setOvershoot(qreal overshoot);
+
+ Type type() const;
+ void setType(Type type);
+ typedef qreal (*EasingFunction)(qreal progress);
+ void setCustomType(EasingFunction func);
+ 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 &, QEasingCurve &);
+#endif
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+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 &, QEasingCurve &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp
new file mode 100644
index 0000000000..0b4b63c9d8
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QElapsedTimer
+ \brief The QElapsedTimer class provides a fast way to calculate elapsed times.
+ \since 4.7
+
+ \reentrant
+ \ingroup tools
+ \inmodule QtCore
+
+ The QElapsedTimer class is usually used to quickly calculate how much
+ time has elapsed between two events. Its API is similar to that of QTime,
+ so code that was using that can be ported quickly to the new class.
+
+ However, unlike QTime, QElapsedTimer tries to use monotonic clocks if
+ possible. This means it's not possible to convert QElapsedTimer objects
+ to a human-readable time.
+
+ The typical use-case for the class is to determine how much time was
+ spent in a slow operation. The simplest example of such a case is for
+ debugging purposes, as in the following example:
+
+ \snippet doc/src/snippets/qelapsedtimer/main.cpp 0
+
+ In this example, the timer is started by a call to start() and the
+ elapsed timer is calculated by the elapsed() function.
+
+ The time elapsed can also be used to recalculate the time available for
+ another operation, after the first one is complete. This is useful when
+ the execution must complete within a certain time period, but several
+ steps are needed. The \tt{waitFor}-type functions in QIODevice and its
+ subclasses are good examples of such need. In that case, the code could
+ be as follows:
+
+ \snippet doc/src/snippets/qelapsedtimer/main.cpp 1
+
+ Another use-case is to execute a certain operation for a specific
+ timeslice. For this, QElapsedTimer provides the hasExpired() convenience
+ function, which can be used to determine if a certain number of
+ milliseconds has already elapsed:
+
+ \snippet doc/src/snippets/qelapsedtimer/main.cpp 2
+
+ \section1 Reference clocks
+
+ QElapsedTimer will use the platform's monotonic reference clock in all
+ platforms that support it (see QElapsedTimer::isMonotonic()). This has
+ the added benefit that QElapsedTimer is immune to time adjustments, such
+ as the user correcting the time. Also unlike QTime, QElapsedTimer is
+ immune to changes in the timezone settings, such as daylight savings
+ periods.
+
+ On the other hand, this means QElapsedTimer values can only be compared
+ with other values that use the same reference. This is especially true if
+ the time since the reference is extracted from the QElapsedTimer object
+ (QElapsedTimer::msecsSinceReference()) and serialised. These values
+ should never be exchanged across the network or saved to disk, since
+ there's no telling whether the computer node receiving the data is the
+ same as the one originating it or if it has rebooted since.
+
+ It is, however, possible to exchange the value with other processes
+ running on the same machine, provided that they also use the same
+ reference clock. QElapsedTimer will always use the same clock, so it's
+ safe to compare with the value coming from another process in the same
+ machine. If comparing to values produced by other APIs, you should check
+ that the clock used is the same as QElapsedTimer (see
+ QElapsedTimer::clockType()).
+
+ \section2 32-bit overflows
+
+ Some of the clocks that 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
+*/
+
+/*!
+ \enum QElapsedTimer::ClockType
+
+ This enum contains the different clock types that QElapsedTimer may use.
+
+ QElapsedTimer will always use the same clock type in a particular
+ machine, so this value will not change during the lifetime of a program.
+ It is provided so that QElapsedTimer can be used with other non-Qt
+ implementations, to guarantee that the same reference clock is being
+ 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 and Symbian systems. This clock may overflow.
+ \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). 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.
+
+ \section2 SystemTime
+
+ The system time clock is purely the real time, expressed in milliseconds
+ since Jan 1, 1970 at 0:00 UTC. It's equivalent to the value returned by
+ the C and POSIX \tt{time} function, with the milliseconds added. This
+ clock type is currently only used on Unix systems that do not support
+ monotonic clocks (see below).
+
+ This is the only non-monotonic clock that QElapsedTimer may use.
+
+ \section2 MonotonicClock
+
+ This is the system's monotonic clock, expressed in milliseconds since an
+ 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 and Symbian 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's 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.
+
+ On Symbian systems, the overflow happens after 2^32 ticks, the duration
+ of which can be obtained from the platform HAL using the constant
+ HAL::ENanoTickPeriod. When comparing values between processes, it's
+ necessary to divide the value by the tick duration and mask off the high
+ 32 bits.
+
+ \section2 MachAbsoluteTime
+
+ This clock type is based on the absolute time presented by Mach kernels,
+ such as that found on Mac OS X. This clock type is presented separately
+ from MonotonicClock since Mac OS X is also a Unix system and may support
+ a POSIX monotonic clock with values differing from the Mach absolute
+ time.
+
+ This clock is monotonic and does not overflow.
+
+ \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.
+
+ This clock is monotonic and does not overflow.
+
+ \sa clockType(), isMonotonic()
+*/
+
+/*!
+ \fn bool QElapsedTimer::operator ==(const QElapsedTimer &other) const
+
+ Returns true if this object and \a other contain the same time.
+*/
+
+/*!
+ \fn bool QElapsedTimer::operator !=(const QElapsedTimer &other) const
+
+ Returns true if this object and \a other contain different times.
+*/
+
+static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
+
+/*!
+ Marks this QElapsedTimer object as invalid.
+
+ An invalid object can be checked with isValid(). Calculations of timer
+ elapsed since invalid data are undefined and will likely produce bizarre
+ results.
+
+ \sa isValid(), start(), restart()
+*/
+void QElapsedTimer::invalidate()
+{
+ t1 = t2 = invalidData;
+}
+
+/*!
+ Returns true if this object was invalidated by a call to invalidate() and
+ has not been restarted since.
+
+ \sa invalidate(), start(), restart()
+*/
+bool QElapsedTimer::isValid() const
+{
+ return t1 != invalidData && t2 != invalidData;
+}
+
+/*!
+ Returns 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.
+
+ \sa elapsed()
+*/
+bool QElapsedTimer::hasExpired(qint64 timeout) const
+{
+ // if timeout is -1, quint64(timeout) is LLINT_MAX, so this will be
+ // considered as never expired
+ return quint64(elapsed()) > quint64(timeout);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h
new file mode 100644
index 0000000000..3cf4a70f62
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTIMESTAMP_H
+#define QTIMESTAMP_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QElapsedTimer
+{
+public:
+ enum ClockType {
+ SystemTime,
+ MonotonicClock,
+ TickCounter,
+ MachAbsoluteTime,
+ PerformanceCounter
+ };
+ static ClockType clockType();
+ static bool isMonotonic();
+
+ void start();
+ qint64 restart();
+ void invalidate();
+ bool isValid() const;
+
+ qint64 nsecsElapsed() const;
+ qint64 elapsed() const;
+ bool hasExpired(qint64 timeout) const;
+
+ qint64 msecsSinceReference() const;
+ qint64 msecsTo(const QElapsedTimer &other) const;
+ qint64 secsTo(const QElapsedTimer &other) const;
+
+ bool operator==(const QElapsedTimer &other) const
+ { return t1 == other.t1 && t2 == other.t2; }
+ bool operator!=(const QElapsedTimer &other) const
+ { return !(*this == other); }
+
+ friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2);
+
+private:
+ qint64 t1;
+ qint64 t2;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTIMESTAMP_H
diff --git a/src/corelib/tools/qelapsedtimer_generic.cpp b/src/corelib/tools/qelapsedtimer_generic.cpp
new file mode 100644
index 0000000000..508c94fb1d
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer_generic.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include "qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Returns the clock type that this QElapsedTimer implementation uses.
+
+ \sa isMonotonic()
+*/
+QElapsedTimer::ClockType QElapsedTimer::clockType()
+{
+ return SystemTime;
+}
+
+/*!
+ Returns 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()
+{
+ 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 doc/src/snippets/qelapsedtimer/main.cpp 0
+
+ Also, starting a timer makes it valid again.
+
+ \sa restart(), invalidate(), elapsed()
+*/
+void QElapsedTimer::start()
+{
+ 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 restart(), but it does so in one
+ single operation, avoiding the need to obtain the clock value twice.
+
+ 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 doc/src/snippets/qelapsedtimer/main.cpp 3
+
+ \sa start(), invalidate(), elapsed()
+*/
+qint64 QElapsedTimer::restart()
+{
+ 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 in a QElapsedTimer that was invalidated
+ will result in undefined results.
+
+ 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
+{
+ return elapsed() * 1000000;
+}
+
+/*!
+ Returns the number of milliseconds since this QElapsedTimer was last
+ started. Calling this function in a QElapsedTimer that was invalidated
+ will result in undefined results.
+
+ \sa start(), restart(), hasExpired(), invalidate()
+*/
+qint64 QElapsedTimer::elapsed() const
+{
+ 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).
+
+ \sa clockType(), elapsed()
+*/
+qint64 QElapsedTimer::msecsSinceReference() const
+{
+ 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 positive. If it was started later, the returned value will be
+ negative.
+
+ The return value is undefined if this object or \a other were invalidated.
+
+ \sa secsTo(), elapsed()
+*/
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
+{
+ 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
+ positive. If it was started later, the returned value will be negative.
+
+ The return value is undefined if this object or \a other were invalidated.
+
+ \sa msecsTo(), elapsed()
+*/
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
+{
+ return msecsTo(other) / 1000;
+}
+
+/*!
+ \relates QElapsedTimer
+
+ Returns 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)
+{
+ return v1.t1 < v2.t1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp
new file mode 100644
index 0000000000..110549a020
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer_mac.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <mach/mach_time.h>
+
+QT_BEGIN_NAMESPACE
+
+QElapsedTimer::ClockType QElapsedTimer::clockType()
+{
+ return MachAbsoluteTime;
+}
+
+bool QElapsedTimer::isMonotonic()
+{
+ return true;
+}
+
+static mach_timebase_info_data_t info = {0,0};
+static qint64 absoluteToNSecs(qint64 cpuTime)
+{
+ if (info.denom == 0)
+ mach_timebase_info(&info);
+ qint64 nsecs = cpuTime * info.numer / info.denom;
+ return nsecs;
+}
+
+static qint64 absoluteToMSecs(qint64 cpuTime)
+{
+ return absoluteToNSecs(cpuTime) / 1000000;
+}
+
+timeval qt_gettime()
+{
+ timeval tv;
+
+ uint64_t cpu_time = mach_absolute_time();
+ uint64_t nsecs = absoluteToNSecs(cpu_time);
+ tv.tv_sec = nsecs / 1000000000ull;
+ tv.tv_usec = (nsecs / 1000) - (tv.tv_sec * 1000000);
+ return tv;
+}
+
+void QElapsedTimer::start()
+{
+ t1 = mach_absolute_time();
+ t2 = 0;
+}
+
+qint64 QElapsedTimer::restart()
+{
+ qint64 old = t1;
+ t1 = mach_absolute_time();
+ t2 = 0;
+
+ return absoluteToMSecs(t1 - old);
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const
+{
+ uint64_t cpu_time = mach_absolute_time();
+ return absoluteToNSecs(cpu_time - t1);
+}
+
+qint64 QElapsedTimer::elapsed() const
+{
+ uint64_t cpu_time = mach_absolute_time();
+ return absoluteToMSecs(cpu_time - t1);
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const
+{
+ return absoluteToMSecs(t1);
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
+{
+ return absoluteToMSecs(other.t1 - t1);
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
+{
+ return msecsTo(other) / 1000;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2)
+{
+ return v1.t1 < v2.t1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qelapsedtimer_symbian.cpp b/src/corelib/tools/qelapsedtimer_symbian.cpp
new file mode 100644
index 0000000000..b831e03208
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer_symbian.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include "qpair.h"
+#include <e32std.h>
+#include <sys/time.h>
+#include <hal.h>
+
+QT_BEGIN_NAMESPACE
+
+// return quint64 to avoid sign-extension
+static quint64 getMicrosecondFromTick()
+{
+ static TInt nanokernel_tick_period;
+ if (!nanokernel_tick_period)
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+ static quint32 highdword = 0;
+ static quint32 lastval = 0;
+ quint32 val = User::NTickCount();
+ if (val < lastval)
+ ++highdword;
+ lastval = val;
+
+ return nanokernel_tick_period * (val | (quint64(highdword) << 32));
+}
+
+timeval qt_gettime()
+{
+ timeval tv;
+ quint64 now = getMicrosecondFromTick();
+ tv.tv_sec = now / 1000000;
+ tv.tv_usec = now % 1000000;
+
+ return tv;
+}
+
+QElapsedTimer::ClockType QElapsedTimer::clockType()
+{
+ return TickCounter;
+}
+
+bool QElapsedTimer::isMonotonic()
+{
+ return true;
+}
+
+void QElapsedTimer::start()
+{
+ t1 = getMicrosecondFromTick();
+ t2 = 0;
+}
+
+qint64 QElapsedTimer::restart()
+{
+ qint64 oldt1 = t1;
+ t1 = getMicrosecondFromTick();
+ t2 = 0;
+ return t1 - oldt1;
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const
+{
+ return (getMicrosecondFromTick() - t1) * 1000;
+}
+
+qint64 QElapsedTimer::elapsed() const
+{
+ return (getMicrosecondFromTick() - t1) / 1000;
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const
+{
+ return t1 / 1000;
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
+{
+ return (other.t1 - t1) / 1000;
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
+{
+ return msecsTo(other) / 1000000;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2)
+{
+ return (v1.t1 - v2.t1) < 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qelapsedtimer_unix.cpp b/src/corelib/tools/qelapsedtimer_unix.cpp
new file mode 100644
index 0000000000..f24c6fb073
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer_unix.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.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
+
+#if (_POSIX_MONOTONIC_CLOCK-0 != 0)
+static const bool monotonicClockChecked = true;
+static const bool monotonicClockAvailable = _POSIX_MONOTONIC_CLOCK > 0;
+#else
+static int monotonicClockChecked = false;
+static int monotonicClockAvailable = false;
+#endif
+
+#ifdef Q_CC_GNU
+# define is_likely(x) __builtin_expect((x), 1)
+#else
+# define is_likely(x) (x)
+#endif
+#define load_acquire(x) ((volatile const int&)(x))
+#define store_release(x,v) ((volatile int&)(x) = (v))
+
+static void unixCheckClockType()
+{
+#if (_POSIX_MONOTONIC_CLOCK-0 == 0)
+ if (is_likely(load_acquire(monotonicClockChecked)))
+ return;
+
+# if defined(_SC_MONOTONIC_CLOCK)
+ // detect if the system support monotonic timers
+ long x = sysconf(_SC_MONOTONIC_CLOCK);
+ store_release(monotonicClockAvailable, x >= 200112L);
+# endif
+
+ store_release(monotonicClockChecked, true);
+#endif
+}
+
+static inline qint64 fractionAdjustment()
+{
+ // disabled, but otherwise indicates bad usage of QElapsedTimer
+ //Q_ASSERT(monotonicClockChecked);
+
+ if (monotonicClockAvailable) {
+ // the monotonic timer is measured in nanoseconds
+ // 1 ms = 1000000 ns
+ return 1000*1000ull;
+ } else {
+ // gettimeofday is measured in microseconds
+ // 1 ms = 1000 us
+ return 1000;
+ }
+}
+
+bool QElapsedTimer::isMonotonic()
+{
+ unixCheckClockType();
+ return monotonicClockAvailable;
+}
+
+QElapsedTimer::ClockType QElapsedTimer::clockType()
+{
+ unixCheckClockType();
+ return monotonicClockAvailable ? MonotonicClock : SystemTime;
+}
+
+static inline void do_gettime(qint64 *sec, qint64 *frac)
+{
+#if (_POSIX_MONOTONIC_CLOCK-0 >= 0)
+ unixCheckClockType();
+ if (is_likely(monotonicClockAvailable)) {
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ *sec = ts.tv_sec;
+ *frac = ts.tv_nsec;
+ return;
+ }
+#endif
+ // use gettimeofday
+ timeval tv;
+ ::gettimeofday(&tv, 0);
+ *sec = tv.tv_sec;
+ *frac = tv.tv_usec;
+}
+
+// used in qcore_unix.cpp and qeventdispatcher_unix.cpp
+timeval qt_gettime()
+{
+ qint64 sec, frac;
+ do_gettime(&sec, &frac);
+
+ timeval tv;
+ tv.tv_sec = sec;
+ tv.tv_usec = frac;
+ if (monotonicClockAvailable)
+ tv.tv_usec /= 1000;
+
+ return tv;
+}
+
+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(1000) + frac / fractionAdjustment();
+}
+
+void QElapsedTimer::start()
+{
+ do_gettime(&t1, &t2);
+}
+
+qint64 QElapsedTimer::restart()
+{
+ return elapsedAndRestart(t1, t2, &t1, &t2);
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const
+{
+ qint64 sec, frac;
+ do_gettime(&sec, &frac);
+ sec = sec - t1;
+ frac = frac - t2;
+ if (!monotonicClockAvailable)
+ frac *= 1000;
+ return sec * Q_INT64_C(1000000000) + frac;
+}
+
+qint64 QElapsedTimer::elapsed() const
+{
+ qint64 sec, frac;
+ return elapsedAndRestart(t1, t2, &sec, &frac);
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const
+{
+ return t1 * Q_INT64_C(1000) + t2 / fractionAdjustment();
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
+{
+ qint64 secs = other.t1 - t1;
+ qint64 fraction = other.t2 - t2;
+ return secs * Q_INT64_C(1000) + fraction / fractionAdjustment();
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
+{
+ return other.t1 - t1;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2)
+{
+ return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp
new file mode 100644
index 0000000000..b3210f18a2
--- /dev/null
+++ b/src/corelib/tools/qelapsedtimer_win.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include <windows.h>
+
+// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable
+static quint64 counterFrequency = 0;
+
+typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void);
+static PtrGetTickCount64 ptrGetTickCount64 = 0;
+
+QT_BEGIN_NAMESPACE
+
+static void resolveLibs()
+{
+ static bool done = false;
+ if (done)
+ return;
+
+ // try to get GetTickCount64 from the system
+ HMODULE kernel32 = GetModuleHandleW(L"kernel32");
+ if (!kernel32)
+ return;
+
+#if defined(Q_OS_WINCE)
+ // does this function exist on WinCE, or will ever exist?
+ ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, L"GetTickCount64");
+#else
+ ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, "GetTickCount64");
+#endif
+
+ // Retrieve the number of high-resolution performance counter ticks per second
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency)) {
+ counterFrequency = 0;
+ } else {
+ counterFrequency = frequency.QuadPart;
+ }
+
+ done = true;
+}
+
+static inline qint64 ticksToNanoseconds(qint64 ticks)
+{
+ if (counterFrequency > 0) {
+ // QueryPerformanceCounter uses an arbitrary frequency
+ return ticks * 1000000000 / counterFrequency;
+ } else {
+ // GetTickCount(64) return milliseconds
+ return ticks * 1000000;
+ }
+}
+
+static quint64 getTickCount()
+{
+ resolveLibs();
+
+ // This avoids a division by zero and disables the high performance counter if it's not available
+ if (counterFrequency > 0) {
+ LARGE_INTEGER counter;
+
+ if (QueryPerformanceCounter(&counter)) {
+ return counter.QuadPart;
+ } else {
+ qWarning("QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded.");
+ return 0;
+ }
+ }
+
+ if (ptrGetTickCount64)
+ return ptrGetTickCount64();
+
+ static quint32 highdword = 0;
+ static quint32 lastval = 0;
+ quint32 val = GetTickCount();
+ if (val < lastval)
+ ++highdword;
+ lastval = val;
+ return val | (quint64(highdword) << 32);
+}
+
+QElapsedTimer::ClockType QElapsedTimer::clockType()
+{
+ resolveLibs();
+
+ if (counterFrequency > 0)
+ return PerformanceCounter;
+ else
+ return TickCounter;
+}
+
+bool QElapsedTimer::isMonotonic()
+{
+ return true;
+}
+
+void QElapsedTimer::start()
+{
+ t1 = getTickCount();
+ t2 = 0;
+}
+
+qint64 QElapsedTimer::restart()
+{
+ qint64 oldt1 = t1;
+ t1 = getTickCount();
+ t2 = 0;
+ return ticksToNanoseconds(t1 - oldt1) / 1000000;
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const
+{
+ qint64 elapsed = getTickCount() - t1;
+ return ticksToNanoseconds(elapsed);
+}
+
+qint64 QElapsedTimer::elapsed() const
+{
+ qint64 elapsed = getTickCount() - t1;
+ return ticksToNanoseconds(elapsed) / 1000000;
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const
+{
+ return ticksToNanoseconds(t1) / 1000000;
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
+{
+ qint64 difference = other.t1 - t1;
+ return ticksToNanoseconds(difference) / 1000000;
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
+{
+ return msecsTo(other) / 1000;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2)
+{
+ return (v1.t1 - v2.t1) < 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp
new file mode 100644
index 0000000000..3d6b37df7d
--- /dev/null
+++ b/src/corelib/tools/qharfbuzz.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qunicodetables_p.h"
+#include "qlibrary.h"
+#include "qtextcodec.h"
+
+#include "qharfbuzz_p.h"
+
+QT_USE_NAMESPACE
+
+extern "C" {
+
+HB_GraphemeClass HB_GetGraphemeClass(HB_UChar32 ch)
+{
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch);
+ return (HB_GraphemeClass) prop->graphemeBreak;
+}
+
+HB_WordClass HB_GetWordClass(HB_UChar32 ch)
+{
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch);
+ return (HB_WordClass) prop->wordBreak;
+}
+
+HB_SentenceClass HB_GetSentenceClass(HB_UChar32 ch)
+{
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch);
+ return (HB_SentenceClass) prop->sentenceBreak;
+}
+
+HB_LineBreakClass HB_GetLineBreakClass(HB_UChar32 ch)
+{
+ return (HB_LineBreakClass)QUnicodeTables::lineBreakClass(ch);
+}
+
+
+void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme, HB_LineBreakClass *lineBreak)
+{
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch);
+ *grapheme = (HB_GraphemeClass) prop->graphemeBreak;
+ *lineBreak = (HB_LineBreakClass) prop->line_break_class;
+}
+
+void HB_GetUnicodeCharProperties(HB_UChar32 ch, HB_CharCategory *category, int *combiningClass)
+{
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch);
+ *category = (HB_CharCategory)prop->category;
+ *combiningClass = prop->combiningClass;
+}
+
+HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch)
+{
+ return (HB_CharCategory)QChar::category(ch);
+}
+
+int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch)
+{
+ return QChar::combiningClass(ch);
+}
+
+HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch)
+{
+ return QChar::mirroredChar(ch);
+}
+
+void *HB_Library_Resolve(const char *library, int version, const char *symbol)
+{
+#ifdef QT_NO_LIBRARY
+ return 0;
+#else
+ return QLibrary::resolve(QLatin1String(library), version, symbol);
+#endif
+}
+
+} // extern "C"
+
+QT_BEGIN_NAMESPACE
+
+HB_Bool qShapeItem(HB_ShaperItem *item)
+{
+ return HB_ShapeItem(item);
+}
+
+HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc)
+{
+ return HB_NewFace(font, tableFunc);
+}
+
+void qHBFreeFace(HB_Face face)
+{
+ HB_FreeFace(face);
+}
+
+void qGetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
+ const HB_ScriptItem *items, hb_uint32 numItems,
+ HB_CharAttributes *attributes)
+{
+ HB_GetCharAttributes(string, stringLength, items, numItems, attributes);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h
new file mode 100644
index 0000000000..a1b8320487
--- /dev/null
+++ b/src/corelib/tools/qharfbuzz_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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 QHARFBUZZ_P_H
+#define QHARFBUZZ_P_H
+
+#include <QtCore/qglobal.h>
+#include <harfbuzz-shaper.h>
+
+QT_BEGIN_NAMESPACE
+
+// temporary forward until all the textengine code has been moved to QtCore
+Q_CORE_EXPORT void qGetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
+ const HB_ScriptItem *items, hb_uint32 numItems,
+ HB_CharAttributes *attributes);
+
+Q_CORE_EXPORT HB_Bool qShapeItem(HB_ShaperItem *item);
+
+// ### temporary
+Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc);
+Q_CORE_EXPORT void qHBFreeFace(HB_Face);
+
+Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
new file mode 100644
index 0000000000..b6ba8b2367
--- /dev/null
+++ b/src/corelib/tools/qhash.cpp
@@ -0,0 +1,1914 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhash.h"
+
+#ifdef truncate
+#undef truncate
+#endif
+
+#include <qbitarray.h>
+#include <qstring.h>
+#include <stdlib.h>
+#ifdef QT_QHASH_DEBUG
+#include <qstring.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+
+// ### Qt 5: see tests/benchmarks/corelib/tools/qhash/qhash_string.cpp
+// Hashing of the whole string is a waste of cycles.
+
+/*
+ These functions are based on Peter J. Weinberger's hash function
+ (from the Dragon Book). The constant 24 in the original function
+ was replaced with 23 to produce fewer collisions on input such as
+ "a", "aa", "aaa", "aaaa", ...
+*/
+
+static uint hash(const uchar *p, int n)
+{
+ uint h = 0;
+
+ while (n--) {
+ h = (h << 4) + *p++;
+ h ^= (h & 0xf0000000) >> 23;
+ h &= 0x0fffffff;
+ }
+ return h;
+}
+
+static uint hash(const QChar *p, int n)
+{
+ uint h = 0;
+
+ while (n--) {
+ h = (h << 4) + (*p++).unicode();
+ h ^= (h & 0xf0000000) >> 23;
+ h &= 0x0fffffff;
+ }
+ return h;
+}
+
+uint qHash(const QByteArray &key)
+{
+ return hash(reinterpret_cast<const uchar *>(key.constData()), key.size());
+}
+
+uint qHash(const QString &key)
+{
+ return hash(key.unicode(), key.size());
+}
+
+uint qHash(const QStringRef &key)
+{
+ return hash(key.unicode(), key.size());
+}
+
+uint qHash(const QBitArray &bitArray)
+{
+ int m = bitArray.d.size() - 1;
+ uint result = hash(reinterpret_cast<const uchar *>(bitArray.d.constData()), qMax(0, m));
+
+ // 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();
+ if (n & 0x7)
+ result = ((result << 4) + bitArray.d.at(m)) & ((1 << n) - 1);
+ return result;
+}
+
+/*
+ The prime_deltas array is a table of selected prime values, even
+ though it doesn't look like one. The primes we are using are 1,
+ 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate
+ surrounding of a power of two.
+
+ The primeForNumBits() function returns the prime associated to a
+ power of two. For example, primeForNumBits(8) returns 257.
+*/
+
+static const uchar prime_deltas[] = {
+ 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
+ 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
+};
+
+static inline int primeForNumBits(int numBits)
+{
+ return (1 << numBits) + prime_deltas[numBits];
+}
+
+/*
+ Returns the smallest integer n such that
+ primeForNumBits(n) >= hint.
+*/
+static int countBits(int hint)
+{
+ int numBits = 0;
+ int bits = hint;
+
+ while (bits > 1) {
+ bits >>= 1;
+ numBits++;
+ }
+
+ if (numBits >= (int)sizeof(prime_deltas)) {
+ numBits = sizeof(prime_deltas) - 1;
+ } else if (primeForNumBits(numBits) < hint) {
+ ++numBits;
+ }
+ return numBits;
+}
+
+/*
+ A QHash has initially around pow(2, MinNumBits) buckets. For
+ example, if MinNumBits is 4, it has 17 buckets.
+*/
+const int MinNumBits = 4;
+
+QHashData QHashData::shared_null = {
+ 0, 0, Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, MinNumBits, 0, 0, true, false, 0
+};
+
+void *QHashData::allocateNode()
+{
+ return allocateNode(0);
+}
+
+void *QHashData::allocateNode(int nodeAlign)
+{
+ void *ptr = strictAlignment ? qMallocAligned(nodeSize, nodeAlign) : qMalloc(nodeSize);
+ Q_CHECK_PTR(ptr);
+ return ptr;
+}
+
+void QHashData::freeNode(void *node)
+{
+ if (strictAlignment)
+ qFreeAligned(node);
+ else
+ qFree(node);
+}
+
+QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize)
+{
+ return detach_helper2( node_duplicate, 0, nodeSize, 0 );
+}
+
+QHashData *QHashData::detach_helper2(void (*node_duplicate)(Node *, void *),
+ void (*node_delete)(Node *),
+ int nodeSize,
+ int nodeAlign)
+{
+ union {
+ QHashData *d;
+ Node *e;
+ };
+ d = new QHashData;
+ d->fakeNext = 0;
+ d->buckets = 0;
+ d->ref = 1;
+ d->size = size;
+ d->nodeSize = nodeSize;
+ d->userNumBits = userNumBits;
+ d->numBits = numBits;
+ d->numBuckets = numBuckets;
+ d->sharable = true;
+ d->strictAlignment = nodeAlign > 8;
+ d->reserved = 0;
+
+ if (numBuckets) {
+ QT_TRY {
+ d->buckets = new Node *[numBuckets];
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ d->numBuckets = 0;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
+
+ Node *this_e = reinterpret_cast<Node *>(this);
+ for (int i = 0; i < numBuckets; ++i) {
+ Node **nextNode = &d->buckets[i];
+ Node *oldNode = buckets[i];
+ while (oldNode != this_e) {
+ QT_TRY {
+ Node *dup = static_cast<Node *>(allocateNode(nodeAlign));
+
+ QT_TRY {
+ node_duplicate(oldNode, dup);
+ } QT_CATCH(...) {
+ freeNode( dup );
+ QT_RETHROW;
+ }
+
+ dup->h = oldNode->h;
+ *nextNode = dup;
+ nextNode = &dup->next;
+ oldNode = oldNode->next;
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ *nextNode = e;
+ d->numBuckets = i+1;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
+ }
+ *nextNode = e;
+ }
+ }
+ return d;
+}
+
+void QHashData::free_helper(void (*node_delete)(Node *))
+{
+ if (node_delete) {
+ Node *this_e = reinterpret_cast<Node *>(this);
+ Node **bucket = reinterpret_cast<Node **>(this->buckets);
+
+ int n = numBuckets;
+ while (n--) {
+ Node *cur = *bucket++;
+ while (cur != this_e) {
+ Node *next = cur->next;
+ node_delete(cur);
+ freeNode(cur);
+ cur = next;
+ }
+ }
+ }
+ delete [] buckets;
+ delete this;
+}
+
+QHashData::Node *QHashData::nextNode(Node *node)
+{
+ union {
+ Node *next;
+ Node *e;
+ QHashData *d;
+ };
+ next = node->next;
+ Q_ASSERT_X(next, "QHash", "Iterating beyond end()");
+ if (next->next)
+ return next;
+
+ int start = (node->h % d->numBuckets) + 1;
+ Node **bucket = d->buckets + start;
+ int n = d->numBuckets - start;
+ while (n--) {
+ if (*bucket != e)
+ return *bucket;
+ ++bucket;
+ }
+ return e;
+}
+
+QHashData::Node *QHashData::previousNode(Node *node)
+{
+ union {
+ Node *e;
+ QHashData *d;
+ };
+
+ e = node;
+ while (e->next)
+ e = e->next;
+
+ int start;
+ if (node == e)
+ start = d->numBuckets - 1;
+ else
+ start = node->h % d->numBuckets;
+
+ Node *sentinel = node;
+ Node **bucket = d->buckets + start;
+ while (start >= 0) {
+ if (*bucket != sentinel) {
+ Node *prev = *bucket;
+ while (prev->next != sentinel)
+ prev = prev->next;
+ return prev;
+ }
+
+ sentinel = e;
+ --bucket;
+ --start;
+ }
+ Q_ASSERT_X(start >= 0, "QHash", "Iterating backward beyond begin()");
+ return e;
+}
+
+/*
+ If hint is negative, -hint gives the approximate number of
+ buckets that should be used for the hash table. If hint is
+ nonnegative, (1 << hint) gives the approximate number
+ of buckets that should be used.
+*/
+void QHashData::rehash(int hint)
+{
+ if (hint < 0) {
+ hint = countBits(-hint);
+ if (hint < MinNumBits)
+ hint = MinNumBits;
+ userNumBits = hint;
+ while (primeForNumBits(hint) < (size >> 1))
+ ++hint;
+ } else if (hint < MinNumBits) {
+ hint = MinNumBits;
+ }
+
+ if (numBits != hint) {
+ Node *e = reinterpret_cast<Node *>(this);
+ Node **oldBuckets = buckets;
+ int oldNumBuckets = numBuckets;
+
+ int nb = primeForNumBits(hint);
+ buckets = new Node *[nb];
+ numBits = hint;
+ numBuckets = nb;
+ for (int i = 0; i < numBuckets; ++i)
+ buckets[i] = e;
+
+ for (int i = 0; i < oldNumBuckets; ++i) {
+ Node *firstNode = oldBuckets[i];
+ while (firstNode != e) {
+ uint h = firstNode->h;
+ Node *lastNode = firstNode;
+ while (lastNode->next != e && lastNode->next->h == h)
+ lastNode = lastNode->next;
+
+ Node *afterLastNode = lastNode->next;
+ Node **beforeFirstNode = &buckets[h % numBuckets];
+ while (*beforeFirstNode != e)
+ beforeFirstNode = &(*beforeFirstNode)->next;
+ lastNode->next = *beforeFirstNode;
+ *beforeFirstNode = firstNode;
+ firstNode = afterLastNode;
+ }
+ }
+ delete [] oldBuckets;
+ }
+}
+
+void QHashData::destroyAndFree()
+{
+ free_helper(0);
+}
+
+#ifdef QT_QHASH_DEBUG
+
+void QHashData::dump()
+{
+ qDebug("Hash data (ref = %d, size = %d, nodeSize = %d, userNumBits = %d, numBits = %d, numBuckets = %d)",
+ int(ref), size, nodeSize, userNumBits, numBits,
+ numBuckets);
+ qDebug(" %p (fakeNode = %p)", this, fakeNext);
+ for (int i = 0; i < numBuckets; ++i) {
+ QString line;
+ Node *n = buckets[i];
+ if (n != reinterpret_cast<Node *>(this)) {
+ line.sprintf("%d:", i);
+ while (n != reinterpret_cast<Node *>(this)) {
+ line += QString().sprintf(" -> [%p]", n);
+ if (!n) {
+ line += " (CORRUPT)";
+ break;
+ }
+ n = n->next;
+ }
+ qDebug(qPrintable(line));
+ }
+ }
+}
+
+void QHashData::checkSanity()
+{
+ if (fakeNext)
+ qFatal("Fake next isn't 0");
+
+ for (int i = 0; i < numBuckets; ++i) {
+ Node *n = buckets[i];
+ Node *p = n;
+ if (!n)
+ qFatal("%d: Bucket entry is 0", i);
+ if (n != reinterpret_cast<Node *>(this)) {
+ while (n != reinterpret_cast<Node *>(this)) {
+ if (!n->next)
+ qFatal("%d: Next of %p is 0, should be %p", i, n, this);
+ n = n->next;
+ }
+ }
+ }
+}
+#endif
+
+/*!
+ \fn uint qHash(const QPair<T1, T2> &key)
+ \since 4.3
+ \relates QHash
+
+ Returns the hash value for the \a key.
+
+ Types \c T1 and \c T2 must be supported by qHash().
+*/
+
+/*! \fn uint qHash(char key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(uchar key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(signed char key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(ushort key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(short key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(uint key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(int key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(ulong key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(long key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(quint64 key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(qint64 key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(QChar key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const QByteArray &key)
+ \fn uint qHash(const QBitArray &key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const QString &key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const T *key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*!
+ \class QHash
+ \brief The QHash class is a template class that provides a hash-table-based dictionary.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QHash\<Key, T\> is one of Qt's generic \l{container classes}. It
+ stores (key, value) pairs and provides very fast lookup of the
+ value associated with a key.
+
+ QHash provides very similar functionality to QMap. The
+ differences are:
+
+ \list
+ \i QHash provides faster lookups than QMap. (See \l{Algorithmic
+ Complexity} for details.)
+ \i When iterating over a QMap, the items are always sorted by
+ key. With QHash, the items are arbitrarily ordered.
+ \i The key type of a QMap must provide operator<(). The key
+ type of a QHash must provide operator==() and a global
+ hash function called qHash() (see the related non-member
+ functions).
+ \endlist
+
+ Here's an example QHash with QString keys and \c int values:
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 0
+
+ To insert a (key, value) pair into the hash, you can use operator[]():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 1
+
+ This inserts the following three (key, value) pairs into the
+ QHash: ("one", 1), ("three", 3), and ("seven", 7). Another way to
+ insert items into the hash is to use insert():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 2
+
+ To look up a value, use operator[]() or value():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 3
+
+ If there is no item with the specified key in the hash, these
+ functions return a \l{default-constructed value}.
+
+ If you want to check whether the hash contains a particular key,
+ use contains():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 5
+
+ In general, we recommend that you use contains() and value()
+ rather than operator[]() for looking up a key in a hash. The
+ reason is that operator[]() silently inserts an item into the
+ hash if no item exists with the same key (unless the hash is
+ const). For example, the following code snippet will create 1000
+ items in memory:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 6
+
+ To avoid this problem, replace \c hash[i] with \c hash.value(i)
+ in the code above.
+
+ If you want to navigate through all the (key, value) pairs stored
+ in a QHash, you can use an iterator. QHash provides both
+ \l{Java-style iterators} (QHashIterator and QMutableHashIterator)
+ and \l{STL-style iterators} (QHash::const_iterator and
+ QHash::iterator). Here's how to iterate over a QHash<QString,
+ int> using a Java-style iterator:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 7
+
+ Here's the same code, but using an STL-style iterator:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 8
+
+ QHash is unordered, so an iterator's sequence cannot be assumed
+ to be predictable. If ordering by key is required, use a QMap.
+
+ Normally, a QHash allows only one value per key. If you call
+ insert() with a key that already exists in the QHash, the
+ previous value is erased. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 9
+
+ However, you can store multiple values per key by using
+ insertMulti() instead of insert() (or using the convenience
+ subclass QMultiHash). 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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 10
+
+ The items that share the same key are available from most
+ recently to least recently inserted. A more efficient approach is
+ to call find() to get the iterator for the first item with a key
+ and iterate from there:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 11
+
+ If you only need to extract the values from a hash (not the keys),
+ you can also use \l{foreach}:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 12
+
+ Items can be removed from the hash in several ways. One way is to
+ call remove(); this will remove any item with the given key.
+ Another way is to use QMutableHashIterator::remove(). In addition,
+ you can clear the entire hash using clear().
+
+ QHash's key and value data types must be \l{assignable data
+ types}. You cannot, for example, store a QWidget as a value;
+ instead, store a QWidget *. In addition, QHash's key type must
+ provide operator==(), and there must also be a global qHash()
+ function that returns a hash value for an argument of the key's
+ type.
+
+ Here's a 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, QChar, QString, and QByteArray. For all of these, the \c
+ <QHash> header defines a qHash() function that computes an
+ adequate hash value. If you want to use other types as the key,
+ make sure that you provide operator==() and a qHash()
+ implementation.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 13
+
+ The qHash() 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
+ attempt to return different hash values for different keys to the
+ largest extent possible.
+
+ In the example above, we've relied on Qt's global qHash(const
+ QString &) to give us a hash value for the employee's name, and
+ XOR'ed this with the day they were born to help produce unique
+ hashes for people with the same name.
+
+ Internally, QHash uses a hash table to perform lookups. Unlike Qt
+ 3's \c QDict class, which needed to be initialized with a prime
+ number, QHash's hash table automatically grows and shrinks to
+ provide fast lookups without wasting too much memory. You can
+ still control the size of the hash table by calling reserve() if
+ you already know approximately how many items the QHash will
+ contain, but this isn't necessary to obtain good performance. You
+ can also call capacity() to retrieve the hash table's size.
+
+ \sa QHashIterator, QMutableHashIterator, QMap, QSet
+*/
+
+/*! \fn QHash::QHash()
+
+ Constructs an empty hash.
+
+ \sa clear()
+*/
+
+/*! \fn QHash::QHash(const QHash<Key, T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QHash is
+ \l{implicitly shared}. This makes returning a QHash 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 QHash::~QHash()
+
+ Destroys the hash. References to the values in the hash and all
+ iterators of this hash become invalid.
+*/
+
+/*! \fn QHash<Key, T> &QHash::operator=(const QHash<Key, T> &other)
+
+ Assigns \a other to this hash and returns a reference to this hash.
+*/
+
+/*! \fn void QHash::swap(QHash<Key, T> &other)
+ \since 4.8
+
+ Swaps hash \a other with this hash. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn void QMultiHash::swap(QMultiHash<Key, T> &other)
+ \since 4.8
+
+ Swaps hash \a other with this hash. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QHash::operator==(const QHash<Key, T> &other) const
+
+ Returns true if \a other is equal to this hash; otherwise returns
+ false.
+
+ Two hashes are considered equal if they contain the same (key,
+ value) pairs.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QHash::operator!=(const QHash<Key, T> &other) const
+
+ Returns true if \a other is not equal to this hash; otherwise
+ returns false.
+
+ Two hashes are considered equal if they contain the same (key,
+ value) pairs.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QHash::size() const
+
+ Returns the number of items in the hash.
+
+ \sa isEmpty(), count()
+*/
+
+/*! \fn bool QHash::isEmpty() const
+
+ Returns true if the hash contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn int QHash::capacity() const
+
+ Returns the number of buckets in the QHash's internal hash table.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QHash's memory usage. In general, you will rarely ever
+ need to call this function. If you want to know how many items are
+ in the hash, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QHash::reserve(int size)
+
+ Ensures that the QHash's internal hash table consists of at least
+ \a size buckets.
+
+ This function is useful for code that needs to build a huge hash
+ and wants to avoid repeated reallocation. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 14
+
+ Ideally, \a size should be slightly more than the maximum number
+ of items expected in the hash. \a size doesn't have to be prime,
+ because QHash will use a prime number internally anyway. If \a size
+ is an underestimate, the worst that will happen is that the QHash
+ will be a bit slower.
+
+ In general, you will rarely ever need to call this function.
+ QHash's internal hash table automatically shrinks or grows to
+ provide good performance without wasting too much memory.
+
+ \sa squeeze(), capacity()
+*/
+
+/*! \fn void QHash::squeeze()
+
+ Reduces the size of the QHash's internal hash table to save
+ memory.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QHash's memory usage. In general, you will rarely ever
+ need to call this function.
+
+ \sa reserve(), capacity()
+*/
+
+/*! \fn void QHash::detach()
+
+ \internal
+
+ Detaches this hash from any other hashes with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn bool QHash::isDetached() const
+
+ \internal
+
+ Returns true if the hash's internal data isn't shared with any
+ other hash object; otherwise returns false.
+
+ \sa detach()
+*/
+
+/*! \fn void QHash::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn bool QHash::isSharedWith(const QHash<Key, T> &other) const
+
+ \internal
+*/
+
+/*! \fn void QHash::clear()
+
+ Removes all items from the hash.
+
+ \sa remove()
+*/
+
+/*! \fn int QHash::remove(const Key &key)
+
+ Removes all the items that have the \a key from the hash.
+ Returns the number of items removed which is usually 1 but will
+ be 0 if the key isn't in the hash, or greater than 1 if
+ insertMulti() has been used with the \a key.
+
+ \sa clear(), take(), QMultiHash::remove()
+*/
+
+/*! \fn T QHash::take(const Key &key)
+
+ Removes the item with the \a key from the hash and returns
+ the value associated with it.
+
+ If the item does not exist in the hash, the function simply
+ returns a \l{default-constructed value}. If there are multiple
+ items for \a key in the hash, only the most recently inserted one
+ is removed.
+
+ If you don't use the return value, remove() is more efficient.
+
+ \sa remove()
+*/
+
+/*! \fn bool QHash::contains(const Key &key) const
+
+ Returns true if the hash contains an item with the \a key;
+ otherwise returns false.
+
+ \sa count(), QMultiHash::contains()
+*/
+
+/*! \fn const T QHash::value(const Key &key) const
+
+ Returns the value associated with the \a key.
+
+ If the hash contains no item with the \a key, the function
+ returns a \l{default-constructed value}. If there are multiple
+ items for the \a key in the hash, the value of the most recently
+ inserted one is returned.
+
+ \sa key(), values(), contains(), operator[]()
+*/
+
+/*! \fn const T QHash::value(const Key &key, const T &defaultValue) const
+ \overload
+
+ If the hash contains no item with the given \a key, the function returns
+ \a defaultValue.
+*/
+
+/*! \fn T &QHash::operator[](const Key &key)
+
+ Returns the value associated with the \a key as a modifiable
+ reference.
+
+ If the hash contains no item with the \a key, the function inserts
+ a \l{default-constructed value} into the hash with the \a key, and
+ returns a reference to it. If the hash contains multiple items
+ with the \a key, this function returns a reference to the most
+ recently inserted value.
+
+ \sa insert(), value()
+*/
+
+/*! \fn const T QHash::operator[](const Key &key) const
+
+ \overload
+
+ Same as value().
+*/
+
+/*! \fn QList<Key> QHash::uniqueKeys() const
+ \since 4.2
+
+ Returns a list containing all the keys in the map. 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 keys(), values()
+*/
+
+/*! \fn QList<Key> QHash::keys() const
+
+ Returns a list containing all the keys in the hash, in an
+ arbitrary order. Keys that occur multiple times in the hash
+ (because items were inserted with insertMulti(), or unite() was
+ used) also occur multiple times in the list.
+
+ To obtain a list of unique keys, where each key from the map only
+ occurs once, use uniqueKeys().
+
+ The order is guaranteed to be the same as that used by values().
+
+ \sa uniqueKeys(), values(), key()
+*/
+
+/*! \fn QList<Key> QHash::keys(const T &value) const
+
+ \overload
+
+ Returns a list containing all the keys associated with value \a
+ value, in an arbitrary order.
+
+ 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 QList<T> QHash::values() const
+
+ Returns a list containing all the values in the hash, in an
+ arbitrary order. If a key is associated multiple values, all of
+ its values will be in the list, and not just the most recently
+ inserted one.
+
+ The order is guaranteed to be the same as that used by keys().
+
+ \sa keys(), value()
+*/
+
+/*! \fn QList<T> QHash::values(const Key &key) const
+
+ \overload
+
+ Returns a list of all the values associated with the \a key,
+ from the most recently inserted to the least recently inserted.
+
+ \sa count(), insertMulti()
+*/
+
+/*! \fn Key QHash::key(const T &value) const
+
+ Returns the first key mapped to \a value.
+
+ If the hash contains no item with the \a value, the function
+ returns a \link {default-constructed value} default-constructed
+ key \endlink.
+
+ This function can be slow (\l{linear time}), because QHash's
+ internal data structure is optimized for fast lookup by key, not
+ by value.
+
+ \sa value(), keys()
+*/
+
+/*!
+ \fn Key QHash::key(const T &value, const Key &defaultKey) const
+ \since 4.3
+ \overload
+
+ Returns the first key mapped to \a value, or \a defaultKey if the
+ hash contains no item mapped to \a value.
+
+ 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 int QHash::count(const Key &key) const
+
+ Returns the number of items associated with the \a key.
+
+ \sa contains(), insertMulti()
+*/
+
+/*! \fn int QHash::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn QHash::iterator QHash::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the hash.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QHash::const_iterator QHash::begin() const
+
+ \overload
+*/
+
+/*! \fn QHash::const_iterator QHash::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the hash.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QHash::iterator QHash::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the hash.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QHash::const_iterator QHash::end() const
+
+ \overload
+*/
+
+/*! \fn QHash::const_iterator QHash::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the hash.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QHash::iterator QHash::erase(iterator pos)
+
+ Removes the (key, value) pair associated with the iterator \a pos
+ from the hash, and returns an iterator to the next item in the
+ hash.
+
+ Unlike remove() and take(), this function never causes QHash to
+ rehash its internal data structure. This means that it can safely
+ be called while iterating, and won't affect the order of items in
+ the hash. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 15
+
+ \sa remove(), take(), find()
+*/
+
+/*! \fn QHash::iterator QHash::find(const Key &key)
+
+ Returns an iterator pointing to the item with the \a key in the
+ hash.
+
+ If the hash contains no item with the \a key, the function
+ returns end().
+
+ If the hash contains multiple items with the \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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 16
+
+ \sa value(), values(), QMultiHash::find()
+*/
+
+/*! \fn QHash::const_iterator QHash::find(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn QHash::iterator QHash::constFind(const Key &key) const
+ \since 4.1
+
+ Returns an iterator pointing to the item with the \a key in the
+ hash.
+
+ If the hash contains no item with the \a key, the function
+ returns constEnd().
+
+ \sa find(), QMultiHash::constFind()
+*/
+
+/*! \fn QHash::iterator QHash::insert(const Key &key, const T &value)
+
+ Inserts a new item with the \a key and a value of \a value.
+
+ If there is already an item with the \a key, that item's value
+ is replaced with \a value.
+
+ If there are multiple items with the \a key, the most
+ recently inserted item's value is replaced with \a value.
+
+ \sa insertMulti()
+*/
+
+/*! \fn QHash::iterator QHash::insertMulti(const Key &key, const T &value)
+
+ Inserts a new item with the \a key and a value of \a value.
+
+ If there is already an item with the same key in the hash, this
+ function will simply create a new one. (This behavior is
+ different from insert(), which overwrites the value of an
+ existing item.)
+
+ \sa insert(), values()
+*/
+
+/*! \fn QHash<Key, T> &QHash::unite(const QHash<Key, T> &other)
+
+ Inserts all the items in the \a other hash into this hash. If a
+ key is common to both hashes, the resulting hash will contain the
+ key multiple times.
+
+ \sa insertMulti()
+*/
+
+/*! \fn bool QHash::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty(), returning true if the hash is empty; otherwise
+ returns false.
+*/
+
+/*! \typedef QHash::ConstIterator
+
+ Qt-style synonym for QHash::const_iterator.
+*/
+
+/*! \typedef QHash::Iterator
+
+ Qt-style synonym for QHash::iterator.
+*/
+
+/*! \typedef QHash::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QHash::key_type
+
+ Typedef for Key. Provided for STL compatibility.
+*/
+
+/*! \typedef QHash::mapped_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \typedef QHash::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*! \typedef QHash::iterator::difference_type
+ \internal
+*/
+
+/*! \typedef QHash::iterator::iterator_category
+ \internal
+*/
+
+/*! \typedef QHash::iterator::pointer
+ \internal
+*/
+
+/*! \typedef QHash::iterator::reference
+ \internal
+*/
+
+/*! \typedef QHash::iterator::value_type
+ \internal
+*/
+
+/*! \typedef QHash::const_iterator::difference_type
+ \internal
+*/
+
+/*! \typedef QHash::const_iterator::iterator_category
+ \internal
+*/
+
+/*! \typedef QHash::const_iterator::pointer
+ \internal
+*/
+
+/*! \typedef QHash::const_iterator::reference
+ \internal
+*/
+
+/*! \typedef QHash::const_iterator::value_type
+ \internal
+*/
+
+/*! \class QHash::iterator
+ \brief The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
+
+ 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 (or
+ QMultiHash) and to modify the value (but not the key) associated
+ with a particular key. If you want to iterate over a const QHash,
+ you should use QHash::const_iterator. It is generally good
+ practice to use QHash::const_iterator on a non-const QHash as
+ well, unless you need to change the QHash through the iterator.
+ Const iterators are slightly faster, and can improve code
+ readability.
+
+ The default QHash::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QHash function like
+ QHash::begin(), QHash::end(), or QHash::find() before you can
+ start iterating. Here's a typical loop that prints all the (key,
+ value) pairs stored in a hash:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 17
+
+ Unlike QMap, which orders its items by key, QHash stores its
+ items in an arbitrary order. The only guarantee is that items that
+ share the same key (because they were inserted using
+ QHash::insertMulti()) 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
+ 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 20
+
+ It might be tempting to write code like this:
+
+ \snippet doc/src/snippets/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 has
+ the potential of dramatically changing the order in which the
+ items are stored in the hash, as they might cause QHash to rehash
+ its internal data structure. There is one notable exception:
+ QHash::erase(). 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.
+
+ \sa QHash::const_iterator, QMutableHashIterator
+*/
+
+/*! \fn QHash::iterator::operator Node *() const
+
+ \internal
+*/
+
+/*! \fn QHash::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 QHash::begin() QHash::end()
+*/
+
+/*! \fn QHash::iterator::iterator(void *node)
+
+ \internal
+*/
+
+/*! \fn const Key &QHash::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 QHash::erase()
+ followed by QHash::insert() or QHash::insertMulti().
+
+ \sa value()
+*/
+
+/*! \fn T &QHash::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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 22
+
+ \sa key(), operator*()
+*/
+
+/*! \fn T &QHash::iterator::operator*() const
+
+ Returns a modifiable reference to the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn T *QHash::iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*!
+ \fn bool QHash::iterator::operator==(const iterator &other) const
+ \fn bool QHash::iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QHash::iterator::operator!=(const iterator &other) const
+ \fn bool QHash::iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QHash::iterator &QHash::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 QHash::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QHash::iterator QHash::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 previously
+ current item.
+*/
+
+/*!
+ \fn QHash::iterator &QHash::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 QHash::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QHash::iterator QHash::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 QHash::iterator QHash::iterator::operator+(int 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 QHash::iterator QHash::iterator::operator-(int 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 QHash::iterator &QHash::iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QHash::iterator &QHash::iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items. (If \a j is negative,
+ the iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \class QHash::const_iterator
+ \brief The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash.
+
+ 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 (or a QMultiHash). If you want to modify the QHash as you
+ iterate over it, you must use QHash::iterator instead. It is
+ generally good practice to use QHash::const_iterator on a
+ non-const QHash as well, unless you need to change the QHash
+ through the iterator. Const iterators are slightly faster, and
+ can improve code readability.
+
+ 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
+ loop that prints all the (key, value) pairs stored in a hash:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 23
+
+ Unlike QMap, which orders its items by key, QHash stores its
+ items in an arbitrary order. The only guarantee is that items that
+ share the same key (because they were inserted using
+ QHash::insertMulti()) will appear consecutively, from the most
+ 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 has the
+ potential of dramatically changing the order in which the items
+ are stored in the hash, as they might cause QHash to rehash its
+ internal data structure. If you need to keep iterators over a long
+ period of time, we recommend that you use QMap rather than QHash.
+
+ \sa QHash::iterator, QHashIterator
+*/
+
+/*! \fn QHash::const_iterator::operator Node *() const
+
+ \internal
+*/
+
+/*! \fn QHash::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 QHash::constBegin() QHash::constEnd()
+*/
+
+/*! \fn QHash::const_iterator::const_iterator(void *node)
+
+ \internal
+*/
+
+/*! \fn QHash::const_iterator::const_iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn const Key &QHash::const_iterator::key() const
+
+ Returns the current item's key.
+
+ \sa value()
+*/
+
+/*! \fn const T &QHash::const_iterator::value() const
+
+ Returns the current item's value.
+
+ \sa key(), operator*()
+*/
+
+/*! \fn const T &QHash::const_iterator::operator*() const
+
+ Returns the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn const T *QHash::const_iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*! \fn bool QHash::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QHash::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QHash::const_iterator &QHash::const_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 QHash::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QHash::const_iterator QHash::const_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 previously
+ current item.
+*/
+
+/*! \fn QHash::const_iterator &QHash::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 QHash::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn QHash::const_iterator QHash::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 QHash::const_iterator QHash::const_iterator::operator+(int 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 QHash::const_iterator QHash::const_iterator::operator-(int 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 QHash::const_iterator &QHash::const_iterator::operator+=(int 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 QHash::const_iterator &QHash::const_iterator::operator-=(int 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-()
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
+ \relates QHash
+
+ Writes the hash \a hash to stream \a out.
+
+ This function requires the key and value types to implement \c
+ operator<<().
+
+ \sa {Serializing Qt Data Types}
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash)
+ \relates QHash
+
+ Reads a hash from stream \a in into \a hash.
+
+ This function requires the key and value types to implement \c
+ operator>>().
+
+ \sa {Serializing Qt Data Types}
+*/
+
+/*! \class QMultiHash
+ \brief The QMultiHash class is a convenience QHash subclass that provides multi-valued hashes.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QMultiHash\<Key, T\> is one of Qt's generic \l{container classes}.
+ It inherits QHash and extends it with a few convenience functions
+ that make it more suitable than QHash for storing multi-valued
+ hashes. A multi-valued hash is a hash that allows multiple values
+ with the same key; QHash normally doesn't allow that, unless you
+ call QHash::insertMulti().
+
+ Because QMultiHash inherits QHash, all of QHash's functionality also
+ applies to QMultiHash. 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 in
+ addition, it provides an insert() function that corresponds to
+ QHash::insertMulti(), and a replace() function that corresponds to
+ QHash::insert(). It also provides convenient operator+() and
+ operator+=().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 24
+
+ Unlike QHash, QMultiHash 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 doc/src/snippets/code/src_corelib_tools_qhash.cpp 25
+
+ The items that share the same key are available from most
+ recently to least recently inserted.
+
+ A more efficient approach is to call find() to get
+ the STL-style iterator for the first item with a key and iterate from
+ there:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 26
+
+ QMultiHash's key and value data types must be \l{assignable data
+ types}. You cannot, for example, store a QWidget as a value;
+ instead, store a QWidget *. In addition, QMultiHash's key type
+ must provide operator==(), and there must also be a global
+ qHash() function that returns a hash value for an argument of the
+ key's type. See the QHash documentation for details.
+
+ \sa QHash, QHashIterator, QMutableHashIterator, QMultiMap
+*/
+
+/*! \fn QMultiHash::QMultiHash()
+
+ Constructs an empty hash.
+*/
+
+/*! \fn QMultiHash::QMultiHash(const QHash<Key, T> &other)
+
+ Constructs a copy of \a other (which can be a QHash or a
+ QMultiHash).
+
+ \sa operator=()
+*/
+
+/*! \fn QMultiHash::iterator QMultiHash::replace(const Key &key, const T &value)
+
+ Inserts a new item with the \a key and a value of \a value.
+
+ If there is already an item with the \a key, that item's value
+ is replaced with \a value.
+
+ If there are multiple items with the \a key, the most
+ recently inserted item's value is replaced with \a value.
+
+ \sa insert()
+*/
+
+/*! \fn QMultiHash::iterator QMultiHash::insert(const Key &key, const T &value)
+
+ Inserts a new item with the \a key and a value of \a value.
+
+ If there is already an item with the same key in the hash, 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 QMultiHash &QMultiHash::operator+=(const QMultiHash &other)
+
+ Inserts all the items in the \a other hash into this hash
+ and returns a reference to this hash.
+
+ \sa insert()
+*/
+
+/*! \fn QMultiHash QMultiHash::operator+(const QMultiHash &other) const
+
+ Returns a hash that contains all the items in this hash in
+ addition to all the items in \a other. If a key is common to both
+ hashes, the resulting hash will contain the key multiple times.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn bool QMultiHash::contains(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns true if the hash contains an item with the \a key and
+ \a value; otherwise returns false.
+
+ \sa QHash::contains()
+*/
+
+/*!
+ \fn bool QMultiHash::contains(const Key &key) const
+ \overload
+ \sa QHash::contains()
+*/
+
+/*!
+ \fn int QMultiHash::remove(const Key &key, const T &value)
+ \since 4.3
+
+ Removes all the items that have the \a key and the value \a
+ value from the hash. Returns the number of items removed.
+
+ \sa QHash::remove()
+*/
+
+/*!
+ \fn int QMultiHash::remove(const Key &key)
+ \overload
+ \sa QHash::remove()
+*/
+
+/*!
+ \fn int QMultiHash::count(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns the number of items with the \a key and \a value.
+
+ \sa QHash::count()
+*/
+
+/*!
+ \fn int QMultiHash::count(const Key &key) const
+ \overload
+ \sa QHash::count()
+*/
+
+/*!
+ \fn int QMultiHash::count() const
+ \overload
+ \sa QHash::count()
+*/
+
+/*!
+ \fn typename QHash<Key, T>::iterator QMultiHash::find(const Key &key, const T &value)
+ \since 4.3
+
+ Returns an iterator pointing to the item with the \a key and \a value.
+ If the hash contains no such item, the function returns end().
+
+ If the hash contains multiple items with the \a key and \a value, the
+ iterator returned points to the most recently inserted item.
+
+ \sa QHash::find()
+*/
+
+/*!
+ \fn typename QHash<Key, T>::iterator QMultiHash::find(const Key &key)
+ \overload
+ \sa QHash::find()
+*/
+
+/*!
+ \fn typename QHash<Key, T>::const_iterator QMultiHash::find(const Key &key, const T &value) const
+ \since 4.3
+ \overload
+*/
+
+/*!
+ \fn typename QHash<Key, T>::const_iterator QMultiHash::find(const Key &key) const
+ \overload
+ \sa QHash::find()
+*/
+
+/*!
+ \fn typename QHash<Key, T>::const_iterator QMultiHash::constFind(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns an iterator pointing to the item with the \a key and the
+ \a value in the hash.
+
+ If the hash contains no such item, the function returns
+ constEnd().
+
+ \sa QHash::constFind()
+*/
+
+/*!
+ \fn typename QHash<Key, T>::const_iterator QMultiHash::constFind(const Key &key) const
+ \overload
+ \sa QHash::constFind()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
new file mode 100644
index 0000000000..4982144ca5
--- /dev/null
+++ b/src/corelib/tools/qhash.h
@@ -0,0 +1,1043 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHASH_H
+#define QHASH_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qchar.h>
+#include <QtCore/qiterator.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QBitArray;
+class QByteArray;
+class QString;
+class QStringRef;
+
+inline uint qHash(char key) { return uint(key); }
+inline uint qHash(uchar key) { return uint(key); }
+inline uint qHash(signed char key) { return uint(key); }
+inline uint qHash(ushort key) { return uint(key); }
+inline uint qHash(short key) { return uint(key); }
+inline uint qHash(uint key) { return key; }
+inline uint qHash(int key) { return uint(key); }
+inline uint qHash(ulong key)
+{
+ if (sizeof(ulong) > sizeof(uint)) {
+ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U));
+ } else {
+ return uint(key & (~0U));
+ }
+}
+inline uint qHash(long key) { return qHash(ulong(key)); }
+inline uint qHash(quint64 key)
+{
+ if (sizeof(quint64) > sizeof(uint)) {
+ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U));
+ } else {
+ return uint(key & (~0U));
+ }
+}
+inline uint qHash(qint64 key) { return qHash(quint64(key)); }
+inline uint qHash(QChar key) { return qHash(key.unicode()); }
+Q_CORE_EXPORT uint qHash(const QByteArray &key);
+Q_CORE_EXPORT uint qHash(const QString &key);
+Q_CORE_EXPORT uint qHash(const QStringRef &key);
+Q_CORE_EXPORT uint qHash(const QBitArray &key);
+
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4311 ) // disable pointer truncation warning
+#endif
+template <class T> inline uint qHash(const T *key)
+{
+ return qHash(reinterpret_cast<quintptr>(key));
+}
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+
+template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key)
+{
+ uint h1 = qHash(key.first);
+ uint h2 = qHash(key.second);
+ return ((h1 << 16) | (h1 >> 16)) ^ h2;
+}
+
+struct Q_CORE_EXPORT QHashData
+{
+ struct Node {
+ Node *next;
+ uint h;
+ };
+
+ Node *fakeNext;
+ Node **buckets;
+ QBasicAtomicInt ref;
+ int size;
+ int nodeSize;
+ short userNumBits;
+ short numBits;
+ int numBuckets;
+ uint sharable : 1;
+ uint strictAlignment : 1;
+ uint reserved : 30;
+
+ void *allocateNode(); // ### Qt5 remove me
+ void *allocateNode(int nodeAlign);
+ void freeNode(void *node);
+ QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me
+ QHashData *detach_helper2(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *),
+ int nodeSize, int nodeAlign);
+ void mightGrow();
+ bool willGrow();
+ void hasShrunk();
+ void rehash(int hint);
+ void free_helper(void (*node_delete)(Node *));
+ void destroyAndFree(); // ### Qt5 remove me
+ Node *firstNode();
+#ifdef QT_QHASH_DEBUG
+ void dump();
+ void checkSanity();
+#endif
+ static Node *nextNode(Node *node);
+ static Node *previousNode(Node *node);
+
+ static QHashData shared_null;
+};
+
+inline void QHashData::mightGrow() // ### Qt 5: eliminate
+{
+ if (size >= numBuckets)
+ rehash(numBits + 1);
+}
+
+inline bool QHashData::willGrow()
+{
+ if (size >= numBuckets) {
+ rehash(numBits + 1);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+inline void QHashData::hasShrunk()
+{
+ if (size <= (numBuckets >> 3) && numBits > userNumBits) {
+ QT_TRY {
+ rehash(qMax(int(numBits) - 2, int(userNumBits)));
+ } QT_CATCH(const std::bad_alloc &) {
+ // ignore bad allocs - shrinking shouldn't throw. rehash is exception safe.
+ }
+ }
+}
+
+inline QHashData::Node *QHashData::firstNode()
+{
+ Node *e = reinterpret_cast<Node *>(this);
+ Node **bucket = buckets;
+ int n = numBuckets;
+ while (n--) {
+ if (*bucket != e)
+ return *bucket;
+ ++bucket;
+ }
+ return e;
+}
+
+struct QHashDummyValue
+{
+};
+
+inline bool operator==(const QHashDummyValue & /* v1 */, const QHashDummyValue & /* v2 */)
+{
+ return true;
+}
+
+Q_DECLARE_TYPEINFO(QHashDummyValue, Q_MOVABLE_TYPE | Q_DUMMY_TYPE);
+
+template <class Key, class T>
+struct QHashDummyNode
+{
+ QHashDummyNode *next;
+ uint h;
+ Key key;
+
+ inline QHashDummyNode(const Key &key0) : key(key0) {}
+};
+
+template <class Key, class T>
+struct QHashNode
+{
+ QHashNode *next;
+ uint h;
+ Key key;
+ T value;
+
+ inline QHashNode(const Key &key0) : key(key0) {} // ### remove in 5.0
+ inline QHashNode(const Key &key0, const T &value0) : key(key0), value(value0) {}
+ inline bool same_key(uint h0, const Key &key0) { return h0 == h && key0 == key; }
+};
+
+
+#define Q_HASH_DECLARE_INT_NODES(key_type) \
+ template <class T> \
+ struct QHashDummyNode<key_type, T> { \
+ QHashDummyNode *next; \
+ union { uint h; key_type key; }; \
+\
+ inline QHashDummyNode(key_type /* key0 */) {} \
+ }; \
+\
+ template <class T> \
+ struct QHashNode<key_type, T> { \
+ QHashNode *next; \
+ union { uint h; key_type key; }; \
+ T value; \
+\
+ inline QHashNode(key_type /* key0 */) {} \
+ inline QHashNode(key_type /* key0 */, const T &value0) : value(value0) {} \
+ inline bool same_key(uint h0, key_type) { return h0 == h; } \
+ }
+
+#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+Q_HASH_DECLARE_INT_NODES(short);
+Q_HASH_DECLARE_INT_NODES(ushort);
+#endif
+Q_HASH_DECLARE_INT_NODES(int);
+Q_HASH_DECLARE_INT_NODES(uint);
+#undef Q_HASH_DECLARE_INT_NODES
+
+template <class Key, class T>
+class QHash
+{
+ typedef QHashDummyNode<Key, T> DummyNode;
+ typedef QHashNode<Key, T> Node;
+
+ union {
+ QHashData *d;
+ QHashNode<Key, T> *e;
+ };
+
+ static inline Node *concrete(QHashData::Node *node) {
+ return reinterpret_cast<Node *>(node);
+ }
+
+#ifdef Q_ALIGNOF
+ static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
+ static inline int alignOfDummyNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(DummyNode)); }
+#else
+ static inline int alignOfNode() { return 0; }
+ static inline int alignOfDummyNode() { return 0; }
+#endif
+
+public:
+ inline QHash() : d(&QHashData::shared_null) { d->ref.ref(); }
+ inline QHash(const QHash<Key, T> &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); }
+ inline ~QHash() { if (!d->ref.deref()) freeData(d); }
+
+ QHash<Key, T> &operator=(const QHash<Key, T> &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QHash<Key, T> &operator=(QHash<Key, T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QHash<Key, T> &other) { qSwap(d, other.d); }
+
+ bool operator==(const QHash<Key, T> &other) const;
+ inline bool operator!=(const QHash<Key, T> &other) const { return !(*this == other); }
+
+ inline int size() const { return d->size; }
+
+ inline bool isEmpty() const { return d->size == 0; }
+
+ inline int capacity() const { return d->numBuckets; }
+ void reserve(int size);
+ inline void squeeze() { reserve(1); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+ inline bool isSharedWith(const QHash<Key, T> &other) const { return d == other.d; }
+
+ void clear();
+
+ int remove(const Key &key);
+ T take(const Key &key);
+
+ bool contains(const Key &key) const;
+ const Key key(const T &value) const;
+ const Key key(const T &value, const Key &defaultKey) const;
+ const T value(const Key &key) const;
+ const T value(const Key &key, const T &defaultValue) const;
+ T &operator[](const Key &key);
+ const T operator[](const Key &key) const;
+
+ QList<Key> uniqueKeys() const;
+ QList<Key> keys() const;
+ QList<Key> keys(const T &value) const;
+ QList<T> values() const;
+ QList<T> values(const Key &key) const;
+ int count(const Key &key) const;
+
+ class const_iterator;
+
+ class iterator
+ {
+ friend class const_iterator;
+ QHashData::Node *i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ // ### Qt 5: get rid of 'operator Node *'
+ inline operator Node *() const { return concrete(i); }
+ inline iterator() : i(0) { }
+ explicit inline iterator(void *node) : i(reinterpret_cast<QHashData::Node *>(node)) { }
+
+ inline const Key &key() const { return concrete(i)->key; }
+ inline T &value() const { return concrete(i)->value; }
+ inline T &operator*() const { return concrete(i)->value; }
+ inline T *operator->() const { return &concrete(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 = QHashData::nextNode(i);
+ return *this;
+ }
+ inline iterator operator++(int) {
+ iterator r = *this;
+ i = QHashData::nextNode(i);
+ return r;
+ }
+ inline iterator &operator--() {
+ i = QHashData::previousNode(i);
+ return *this;
+ }
+ inline iterator operator--(int) {
+ iterator r = *this;
+ i = QHashData::previousNode(i);
+ return r;
+ }
+ inline iterator operator+(int j) const
+ { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
+ inline iterator operator-(int j) const { return operator+(-j); }
+ inline iterator &operator+=(int j) { return *this = *this + j; }
+ inline iterator &operator-=(int j) { return *this = *this - j; }
+
+ // ### Qt 5: not sure this is necessary anymore
+#ifdef QT_STRICT_ITERATORS
+ private:
+#else
+ public:
+#endif
+ inline bool operator==(const const_iterator &o) const
+ { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const
+ { return i != o.i; }
+
+ private:
+ // ### Qt 5: remove
+ inline operator bool() const { return false; }
+ };
+ friend class iterator;
+
+ class const_iterator
+ {
+ friend class iterator;
+ QHashData::Node *i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ // ### Qt 5: get rid of 'operator Node *'
+ inline operator Node *() const { return concrete(i); }
+ inline const_iterator() : i(0) { }
+ explicit inline const_iterator(void *node)
+ : i(reinterpret_cast<QHashData::Node *>(node)) { }
+#ifdef QT_STRICT_ITERATORS
+ explicit inline const_iterator(const iterator &o)
+#else
+ inline const_iterator(const iterator &o)
+#endif
+ { i = o.i; }
+
+ inline const Key &key() const { return concrete(i)->key; }
+ inline const T &value() const { return concrete(i)->value; }
+ inline const T &operator*() const { return concrete(i)->value; }
+ inline const T *operator->() const { return &concrete(i)->value; }
+ 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 const_iterator &operator++() {
+ i = QHashData::nextNode(i);
+ return *this;
+ }
+ inline const_iterator operator++(int) {
+ const_iterator r = *this;
+ i = QHashData::nextNode(i);
+ return r;
+ }
+ inline const_iterator &operator--() {
+ i = QHashData::previousNode(i);
+ return *this;
+ }
+ inline const_iterator operator--(int) {
+ const_iterator r = *this;
+ i = QHashData::previousNode(i);
+ return r;
+ }
+ inline const_iterator operator+(int j) const
+ { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
+ inline const_iterator operator-(int j) const { return operator+(-j); }
+ inline const_iterator &operator+=(int j) { return *this = *this + j; }
+ inline const_iterator &operator-=(int j) { return *this = *this - j; }
+
+ // ### Qt 5: not sure this is necessary anymore
+#ifdef QT_STRICT_ITERATORS
+ private:
+ inline bool operator==(const iterator &o) const { return operator==(const_iterator(o)); }
+ inline bool operator!=(const iterator &o) const { return operator!=(const_iterator(o)); }
+#endif
+
+ private:
+ // ### Qt 5: remove
+ inline operator bool() const { return false; }
+ };
+ friend class const_iterator;
+
+ // STL style
+ inline iterator begin() { detach(); return iterator(d->firstNode()); }
+ inline const_iterator begin() const { return const_iterator(d->firstNode()); }
+ inline const_iterator constBegin() const { return const_iterator(d->firstNode()); }
+ inline iterator end() { detach(); return iterator(e); }
+ inline const_iterator end() const { return const_iterator(e); }
+ inline const_iterator constEnd() const { return const_iterator(e); }
+ iterator erase(iterator it);
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline int 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 insert(const Key &key, const T &value);
+ iterator insertMulti(const Key &key, const T &value);
+ QHash<Key, T> &unite(const QHash<Key, T> &other);
+
+ // STL compatibility
+ typedef T mapped_type;
+ typedef Key key_type;
+ typedef qptrdiff difference_type;
+ typedef int size_type;
+
+ inline bool empty() const { return isEmpty(); }
+
+#ifdef QT_QHASH_DEBUG
+ inline void dump() const { d->dump(); }
+ inline void checkSanity() const { d->checkSanity(); }
+#endif
+
+private:
+ void detach_helper();
+ void freeData(QHashData *d);
+ Node **findNode(const Key &key, uint *hp = 0) const;
+ Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
+ void deleteNode(Node *node);
+ static void deleteNode2(QHashData::Node *node);
+
+ static void duplicateNode(QHashData::Node *originalNode, void *newNode);
+};
+
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node)
+{
+ deleteNode2(reinterpret_cast<QHashData::Node*>(node));
+ d->freeNode(node);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node)
+{
+#ifdef Q_CC_BOR
+ concrete(node)->~QHashNode<Key, T>();
+#else
+ concrete(node)->~Node();
+#endif
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode)
+{
+ Node *concreteNode = concrete(node);
+ if (QTypeInfo<T>::isDummy) {
+ (void) new (newNode) DummyNode(concreteNode->key);
+ } else {
+ (void) new (newNode) Node(concreteNode->key, concreteNode->value);
+ }
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::Node *
+QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode)
+{
+ Node *node;
+
+ if (QTypeInfo<T>::isDummy) {
+ node = reinterpret_cast<Node *>(new (d->allocateNode(alignOfDummyNode())) DummyNode(akey));
+ } else {
+ node = new (d->allocateNode(alignOfNode())) Node(akey, avalue);
+ }
+
+ node->h = ah;
+ node->next = *anextNode;
+ *anextNode = node;
+ ++d->size;
+ return node;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash<Key, T> &other)
+{
+ QHash<Key, T> copy(other);
+ const_iterator it = copy.constEnd();
+ while (it != copy.constBegin()) {
+ --it;
+ insertMulti(it.key(), it.value());
+ }
+ return *this;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
+{
+ x->free_helper(deleteNode2);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
+{
+ *this = QHash<Key,T>();
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
+{
+ QHashData *x = d->detach_helper2(duplicateNode, deleteNode2,
+ QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node),
+ QTypeInfo<T>::isDummy ? alignOfDummyNode() : alignOfNode());
+ if (!d->ref.deref())
+ freeData(d);
+ d = x;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::operator=(const QHash<Key, T> &other)
+{
+ if (d != other.d) {
+ QHashData *o = other.d;
+ o->ref.ref();
+ if (!d->ref.deref())
+ freeData(d);
+ d = o;
+ if (!d->sharable)
+ detach_helper();
+ }
+ return *this;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey) const
+{
+ Node *node;
+ if (d->size == 0 || (node = *findNode(akey)) == e) {
+ return T();
+ } else {
+ return node->value;
+ }
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey, const T &adefaultValue) const
+{
+ Node *node;
+ if (d->size == 0 || (node = *findNode(akey)) == e) {
+ return adefaultValue;
+ } else {
+ return node->value;
+ }
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
+{
+ QList<Key> res;
+ res.reserve(size()); // May be too much, but assume short lifetime
+ const_iterator i = begin();
+ if (i != end()) {
+ for (;;) {
+ const Key &aKey = i.key();
+ res.append(aKey);
+ do {
+ if (++i == end())
+ goto break_out_of_outer_loop;
+ } while (aKey == i.key());
+ }
+ }
+break_out_of_outer_loop:
+ return res;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::keys() const
+{
+ QList<Key> res;
+ res.reserve(size());
+ const_iterator i = begin();
+ while (i != end()) {
+ res.append(i.key());
+ ++i;
+ }
+ return res;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QHash<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;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE const Key QHash<Key, T>::key(const T &avalue) const
+{
+ return key(avalue, Key());
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE const Key QHash<Key, T>::key(const T &avalue, const Key &defaultValue) const
+{
+ const_iterator i = begin();
+ while (i != end()) {
+ if (i.value() == avalue)
+ return i.key();
+ ++i;
+ }
+
+ return defaultValue;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
+{
+ QList<T> res;
+ res.reserve(size());
+ const_iterator i = begin();
+ while (i != end()) {
+ res.append(i.value());
+ ++i;
+ }
+ return res;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
+{
+ QList<T> res;
+ Node *node = *findNode(akey);
+ if (node != e) {
+ do {
+ res.append(node->value);
+ } while ((node = node->next) != e && node->key == akey);
+ }
+ return res;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
+{
+ int cnt = 0;
+ Node *node = *findNode(akey);
+ if (node != e) {
+ do {
+ ++cnt;
+ } while ((node = node->next) != e && node->key == akey);
+ }
+ return cnt;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const
+{
+ return value(akey);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE T &QHash<Key, T>::operator[](const Key &akey)
+{
+ detach();
+
+ uint h;
+ Node **node = findNode(akey, &h);
+ if (*node == e) {
+ if (d->willGrow())
+ node = findNode(akey, &h);
+ return createNode(h, akey, T(), node)->value;
+ }
+ return (*node)->value;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insert(const Key &akey,
+ const T &avalue)
+{
+ detach();
+
+ uint h;
+ Node **node = findNode(akey, &h);
+ if (*node == e) {
+ if (d->willGrow())
+ node = findNode(akey, &h);
+ return iterator(createNode(h, akey, avalue, node));
+ }
+
+ if (!QTypeInfo<T>::isDummy)
+ (*node)->value = avalue;
+ return iterator(*node);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insertMulti(const Key &akey,
+ const T &avalue)
+{
+ detach();
+ d->willGrow();
+
+ uint h;
+ Node **nextNode = findNode(akey, &h);
+ return iterator(createNode(h, akey, avalue, nextNode));
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::remove(const Key &akey)
+{
+ if (isEmpty()) // prevents detaching shared null
+ return 0;
+ detach();
+
+ int oldSize = d->size;
+ Node **node = findNode(akey);
+ if (*node != e) {
+ bool deleteNext = true;
+ do {
+ Node *next = (*node)->next;
+ deleteNext = (next != e && next->key == (*node)->key);
+ deleteNode(*node);
+ *node = next;
+ --d->size;
+ } while (deleteNext);
+ d->hasShrunk();
+ }
+ return oldSize - d->size;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE T QHash<Key, T>::take(const Key &akey)
+{
+ if (isEmpty()) // prevents detaching shared null
+ return T();
+ detach();
+
+ Node **node = findNode(akey);
+ if (*node != e) {
+ T t = (*node)->value;
+ Node *next = (*node)->next;
+ deleteNode(*node);
+ *node = next;
+ --d->size;
+ d->hasShrunk();
+ return t;
+ }
+ return T();
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::erase(iterator it)
+{
+ if (it == iterator(e))
+ return it;
+
+ iterator ret = it;
+ ++ret;
+
+ Node *node = it;
+ Node **node_ptr = reinterpret_cast<Node **>(&d->buckets[node->h % d->numBuckets]);
+ while (*node_ptr != node)
+ node_ptr = &(*node_ptr)->next;
+ *node_ptr = node->next;
+ deleteNode(node);
+ --d->size;
+ return ret;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::reserve(int asize)
+{
+ detach();
+ d->rehash(-qMax(asize, 1));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::const_iterator QHash<Key, T>::find(const Key &akey) const
+{
+ return const_iterator(*findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::const_iterator QHash<Key, T>::constFind(const Key &akey) const
+{
+ return const_iterator(*findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::find(const Key &akey)
+{
+ detach();
+ return iterator(*findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE bool QHash<Key, T>::contains(const Key &akey) const
+{
+ return *findNode(akey) != e;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey,
+ uint *ahp) const
+{
+ Node **node;
+ uint h = qHash(akey);
+
+ if (d->numBuckets) {
+ node = reinterpret_cast<Node **>(&d->buckets[h % d->numBuckets]);
+ Q_ASSERT(*node == e || (*node)->next);
+ while (*node != e && !(*node)->same_key(h, akey))
+ node = &(*node)->next;
+ } else {
+ node = const_cast<Node **>(reinterpret_cast<const Node * const *>(&e));
+ }
+ if (ahp)
+ *ahp = h;
+ return node;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash<Key, T> &other) const
+{
+ if (size() != other.size())
+ return false;
+ if (d == other.d)
+ return true;
+
+ const_iterator it = begin();
+
+ while (it != end()) {
+ const Key &akey = it.key();
+
+ const_iterator it2 = other.find(akey);
+ do {
+ if (it2 == other.end() || !(it2.key() == akey))
+ return false;
+ if (!QTypeInfo<T>::isDummy && !(it.value() == it2.value()))
+ return false;
+ ++it;
+ ++it2;
+ } while (it != end() && it.key() == akey);
+ }
+ return true;
+}
+
+template <class Key, class T>
+class QMultiHash : public QHash<Key, T>
+{
+public:
+ QMultiHash() {}
+ QMultiHash(const QHash<Key, T> &other) : QHash<Key, T>(other) {}
+ inline void swap(QMultiHash<Key, T> &other) { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps
+
+ inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value)
+ { return QHash<Key, T>::insert(key, value); }
+
+ inline typename QHash<Key, T>::iterator insert(const Key &key, const T &value)
+ { return QHash<Key, T>::insertMulti(key, value); }
+
+ inline QMultiHash &operator+=(const QMultiHash &other)
+ { this->unite(other); return *this; }
+ inline QMultiHash operator+(const QMultiHash &other) const
+ { QMultiHash result = *this; result += other; return result; }
+
+#if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
+ // RVCT compiler doesn't handle using-keyword right when used functions are overloaded in child class
+ using QHash<Key, T>::contains;
+ using QHash<Key, T>::remove;
+ using QHash<Key, T>::count;
+ using QHash<Key, T>::find;
+ using QHash<Key, T>::constFind;
+#else
+ inline bool contains(const Key &key) const
+ { return QHash<Key, T>::contains(key); }
+ inline int remove(const Key &key)
+ { return QHash<Key, T>::remove(key); }
+ inline int count(const Key &key) const
+ { return QHash<Key, T>::count(key); }
+ inline int count() const
+ { return QHash<Key, T>::count(); }
+ inline typename QHash<Key, T>::iterator find(const Key &key)
+ { return QHash<Key, T>::find(key); }
+ inline typename QHash<Key, T>::const_iterator find(const Key &key) const
+ { return QHash<Key, T>::find(key); }
+ inline typename QHash<Key, T>::const_iterator constFind(const Key &key) const
+ { return QHash<Key, T>::constFind(key); }
+#endif
+
+ bool contains(const Key &key, const T &value) const;
+
+ int remove(const Key &key, const T &value);
+
+ int count(const Key &key, const T &value) const;
+
+ typename QHash<Key, T>::iterator find(const Key &key, const T &value) {
+ typename QHash<Key, T>::iterator i(find(key));
+ typename QHash<Key, T>::iterator end(this->end());
+ while (i != end && i.key() == key) {
+ if (i.value() == value)
+ return i;
+ ++i;
+ }
+ return end;
+ }
+ typename QHash<Key, T>::const_iterator find(const Key &key, const T &value) const {
+ typename QHash<Key, T>::const_iterator i(constFind(key));
+ typename QHash<Key, T>::const_iterator end(QHash<Key, T>::constEnd());
+ while (i != end && i.key() == key) {
+ if (i.value() == value)
+ return i;
+ ++i;
+ }
+ return end;
+ }
+ typename QHash<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_INLINE_TEMPLATE bool QMultiHash<Key, T>::contains(const Key &key, const T &value) const
+{
+ return constFind(key, value) != QHash<Key, T>::constEnd();
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE int QMultiHash<Key, T>::remove(const Key &key, const T &value)
+{
+ int n = 0;
+ typename QHash<Key, T>::iterator i(find(key));
+ typename QHash<Key, T>::iterator end(QHash<Key, T>::end());
+ while (i != end && i.key() == key) {
+ if (i.value() == value) {
+ i = this->erase(i);
+ ++n;
+ } else {
+ ++i;
+ }
+ }
+ return n;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value) const
+{
+ int n = 0;
+ typename QHash<Key, T>::const_iterator i(constFind(key));
+ typename QHash<Key, T>::const_iterator end(QHash<Key, T>::constEnd());
+ while (i != end && i.key() == key) {
+ if (i.value() == value)
+ ++n;
+ ++i;
+ }
+ return n;
+}
+
+Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHASH_H
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
new file mode 100644
index 0000000000..2f7e1b14b7
--- /dev/null
+++ b/src/corelib/tools/qiterator.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QITERATOR_H
+#define QITERATOR_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+namespace std {
+ struct bidirectional_iterator_tag;
+ struct random_access_iterator_tag;
+}
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#define Q_DECLARE_SEQUENTIAL_ITERATOR(C) \
+\
+template <class T> \
+class Q##C##Iterator \
+{ \
+ typedef typename Q##C<T>::const_iterator const_iterator; \
+ Q##C<T> c; \
+ const_iterator i; \
+public: \
+ inline Q##C##Iterator(const Q##C<T> &container) \
+ : c(container), i(c.constBegin()) {} \
+ inline Q##C##Iterator &operator=(const Q##C<T> &container) \
+ { c = container; i = c.constBegin(); return *this; } \
+ inline void toFront() { i = c.constBegin(); } \
+ inline void toBack() { i = c.constEnd(); } \
+ inline bool hasNext() const { return i != c.constEnd(); } \
+ inline const T &next() { return *i++; } \
+ inline const T &peekNext() const { return *i; } \
+ inline bool hasPrevious() const { return i != c.constBegin(); } \
+ inline const T &previous() { return *--i; } \
+ 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; } \
+ inline bool findPrevious(const T &t) \
+ { while (i != c.constBegin()) if (*(--i) == t) return true; \
+ return false; } \
+};
+
+#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C) \
+\
+template <class T> \
+class QMutable##C##Iterator \
+{ \
+ typedef typename Q##C<T>::iterator iterator; \
+ typedef typename Q##C<T>::const_iterator const_iterator; \
+ Q##C<T> *c; \
+ iterator i, n; \
+ inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
+public: \
+ inline QMutable##C##Iterator(Q##C<T> &container) \
+ : c(&container) \
+ { c->setSharable(false); i = c->begin(); n = c->end(); } \
+ inline ~QMutable##C##Iterator() \
+ { c->setSharable(true); } \
+ inline QMutable##C##Iterator &operator=(Q##C<T> &container) \
+ { c->setSharable(true); c = &container; c->setSharable(false); \
+ i = c->begin(); n = c->end(); return *this; } \
+ inline void toFront() { i = c->begin(); n = c->end(); } \
+ inline void toBack() { i = c->end(); n = i; } \
+ inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
+ inline T &next() { n = i++; return *n; } \
+ inline T &peekNext() const { return *i; } \
+ inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \
+ inline T &previous() { n = --i; return *n; } \
+ 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(); } } \
+ inline void setValue(const T &t) const { if (c->constEnd() != const_iterator(n)) *n = t; } \
+ inline T &value() { Q_ASSERT(item_exists()); return *n; } \
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
+ 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; } \
+ inline bool findPrevious(const T &t) \
+ { while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \
+ n = c->end(); return false; } \
+};
+
+#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C) \
+\
+template <class Key, class T> \
+class Q##C##Iterator \
+{ \
+ typedef typename Q##C<Key,T>::const_iterator const_iterator; \
+ typedef const_iterator Item; \
+ Q##C<Key,T> c; \
+ const_iterator i, n; \
+ inline bool item_exists() const { return n != c.constEnd(); } \
+public: \
+ 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 bool hasPrevious() const { return i != c.constBegin(); } \
+ inline Item previous() { n = --i; return n; } \
+ 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; } \
+ inline bool findPrevious(const T &t) \
+ { while (i != c.constBegin()) if (*(n = --i) == t) return true; \
+ n = c.constEnd(); return false; } \
+};
+
+#define Q_DECLARE_MUTABLE_ASSOCIATIVE_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; \
+ typedef iterator Item; \
+ Q##C<Key,T> *c; \
+ iterator i, n; \
+ inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
+public: \
+ inline QMutable##C##Iterator(Q##C<Key,T> &container) \
+ : c(&container) \
+ { c->setSharable(false); i = c->begin(); n = c->end(); } \
+ inline ~QMutable##C##Iterator() \
+ { c->setSharable(true); } \
+ inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
+ { c->setSharable(true); c = &container; c->setSharable(false); 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 bool hasPrevious() const { return const_iterator(i) != c->constBegin(); } \
+ inline Item previous() { n = --i; return n; } \
+ 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(); } } \
+ 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; } \
+ inline bool findPrevious(const T &t) \
+ { while (const_iterator(i) != c->constBegin()) if (*(n = --i) == t) return true; \
+ n = c->end(); return false; } \
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QITERATOR_H
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
new file mode 100644
index 0000000000..6830442d63
--- /dev/null
+++ b/src/corelib/tools/qiterator.qdoc
@@ -0,0 +1,1417 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QListIterator
+ \inmodule QtCore
+
+ \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.
+
+ An alternative to using iterators is to use index positions. Most
+ QList member functions take an index as their first parameter,
+ making it possible to access, modify, and remove items without
+ using iterators.
+
+ QListIterator\<T\> allows you to iterate over a QList\<T\> (or a
+ QQueue\<T\>). If you want to modify the list as you iterate over
+ it, use QMutableListIterator\<T\> instead.
+
+ The QListIterator constructor takes a QList as argument. After
+ construction, the iterator is located at the very beginning of
+ the list (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 0
+
+ The next() function returns the next item in the list and
+ advances the iterator. 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 returns the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 1
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same list. If the list is
+ modified while a QListIterator is active, the QListIterator will
+ continue iterating over the original list, ignoring the modified
+ copy.
+
+ \sa QMutableListIterator, QList::const_iterator
+*/
+
+/*!
+ \class QLinkedListIterator
+ \inmodule QtCore
+
+ \brief The QLinkedListIterator class provides a Java-style const iterator for QLinkedList.
+
+ QLinkedList 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.
+
+ QLinkedListIterator\<T\> allows you to iterate over a
+ QLinkedList\<T\>. If you want to modify the list as you iterate
+ over it, use QMutableLinkedListIterator\<T\> instead.
+
+ The QLinkedListIterator constructor takes a QLinkedList as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 2
+
+ The next() function returns the next item in the list and
+ advances the iterator. 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 returns the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 3
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same list. If the list is
+ modified while a QLinkedListIterator is active, the
+ QLinkedListIterator will continue iterating over the original
+ list, ignoring the modified copy.
+
+ \sa QMutableLinkedListIterator, QLinkedList::const_iterator
+*/
+
+/*!
+ \class QVectorIterator
+ \inmodule QtCore
+ \brief The QVectorIterator class provides a Java-style const iterator for QVector and QStack.
+
+ QVector 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.
+
+ An alternative to using iterators is to use index positions. Most
+ QVector member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QVectorIterator\<T\> allows you to iterate over a QVector\<T\>
+ (or a QStack\<T\>). If you want to modify the vector as you
+ iterate over it, use QMutableVectorIterator\<T\> instead.
+
+ The QVectorIterator constructor takes a QVector as argument.
+ After construction, the iterator is located at the very beginning
+ of the vector (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 4
+
+ The next() function returns the next item in the vector and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 5
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same vector. If the vector
+ is modified while a QVectorIterator is active, the QVectorIterator
+ will continue iterating over the original vector, ignoring the
+ modified copy.
+
+ \sa QMutableVectorIterator, QVector::const_iterator
+*/
+
+/*!
+ \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.
+
+ QSetIterator\<T\> allows you to iterate over a QSet\<T\>. If you
+ want to modify the set as you iterate over it, use
+ QMutableSetIterator\<T\> instead.
+
+ The constructor takes a QSet as argument. After construction, the
+ iterator is located at the very beginning of the set (before
+ the first item). Here's how to iterate over all the elements
+ sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 6
+
+ The next() function returns the next item in the set and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 7
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same set. If the set
+ is modified while a QSetIterator is active, the QSetIterator
+ will continue iterating over the original set, ignoring the
+ modified copy.
+
+ \sa QMutableSetIterator, QSet::const_iterator
+*/
+
+/*!
+ \class QMutableListIterator
+ \inmodule QtCore
+
+ \brief The QMutableListIterator class provides a Java-style non-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.
+
+ An alternative to using iterators is to use index positions. Most
+ QList member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QMutableListIterator\<T\> allows you to iterate over a QList\<T\>
+ (or a QQueue\<T\>) and modify the list. If you don't want to
+ modify the list (or have a const QList), use the slightly faster
+ QListIterator\<T\> instead.
+
+ The QMutableListIterator constructor takes a QList as argument.
+ After construction, the iterator is located at the very beginning
+ of the list (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 8
+
+ The next() function returns the next item in the list and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 9
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the list, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the list, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 10
+
+ The example traverses a list, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given list at any
+ time. Furthermore, no changes should be done directly to the list
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QListIterator, QList::iterator
+*/
+
+/*!
+ \class QMutableLinkedListIterator
+ \inmodule QtCore
+
+ \brief The QMutableLinkedListIterator class provides a Java-style non-const iterator for QLinkedList.
+
+ QLinkedList 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.
+
+ QMutableLinkedListIterator\<T\> allows you to iterate over a
+ QLinkedList\<T\> and modify the list. If you don't want to modify
+ the list (or have a const QLinkedList), use the slightly faster
+ QLinkedListIterator\<T\> instead.
+
+ The QMutableLinkedListIterator constructor takes a QLinkedList as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 11
+
+ The next() function returns the next item in the list and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 12
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the list, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the list, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 13
+
+ The example traverses a list, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given list at any
+ time. Furthermore, no changes should be done directly to the list
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QLinkedListIterator, QLinkedList::iterator
+*/
+
+/*!
+ \class QMutableVectorIterator
+ \inmodule QtCore
+
+ \brief The QMutableVectorIterator class provides a Java-style non-const iterator for QVector and QStack.
+
+ QVector 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.
+
+ An alternative to using iterators is to use index positions. Most
+ QVector member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QMutableVectorIterator\<T\> allows you to iterate over a
+ QVector\<T\> and modify the vector. If you don't want to modify
+ the vector (or have a const QVector), use the slightly faster
+ QVectorIterator\<T\> instead.
+
+ The QMutableVectorIterator constructor takes a QVector as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 14
+
+ The next() function returns the next item in the vector and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 15
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the vector, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the vector, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 16
+
+ The example traverses a vector, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given vector at any
+ time. Furthermore, no changes should be done directly to the
+ vector while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QVectorIterator, QVector::iterator
+*/
+
+/*!
+ \class QMutableSetIterator
+ \inmodule QtCore
+ \since 4.2
+
+ \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.
+
+ QMutableSetIterator\<T\> allows you to iterate over a QSet\<T\>
+ and remove items from the set as you iterate. If you don't want
+ to modify the set (or have a const QSet), use the slightly faster
+ QSetIterator\<T\> instead.
+
+ The QMutableSetIterator constructor takes a QSet as argument.
+ After construction, the iterator is located at the very beginning
+ of the set (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 17
+
+ The next() function returns the next item in the set and
+ advances the iterator. 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, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 18
+
+ If you want to remove items as you iterate over the set, use
+ remove().
+
+ Only one mutable iterator can be active on a given set at any
+ time. Furthermore, no changes should be done directly to the set
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QSetIterator, QSet::iterator
+*/
+
+/*!
+ \fn QListIterator::QListIterator(const QList<T> &list)
+ \fn QLinkedListIterator::QLinkedListIterator(const QLinkedList<T> &list)
+ \fn QMutableListIterator::QMutableListIterator(QList<T> &list)
+ \fn QMutableLinkedListIterator::QMutableLinkedListIterator(QLinkedList<T> &list)
+
+ Constructs an iterator for traversing \a list. The iterator is
+ set to be at the front of the list (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QVectorIterator::QVectorIterator(const QVector<T> &vector)
+ \fn QMutableVectorIterator::QMutableVectorIterator(QVector<T> &vector)
+
+ Constructs an iterator for traversing \a vector. The iterator is
+ set to be at the front of the vector (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QSetIterator::QSetIterator(const QSet<T> &set)
+ \fn QMutableSetIterator::QMutableSetIterator(QSet<T> &set)
+
+ Constructs an iterator for traversing \a set. The iterator is
+ set to be at the front of the set (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QMutableListIterator::~QMutableListIterator()
+ \fn QMutableLinkedListIterator::~QMutableLinkedListIterator()
+ \fn QMutableVectorIterator::~QMutableVectorIterator()
+ \fn QMutableSetIterator::~QMutableSetIterator()
+
+ Destroys the iterator.
+
+ \sa operator=()
+*/
+
+/*! \fn QMutableListIterator &QMutableListIterator::operator=(QList<T> &list)
+ \fn QMutableLinkedListIterator &QMutableLinkedListIterator::operator=(QLinkedList<T> &list)
+ \fn QListIterator &QListIterator::operator=(const QList<T> &list)
+ \fn QLinkedListIterator &QLinkedListIterator::operator=(const QLinkedList<T> &list)
+
+ Makes the iterator operate on \a list. The iterator is set to be
+ at the front of the list (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QVectorIterator &QVectorIterator::operator=(const QVector<T> &vector)
+ \fn QMutableVectorIterator &QMutableVectorIterator::operator=(QVector<T> &vector)
+
+ Makes the iterator operate on \a vector. The iterator is set to be
+ at the front of the vector (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QSetIterator &QSetIterator::operator=(const QSet<T> &set)
+ \fn QMutableSetIterator &QMutableSetIterator::operator=(QSet<T> &set)
+
+ Makes the iterator operate on \a set. The iterator is set to be
+ at the front of the set (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QListIterator::toFront()
+ \fn void QLinkedListIterator::toFront()
+ \fn void QVectorIterator::toFront()
+ \fn void QSetIterator::toFront()
+ \fn void QMutableListIterator::toFront()
+ \fn void QMutableLinkedListIterator::toFront()
+ \fn void QMutableVectorIterator::toFront()
+ \fn void QMutableSetIterator::toFront()
+
+ Moves the iterator to the front of the container (before the
+ first item).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QListIterator::toBack()
+ \fn void QLinkedListIterator::toBack()
+ \fn void QVectorIterator::toBack()
+ \fn void QSetIterator::toBack()
+ \fn void QMutableListIterator::toBack()
+ \fn void QMutableLinkedListIterator::toBack()
+ \fn void QMutableVectorIterator::toBack()
+ \fn void QMutableSetIterator::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QListIterator::hasNext() const
+ \fn bool QLinkedListIterator::hasNext() const
+ \fn bool QVectorIterator::hasNext() const
+ \fn bool QSetIterator::hasNext() const
+ \fn bool QMutableListIterator::hasNext() const
+ \fn bool QMutableLinkedListIterator::hasNext() const
+ \fn bool QMutableVectorIterator::hasNext() const
+ \fn bool QMutableSetIterator::hasNext() const
+
+ Returns 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 false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn const T &QListIterator::next()
+ \fn const T &QLinkedListIterator::next()
+ \fn const T &QVectorIterator::next()
+ \fn const T &QSetIterator::next()
+ \fn const T &QMutableSetIterator::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(), previous()
+*/
+
+/*! \fn T &QMutableListIterator::next()
+ \fn T &QMutableLinkedListIterator::next()
+ \fn T &QMutableVectorIterator::next()
+
+ Returns a reference to 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(), previous()
+*/
+
+/*! \fn const T &QListIterator::peekNext() const
+ \fn const T &QLinkedListIterator::peekNext() const
+ \fn const T &QVectorIterator::peekNext() const
+ \fn const T &QSetIterator::peekNext() const
+ \fn const T &QMutableSetIterator::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()
+*/
+
+/*! \fn T &QMutableListIterator::peekNext() const
+ \fn T &QMutableLinkedListIterator::peekNext() const
+ \fn T &QMutableVectorIterator::peekNext() const
+
+ Returns a reference to 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()
+*/
+
+/*! \fn bool QListIterator::hasPrevious() const
+ \fn bool QLinkedListIterator::hasPrevious() const
+ \fn bool QVectorIterator::hasPrevious() const
+ \fn bool QSetIterator::hasPrevious() const
+ \fn bool QMutableListIterator::hasPrevious() const
+ \fn bool QMutableLinkedListIterator::hasPrevious() const
+ \fn bool QMutableVectorIterator::hasPrevious() const
+ \fn bool QMutableSetIterator::hasPrevious() const
+
+ Returns 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 false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn const T &QListIterator::previous()
+ \fn const T &QLinkedListIterator::previous()
+ \fn const T &QVectorIterator::previous()
+ \fn const T &QSetIterator::previous()
+ \fn const T &QMutableSetIterator::previous()
+
+ 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 T &QMutableListIterator::previous()
+ \fn T &QMutableLinkedListIterator::previous()
+ \fn T &QMutableVectorIterator::previous()
+
+ Returns a reference to 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 const T &QListIterator::peekPrevious() const
+ \fn const T &QLinkedListIterator::peekPrevious() const
+ \fn const T &QVectorIterator::peekPrevious() const
+ \fn const T &QSetIterator::peekPrevious() const
+ \fn const T &QMutableSetIterator::peekPrevious() const
+
+ 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 T &QMutableListIterator::peekPrevious() const
+ \fn T &QMutableLinkedListIterator::peekPrevious() const
+ \fn T &QMutableVectorIterator::peekPrevious() const
+
+ Returns a reference to 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 bool QListIterator::findNext(const T &value)
+ \fn bool QLinkedListIterator::findNext(const T &value)
+ \fn bool QVectorIterator::findNext(const T &value)
+ \fn bool QSetIterator::findNext(const T &value)
+ \fn bool QMutableListIterator::findNext(const T &value)
+ \fn bool QMutableLinkedListIterator::findNext(const T &value)
+ \fn bool QMutableVectorIterator::findNext(const T &value)
+ \fn bool QMutableSetIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ forward. Returns true if \a value is found; otherwise returns 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.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QListIterator::findPrevious(const T &value)
+ \fn bool QLinkedListIterator::findPrevious(const T &value)
+ \fn bool QVectorIterator::findPrevious(const T &value)
+ \fn bool QSetIterator::findPrevious(const T &value)
+ \fn bool QMutableListIterator::findPrevious(const T &value)
+ \fn bool QMutableLinkedListIterator::findPrevious(const T &value)
+ \fn bool QMutableVectorIterator::findPrevious(const T &value)
+ \fn bool QMutableSetIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if \a value is found; otherwise returns
+ false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just before the matching item; otherwise, the iterator is
+ positioned at the front of the container.
+
+ \sa findNext()
+*/
+
+/*! \fn void QMutableListIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 19
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableLinkedListIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 20
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableVectorIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 21
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableSetIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 22
+
+ \sa value()
+*/
+
+/*! \fn void QMutableListIterator::setValue(const T &value) const
+
+ 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(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 23
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn void QMutableLinkedListIterator::setValue(const T &value) const
+
+ 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(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 24
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn void QMutableVectorIterator::setValue(const T &value) const
+
+ 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(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 25
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn const T &QMutableListIterator::value() const
+ \fn const T &QMutableLinkedListIterator::value() const
+ \fn const T &QMutableVectorIterator::value() const
+ \fn const T &QMutableSetIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is equivalent to
+ peekPrevious(). After a call to previous() or findPrevious(), value() is
+ equivalent to peekNext().
+*/
+
+/*!
+ \fn T &QMutableListIterator::value()
+ \fn T &QMutableLinkedListIterator::value()
+ \fn T &QMutableVectorIterator::value()
+ \overload
+
+ Returns a non-const reference to the value of the last item that
+ was jumped over using one of the traversal functions.
+*/
+
+/*! \fn void QMutableListIterator::insert(const T &value)
+ \fn void QMutableLinkedListIterator::insert(const T &value)
+ \fn void QMutableVectorIterator::insert(const T &value)
+
+ Inserts \a value at the current iterator position. After the
+ call, the iterator is located just after the inserted item.
+
+ \sa remove(), setValue()
+*/
+
+/*!
+ \class QMapIterator
+ \inmodule QtCore
+
+ \brief The QMapIterator class provides a Java-style const iterator for QMap and QMultiMap.
+
+ 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.
+
+ QMapIterator\<Key, T\> allows you to iterate over a QMap (or a
+ QMultiMap). If you want to modify the map as you iterate over
+ it, use QMutableMapIterator instead.
+
+ The QMapIterator constructor takes a QMap 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 doc/src/snippets/code/doc_src_qiterator.cpp 26
+
+ 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.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 27
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 28
+
+ Multiple iterators can be used on the same map. If the map is
+ modified while a QMapIterator is active, the QMapIterator will
+ continue iterating over the original map, ignoring the modified
+ copy.
+
+ \sa QMutableMapIterator, QMap::const_iterator
+*/
+
+/*!
+ \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.
+
+ QHashIterator\<Key, T\> allows you to iterate over a QHash (or a
+ QMultiHash). If you want to modify the hash as you iterate over
+ it, use QMutableHashIterator instead.
+
+ The QHashIterator constructor takes a QHash as argument. After
+ construction, the iterator is located at the very beginning of
+ the hash (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 29
+
+ The next() function returns the next item in the hash 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.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/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:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 31
+
+ Multiple iterators can be used on the same hash. If the hash is
+ modified while a QHashIterator is active, the QHashIterator will
+ continue iterating over the original hash, ignoring the modified
+ copy.
+
+ \sa QMutableHashIterator, QHash::const_iterator
+*/
+
+/*!
+ \class QMutableMapIterator
+ \inmodule QtCore
+
+ \brief The QMutableMapIterator class provides a Java-style non-const iterator for QMap and QMultiMap.
+
+ 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.
+
+ QMutableMapIterator\<Key, T\> allows you to iterate over a QMap
+ (or a QMultiMap) and modify the map. If you don't want to modify
+ the map (or have a const QMap), use the slightly faster
+ QMapIterator instead.
+
+ The QMutableMapIterator constructor takes a QMap 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 doc/src/snippets/code/doc_src_qiterator.cpp 32
+
+ 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.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 33
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 34
+
+ 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 doc/src/snippets/code/doc_src_qiterator.cpp 35
+
+ 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 QMapIterator, QMap::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.
+
+ 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.
+
+ The QMutableHashIterator constructor takes a QHash as argument.
+ After construction, the iterator is located at the very beginning
+ of the hash (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 36
+
+ The next() function returns the next item in the hash 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.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/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:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 38
+
+ If you want to remove items as you iterate over the hash, use
+ remove(). If you want to modify the value of an item, use
+ setValue().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.cpp 39
+
+ 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 hash at any
+ time. Furthermore, no changes should be done directly to the hash
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QHashIterator, QHash::iterator
+*/
+
+/*! \fn QMapIterator::QMapIterator(const QMap<Key, T> &map)
+ \fn QMutableMapIterator::QMutableMapIterator(QMap<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).
+
+ \sa operator=()
+*/
+
+/*! \fn QHashIterator::QHashIterator(const QHash<Key, T> &hash)
+ \fn QMutableHashIterator::QMutableHashIterator(QHash<Key, T> &hash)
+
+ Constructs an iterator for traversing \a hash. The iterator is
+ set to be at the front of the hash (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QMutableMapIterator::~QMutableMapIterator()
+ \fn QMutableHashIterator::~QMutableHashIterator()
+
+ Destroys the iterator.
+
+ \sa operator=()
+*/
+
+/*! \fn QMapIterator &QMapIterator::operator=(const QMap<Key, T> &map)
+ \fn QMutableMapIterator &QMutableMapIterator::operator=(QMap<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).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QHashIterator &QHashIterator::operator=(const QHash<Key, T> &hash)
+ \fn QMutableHashIterator &QMutableHashIterator::operator=(QHash<Key, T> &hash)
+
+ Makes the iterator operate on \a hash. The iterator is set to be
+ at the front of the hash (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QMapIterator::toFront()
+ \fn void QHashIterator::toFront()
+ \fn void QMutableMapIterator::toFront()
+ \fn void QMutableHashIterator::toFront()
+
+ Moves the iterator to the front of the container (before the
+ first item).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QMapIterator::toBack()
+ \fn void QHashIterator::toBack()
+ \fn void QMutableMapIterator::toBack()
+ \fn void QMutableHashIterator::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QMapIterator::hasNext() const
+ \fn bool QHashIterator::hasNext() const
+ \fn bool QMutableMapIterator::hasNext() const
+ \fn bool QMutableHashIterator::hasNext() const
+
+ Returns 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 false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::next()
+ \fn QHashIterator::Item QHashIterator::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(), previous()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::next()
+ \fn QMutableHashIterator::Item QMutableHashIterator::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(), previous()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::peekNext() const
+ \fn QHashIterator::Item QHashIterator::peekNext() const
+
+ 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 back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::peekNext() const
+ \fn QMutableHashIterator::Item QMutableHashIterator::peekNext() const
+
+ 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 back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn bool QMapIterator::hasPrevious() const
+ \fn bool QHashIterator::hasPrevious() const
+ \fn bool QMutableMapIterator::hasPrevious() const
+ \fn bool QMutableHashIterator::hasPrevious() const
+
+ Returns 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 false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::previous()
+ \fn QHashIterator::Item QHashIterator::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.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::previous()
+ \fn QMutableHashIterator::Item QMutableHashIterator::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.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::peekPrevious() const
+ \fn QHashIterator::Item QHashIterator::peekPrevious() const
+
+ Returns the previous 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
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::peekPrevious() const
+ \fn QMutableHashIterator::Item QMutableHashIterator::peekPrevious() const
+
+ Returns the previous 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
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn const T &QMapIterator::value() const
+ \fn const T &QHashIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is
+ equivalent to peekPrevious().value(). After a call to previous()
+ or findPrevious(), value() is equivalent to peekNext().value().
+
+ \sa key()
+*/
+
+/*!
+ \fn const T &QMutableMapIterator::value() const
+ \fn const T &QMutableHashIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is
+ equivalent to peekPrevious().value(). After a call to previous()
+ or findPrevious(), value() is equivalent to peekNext().value().
+
+ \sa key(), setValue()
+*/
+
+/*!
+ \fn T &QMutableMapIterator::value()
+ \fn T &QMutableHashIterator::value()
+ \overload
+
+ Returns a non-const reference to the value of
+ the last item that was jumped over using one
+ of the traversal functions.
+*/
+
+/*! \fn const Key &QMapIterator::key() const
+ \fn const Key &QHashIterator::key() const
+ \fn const Key &QMutableMapIterator::key() const
+ \fn const Key &QMutableHashIterator::key() const
+
+ Returns the key of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), key() is
+ equivalent to peekPrevious().key(). After a call to previous() or
+ findPrevious(), key() is equivalent to peekNext().key().
+
+ \sa value()
+*/
+
+/*! \fn bool QMapIterator::findNext(const T &value)
+ \fn bool QHashIterator::findNext(const T &value)
+ \fn bool QMutableMapIterator::findNext(const T &value)
+ \fn bool QMutableHashIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ forward. Returns true if a (key, value) pair with value \a value
+ is found; otherwise returns 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.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QMapIterator::findPrevious(const T &value)
+ \fn bool QHashIterator::findPrevious(const T &value)
+ \fn bool QMutableMapIterator::findPrevious(const T &value)
+ \fn bool QMutableHashIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if a (key, value) pair with value \a value
+ is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just before the matching item; otherwise, the iterator is
+ positioned at the front of the container.
+
+ \sa findNext()
+*/
+
+/*! \fn void QMutableMapIterator::remove()
+ \fn void QMutableHashIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ \sa setValue()
+*/
+
+/*! \fn void QMutableMapIterator::setValue(const T &value)
+ \fn void QMutableHashIterator::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(), previous(), findNext(), and
+ findPrevious().
+
+ \sa key(), value(), remove()
+*/
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
new file mode 100644
index 0000000000..dfc55e62b6
--- /dev/null
+++ b/src/corelib/tools/qline.cpp
@@ -0,0 +1,867 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qline.h"
+#include "qdebug.h"
+#include "qdatastream.h"
+#include "qmath.h"
+#include <private/qnumeric_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QLine
+ \ingroup painting
+
+ \brief The QLine class provides a two-dimensional vector using
+ integer precision.
+
+ A QLine describes a finite length line (or a line segment) on a
+ two-dimensional surface. The start and end points of the line are
+ specified using integer point accuracy for coordinates. Use the
+ QLineF constructor to retrieve a floating point copy.
+
+ \table
+ \row
+ \o \inlineimage qline-point.png
+ \o \inlineimage qline-coordinates.png
+ \endtable
+
+ The positions of the line's start and end points can be retrieved
+ using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The
+ dx() and dy() functions return the horizontal and vertical
+ components of the line. Use isNull() to determine whether the
+ QLine represents a valid line or a null line.
+
+ Finally, the line can be translated a given offset using the
+ translate() function.
+
+ \sa QLineF, QPolygon, QRect
+*/
+
+/*!
+ \fn QLine::QLine()
+
+ Constructs a null line.
+*/
+
+/*!
+ \fn QLine::QLine(const QPoint &p1, const QPoint &p2)
+
+ Constructs a line object that represents the line between \a p1 and
+ \a p2.
+*/
+
+/*!
+ \fn QLine::QLine(int x1, int y1, int x2, int y2)
+
+ Constructs a line object that represents the line between (\a x1, \a y1) and
+ (\a x2, \a y2).
+*/
+
+/*!
+ \fn bool QLine::isNull() const
+
+ Returns true if the line is not set up with valid start and end point;
+ otherwise returns false.
+*/
+
+/*!
+ \fn QPoint QLine::p1() const
+
+ Returns the line's start point.
+
+ \sa x1(), y1(), p2()
+*/
+
+/*!
+ \fn QPoint QLine::p2() const
+
+ Returns the line's end point.
+
+ \sa x2(), y2(), p1()
+*/
+
+/*!
+ \fn int QLine::x1() const
+
+ Returns the x-coordinate of the line's start point.
+
+ \sa p1()
+*/
+
+/*!
+ \fn int QLine::y1() const
+
+ Returns the y-coordinate of the line's start point.
+
+ \sa p1()
+*/
+
+/*!
+ \fn int QLine::x2() const
+
+ Returns the x-coordinate of the line's end point.
+
+ \sa p2()
+*/
+
+/*!
+ \fn int QLine::y2() const
+
+ Returns the y-coordinate of the line's end point.
+
+ \sa p2()
+*/
+
+/*!
+ \fn int QLine::dx() const
+
+ Returns the horizontal component of the line's vector.
+
+ \sa dy()
+*/
+
+/*!
+ \fn int QLine::dy() const
+
+ Returns the vertical component of the line's vector.
+
+ \sa dx()
+*/
+
+/*!
+ \fn bool QLine::operator!=(const QLine &line) const
+
+ Returns true if the given \a line is not the same as \e this line.
+
+ 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
+
+ Returns true if the given \a line is the same as \e this line.
+
+ 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.
+*/
+
+/*!
+ \fn void QLine::translate(const QPoint &offset)
+
+ Translates this line by the given \a offset.
+*/
+
+/*!
+ \fn void QLine::translate(int dx, int dy)
+ \overload
+
+ Translates this line the distance specified by \a dx and \a dy.
+*/
+
+/*!
+ \fn QLine QLine::translated(const QPoint &offset) const
+
+ \since 4.4
+
+ Returns this line translated by the given \a offset.
+*/
+
+/*!
+ \fn QLine QLine::translated(int dx, int dy) const
+ \overload
+ \since 4.4
+
+ Returns this line translated the distance specified by \a dx and \a dy.
+*/
+
+
+/*!
+ \fn void QLine::setP1(const QPoint &p1)
+ \since 4.4
+
+ Sets the starting point of this line to \a p1.
+
+ \sa setP2(), p1()
+*/
+
+
+/*!
+ \fn void QLine::setP2(const QPoint &p2)
+ \since 4.4
+
+ Sets the end point of this line to \a p2.
+
+ \sa setP1(), p2()
+*/
+
+
+/*!
+ \fn void QLine::setPoints(const QPoint &p1, const QPoint &p2)
+ \since 4.4
+
+ Sets the start point of this line to \a p1 and the end point of this line to \a p2.
+
+ \sa setP1(), setP2(), p1(), p2()
+*/
+
+
+/*!
+ \fn void QLine::setLine(int x1, int y1, int x2, int y2)
+ \since 4.4
+
+ Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
+
+ \sa setP1(), setP2(), p1(), p2()
+*/
+
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QLine &p)
+{
+ d << "QLine(" << p.p1() << ',' << p.p2() << ')';
+ return d;
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QLine
+
+ Writes the given \a line to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QLine &line)
+{
+ stream << line.p1() << line.p2();
+ return stream;
+}
+
+/*!
+ \relates QLine
+
+ Reads a line from the given \a stream into the given \a line and
+ returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QLine &line)
+{
+ QPoint p1, p2;
+ stream >> p1;
+ stream >> p2;
+ line = QLine(p1, p2);
+
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef M_2PI
+#define M_2PI 6.28318530717958647692528676655900576
+#endif
+
+/*!
+ \class QLineF
+ \ingroup painting
+
+ \brief The QLineF class provides a two-dimensional vector using
+ floating point precision.
+
+ 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
+ line.
+
+ \table
+ \row
+ \o \inlineimage qline-point.png
+ \o \inlineimage qline-coordinates.png
+ \endtable
+
+ The positions of the line's start and end points can be retrieved
+ using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The
+ dx() and dy() functions return the horizontal and vertical
+ components of the line, respectively.
+
+ The line's length can be retrieved using the length() function,
+ and altered using the setLength() function. Similarly, angle()
+ and setAngle() are respectively used for retrieving and altering
+ the angle of the line. Use the isNull()
+ function to determine whether the QLineF represents a valid line
+ or a null line.
+
+ The intersect() function determines the IntersectType for this
+ line and a given line, while the angle() function returns the
+ angle between the lines. In addition, the unitVector() function
+ returns a line that has the same starting point as this line, but
+ with a length of only 1, while the normalVector() function returns
+ a line that is perpendicular to this line with the same starting
+ point and length.
+
+ Finally, the line can be translated a given offset using the
+ translate() function, and can be traversed using the pointAt()
+ function.
+
+ \sa QLine, QPolygonF, QRectF
+*/
+
+/*!
+ \enum QLineF::IntersectType
+
+ Describes the intersection between two lines.
+
+ \table
+ \row
+ \o \inlineimage qlinef-unbounded.png
+ \o \inlineimage qlinef-bounded.png
+ \row
+ \o QLineF::UnboundedIntersection
+ \o QLineF::BoundedIntersection
+ \endtable
+
+ \value NoIntersection Indicates that the lines do not intersect;
+ i.e. they are parallel.
+
+ \value UnboundedIntersection The two lines intersect, but not
+ within the range defined by their lengths. This will be the case
+ if the lines are not parallel.
+
+ intersect() will also return this value if the intersect point is
+ within the start and end point of only one of the lines.
+
+ \value BoundedIntersection The two lines intersect with each other
+ within the start and end points of each line.
+
+ \sa intersect()
+*/
+
+/*!
+ \fn QLineF::QLineF()
+
+ Constructs a null line.
+*/
+
+/*!
+ \fn QLineF::QLineF(const QPointF &p1, const QPointF &p2)
+
+ Constructs a line object that represents the line between \a p1 and
+ \a p2.
+*/
+
+/*!
+ \fn QLineF::QLineF(qreal x1, qreal y1, qreal x2, qreal y2)
+
+ Constructs a line object that represents the line between (\a x1, \a y1) and
+ (\a x2, \a y2).
+*/
+
+/*!
+ \fn QLineF::QLineF(const QLine &line)
+
+ Construct a QLineF object from the given integer-based \a line.
+
+ \sa toLine()
+*/
+
+/*!
+ Returns true if the line is not set up with valid start and end point;
+ otherwise returns false.
+*/
+
+bool QLineF::isNull() const
+{
+ return (qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y())) ? true : false;
+}
+
+
+/*!
+ \fn QPointF QLineF::p1() const
+
+ Returns the line's start point.
+
+ \sa x1(), y1(), p2()
+*/
+
+/*!
+ \fn QPointF QLineF::p2() const
+
+ Returns the line's end point.
+
+ \sa x2(), y2(), p1()
+*/
+
+/*!
+ \fn QLine QLineF::toLine() const
+
+ 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()
+*/
+/*!
+ \fn qreal QLineF::x1() const
+
+ Returns the x-coordinate of the line's start point.
+
+ \sa p1()
+*/
+
+/*!
+ \fn qreal QLineF::y1() const
+
+ Returns the y-coordinate of the line's start point.
+
+ \sa p1()
+*/
+
+/*!
+ \fn qreal QLineF::x2() const
+
+ Returns the x-coordinate of the line's end point.
+
+ \sa p2()
+*/
+
+/*!
+ \fn qreal QLineF::y2() const
+
+ Returns the y-coordinate of the line's end point.
+
+ \sa p2()
+*/
+
+/*!
+ \fn qreal QLineF::dx() const
+
+ Returns the horizontal component of the line's vector.
+
+ \sa dy(), pointAt()
+*/
+
+/*!
+ \fn qreal QLineF::dy() const
+
+ Returns the vertical component of the line's vector.
+
+ \sa dx(), pointAt()
+*/
+
+/*!
+ \fn 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.
+
+ If the line is a null line, the length will remain zero regardless
+ of the length specified.
+
+ \sa length(), isNull()
+*/
+
+/*!
+ \fn QLineF QLineF::normalVector() const
+
+ Returns a line that is perpendicular to this line with the same starting
+ point and length.
+
+ \image qlinef-normalvector.png
+
+ \sa unitVector()
+*/
+
+/*!
+ \fn bool QLineF::operator!=(const QLineF &line) const
+
+ Returns true if the given \a line is not the same as \e this line.
+
+ 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
+
+ Returns true if the given \a line is the same as this line.
+
+ 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.
+*/
+
+/*!
+ \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.
+
+ \sa dx(), dy()
+*/
+
+/*!
+ Returns the length of the line.
+
+ \sa setLength()
+*/
+qreal QLineF::length() const
+{
+ qreal x = pt2.x() - pt1.x();
+ qreal y = pt2.y() - pt1.y();
+ return qSqrt(x*x + y*y);
+}
+
+/*!
+ \since 4.4
+
+ Returns the angle of the line in degrees.
+
+ Positive values for the angles mean counter-clockwise while negative values
+ mean the clockwise direction. Zero degrees is at the 3 o'clock position.
+
+ \sa setAngle()
+*/
+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_normalized = theta < 0 ? theta + 360 : theta;
+
+ if (qFuzzyCompare(theta_normalized, qreal(360)))
+ return qreal(0);
+ else
+ return theta_normalized;
+}
+
+/*!
+ \since 4.4
+
+ Sets the angle of the line to the given \a angle (in degrees).
+ This will change the position of the second point of the line such that
+ the line has the given angle.
+
+ Positive values for the angles mean counter-clockwise while negative values
+ mean the clockwise direction. Zero degrees is at the 3 o'clock position.
+
+ \sa angle()
+*/
+void QLineF::setAngle(qreal angle)
+{
+ const qreal angleR = angle * M_2PI / 360.0;
+ const qreal l = length();
+
+ const qreal dx = qCos(angleR) * l;
+ const qreal dy = -qSin(angleR) * l;
+
+ pt2.rx() = pt1.x() + dx;
+ pt2.ry() = pt1.y() + dy;
+}
+
+/*!
+ \since 4.4
+
+ Returns a QLineF with the given \a length and \a angle.
+
+ The first point of the line will be on the origin.
+
+ Positive values for the angles mean counter-clockwise while negative values
+ mean the clockwise direction. Zero degrees is at the 3 o'clock position.
+*/
+QLineF QLineF::fromPolar(qreal length, qreal angle)
+{
+ const qreal angleR = angle * M_2PI / 360.0;
+ 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.
+
+ \sa normalVector()
+*/
+QLineF QLineF::unitVector() const
+{
+ qreal x = pt2.x() - pt1.x();
+ qreal y = pt2.y() - pt1.y();
+
+ qreal len = qSqrt(x*x + y*y);
+ QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
+
+#ifndef QT_NO_DEBUG
+ if (qAbs(f.length() - 1) >= 0.001)
+ qWarning("QLine::unitVector: New line does not have unit length");
+#endif
+
+ return f;
+}
+
+/*!
+ \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const
+
+ 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
+{
+ // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
+ const QPointF a = pt2 - pt1;
+ const QPointF b = l.pt1 - l.pt2;
+ const QPointF c = pt1 - l.pt1;
+
+ const qreal denominator = a.y() * b.x() - a.x() * b.y();
+ if (denominator == 0 || !qt_is_finite(denominator))
+ return NoIntersection;
+
+ const qreal reciprocal = 1 / denominator;
+ const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
+ if (intersectionPoint)
+ *intersectionPoint = pt1 + a * na;
+
+ if (na < 0 || na > 1)
+ return UnboundedIntersection;
+
+ const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
+ if (nb < 0 || nb > 1)
+ return UnboundedIntersection;
+
+ return BoundedIntersection;
+}
+
+/*!
+ \fn void QLineF::translate(const QPointF &offset)
+
+ Translates this line by the given \a offset.
+*/
+
+/*!
+ \fn void QLineF::translate(qreal dx, qreal dy)
+ \overload
+
+ Translates this line the distance specified by \a dx and \a dy.
+*/
+
+/*!
+ \fn QLineF QLineF::translated(const QPointF &offset) const
+
+ \since 4.4
+
+ Returns this line translated by the given \a offset.
+*/
+
+/*!
+ \fn QLineF QLineF::translated(qreal dx, qreal dy) const
+ \overload
+ \since 4.4
+
+ Returns this line translated the distance specified by \a dx and \a dy.
+*/
+
+/*!
+ \fn void QLineF::setP1(const QPointF &p1)
+ \since 4.4
+
+ Sets the starting point of this line to \a p1.
+
+ \sa setP2(), p1()
+*/
+
+
+/*!
+ \fn void QLineF::setP2(const QPointF &p2)
+ \since 4.4
+
+ Sets the end point of this line to \a p2.
+
+ \sa setP1(), p2()
+*/
+
+
+/*!
+ \fn void QLineF::setPoints(const QPointF &p1, const QPointF &p2)
+ \since 4.4
+
+ Sets the start point of this line to \a p1 and the end point of this line to \a p2.
+
+ \sa setP1(), setP2(), p1(), p2()
+*/
+
+
+/*!
+ \fn void QLineF::setLine(qreal x1, qreal y1, qreal x2, qreal y2)
+ \since 4.4
+
+ Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
+
+ \sa setP1(), setP2(), p1(), p2()
+*/
+
+/*!
+ \fn qreal QLineF::angleTo(const QLineF &line) const
+
+ \since 4.4
+
+ 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
+ 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()
+*/
+qreal QLineF::angleTo(const QLineF &l) const
+{
+ if (isNull() || l.isNull())
+ return 0;
+
+ const qreal a1 = angle();
+ const qreal a2 = l.angle();
+
+ const qreal delta = a2 - a1;
+ const qreal delta_normalized = delta < 0 ? delta + 360 : delta;
+
+ if (qFuzzyCompare(delta, qreal(360)))
+ return 0;
+ else
+ return delta_normalized;
+}
+
+/*!
+ \fn qreal QLineF::angle(const QLineF &line) const
+
+ \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).
+
+ \table
+ \row
+ \o \inlineimage qlinef-angle-identicaldirection.png
+ \o \inlineimage qlinef-angle-oppositedirection.png
+ \endtable
+
+ When the lines are parallel, this function returns 0 if they have
+ the same direction; otherwise it returns 180.
+
+ \sa intersect()
+*/
+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;
+}
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QLineF &p)
+{
+ d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
+ return d;
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QLineF
+
+ Writes the given \a line to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QLineF &line)
+{
+ stream << line.p1() << line.p2();
+ return stream;
+}
+
+/*!
+ \relates QLineF
+
+ Reads a line from the given \a stream into the given \a line and
+ returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QLineF &line)
+{
+ QPointF start, end;
+ stream >> start;
+ stream >> end;
+ line = QLineF(start, end);
+
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
new file mode 100644
index 0000000000..409bed102c
--- /dev/null
+++ b/src/corelib/tools/qline.h
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINE_H
+#define QLINE_H
+
+#include <QtCore/qpoint.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*******************************************************************************
+ * class QLine
+ *******************************************************************************/
+
+class Q_CORE_EXPORT QLine
+{
+public:
+ inline QLine();
+ inline QLine(const QPoint &pt1, const QPoint &pt2);
+ inline QLine(int x1, int y1, int x2, int y2);
+
+ inline bool isNull() const;
+
+ inline QPoint p1() const;
+ inline QPoint p2() const;
+
+ inline int x1() const;
+ inline int y1() const;
+
+ inline int x2() const;
+ inline int y2() const;
+
+ inline int dx() const;
+ inline int dy() const;
+
+ inline void translate(const QPoint &p);
+ inline void translate(int dx, int dy);
+
+ inline QLine translated(const QPoint &p) const;
+ inline QLine translated(int dx, int dy) 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);
+
+ inline bool operator==(const QLine &d) const;
+ inline bool operator!=(const QLine &d) const { return !(*this == d); }
+
+private:
+ QPoint pt1, pt2;
+};
+Q_DECLARE_TYPEINFO(QLine, Q_MOVABLE_TYPE);
+
+/*******************************************************************************
+ * class QLine inline members
+ *******************************************************************************/
+
+inline QLine::QLine() { }
+
+inline QLine::QLine(const QPoint &pt1_, const QPoint &pt2_) : pt1(pt1_), pt2(pt2_) { }
+
+inline QLine::QLine(int x1pos, int y1pos, int x2pos, int y2pos) : pt1(QPoint(x1pos, y1pos)), pt2(QPoint(x2pos, y2pos)) { }
+
+inline bool QLine::isNull() const
+{
+ return pt1 == pt2;
+}
+
+inline int QLine::x1() const
+{
+ return pt1.x();
+}
+
+inline int QLine::y1() const
+{
+ return pt1.y();
+}
+
+inline int QLine::x2() const
+{
+ return pt2.x();
+}
+
+inline int QLine::y2() const
+{
+ return pt2.y();
+}
+
+inline QPoint QLine::p1() const
+{
+ return pt1;
+}
+
+inline QPoint QLine::p2() const
+{
+ return pt2;
+}
+
+inline int QLine::dx() const
+{
+ return pt2.x() - pt1.x();
+}
+
+inline int QLine::dy() const
+{
+ return pt2.y() - pt1.y();
+}
+
+inline void QLine::translate(const QPoint &point)
+{
+ pt1 += point;
+ pt2 += point;
+}
+
+inline void QLine::translate(int adx, int ady)
+{
+ this->translate(QPoint(adx, ady));
+}
+
+inline QLine QLine::translated(const QPoint &p) const
+{
+ return QLine(pt1 + p, pt2 + p);
+}
+
+inline QLine QLine::translated(int adx, int ady) const
+{
+ return translated(QPoint(adx, ady));
+}
+
+inline void QLine::setP1(const QPoint &aP1)
+{
+ pt1 = aP1;
+}
+
+inline void QLine::setP2(const QPoint &aP2)
+{
+ pt2 = aP2;
+}
+
+inline void QLine::setPoints(const QPoint &aP1, const QPoint &aP2)
+{
+ pt1 = aP1;
+ pt2 = aP2;
+}
+
+inline void QLine::setLine(int aX1, int aY1, int aX2, int aY2)
+{
+ pt1 = QPoint(aX1, aY1);
+ pt2 = QPoint(aX2, aY2);
+}
+
+inline bool QLine::operator==(const QLine &d) const
+{
+ return pt1 == d.pt1 && pt2 == d.pt2;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLine &p);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLine &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLine &);
+#endif
+
+/*******************************************************************************
+ * class QLineF
+ *******************************************************************************/
+class Q_CORE_EXPORT QLineF {
+public:
+
+ enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection };
+
+ inline QLineF();
+ inline QLineF(const QPointF &pt1, const QPointF &pt2);
+ inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
+ inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
+
+ static QLineF fromPolar(qreal length, qreal angle);
+
+ bool isNull() const;
+
+ inline QPointF p1() const;
+ inline QPointF p2() const;
+
+ inline qreal x1() const;
+ inline qreal y1() const;
+
+ inline qreal x2() const;
+ inline qreal y2() const;
+
+ inline qreal dx() const;
+ inline qreal dy() const;
+
+ qreal length() const;
+ void setLength(qreal len);
+
+ qreal angle() const;
+ void setAngle(qreal angle);
+
+ qreal angleTo(const QLineF &l) const;
+
+ QLineF unitVector() const;
+ QLineF normalVector() const;
+
+ // ### Qt 5: rename intersects() or intersection() and rename IntersectType IntersectionType
+ IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
+
+ qreal angle(const QLineF &l) const;
+
+ QPointF pointAt(qreal t) const;
+ inline void translate(const QPointF &p);
+ inline void translate(qreal dx, qreal dy);
+
+ inline QLineF translated(const QPointF &p) const;
+ inline QLineF translated(qreal dx, qreal dy) 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);
+
+ inline bool operator==(const QLineF &d) const;
+ inline bool operator!=(const QLineF &d) const { return !(*this == d); }
+
+ QLine toLine() const;
+
+private:
+ QPointF pt1, pt2;
+};
+Q_DECLARE_TYPEINFO(QLineF, Q_MOVABLE_TYPE);
+
+/*******************************************************************************
+ * class QLineF inline members
+ *******************************************************************************/
+
+inline QLineF::QLineF()
+{
+}
+
+inline QLineF::QLineF(const QPointF &apt1, const QPointF &apt2)
+ : pt1(apt1), pt2(apt2)
+{
+}
+
+inline QLineF::QLineF(qreal x1pos, qreal y1pos, qreal x2pos, qreal y2pos)
+ : pt1(x1pos, y1pos), pt2(x2pos, y2pos)
+{
+}
+
+inline qreal QLineF::x1() const
+{
+ return pt1.x();
+}
+
+inline qreal QLineF::y1() const
+{
+ return pt1.y();
+}
+
+inline qreal QLineF::x2() const
+{
+ return pt2.x();
+}
+
+inline qreal QLineF::y2() const
+{
+ return pt2.y();
+}
+
+inline QPointF QLineF::p1() const
+{
+ return pt1;
+}
+
+inline QPointF QLineF::p2() const
+{
+ return pt2;
+}
+
+inline qreal QLineF::dx() const
+{
+ return pt2.x() - pt1.x();
+}
+
+inline qreal QLineF::dy() const
+{
+ return pt2.y() - pt1.y();
+}
+
+inline QLineF QLineF::normalVector() const
+{
+ return QLineF(p1(), p1() + QPointF(dy(), -dx()));
+}
+
+inline void QLineF::translate(const QPointF &point)
+{
+ pt1 += point;
+ pt2 += point;
+}
+
+inline void QLineF::translate(qreal adx, qreal ady)
+{
+ this->translate(QPointF(adx, ady));
+}
+
+inline QLineF QLineF::translated(const QPointF &p) const
+{
+ return QLineF(pt1 + p, pt2 + p);
+}
+
+inline QLineF QLineF::translated(qreal adx, qreal ady) const
+{
+ return translated(QPointF(adx, ady));
+}
+
+inline void QLineF::setLength(qreal len)
+{
+ if (isNull())
+ return;
+ QLineF v = unitVector();
+ pt2 = QPointF(pt1.x() + v.dx() * len, pt1.y() + v.dy() * len);
+}
+
+inline QPointF QLineF::pointAt(qreal t) const
+{
+ qreal vx = pt2.x() - pt1.x();
+ qreal vy = pt2.y() - pt1.y();
+ return QPointF(pt1.x() + vx * t, pt1.y() + vy * t);
+}
+
+inline QLine QLineF::toLine() const
+{
+ return QLine(pt1.toPoint(), pt2.toPoint());
+}
+
+
+inline void QLineF::setP1(const QPointF &aP1)
+{
+ pt1 = aP1;
+}
+
+inline void QLineF::setP2(const QPointF &aP2)
+{
+ pt2 = aP2;
+}
+
+inline void QLineF::setPoints(const QPointF &aP1, const QPointF &aP2)
+{
+ pt1 = aP1;
+ pt2 = aP2;
+}
+
+inline void QLineF::setLine(qreal aX1, qreal aY1, qreal aX2, qreal aY2)
+{
+ pt1 = QPointF(aX1, aY1);
+ pt2 = QPointF(aX2, aY2);
+}
+
+
+inline bool QLineF::operator==(const QLineF &d) const
+{
+ return pt1 == d.pt1 && pt2 == d.pt2;
+}
+
+
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLineF &p);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLineF &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLineF &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLINE_H
diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp
new file mode 100644
index 0000000000..724cace8e6
--- /dev/null
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -0,0 +1,1170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlinkedlist.h"
+
+QT_BEGIN_NAMESPACE
+
+QLinkedListData QLinkedListData::shared_null = {
+ &QLinkedListData::shared_null, &QLinkedListData::shared_null,
+ Q_BASIC_ATOMIC_INITIALIZER(1), 0, true
+};
+
+/*! \class QLinkedList
+ \brief The QLinkedList class is a template class that provides linked lists.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QLinkedList\<T\> is one of Qt's generic \l{container classes}. It
+ stores a list of values and provides iterator-based access as
+ well as \l{constant time} insertions and removals.
+
+ QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar
+ functionality. Here's an overview:
+
+ \list
+ \i For most purposes, QList is the right class to use. Its
+ index-based API is more convenient than QLinkedList's
+ iterator-based API, and it is usually faster than
+ QVector because of the way it stores its items in
+ memory (see \l{Algorithmic Complexity} for details).
+ It also expands to less code in your executable.
+ \i If you need a real linked list, with guarantees of \l{constant
+ time} insertions in the middle of the list and iterators to
+ items rather than indexes, use QLinkedList.
+ \i If you want the items to occupy adjacent memory positions,
+ use QVector.
+ \endlist
+
+ Here's an example of a QLinkedList that stores integers and a
+ QLinkedList that stores QTime values:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 0
+
+ QLinkedList stores a list of items. The default constructor
+ creates an empty list. To insert items into the list, you can use
+ operator<<():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 1
+
+ If you want to get the first or last item in a linked list, use
+ first() or last(). If you want to remove an item from either end
+ of the list, use removeFirst() or removeLast(). If you want to
+ remove all occurrences of a given value in the list, use
+ removeAll().
+
+ A common requirement is to remove the first or last item in the
+ list and do something with it. For this, QLinkedList provides
+ takeFirst() and takeLast(). Here's a loop that removes the items
+ from a list one at a time and calls \c delete on them:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 2
+
+ QLinkedList's value type must be an \l {assignable data type}. This
+ covers most data types that are commonly used, but the compiler
+ won't let you, for example, store a QWidget as a value; instead,
+ store a QWidget *. A few functions have additional requirements;
+ for example, contains() and removeAll() expect the value type to
+ support \c operator==(). These requirements are documented on a
+ per-function basis.
+
+ If you want to insert, modify, or remove items in the middle of
+ the list, you must use an iterator. QLinkedList provides both
+ \l{Java-style iterators} (QLinkedListIterator and
+ QMutableLinkedListIterator) and \l{STL-style iterators}
+ (QLinkedList::const_iterator and QLinkedList::iterator). See the
+ documentation for these classes for details.
+
+ \sa QLinkedListIterator, QMutableLinkedListIterator, QList, QVector
+*/
+
+/*! \fn QLinkedList::QLinkedList()
+
+ Constructs an empty list.
+*/
+
+/*! \fn QLinkedList::QLinkedList(const QLinkedList<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QLinkedList
+ is \l{implicitly shared}. This makes returning a QLinkedList 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 QLinkedList::~QLinkedList()
+
+ Destroys the list. References to the values in the list, and all
+ iterators over this list, become invalid.
+*/
+
+/*! \fn QLinkedList<T> &QLinkedList::operator=(const QLinkedList<T> &other)
+
+ Assigns \a other to this list and returns a reference to this
+ list.
+*/
+
+/*! \fn void QLinkedList::swap(QLinkedList<T> &other)
+ \since 4.8
+
+ Swaps list \a other with this list. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QLinkedList::operator==(const QLinkedList<T> &other) const
+
+ Returns true if \a other is equal to this list; otherwise returns
+ false.
+
+ Two lists are considered equal if they contain the same values in
+ the same order.
+
+ This function requires the value type to implement \c
+ operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QLinkedList::operator!=(const QLinkedList<T> &other) const
+
+ Returns true if \a other is not equal to this list; otherwise
+ returns false.
+
+ Two lists are considered equal if they contain the same values in
+ the same order.
+
+ This function requires the value type to implement \c
+ operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QLinkedList::size() const
+
+ Returns the number of items in the list.
+
+ \sa isEmpty(), count()
+*/
+
+/*! \fn void QLinkedList::detach()
+
+ \internal
+*/
+
+/*! \fn bool QLinkedList::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QLinkedList::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn bool QLinkedList::isSharedWith(const QLinkedList<T> &other) const
+
+ \internal
+*/
+
+/*! \fn bool QLinkedList::isEmpty() const
+
+ Returns true if the list contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn void QLinkedList::clear()
+
+ Removes all the items in the list.
+
+ \sa removeAll()
+*/
+
+/*! \fn void QLinkedList::append(const T &value)
+
+ Inserts \a value at the end of the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 3
+
+ This is the same as list.insert(end(), \a value).
+
+ \sa operator<<(), prepend(), insert()
+*/
+
+/*! \fn void QLinkedList::prepend(const T &value)
+
+ Inserts \a value at the beginning of the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 4
+
+ This is the same as list.insert(begin(), \a value).
+
+ \sa append(), insert()
+*/
+
+/*! \fn int QLinkedList::removeAll(const T &value)
+
+ Removes all occurrences of \a value in the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 5
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa insert()
+*/
+
+/*!
+ \fn bool QLinkedList::removeOne(const T &value)
+ \since 4.4
+
+ Removes the first occurrences of \a value in the list. Returns true on
+ success; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 6
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa insert()
+*/
+
+/*! \fn bool QLinkedList::contains(const T &value) const
+
+ Returns true if the list contains an occurrence of \a value;
+ otherwise returns false.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa QLinkedListIterator::findNext(), QLinkedListIterator::findPrevious()
+*/
+
+/*! \fn int QLinkedList::count(const T &value) const
+
+ Returns the number of occurrences of \a value in the list.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa contains()
+*/
+
+/*! \fn bool QLinkedList::startsWith(const T &value) const
+ \since 4.5
+
+ Returns true if the list is not empty and its first
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), first()
+*/
+
+/*! \fn bool QLinkedList::endsWith(const T &value) const
+ \since 4.5
+
+ Returns true if the list is not empty and its last
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), last()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the list.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::begin() const
+
+ \overload
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the list.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the list.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::end() const
+
+ \overload
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the list.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::insert(iterator before, const T &value)
+
+ Inserts \a value in front of the item pointed to by the iterator
+ \a before. Returns an iterator pointing at the inserted item.
+
+ \sa erase()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::erase(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()).
+
+ \sa insert()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::erase(iterator begin, iterator end)
+
+ \overload
+
+ Removes all the items from \a begin up to (but not including) \a
+ end.
+*/
+
+/*! \typedef QLinkedList::Iterator
+
+ Qt-style synonym for QLinkedList::iterator.
+*/
+
+/*! \typedef QLinkedList::ConstIterator
+
+ Qt-style synonym for QLinkedList::const_iterator.
+*/
+
+/*!
+ \typedef QLinkedList::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::pointer
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::const_pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::const_reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QLinkedList::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \fn int QLinkedList::count() const
+
+ Same as size().
+*/
+
+/*! \fn T& QLinkedList::first()
+
+ Returns a reference to the first item in the list. This function
+ assumes that the list isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn const T& QLinkedList::first() const
+
+ \overload
+*/
+
+/*! \fn T& QLinkedList::last()
+
+ Returns a reference to the last item in the list. This function
+ assumes that the list isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QLinkedList::last() const
+
+ \overload
+*/
+
+/*! \fn void QLinkedList::removeFirst()
+
+ Removes the first item in the list.
+
+ This is the same as erase(begin()).
+
+ \sa removeLast(), erase()
+*/
+
+/*! \fn void QLinkedList::removeLast()
+
+ Removes the last item in the list.
+
+ \sa removeFirst(), erase()
+*/
+
+/*! \fn T QLinkedList::takeFirst()
+
+ Removes the first item in the list and returns it.
+
+ If you don't use the return value, removeFirst() is more
+ efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QLinkedList::takeLast()
+
+ Removes the last item in the list and returns it.
+
+ If you don't use the return value, removeLast() is more
+ efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QLinkedList::push_back(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to append(\a value).
+*/
+
+/*! \fn void QLinkedList::push_front(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to prepend(\a value).
+*/
+
+/*! \fn T& QLinkedList::front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to first().
+*/
+
+/*! \fn const T& QLinkedList::front() const
+
+ \overload
+*/
+
+/*! \fn T& QLinkedList::back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to last().
+*/
+
+/*! \fn const T& QLinkedList::back() const
+
+ \overload
+*/
+
+/*! \fn void QLinkedList::pop_front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to removeFirst().
+*/
+
+/*! \fn void QLinkedList::pop_back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to removeLast().
+*/
+
+/*! \fn bool QLinkedList::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty() and returns true if the list is empty.
+*/
+
+/*! \fn QLinkedList<T> &QLinkedList::operator+=(const QLinkedList<T> &other)
+
+ Appends the items of the \a other list to this list and returns a
+ reference to this list.
+
+ \sa operator+(), append()
+*/
+
+/*! \fn void QLinkedList::operator+=(const T &value)
+
+ \overload
+
+ Appends \a value to the list.
+*/
+
+/*! \fn QLinkedList<T> QLinkedList::operator+(const QLinkedList<T> &other) const
+
+ Returns a list that contains all the items in this list followed
+ by all the items in the \a other list.
+
+ \sa operator+=()
+*/
+
+/*! \fn QLinkedList<T> &QLinkedList::operator<<(const QLinkedList<T> &other)
+
+ Appends the items of the \a other list to this list and returns a
+ reference to this list.
+
+ \sa operator+=(), append()
+*/
+
+/*! \fn QLinkedList<T> &QLinkedList::operator<<(const T &value)
+
+ \overload
+
+ Appends \a value to the list.
+*/
+
+/*! \class QLinkedList::iterator
+ \brief The QLinkedList::iterator class provides an STL-style non-const iterator for QLinkedList.
+
+ QLinkedList 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.
+
+ QLinkedList\<T\>::iterator allows you to iterate over a
+ QLinkedList\<T\> and to modify the list item associated with the
+ iterator. If you want to iterate over a const QLinkedList, use
+ QLinkedList::const_iterator instead. It is generally good
+ practice to use QLinkedList::const_iterator on a non-const
+ QLinkedList as well, unless you need to change the QLinkedList
+ through the iterator. Const iterators are slightly faster, and
+ can improve code readability.
+
+ The default QLinkedList::iterator constructor creates an
+ uninitialized iterator. You must initialize it using a
+ function like QLinkedList::begin(), QLinkedList::end(), or
+ QLinkedList::insert() before you can start iterating. Here's a
+ typical loop that prints all the items stored in a list:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 7
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the list
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 8
+
+ Let's see a few examples of things we can do with a
+ QLinkedList::iterator that we cannot do with a QLinkedList::const_iterator.
+ Here's an example that increments every value stored in a
+ QLinkedList\<int\> by 2:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 9
+
+ Here's an example that removes all the items that start with an
+ underscore character in a QLinkedList\<QString\>:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 10
+
+ The call to QLinkedList::erase() removes the item pointed to by
+ the iterator from the list, and returns an iterator to the next
+ item. Here's another way of removing an item while iterating:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 11
+
+ It might be tempting to write code like this:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 12
+
+ 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 list. If you add items
+ to the list, existing iterators will remain valid. If you remove
+ items from the list, iterators that point to the removed items
+ will become dangling iterators. However, because of how \l{implicit
+ sharing} works, you must not take a copy of a container while
+ iterators are active on that container.
+
+ \sa QLinkedList::const_iterator, QMutableLinkedListIterator
+*/
+
+/*! \fn QLinkedList::iterator::iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QLinkedList::begin() QLinkedList::end()
+*/
+
+/*! \fn QLinkedList::iterator::iterator(Node *node)
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::iterator::iterator_category
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::iterator::value_type
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::iterator::reference
+
+ \internal
+*/
+
+/*! \fn QLinkedList::iterator::iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator=(const iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*! \fn T &QLinkedList::iterator::operator*() const
+
+ Returns a modifiable reference to the current item.
+
+ You can change the value of an item by using operator*() on the
+ left side of an assignment, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 13
+
+ \sa operator->()
+*/
+
+/*! \fn T *QLinkedList::iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*!
+ \fn bool QLinkedList::iterator::operator==(const iterator &other) const
+ \fn bool QLinkedList::iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QLinkedList::iterator::operator!=(const iterator &other) const
+ \fn bool QLinkedList::iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the list and returns an iterator to the new current
+ item.
+
+ Calling this function on QLinkedList::end() leads to undefined
+ results.
+
+ \sa operator--()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the list and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QLinkedList::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*! \fn QLinkedList::iterator QLinkedList::iterator::operator+(int 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 QLinkedList::iterator QLinkedList::iterator::operator-(int 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 QLinkedList::iterator &QLinkedList::iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items. (If \a j is negative,
+ the iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \class QLinkedList::const_iterator
+ \brief The QLinkedList::const_iterator class provides an STL-style const iterator for QLinkedList.
+
+ QLinkedList 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.
+
+ QLinkedList\<T\>::const_iterator allows you to iterate over a
+ QLinkedList\<T\>. If you want modify the QLinkedList as you iterate
+ over it, you must use QLinkedList::iterator instead. It is
+ generally good practice to use QLinkedList::const_iterator on a
+ non-const QLinkedList as well, unless you need to change the
+ QLinkedList through the iterator. Const iterators are slightly
+ faster, and can improve code readability.
+
+ The default QLinkedList::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a function
+ like QLinkedList::constBegin(), QLinkedList::constEnd(), or
+ QLinkedList::insert() before you can start iterating. Here's a
+ typical loop that prints all the items stored in a list:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 14
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the list
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 15
+
+ Multiple iterators can be used on the same list. If you add items
+ to the list, existing iterators will remain valid. If you remove
+ items from the list, iterators that point to the removed items
+ will become dangling iterators.
+
+ \sa QLinkedList::iterator, QLinkedListIterator
+*/
+
+/*! \fn QLinkedList::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QLinkedList::constBegin() QLinkedList::constEnd()
+*/
+
+/*! \fn QLinkedList::const_iterator::const_iterator(Node *node)
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::const_iterator::iterator_category
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::const_iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::const_iterator::value_type
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::const_iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QLinkedList::const_iterator::reference
+
+ \internal
+*/
+
+/*! \fn QLinkedList::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QLinkedList::const_iterator::const_iterator(iterator other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator=( \
+ const const_iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*! \fn const T &QLinkedList::const_iterator::operator*() const
+
+ Returns a reference to the current item.
+
+ \sa operator->()
+*/
+
+/*! \fn const T *QLinkedList::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*! \fn bool QLinkedList::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QLinkedList::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the list and returns an iterator to the new current
+ item.
+
+ Calling this function on QLinkedList::constEnd() leads to
+ undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the list and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QLinkedList::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator+(int 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 QLinkedList::const_iterator QLinkedList::const_iterator::operator-(int j) const
+
+ This function 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 QLinkedList::const_iterator &QLinkedList::const_iterator::operator+=(int 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 QLinkedList::const_iterator &QLinkedList::const_iterator::operator-=(int 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-()
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QLinkedList<T> &list)
+ \relates QLinkedList
+
+ Writes the linked list \a list to stream \a out.
+
+ This function requires the value type to implement \c
+ operator<<().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QLinkedList<T> &list)
+ \relates QLinkedList
+
+ Reads a linked list from stream \a in into \a list.
+
+ This function requires the value type to implement \c operator>>().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*!
+ \fn iterator QLinkedList::remove(iterator pos)
+
+ Use erase() instead.
+*/
+
+/*!
+ \fn int QLinkedList::findIndex(const T& t) const
+
+ If you need indexes then QList or QVector are better choices than
+ QLinkedList.
+
+ \oldcode
+ int index = list->findIndex(value);
+ \newcode
+ int index = 0;
+ bool found = false;
+ for (const_iterator i = list->begin(); i != list->end(); ++i; ++index)
+ if (*i == value) {
+ found = true;
+ break;
+ }
+ if (!found)
+ index = -1;
+ \endcode
+*/
+
+/*!
+ \fn iterator QLinkedList::find(iterator from, const T& t)
+
+ If you need random access to a data structure then QList, QVector,
+ QMap, or QHash, are all better choices than QLinkedList.
+
+ \oldcode
+ QLinkedList::iterator i = list->find(from, value);
+ \newcode
+ QLinkedList::iterator i = from;
+ while (i != list->end() && *i != value)
+ ++i;
+ \endcode
+*/
+
+/*!
+ \fn iterator QLinkedList::find(const T& t)
+
+ If you need random access to a data structure then QList, QVector,
+ QMap, or QHash, are all better choices than QLinkedList.
+
+ \oldcode
+ QLinkedList::iterator i = list->find(value);
+ \newcode
+ QLinkedList::iterator i = list->begin();
+ while (i != list->end() && *i != value)
+ ++i;
+ \endcode
+*/
+
+/*!
+ \fn const_iterator QLinkedList::find(const_iterator from, const T& t) const
+
+ If you need random access to a data structure then QList, QVector,
+ QMap, or QHash, are all better choices than QLinkedList.
+
+ \oldcode
+ QLinkedList::const_iterator i = list->find(from, value);
+ \newcode
+ QLinkedList::const_iterator i = from;
+ while (i != list->end() && *i != value)
+ ++i;
+ \endcode
+*/
+
+/*!
+ \fn const_iterator QLinkedList::find(const T& t) const
+
+ If you need random access to a data structure then QList, QVector,
+ QMap, or QHash, are all better choices than QLinkedList.
+
+ \oldcode
+ QLinkedList::const_iterator i = list->find(value);
+ \newcode
+ QLinkedList::const_iterator i = list->begin();
+ while (i != list->end() && *i != value)
+ ++i;
+ \endcode
+*/
+
+/*!
+ \since 4.1
+ \fn QLinkedList<T> QLinkedList<T>::fromStdList(const std::list<T> &list)
+
+ Returns a QLinkedList object with the data contained in \a list.
+ The order of the elements in the QLinkedList is the same as in \a
+ list.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 16
+
+ \sa toStdList()
+*/
+
+/*!
+ \since 4.1
+ \fn std::list<T> QLinkedList<T>::toStdList() const
+
+ Returns a std::list object with the data contained in this
+ QLinkedList. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 17
+
+ \sa fromStdList()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
new file mode 100644
index 0000000000..b01dcc4ee6
--- /dev/null
+++ b/src/corelib/tools/qlinkedlist.h
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINKEDLIST_H
+#define QLINKEDLIST_H
+
+#include <QtCore/qiterator.h>
+#include <QtCore/qatomic.h>
+
+#ifndef QT_NO_STL
+#include <iterator>
+#include <list>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QLinkedListData
+{
+ QLinkedListData *n, *p;
+ QBasicAtomicInt ref;
+ int size;
+ uint sharable : 1;
+
+ static QLinkedListData shared_null;
+};
+
+template <typename T>
+struct QLinkedListNode
+{
+ inline QLinkedListNode(const T &arg): t(arg) { }
+ QLinkedListNode *n, *p;
+ T t;
+};
+
+template <class T>
+class QLinkedList
+{
+ typedef QLinkedListNode<T> Node;
+ union { QLinkedListData *d; QLinkedListNode<T> *e; };
+
+public:
+ inline QLinkedList() : d(&QLinkedListData::shared_null) { d->ref.ref(); }
+ inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); }
+ ~QLinkedList();
+ QLinkedList<T> &operator=(const QLinkedList<T> &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QLinkedList<T> &operator=(QLinkedList<T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QLinkedList<T> &other) { qSwap(d, other.d); }
+ bool operator==(const QLinkedList<T> &l) const;
+ inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); }
+
+ inline int size() const { return d->size; }
+ inline void detach()
+ { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+ inline bool isSharedWith(const QLinkedList<T> &other) const { return d == other.d; }
+
+ inline bool isEmpty() const { return d->size == 0; }
+
+ void clear();
+
+ void append(const T &);
+ void prepend(const T &);
+ T takeFirst();
+ T takeLast();
+ int removeAll(const T &t);
+ bool removeOne(const T &t);
+ bool contains(const T &t) const;
+ int count(const T &t) const;
+
+ class const_iterator;
+
+ class iterator
+ {
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+ Node *i;
+ inline iterator() : i(0) {}
+ inline iterator(Node *n) : i(n) {}
+ inline iterator(const iterator &o) : i(o.i) {}
+ inline iterator &operator=(const iterator &o) { i = o.i; return *this; }
+ inline T &operator*() const { return i->t; }
+ inline T *operator->() const { return &i->t; }
+ 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 const_iterator &o) const
+ { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const
+ { return i != o.i; }
+ inline iterator &operator++() { i = i->n; return *this; }
+ inline iterator operator++(int) { Node *n = i; i = i->n; return n; }
+ inline iterator &operator--() { i = i->p; return *this; }
+ inline iterator operator--(int) { Node *n = i; i = i->p; return n; }
+ inline iterator operator+(int j) const
+ { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
+ inline iterator operator-(int j) const { return operator+(-j); }
+ inline iterator &operator+=(int j) { return *this = *this + j; }
+ inline iterator &operator-=(int j) { return *this = *this - j; }
+ };
+ friend class iterator;
+
+ class const_iterator
+ {
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+ Node *i;
+ inline const_iterator() : i(0) {}
+ inline const_iterator(Node *n) : i(n) {}
+ inline const_iterator(const const_iterator &o) : i(o.i){}
+ inline const_iterator(iterator ci) : i(ci.i){}
+ inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; }
+ inline const T &operator*() const { return i->t; }
+ inline const T *operator->() const { return &i->t; }
+ 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 const_iterator &operator++() { i = i->n; return *this; }
+ inline const_iterator operator++(int) { Node *n = i; i = i->n; return n; }
+ inline const_iterator &operator--() { i = i->p; return *this; }
+ inline const_iterator operator--(int) { Node *n = i; i = i->p; return n; }
+ inline const_iterator operator+(int j) const
+ { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
+ inline const_iterator operator-(int j) const { return operator+(-j); }
+ inline const_iterator &operator+=(int j) { return *this = *this + j; }
+ inline const_iterator &operator-=(int j) { return *this = *this - j; }
+ };
+ friend class const_iterator;
+
+ // stl style
+ inline iterator begin() { detach(); return e->n; }
+ inline const_iterator begin() const { return e->n; }
+ inline const_iterator constBegin() const { return e->n; }
+ inline iterator end() { detach(); return e; }
+ inline const_iterator end() const { return e; }
+ inline const_iterator constEnd() const { return e; }
+ iterator insert(iterator before, const T &t);
+ iterator erase(iterator pos);
+ iterator erase(iterator first, iterator last);
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline int count() const { return d->size; }
+ 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()); }
+ const T& last() const { Q_ASSERT(!isEmpty()); return *(--end()); }
+ inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
+ inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
+ inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
+ inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+
+ // stl compatibility
+ inline void push_back(const T &t) { append(t); }
+ inline void push_front(const T &t) { prepend(t); }
+ inline T& front() { return first(); }
+ inline const T& front() const { return first(); }
+ inline T& back() { return last(); }
+ inline const T& back() const { return last(); }
+ inline void pop_front() { removeFirst(); }
+ inline void pop_back() { removeLast(); }
+ inline bool empty() const { return isEmpty(); }
+ typedef int 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;
+
+#ifndef QT_NO_STL
+ static inline QLinkedList<T> fromStdList(const std::list<T> &list)
+ { QLinkedList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
+ inline std::list<T> toStdList() const
+ { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+#endif
+
+#ifdef QT3_SUPPORT
+ // compatibility
+ inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); }
+ inline QT3_SUPPORT int findIndex(const T& t) const
+ { int i=0; for (const_iterator it = begin(); it != end(); ++it, ++i) if(*it == t) return i; return -1;}
+ inline QT3_SUPPORT iterator find(iterator from, const T& t)
+ { while (from != end() && !(*from == t)) ++from; return from; }
+ inline QT3_SUPPORT iterator find(const T& t)
+ { return find(begin(), t); }
+ inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const
+ { while (from != end() && !(*from == t)) ++from; return from; }
+ inline QT3_SUPPORT const_iterator find(const T& t) const
+ { return find(begin(), t); }
+#endif
+
+ // comfort
+ QLinkedList<T> &operator+=(const QLinkedList<T> &l);
+ QLinkedList<T> operator+(const QLinkedList<T> &l) const;
+ inline QLinkedList<T> &operator+=(const T &t) { append(t); return *this; }
+ inline QLinkedList<T> &operator<< (const T &t) { append(t); return *this; }
+ inline QLinkedList<T> &operator<<(const QLinkedList<T> &l) { *this += l; return *this; }
+
+private:
+ void detach_helper();
+ void free(QLinkedListData*);
+};
+
+template <typename T>
+inline QLinkedList<T>::~QLinkedList()
+{
+ if (!d)
+ return;
+ if (!d->ref.deref())
+ free(d);
+}
+
+template <typename T>
+void QLinkedList<T>::detach_helper()
+{
+ union { QLinkedListData *d; Node *e; } x;
+ x.d = new QLinkedListData;
+ x.d->ref = 1;
+ x.d->size = d->size;
+ x.d->sharable = true;
+ Node *original = e->n;
+ Node *copy = x.e;
+ while (original != e) {
+ QT_TRY {
+ copy->n = new Node(original->t);
+ copy->n->p = copy;
+ original = original->n;
+ copy = copy->n;
+ } QT_CATCH(...) {
+ copy->n = x.e;
+ free(x.d);
+ QT_RETHROW;
+ }
+ }
+ copy->n = x.e;
+ x.e->p = copy;
+ if (!d->ref.deref())
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QLinkedList<T>::free(QLinkedListData *x)
+{
+ Node *y = reinterpret_cast<Node*>(x);
+ Node *i = y->n;
+ if (x->ref == 0) {
+ while(i != y) {
+ Node *n = i;
+ i = i->n;
+ delete n;
+ }
+ delete x;
+ }
+}
+
+template <typename T>
+void QLinkedList<T>::clear()
+{
+ *this = QLinkedList<T>();
+}
+
+template <typename T>
+QLinkedList<T> &QLinkedList<T>::operator=(const QLinkedList<T> &l)
+{
+ if (d != l.d) {
+ QLinkedListData *o = l.d;
+ o->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = o;
+ if (!d->sharable)
+ detach_helper();
+ }
+ return *this;
+}
+
+template <typename T>
+bool QLinkedList<T>::operator== (const QLinkedList<T> &l) const
+{
+ if (d->size != l.d->size)
+ return false;
+ if (e == l.e)
+ return true;
+ Node *i = e->n;
+ Node *il = l.e->n;
+ while (i != e) {
+ if (! (i->t == il->t))
+ return false;
+ i = i->n;
+ il = il->n;
+ }
+ return true;
+}
+
+template <typename T>
+void QLinkedList<T>::append(const T &t)
+{
+ detach();
+ Node *i = new Node(t);
+ i->n = e;
+ i->p = e->p;
+ i->p->n = i;
+ e->p = i;
+ d->size++;
+}
+
+template <typename T>
+void QLinkedList<T>::prepend(const T &t)
+{
+ detach();
+ Node *i = new Node(t);
+ i->n = e->n;
+ i->p = e;
+ i->n->p = i;
+ e->n = i;
+ d->size++;
+}
+
+template <typename T>
+int QLinkedList<T>::removeAll(const T &_t)
+{
+ detach();
+ const T t = _t;
+ Node *i = e->n;
+ int c = 0;
+ while (i != e) {
+ if (i->t == t) {
+ Node *n = i;
+ i->n->p = i->p;
+ i->p->n = i->n;
+ i = i->n;
+ delete n;
+ c++;
+ } else {
+ i = i->n;
+ }
+ }
+ d->size-=c;
+ return c;
+}
+
+template <typename T>
+bool QLinkedList<T>::removeOne(const T &_t)
+{
+ detach();
+ iterator it = qFind(begin(), end(), _t);
+ if (it != end()) {
+ erase(it);
+ return true;
+ }
+ return false;
+}
+
+template <typename T>
+inline T QLinkedList<T>::takeFirst()
+{
+ T t = first();
+ removeFirst();
+ return t;
+}
+
+template <typename T>
+inline T QLinkedList<T>::takeLast()
+{
+ T t = last();
+ removeLast();
+ return t;
+}
+
+template <typename T>
+bool QLinkedList<T>::contains(const T &t) const
+{
+ Node *i = e;
+ while ((i = i->n) != e)
+ if (i->t == t)
+ return true;
+ return false;
+}
+
+template <typename T>
+int QLinkedList<T>::count(const T &t) const
+{
+ Node *i = e;
+ int c = 0;
+ while ((i = i->n) != e)
+ if (i->t == t)
+ c++;
+ return c;
+}
+
+
+template <typename T>
+typename QLinkedList<T>::iterator QLinkedList<T>::insert(iterator before, const T &t)
+{
+ Node *i = before.i;
+ Node *m = new Node(t);
+ m->n = i;
+ m->p = i->p;
+ m->p->n = m;
+ i->p = m;
+ d->size++;
+ return m;
+}
+
+template <typename T>
+typename QLinkedList<T>::iterator QLinkedList<T>::erase(typename QLinkedList<T>::iterator afirst,
+ typename QLinkedList<T>::iterator alast)
+{
+ while (afirst != alast)
+ erase(afirst++);
+ return alast;
+}
+
+
+template <typename T>
+typename QLinkedList<T>::iterator QLinkedList<T>::erase(iterator pos)
+{
+ detach();
+ Node *i = pos.i;
+ if (i != e) {
+ Node *n = i;
+ i->n->p = i->p;
+ i->p->n = i->n;
+ i = i->n;
+ delete n;
+ d->size--;
+ }
+ return i;
+}
+
+template <typename T>
+QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l)
+{
+ detach();
+ int n = l.d->size;
+ d->size += n;
+ Node *original = l.e->n;
+ while (n--) {
+ QT_TRY {
+ Node *copy = new Node(original->t);
+ original = original->n;
+ copy->n = e;
+ copy->p = e->p;
+ copy->p->n = copy;
+ e->p = copy;
+ } QT_CATCH(...) {
+ // restore the original list
+ while (n++<d->size)
+ removeLast();
+ QT_RETHROW;
+ }
+ }
+ return *this;
+}
+
+template <typename T>
+QLinkedList<T> QLinkedList<T>::operator+(const QLinkedList<T> &l) const
+{
+ QLinkedList<T> n = *this;
+ n += l;
+ return n;
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(LinkedList)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(LinkedList)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLINKEDLIST_H
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
new file mode 100644
index 0000000000..1501daf5a9
--- /dev/null
+++ b/src/corelib/tools/qlist.cpp
@@ -0,0 +1,1919 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <new>
+#include "qlist.h"
+#include "qtools_p.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QList as an array-list combines the easy-of-use of a random
+ access interface with fast list operations and the low memory
+ management overhead of an array. Accessing elements by index,
+ appending, prepending, and removing elements from both the front
+ and the back all happen in constant time O(1). Inserting or
+ removing elements at random index positions \ai happens in linear
+ time, or more precisly in O(min{i,n-i}) <= O(n/2), with n being
+ the number of elements in the list.
+*/
+
+QListData::Data QListData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, true, { 0 } };
+
+static int grow(int size)
+{
+ // dear compiler: don't optimize me out.
+ volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *);
+ return x;
+}
+
+/*!
+ * Detaches the QListData by allocating new memory for a list which will be bigger
+ * than the copied one and is expected to grow further.
+ * *idx is the desired insertion point and is clamped to the actual size of the list.
+ * num is the number of new elements to insert at the insertion point.
+ * Returns the old (shared) data, it is up to the caller to deref() and free().
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+QListData::Data *QListData::detach_grow(int *idx, int num)
+{
+ Data *x = d;
+ int l = x->end - x->begin;
+ int nl = l + num;
+ int alloc = grow(nl);
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+
+ t->ref = 1;
+ t->sharable = true;
+ t->alloc = alloc;
+ // The space reservation algorithm's optimization is biased towards appending:
+ // Something which looks like an append will put the data at the beginning,
+ // while something which looks like a prepend will put it in the middle
+ // instead of at the end. That's based on the assumption that prepending
+ // is uncommon and even an initial prepend will eventually be followed by
+ // at least some appends.
+ int bg;
+ if (*idx < 0) {
+ *idx = 0;
+ bg = (alloc - nl) >> 1;
+ } else if (*idx > l) {
+ *idx = l;
+ bg = 0;
+ } else if (*idx < (l >> 1)) {
+ bg = (alloc - nl) >> 1;
+ } else {
+ bg = 0;
+ }
+ t->begin = bg;
+ t->end = bg + nl;
+ d = t;
+
+ return x;
+}
+
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::detach(), it is only required for binary compatibility for 4.0.x to 4.2.x"
+#endif
+QListData::Data *QListData::detach()
+{
+ Data *x = static_cast<Data *>(qMalloc(DataHeaderSize + d->alloc * sizeof(void *)));
+ Q_CHECK_PTR(x);
+
+ x->ref = 1;
+ x->sharable = true;
+ x->alloc = d->alloc;
+ if (!x->alloc) {
+ x->begin = 0;
+ x->end = 0;
+ } else {
+ x->begin = d->begin;
+ x->end = d->end;
+ }
+
+ qSwap(d, x);
+ if (!x->ref.deref())
+ return x;
+ return 0;
+}
+
+/*!
+ * Detaches the QListData by reallocating new memory.
+ * Returns the old (shared) data, it is up to the caller to deref() and free()
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::detach2(), it is only required for binary compatibility for 4.3.x to 4.5.x"
+#endif
+QListData::Data *QListData::detach2()
+{
+ Data *x = d;
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+
+ ::memcpy(t, d, DataHeaderSize + d->alloc * sizeof(void *));
+
+ t->ref = 1;
+ t->sharable = true;
+ t->alloc = x->alloc;
+ if (!t->alloc) {
+ t->begin = 0;
+ t->end = 0;
+ } else {
+ t->begin = x->begin;
+ t->end = x->end;
+ }
+ d = t;
+
+ return x;
+}
+
+/*!
+ * Detaches the QListData by allocating new memory for a list which possibly
+ * has a different size than the copied one.
+ * Returns the old (shared) data, it is up to the caller to deref() and free()
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+QListData::Data *QListData::detach(int alloc)
+{
+ Data *x = d;
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+
+ t->ref = 1;
+ t->sharable = true;
+ t->alloc = alloc;
+ if (!alloc) {
+ t->begin = 0;
+ t->end = 0;
+ } else {
+ t->begin = x->begin;
+ t->end = x->end;
+ }
+ d = t;
+
+ return x;
+}
+
+/*!
+ * Detaches the QListData by reallocating new memory.
+ * Returns the old (shared) data, it is up to the caller to deref() and free()
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::detach3(), it is only required for binary compatibility for 4.5.x to 4.6.x"
+#endif
+QListData::Data *QListData::detach3()
+{
+ return detach(d->alloc);
+}
+
+void QListData::realloc(int alloc)
+{
+ Q_ASSERT(d->ref == 1);
+ Data *x = static_cast<Data *>(qRealloc(d, DataHeaderSize + alloc * sizeof(void *)));
+ Q_CHECK_PTR(x);
+
+ d = x;
+ d->alloc = alloc;
+ if (!alloc)
+ d->begin = d->end = 0;
+}
+
+// ensures that enough space is available to append n elements
+void **QListData::append(int n)
+{
+ Q_ASSERT(d->ref == 1);
+ int e = d->end;
+ if (e + n > d->alloc) {
+ int b = d->begin;
+ if (b - n >= 2 * d->alloc / 3) {
+ // we have enough space. Just not at the end -> move it.
+ e -= b;
+ ::memcpy(d->array, d->array + b, e * sizeof(void *));
+ d->begin = 0;
+ } else {
+ realloc(grow(d->alloc + n));
+ }
+ }
+ d->end = e + n;
+ return d->array + e;
+}
+
+// ensures that enough space is available to append one element
+void **QListData::append()
+{
+ return append(1);
+}
+
+// ensures that enough space is available to append the list
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::append(), it is only required for binary compatibility up to 4.5.x"
+#endif
+void **QListData::append(const QListData& l)
+{
+ Q_ASSERT(d->ref == 1);
+ int e = d->end;
+ int n = l.d->end - l.d->begin;
+ if (n) {
+ if (e + n > d->alloc)
+ realloc(grow(e + n));
+ ::memcpy(d->array + d->end, l.d->array + l.d->begin, n*sizeof(void*));
+ d->end += n;
+ }
+ return d->array + e;
+}
+
+// ensures that enough space is available to append the list
+void **QListData::append2(const QListData& l)
+{
+ return append(l.d->end - l.d->begin);
+}
+
+void **QListData::prepend()
+{
+ Q_ASSERT(d->ref == 1);
+ if (d->begin == 0) {
+ if (d->end >= d->alloc / 3)
+ realloc(grow(d->alloc + 1));
+
+ if (d->end < d->alloc / 3)
+ d->begin = d->alloc - 2 * d->end;
+ else
+ d->begin = d->alloc - d->end;
+
+ ::memmove(d->array + d->begin, d->array, d->end * sizeof(void *));
+ d->end += d->begin;
+ }
+ return d->array + --d->begin;
+}
+
+void **QListData::insert(int i)
+{
+ Q_ASSERT(d->ref == 1);
+ if (i <= 0)
+ return prepend();
+ int size = d->end - d->begin;
+ if (i >= size)
+ return append();
+
+ bool leftward = false;
+
+ if (d->begin == 0) {
+ if (d->end == d->alloc) {
+ // If the array is full, we expand it and move some items rightward
+ realloc(grow(d->alloc + 1));
+ } else {
+ // If there is free space at the end of the array, we move some items rightward
+ }
+ } else {
+ if (d->end == d->alloc) {
+ // If there is free space at the beginning of the array, we move some items leftward
+ leftward = true;
+ } else {
+ // If there is free space at both ends, we move as few items as possible
+ leftward = (i < size - i);
+ }
+ }
+
+ if (leftward) {
+ --d->begin;
+ ::memmove(d->array + d->begin, d->array + d->begin + 1, i * sizeof(void *));
+ } else {
+ ::memmove(d->array + d->begin + i + 1, d->array + d->begin + i,
+ (size - i) * sizeof(void *));
+ ++d->end;
+ }
+ return d->array + d->begin + i;
+}
+
+void QListData::remove(int i)
+{
+ Q_ASSERT(d->ref == 1);
+ i += d->begin;
+ if (i - d->begin < d->end - i) {
+ if (int offset = i - d->begin)
+ ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *));
+ d->begin++;
+ } else {
+ if (int offset = d->end - i - 1)
+ ::memmove(d->array + i, d->array + i + 1, offset * sizeof(void *));
+ d->end--;
+ }
+}
+
+void QListData::remove(int i, int n)
+{
+ Q_ASSERT(d->ref == 1);
+ i += d->begin;
+ int middle = i + n/2;
+ if (middle - d->begin < d->end - middle) {
+ ::memmove(d->array + d->begin + n, d->array + d->begin,
+ (i - d->begin) * sizeof(void*));
+ d->begin += n;
+ } else {
+ ::memmove(d->array + i, d->array + i + n,
+ (d->end - i - n) * sizeof(void*));
+ d->end -= n;
+ }
+}
+
+void QListData::move(int from, int to)
+{
+ Q_ASSERT(d->ref == 1);
+ if (from == to)
+ return;
+
+ from += d->begin;
+ to += d->begin;
+ void *t = d->array[from];
+
+ if (from < to) {
+ if (d->end == d->alloc || 3 * (to - from) < 2 * (d->end - d->begin)) {
+ ::memmove(d->array + from, d->array + from + 1, (to - from) * sizeof(void *));
+ } else {
+ // optimization
+ if (int offset = from - d->begin)
+ ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *));
+ if (int offset = d->end - (to + 1))
+ ::memmove(d->array + to + 2, d->array + to + 1, offset * sizeof(void *));
+ ++d->begin;
+ ++d->end;
+ ++to;
+ }
+ } else {
+ if (d->begin == 0 || 3 * (from - to) < 2 * (d->end - d->begin)) {
+ ::memmove(d->array + to + 1, d->array + to, (from - to) * sizeof(void *));
+ } else {
+ // optimization
+ if (int offset = to - d->begin)
+ ::memmove(d->array + d->begin - 1, d->array + d->begin, offset * sizeof(void *));
+ if (int offset = d->end - (from + 1))
+ ::memmove(d->array + from, d->array + from + 1, offset * sizeof(void *));
+ --d->begin;
+ --d->end;
+ --to;
+ }
+ }
+ d->array[to] = t;
+}
+
+void **QListData::erase(void **xi)
+{
+ Q_ASSERT(d->ref == 1);
+ int i = xi - (d->array + d->begin);
+ remove(i);
+ return d->array + d->begin + i;
+}
+
+/*! \class QList
+ \brief The QList class is a template class that provides lists.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QList\<T\> is one of Qt's generic \l{container classes}. It
+ stores a list of values and provides fast index-based access as
+ well as fast insertions and removals.
+
+ QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar
+ functionality. Here's an overview:
+
+ \list
+ \i For most purposes, QList is the right class to use. Its
+ index-based API is more convenient than QLinkedList's
+ iterator-based API, and it is usually faster than
+ QVector because of the way it stores its items in
+ memory. It also expands to less code in your executable.
+ \i If you need a real linked list, with guarantees of \l{constant
+ time} insertions in the middle of the list and iterators to
+ items rather than indexes, use QLinkedList.
+ \i If you want the items to occupy adjacent memory positions,
+ use QVector.
+ \endlist
+
+
+ Internally, QList\<T\> is represented as an array of pointers to
+ items of type T. If T is itself a pointer type or a basic type
+ that is no larger than a pointer, or if T is one of Qt's \l{shared
+ classes}, then QList\<T\> stores the items directly in the pointer
+ array. For lists under a thousand items, this array representation
+ allows for very fast insertions in the middle, and it allows
+ index-based access. Furthermore, operations like prepend() and
+ append() are very fast, because QList preallocates memory at both
+ ends of its internal array. (See \l{Algorithmic Complexity} for
+ details.) Note, however, that for unshared list items that are
+ larger than a pointer, each append or insert of a new item
+ requires allocating the new item on the heap, and this per item
+ allocation might make QVector a better choice in cases that do
+ lots of appending or inserting, since QVector allocates memory for
+ its items in a single heap allocation.
+
+ Note that the internal array only ever gets bigger over the life
+ of the list. It never shrinks. The internal array is deallocated
+ by the destructor and by the assignment operator, when one list
+ is assigned to another.
+
+ Here's an example of a QList that stores integers and
+ a QList that stores QDate values:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 0
+
+ Qt includes a QStringList class that inherits QList\<QString\>
+ and adds a few convenience functions, such as QStringList::join()
+ and QStringList::find(). (QString::split() creates QStringLists
+ from strings.)
+
+ QList stores a list of items. The default constructor creates an
+ empty list. To insert items into the list, you can use
+ operator<<():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 1
+
+ QList provides these basic functions to add, move, and remove
+ items: insert(), replace(), removeAt(), move(), and swap(). In
+ addition, it provides the following convenience functions:
+ append(), prepend(), removeFirst(), and removeLast().
+
+ QList uses 0-based indexes, just like C++ arrays. To access the
+ item at a particular index position, you can use operator[](). On
+ non-const lists, operator[]() returns a reference to the item and
+ can be used on the left side of an assignment:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 2
+
+ Because QList is implemented as an array of pointers, this
+ operation is very fast (\l{constant time}). For read-only access,
+ an alternative syntax is to use at():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 3
+
+ at() can be faster than operator[](), because it never causes a
+ \l{deep copy} to occur.
+
+ A common requirement is to remove an item from a list and do
+ something with it. For this, QList provides takeAt(), takeFirst(),
+ and takeLast(). Here's a loop that removes the items from a list
+ one at a time and calls \c delete on them:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 4
+
+ Inserting and removing items at either ends of the list is very
+ fast (\l{constant time} in most cases), because QList
+ preallocates extra space on both sides of its internal buffer to
+ allow for fast growth at both ends of the list.
+
+ If you want to find all occurrences of a particular value in a
+ list, use indexOf() or lastIndexOf(). The former searches forward
+ starting from a given index position, the latter searches
+ backward. Both return the index of a matching item if they find
+ it; otherwise, they return -1. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 5
+
+ If you simply want to check whether a list contains a particular
+ value, use contains(). If you want to find out how many times a
+ particular value occurs in the list, use count(). If you want to
+ replace all occurrences of a particular value with another, use
+ replace().
+
+ QList's value type must be an \l{assignable data type}. This
+ covers most data types that are commonly used, but the compiler
+ won't let you, for example, store a QWidget as a value; instead,
+ store a QWidget *. A few functions have additional requirements;
+ for example, indexOf() and lastIndexOf() expect the value type to
+ 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. QList is implemented in such a way
+ that direct index-based access is just as fast as using iterators.
+
+ 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.
+
+ To make QList as efficient as possible, its member functions don't
+ validate their input before using it. Except for isEmpty(), member
+ functions always assume the list is \e not empty. Member functions
+ that take index values as parameters always assume their index
+ value parameters are in the valid range. This means QList member
+ functions can fail. If you define QT_NO_DEBUG when you compile,
+ failures will not be detected. If you \e don't define QT_NO_DEBUG,
+ failures will be detected using Q_ASSERT() or Q_ASSERT_X() with an
+ appropriate message.
+
+ To avoid failures when your list can be empty, call isEmpty()
+ before calling other member functions. If you must pass an index
+ value that might not be in the valid range, check that it is less
+ than the value returned by size() but \e not less than 0.
+
+ \sa QListIterator, QMutableListIterator, QLinkedList, QVector
+*/
+
+/*!
+ \fn QList<T> QList<T>::mid(int pos, int length) const
+
+ Returns a list whose elements are copied from this list,
+ starting at position \a pos. If \a length is -1 (the default), all
+ elements from \a pos are copied; otherwise \a length elements (or
+ all remaining elements if there are less than \a length elements)
+ are copied.
+*/
+
+/*! \fn QList::QList()
+
+ Constructs an empty list.
+*/
+
+/*! \fn QList::QList(const QList<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QList is
+ \l{implicitly shared}. This makes returning a QList from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QList::QList(std::initializer_list<T> args)
+ \since 4.8
+
+ Construct a list from a std::initilizer_list.
+
+ This constructor is only enabled if the compiler supports C++0x
+*/
+
+/*! \fn QList::~QList()
+
+ Destroys the list. References to the values in the list and all
+ iterators of this list become invalid.
+*/
+
+/*! \fn QList<T> &QList::operator=(const QList<T> &other)
+
+ Assigns \a other to this list and returns a reference to this
+ list.
+*/
+
+/*! \fn void QList::swap(QList<T> &other)
+ \since 4.8
+
+ Swaps list \a other with this list. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QList::operator==(const QList<T> &other) const
+
+ Returns true if \a other is equal to this list; otherwise returns
+ false.
+
+ Two lists are considered equal if they contain the same values in
+ the same order.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QList::operator!=(const QList<T> &other) const
+
+ Returns true if \a other is not equal to this list; otherwise
+ returns false.
+
+ Two lists are considered equal if they contain the same values in
+ the same order.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa operator==()
+*/
+
+/*!
+ \fn int QList::size() const
+
+ Returns the number of items in the list.
+
+ \sa isEmpty(), count()
+*/
+
+/*! \fn void QList::detach()
+
+ \internal
+*/
+
+/*! \fn void QList::detachShared()
+
+ \internal
+
+ like detach(), but does nothing if we're shared_null.
+ This prevents needless mallocs, and makes QList more exception safe
+ in case of cleanup work done in destructors on empty lists.
+*/
+
+/*! \fn bool QList::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QList::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn bool QList::isSharedWith(const QList<T> &other) const
+
+ \internal
+*/
+
+/*! \fn bool QList::isEmpty() const
+
+ Returns true if the list contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn void QList::clear()
+
+ Removes all items from the list.
+
+ \sa removeAll()
+*/
+
+/*! \fn const T &QList::at(int i) const
+
+ Returns the item at index position \a i in the list. \a i must be
+ a valid index position in the list (i.e., 0 <= \a i < size()).
+
+ This function is very fast (\l{constant time}).
+
+ \sa value(), operator[]()
+*/
+
+/*! \fn T &QList::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference.
+ \a i must be a valid index position in the list (i.e., 0 <= \a i <
+ size()).
+
+ This function is very fast (\l{constant time}).
+
+ \sa at(), value()
+*/
+
+/*! \fn const T &QList::operator[](int i) const
+
+ \overload
+
+ Same as at().
+*/
+
+/*! \fn QList::reserve(int alloc)
+
+ Reserve space for \a alloc elements.
+
+ If \a alloc is smaller than the current size of the list, nothing will happen.
+
+ Use this function to avoid repetetive reallocation of QList's internal
+ data if you can predict how many elements will be appended.
+ Note that the reservation applies only to the internal pointer array.
+
+ \since 4.7
+*/
+
+/*! \fn void QList::append(const T &value)
+
+ Inserts \a value at the end of the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 6
+
+ This is the same as list.insert(size(), \a value).
+
+ This operation is typically very fast (\l{constant time}),
+ because QList preallocates extra space on both sides of its
+ internal buffer to allow for fast growth at both ends of the
+ list.
+
+ \sa operator<<(), prepend(), insert()
+*/
+
+/*! \fn void QList::append(const QList<T> &value)
+
+ \overload
+
+ \since 4.5
+
+ Appends the items of the \a value list to this list.
+
+ \sa operator<<(), operator+=()
+*/
+
+/*! \fn void QList::prepend(const T &value)
+
+ Inserts \a value at the beginning of the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 7
+
+ This is the same as list.insert(0, \a value).
+
+ This operation is usually very fast (\l{constant time}), because
+ QList preallocates extra space on both sides of its internal
+ buffer to allow for fast growth at both ends of the list.
+
+ \sa append(), insert()
+*/
+
+/*! \fn void QList::insert(int i, const T &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
+ value is appended to the list.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 8
+
+ \sa append(), prepend(), replace(), removeAt()
+*/
+
+/*! \fn QList::iterator QList::insert(iterator before, const T &value)
+
+ \overload
+
+ Inserts \a value in front of the item pointed to by the
+ iterator \a before. Returns an iterator pointing at the inserted
+ item. Note that the iterator passed to the function will be
+ invalid after the call; the returned iterator should be used
+ instead.
+*/
+
+/*! \fn void QList::replace(int i, const T &value)
+
+ Replaces the item at index position \a i with \a value. \a i must
+ be a valid index position in the list (i.e., 0 <= \a i < size()).
+
+ \sa operator[](), removeAt()
+*/
+
+/*!
+ \fn int QList::removeAll(const T &value)
+
+ Removes all occurrences of \a value in the list and returns the
+ number of entries removed.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 9
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa removeOne(), removeAt(), takeAt(), replace()
+*/
+
+/*!
+ \fn bool QList::removeOne(const T &value)
+ \since 4.4
+
+ Removes the first occurrence of \a value in the list and returns
+ true on success; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 10
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa removeAll(), removeAt(), takeAt(), replace()
+*/
+
+/*! \fn void QList::removeAt(int i)
+
+ Removes the item at index position \a i. \a i must be a valid
+ index position in the list (i.e., 0 <= \a i < size()).
+
+ \sa takeAt(), removeFirst(), removeLast(), removeOne()
+*/
+
+/*! \fn T QList::takeAt(int i)
+
+ Removes the item at index position \a i and returns it. \a i must
+ be a valid index position in the list (i.e., 0 <= \a i < size()).
+
+ If you don't use the return value, removeAt() is more efficient.
+
+ \sa removeAt(), takeFirst(), takeLast()
+*/
+
+/*! \fn T QList::takeFirst()
+
+ Removes the first item in the list and returns it. This is the
+ same as takeAt(0). This function assumes the list is not empty. To
+ avoid failure, call isEmpty() before calling this function.
+
+ This operation takes \l{constant time}.
+
+ If you don't use the return value, removeFirst() is more
+ efficient.
+
+ \sa takeLast(), takeAt(), removeFirst()
+*/
+
+/*! \fn T QList::takeLast()
+
+ Removes the last item in the list and returns it. This is the
+ same as takeAt(size() - 1). This function assumes the list is
+ not empty. To avoid failure, call isEmpty() before calling this
+ function.
+
+ This operation takes \l{constant time}.
+
+ If you don't use the return value, removeLast() is more
+ efficient.
+
+ \sa takeFirst(), takeAt(), removeLast()
+*/
+
+/*! \fn void QList::move(int from, int to)
+
+ Moves the item at index position \a from to index position \a to.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 11
+
+ This is the same as insert(\a{to}, takeAt(\a{from})).This function
+ assumes that both \a from and \a to are at least 0 but less than
+ size(). To avoid failure, test that both \a from and \a to are at
+ least 0 and less than size().
+
+ \sa swap(), insert(), takeAt()
+*/
+
+/*! \fn void QList::swap(int i, int 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
+ at least 0 but less than size(). To avoid failure, test that both
+ \a i and \a j are at least 0 and less than size().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 12
+
+ \sa move()
+*/
+
+/*! \fn int QList::indexOf(const T &value, int from = 0) const
+
+ Returns the index position of the first occurrence of \a value in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 13
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ Note that QList uses 0-based indexes, just like C++ arrays. Negative
+ indexes are not supported with the exception of the value mentioned
+ above.
+
+ \sa lastIndexOf(), contains()
+*/
+
+/*! \fn int QList::lastIndexOf(const T &value, int from = -1) const
+
+ Returns the index position of the last occurrence of \a value 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.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 14
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ Note that QList uses 0-based indexes, just like C++ arrays. Negative
+ indexes are not supported with the exception of the value mentioned
+ above.
+
+ \sa indexOf()
+*/
+
+/*! \fn QBool QList::contains(const T &value) const
+
+ Returns true if the list contains an occurrence of \a value;
+ otherwise returns false.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn int QList::count(const T &value) const
+
+ Returns the number of occurrences of \a value in the list.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa contains(), indexOf()
+*/
+
+/*! \fn bool QList::startsWith(const T &value) const
+ \since 4.5
+
+ Returns true if this list is not empty and its first
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), contains()
+*/
+
+/*! \fn bool QList::endsWith(const T &value) const
+ \since 4.5
+
+ Returns true if this list is not empty and its last
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), contains()
+*/
+
+/*! \fn QList::iterator QList::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the list.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QList::const_iterator QList::begin() const
+
+ \overload
+*/
+
+/*! \fn QList::const_iterator QList::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the list.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QList::iterator QList::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the list.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn const_iterator QList::end() const
+
+ \overload
+*/
+
+/*! \fn QList::const_iterator QList::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the list.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QList::iterator QList::erase(iterator pos)
+
+ Removes the item associated with the iterator \a pos from the
+ list, and returns an iterator to the next item in the list (which
+ may be end()).
+
+ \sa insert(), removeAt()
+*/
+
+/*! \fn QList::iterator QList::erase(iterator begin, 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.
+*/
+
+/*! \typedef QList::Iterator
+
+ Qt-style synonym for QList::iterator.
+*/
+
+/*! \typedef QList::ConstIterator
+
+ Qt-style synonym for QList::const_iterator.
+*/
+
+/*!
+ \typedef QList::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::pointer
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::const_pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QList::const_reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*! \fn int QList::count() const
+
+ Returns the number of items in the list. This is effectively the
+ same as size().
+*/
+
+/*! \fn int QList::length() const
+ \since 4.5
+
+ This function is identical to count().
+
+ \sa count()
+*/
+
+/*! \fn T& QList::first()
+
+ Returns a reference to the first item in the list. The list must
+ not be empty. If the list can be empty, call isEmpty() before
+ calling this function.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn const T& QList::first() const
+
+ \overload
+*/
+
+/*! \fn T& QList::last()
+
+ Returns a reference to the last item in the list. The list must
+ not be empty. If the list can be empty, call isEmpty() before
+ calling this function.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QList::last() const
+
+ \overload
+*/
+
+/*! \fn void QList::removeFirst()
+
+ Removes the first item in the list. Calling this function is
+ equivalent to calling removeAt(0). The list must not be empty. If
+ the list can be empty, call isEmpty() before calling this
+ function.
+
+ \sa removeAt(), takeFirst()
+*/
+
+/*! \fn void QList::removeLast()
+
+ Removes the last item in the list. Calling this function is
+ equivalent to calling removeAt(size() - 1). The list must not be
+ empty. If the list can be empty, call isEmpty() before calling
+ this function.
+
+ \sa removeAt(), takeLast()
+*/
+
+/*! \fn T QList::value(int 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 the index
+ is going to be within bounds, you can use at() instead, which is
+ slightly faster.
+
+ \sa at(), operator[]()
+*/
+
+/*! \fn T QList::value(int i, const T &defaultValue) const
+
+ \overload
+
+ If the index \a i is out of bounds, the function returns
+ \a defaultValue.
+*/
+
+/*! \fn void QList::push_back(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to \l{QList::append()}{append(\a value)}.
+*/
+
+/*! \fn void QList::push_front(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to \l{QList::prepend()}{prepend(\a value)}.
+*/
+
+/*! \fn T& QList::front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to first(). The list must not be empty. If the list can be empty,
+ call isEmpty() before calling this function.
+*/
+
+/*! \fn const T& QList::front() const
+
+ \overload
+*/
+
+/*! \fn T& QList::back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to last(). The list must not be empty. If the list can be empty,
+ call isEmpty() before calling this function.
+*/
+
+/*! \fn const T& QList::back() const
+
+ \overload
+*/
+
+/*! \fn void QList::pop_front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to removeFirst(). The list must not be empty. If the list can be
+ empty, call isEmpty() before calling this function.
+*/
+
+/*! \fn void QList::pop_back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to removeLast(). The list must not be empty. If the list can be
+ empty, call isEmpty() before calling this function.
+*/
+
+/*! \fn bool QList::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty() and returns true if the list is empty.
+*/
+
+/*! \fn QList<T> &QList::operator+=(const QList<T> &other)
+
+ Appends the items of the \a other list to this list and returns a
+ reference to this list.
+
+ \sa operator+(), append()
+*/
+
+/*! \fn void QList::operator+=(const T &value)
+
+ \overload
+
+ Appends \a value to the list.
+
+ \sa append(), operator<<()
+*/
+
+/*! \fn QList<T> QList::operator+(const QList<T> &other) const
+
+ Returns a list that contains all the items in this list followed
+ by all the items in the \a other list.
+
+ \sa operator+=()
+*/
+
+/*! \fn QList<T> &QList::operator<<(const QList<T> &other)
+
+ Appends the items of the \a other list to this list and returns a
+ reference to this list.
+
+ \sa operator+=(), append()
+*/
+
+/*! \fn void QList::operator<<(const T &value)
+
+ \overload
+
+ Appends \a value to the list.
+*/
+
+/*! \class QList::iterator
+ \brief The QList::iterator class provides an STL-style non-const iterator for QList and QQueue.
+
+ QList 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.
+
+ QList\<T\>::iterator allows you to iterate over a QList\<T\> (or
+ QQueue\<T\>) and to modify the list item associated with the
+ iterator. If you want to iterate over a const QList, use
+ QList::const_iterator instead. It is generally good practice to
+ use QList::const_iterator on a non-const QList as well, unless
+ you need to change the QList through the iterator. Const
+ iterators are slightly faster, and can improve code readability.
+
+ The default QList::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QList function like
+ QList::begin(), QList::end(), or QList::insert() before you can
+ start iterating. Here's a typical loop that prints all the items
+ stored in a list:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 15
+
+ Let's see a few examples of things we can do with a
+ QList::iterator that we cannot do with a QList::const_iterator.
+ Here's an example that increments every value stored in a
+ QList\<int\> by 2:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 16
+
+ Most QList functions accept an integer index rather than an
+ iterator. For that reason, iterators are rarely useful in
+ connection with QList. One place where STL-style iterators do
+ make sense is as arguments to \l{generic algorithms}.
+
+ For example, here's how to delete all the widgets stored in a
+ QList\<QWidget *\>:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 17
+
+ Multiple iterators can be used on the same list. However, be
+ aware that any non-const function call performed on the QList
+ will render all existing iterators undefined. If you need to keep
+ iterators over a long period of time, we recommend that you use
+ QLinkedList rather than QList.
+
+ \sa QList::const_iterator, QMutableListIterator
+*/
+
+/*! \typedef QList::iterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating
+ this iterator is a random access iterator.
+*/
+
+/*! \typedef QList::iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QList::iterator::value_type
+
+ \internal
+*/
+
+/*! \typedef QList::iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QList::iterator::reference
+
+ \internal
+*/
+
+/*! \fn QList::iterator::iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QList::begin() QList::end()
+*/
+
+/*! \fn QList::iterator::iterator(Node *node)
+
+ \internal
+*/
+
+/*! \fn QList::iterator::iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn T &QList::iterator::operator*() const
+
+ Returns a modifiable reference to the current item.
+
+ You can change the value of an item by using operator*() on the
+ left side of an assignment, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 18
+
+ \sa operator->()
+*/
+
+/*! \fn T *QList::iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*! \fn T &QList::iterator::operator[](int j) const
+
+ Returns a modifiable reference to the item at position *this +
+ \a{j}.
+
+ This function is provided to make QList iterators behave like C++
+ pointers.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn bool QList::iterator::operator==(const iterator &other) const
+ \fn bool QList::iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QList::iterator::operator!=(const iterator &other) const
+ \fn bool QList::iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QList::iterator::operator<(const iterator& other) const
+ \fn bool QList::iterator::operator<(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is less than
+ the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::iterator::operator<=(const iterator& other) const
+ \fn bool QList::iterator::operator<=(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is less than
+ or equal to the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::iterator::operator>(const iterator& other) const
+ \fn bool QList::iterator::operator>(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is greater
+ than the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::iterator::operator>=(const iterator& other) const
+ \fn bool QList::iterator::operator>=(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is greater
+ than or equal to the item pointed to by the \a other iterator.
+*/
+
+/*! \fn QList::iterator &QList::iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the list and returns an iterator to the new current
+ item.
+
+ Calling this function on QList::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QList::iterator QList::iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the list and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QList::iterator &QList::iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QList::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*! \fn QList::iterator QList::iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*! \fn QList::iterator &QList::iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QList::iterator &QList::iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items. (If \a j is negative,
+ the iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QList::iterator QList::iterator::operator+(int 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.)
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QList::iterator QList::iterator::operator-(int 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.)
+
+ \sa operator+(), operator-=()
+*/
+
+/*! \fn int QList::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.
+*/
+
+/*! \class QList::const_iterator
+ \brief The QList::const_iterator class provides an STL-style const iterator for QList and QQueue.
+
+ QList provides 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.
+
+ QList\<T\>::const_iterator allows you to iterate over a
+ QList\<T\> (or a QQueue\<T\>). If you want to modify the QList as
+ you iterate over it, use QList::iterator instead. It is generally
+ good practice to use QList::const_iterator on a non-const QList
+ as well, unless you need to change the QList through the
+ iterator. Const iterators are slightly faster, and can improve
+ code readability.
+
+ The default QList::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a QList
+ function like QList::constBegin(), QList::constEnd(), or
+ QList::insert() before you can start iterating. Here's a typical
+ loop that prints all the items stored in a list:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 19
+
+ Most QList functions accept an integer index rather than an
+ iterator. For that reason, iterators are rarely useful in
+ connection with QList. One place where STL-style iterators do
+ make sense is as arguments to \l{generic algorithms}.
+
+ For example, here's how to delete all the widgets stored in a
+ QList\<QWidget *\>:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 20
+
+ Multiple iterators can be used on the same list. However, be
+ aware that any non-const function call performed on the QList
+ will render all existing iterators undefined. If you need to keep
+ iterators over a long period of time, we recommend that you use
+ QLinkedList rather than QList.
+
+ \sa QList::iterator, QListIterator
+*/
+
+/*! \fn QList::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QList::constBegin() QList::constEnd()
+*/
+
+/*! \typedef QList::const_iterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating
+ this iterator is a random access iterator.
+*/
+
+/*! \typedef QList::const_iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QList::const_iterator::value_type
+
+ \internal
+*/
+
+/*! \typedef QList::const_iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QList::const_iterator::reference
+
+ \internal
+*/
+
+/*! \fn QList::const_iterator::const_iterator(Node *node)
+
+ \internal
+*/
+
+/*! \fn QList::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QList::const_iterator::const_iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn const T &QList::const_iterator::operator*() const
+
+ Returns the current item.
+
+ \sa operator->()
+*/
+
+/*! \fn const T *QList::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*! \fn const T &QList::const_iterator::operator[](int j) const
+
+ Returns the item at position *this + \a{j}.
+
+ This function is provided to make QList iterators behave like C++
+ pointers.
+
+ \sa operator+()
+*/
+
+/*! \fn bool QList::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QList::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QList::const_iterator::operator<(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is less than
+ the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::const_iterator::operator<=(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is less than
+ or equal to the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::const_iterator::operator>(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is greater
+ than the item pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QList::const_iterator::operator>=(const const_iterator& other) const
+
+ Returns true if the item pointed to by this iterator is greater
+ than or equal to the item pointed to by the \a other iterator.
+*/
+
+/*! \fn QList::const_iterator &QList::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the list and returns an iterator to the new current
+ item.
+
+ Calling this function on QList::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QList::const_iterator QList::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the list and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn QList::const_iterator &QList::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QList::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*! \fn QList::const_iterator QList::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*! \fn QList::const_iterator &QList::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QList::const_iterator &QList::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items. (If \a j is negative,
+ the iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QList::const_iterator QList::const_iterator::operator+(int 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.)
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QList::const_iterator QList::const_iterator::operator-(int 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.)
+
+ \sa operator+(), operator-=()
+*/
+
+/*! \fn int QList::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.
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QList<T> &list)
+ \relates QList
+
+ Writes the list \a list to stream \a out.
+
+ This function requires the value type to implement \c
+ operator<<().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QList<T> &list)
+ \relates QList
+
+ Reads a list from stream \a in into \a list.
+
+ This function requires the value type to implement \c
+ operator>>().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*!
+ \fn iterator QList::remove(iterator pos)
+
+ Use erase() instead.
+*/
+
+/*!
+ \fn int QList::remove(const T &t)
+
+ Use removeAll() instead.
+*/
+
+/*!
+ \fn int QList::findIndex(const T& t) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn iterator QList::find(const T& t)
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn const_iterator QList::find (const T& t) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn iterator QList::find(iterator from, const T& t)
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn const_iterator QList::find(const_iterator from, const T& t) const
+
+ Use indexOf() instead.
+*/
+
+/*! \fn QList<T> QList<T>::fromVector(const QVector<T> &vector)
+
+ Returns a QList object with the data contained in \a vector.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 21
+
+ \sa fromSet(), toVector(), QVector::toList()
+*/
+
+/*! \fn QVector<T> QList<T>::toVector() const
+
+ Returns a QVector object with the data contained in this QList.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 22
+
+ \sa toSet(), fromVector(), QVector::fromList()
+*/
+
+/*! \fn QList<T> QList<T>::fromSet(const QSet<T> &set)
+
+ Returns a QList object with the data contained in \a set. The
+ order of the elements in the QList is undefined.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 23
+
+ \sa fromVector(), toSet(), QSet::toList(), qSort()
+*/
+
+/*! \fn QSet<T> QList<T>::toSet() const
+
+ Returns a QSet object with the data contained in this QList.
+ Since QSet doesn't allow duplicates, the resulting QSet might be
+ smaller than the original list was.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 24
+
+ \sa toVector(), fromSet(), QSet::fromList()
+*/
+
+/*! \fn QList<T> QList<T>::fromStdList(const std::list<T> &list)
+
+ Returns a QList object with the data contained in \a list. The
+ order of the elements in the QList is the same as in \a list.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 25
+
+ \sa toStdList(), QVector::fromStdVector()
+*/
+
+/*! \fn std::list<T> QList<T>::toStdList() const
+
+ Returns a std::list object with the data contained in this QList.
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 26
+
+ \sa fromStdList(), QVector::toStdVector()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
new file mode 100644
index 0000000000..da70b8003d
--- /dev/null
+++ b/src/corelib/tools/qlist.h
@@ -0,0 +1,900 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIST_H
+#define QLIST_H
+
+#include <QtCore/qiterator.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qalgorithms.h>
+
+#ifndef QT_NO_STL
+#include <iterator>
+#include <list>
+#endif
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+#include <iterator>
+#include <initializer_list>
+#endif
+
+#include <new>
+#include <limits.h>
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T> class QVector;
+template <typename T> class QSet;
+
+struct Q_CORE_EXPORT QListData {
+ struct Data {
+ QBasicAtomicInt ref;
+ int alloc, begin, end;
+ uint sharable : 1;
+ void *array[1];
+ };
+ enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
+
+ Data *detach(int alloc);
+ Data *detach_grow(int *i, int n);
+ Data *detach(); // remove in 5.0
+ Data *detach2(); // remove in 5.0
+ Data *detach3(); // remove in 5.0
+ void realloc(int alloc);
+ static Data shared_null;
+ Data *d;
+ void **erase(void **xi);
+ void **append(int n);
+ void **append();
+ void **append(const QListData &l);
+ void **append2(const QListData &l); // remove in 5.0
+ void **prepend();
+ void **insert(int i);
+ void remove(int i);
+ void remove(int i, int n);
+ void move(int from, int to);
+ inline int size() const { return d->end - d->begin; }
+ inline bool isEmpty() const { return d->end == d->begin; }
+ inline void **at(int i) const { return d->array + d->begin + i; }
+ inline void **begin() const { return d->array + d->begin; }
+ inline void **end() const { return d->array + d->end; }
+};
+
+template <typename T>
+class QList
+{
+ struct Node { void *v;
+#if defined(Q_CC_BOR)
+ Q_INLINE_TEMPLATE T &t();
+#else
+ Q_INLINE_TEMPLATE T &t()
+ { return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
+ ? v : this); }
+#endif
+ };
+
+ union { QListData p; QListData::Data *d; };
+
+public:
+ inline QList() : d(&QListData::shared_null) { d->ref.ref(); }
+ inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+ ~QList();
+ QList<T> &operator=(const QList<T> &l);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QList &operator=(QList &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QList<T> &other) { qSwap(d, other.d); }
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QList(std::initializer_list<T> args) : d(&QListData::shared_null)
+ { d->ref.ref(); qCopy(args.begin(), args.end(), std::back_inserter(*this)); }
+#endif
+ bool operator==(const QList<T> &l) const;
+ inline bool operator!=(const QList<T> &l) const { return !(*this == l); }
+
+ inline int size() const { return p.size(); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+
+ inline void detachShared()
+ {
+ // The "this->" qualification is needed for GCCE.
+ if (d->ref != 1 && this->d != &QListData::shared_null)
+ detach_helper();
+ }
+
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+ inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
+
+ inline bool isEmpty() const { return p.isEmpty(); }
+
+ void clear();
+
+ const T &at(int i) const;
+ const T &operator[](int i) const;
+ T &operator[](int i);
+
+ void reserve(int size);
+ void append(const T &t);
+ void append(const QList<T> &t);
+ void prepend(const T &t);
+ void insert(int i, const T &t);
+ void replace(int i, const T &t);
+ void removeAt(int i);
+ int removeAll(const T &t);
+ bool removeOne(const T &t);
+ T takeAt(int i);
+ T takeFirst();
+ T takeLast();
+ void move(int from, int to);
+ void swap(int i, int j);
+ int indexOf(const T &t, int from = 0) const;
+ int lastIndexOf(const T &t, int from = -1) const;
+ QBool contains(const T &t) const;
+ int count(const T &t) const;
+
+ class const_iterator;
+
+ class iterator {
+ public:
+ Node *i;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ inline iterator() : i(0) {}
+ inline iterator(Node *n) : i(n) {}
+ inline iterator(const iterator &o): i(o.i){}
+ inline T &operator*() const { return i->t(); }
+ inline T *operator->() const { return &i->t(); }
+ inline T &operator[](int j) const { return i[j].t(); }
+ 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; }
+#ifndef QT_STRICT_ITERATORS
+ 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; }
+#endif
+ inline iterator &operator++() { ++i; return *this; }
+ inline iterator operator++(int) { Node *n = i; ++i; return n; }
+ inline iterator &operator--() { i--; return *this; }
+ inline iterator operator--(int) { Node *n = i; 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(i+j); }
+ inline iterator operator-(int j) const { return iterator(i-j); }
+ inline int operator-(iterator j) const { return int(i - j.i); }
+ };
+ friend class iterator;
+
+ class const_iterator {
+ public:
+ Node *i;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline const_iterator() : i(0) {}
+ inline const_iterator(Node *n) : i(n) {}
+ inline const_iterator(const const_iterator &o): i(o.i) {}
+#ifdef QT_STRICT_ITERATORS
+ inline explicit const_iterator(const iterator &o): i(o.i) {}
+#else
+ inline const_iterator(const iterator &o): i(o.i) {}
+#endif
+ inline const T &operator*() const { return i->t(); }
+ inline const T *operator->() const { return &i->t(); }
+ inline const T &operator[](int j) const { return i[j].t(); }
+ 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) { Node *n = i; ++i; return n; }
+ inline const_iterator &operator--() { i--; return *this; }
+ inline const_iterator operator--(int) { Node *n = i; 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(i+j); }
+ inline const_iterator operator-(int j) const { return const_iterator(i-j); }
+ inline int operator-(const_iterator j) const { return i - j.i; }
+ };
+ friend class const_iterator;
+
+ // stl style
+ inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); }
+ inline const_iterator begin() const { return reinterpret_cast<Node *>(p.begin()); }
+ inline const_iterator constBegin() const { return reinterpret_cast<Node *>(p.begin()); }
+ inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); }
+ inline const_iterator end() const { return reinterpret_cast<Node *>(p.end()); }
+ inline const_iterator constEnd() const { return reinterpret_cast<Node *>(p.end()); }
+ iterator insert(iterator before, const T &t);
+ iterator erase(iterator pos);
+ iterator erase(iterator first, iterator last);
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline int count() const { return p.size(); }
+ inline int length() const { return p.size(); } // Same as count()
+ inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T& first() const { Q_ASSERT(!isEmpty()); return at(0); }
+ T& last() { Q_ASSERT(!isEmpty()); return *(--end()); }
+ const T& last() const { Q_ASSERT(!isEmpty()); return at(count() - 1); }
+ inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
+ inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
+ 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 length = -1) const;
+
+ T value(int i) const;
+ T value(int i, const T &defaultValue) const;
+
+ // stl compatibility
+ inline void push_back(const T &t) { append(t); }
+ inline void push_front(const T &t) { prepend(t); }
+ inline T& front() { return first(); }
+ inline const T& front() const { return first(); }
+ inline T& back() { return last(); }
+ inline const T& back() const { return last(); }
+ inline void pop_front() { removeFirst(); }
+ inline void pop_back() { removeLast(); }
+ inline bool empty() const { return isEmpty(); }
+ typedef int 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;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); }
+ inline QT3_SUPPORT int remove(const T &t) { return removeAll(t); }
+ inline QT3_SUPPORT int findIndex(const T& t) const { return indexOf(t); }
+ inline QT3_SUPPORT iterator find(const T& t)
+ { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); }
+ inline QT3_SUPPORT const_iterator find (const T& t) const
+ { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); }
+ inline QT3_SUPPORT iterator find(iterator from, const T& t)
+ { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; }
+ inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const
+ { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; }
+#endif
+
+ // comfort
+ QList<T> &operator+=(const QList<T> &l);
+ inline QList<T> operator+(const QList<T> &l) const
+ { QList n = *this; n += l; return n; }
+ inline QList<T> &operator+=(const T &t)
+ { append(t); return *this; }
+ inline QList<T> &operator<< (const T &t)
+ { append(t); return *this; }
+ inline QList<T> &operator<<(const QList<T> &l)
+ { *this += l; return *this; }
+
+ QVector<T> toVector() const;
+ QSet<T> toSet() const;
+
+ static QList<T> fromVector(const QVector<T> &vector);
+ static QList<T> fromSet(const QSet<T> &set);
+
+#ifndef QT_NO_STL
+ static inline QList<T> fromStdList(const std::list<T> &list)
+ { QList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
+ inline std::list<T> toStdList() const
+ { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+#endif
+
+private:
+ Node *detach_helper_grow(int i, int n);
+ void detach_helper(int alloc);
+ void detach_helper();
+ void free(QListData::Data *d);
+
+ void node_construct(Node *n, const T &t);
+ void node_destruct(Node *n);
+ void node_copy(Node *from, Node *to, Node *src);
+ void node_destruct(Node *from, Node *to);
+};
+
+#if defined(Q_CC_BOR)
+template <typename T>
+Q_INLINE_TEMPLATE T &QList<T>::Node::t()
+{ return QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic ? *(T*)v:*(T*)this; }
+#endif
+
+template <typename T>
+Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
+{
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
+ else if (QTypeInfo<T>::isComplex) new (n) T(t);
+#if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
+ // This violates pointer aliasing rules, but it is known to be safe (and silent)
+ // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which
+ // set the same define are assumed to be safe.
+ else *reinterpret_cast<T*>(n) = t;
+#else
+ // This is always safe, but penaltizes unoptimized builds a lot.
+ else ::memcpy(n, &t, sizeof(T));
+#endif
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
+{
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) delete reinterpret_cast<T*>(n->v);
+ else if (QTypeInfo<T>::isComplex) reinterpret_cast<T*>(n)->~T();
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
+{
+ Node *current = from;
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ QT_TRY {
+ while(current != to) {
+ current->v = new T(*reinterpret_cast<T*>(src->v));
+ ++current;
+ ++src;
+ }
+ } QT_CATCH(...) {
+ while (current-- != from)
+ delete reinterpret_cast<T*>(current->v);
+ QT_RETHROW;
+ }
+
+ } else if (QTypeInfo<T>::isComplex) {
+ QT_TRY {
+ while(current != to) {
+ new (current) T(*reinterpret_cast<T*>(src));
+ ++current;
+ ++src;
+ }
+ } QT_CATCH(...) {
+ while (current-- != from)
+ (reinterpret_cast<T*>(current))->~T();
+ QT_RETHROW;
+ }
+ } else {
+ if (src != from && to - from > 0)
+ memcpy(from, src, (to - from) * sizeof(Node *));
+ }
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *from, Node *to)
+{
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
+ while(from != to) --to, delete reinterpret_cast<T*>(to->v);
+ else if (QTypeInfo<T>::isComplex)
+ while (from != to) --to, reinterpret_cast<T*>(to)->~T();
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
+{
+ if (d != l.d) {
+ QListData::Data *o = l.d;
+ o->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = o;
+ if (!d->sharable)
+ detach_helper();
+ }
+ return *this;
+}
+template <typename T>
+inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
+{
+ int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin()));
+ Node *n = reinterpret_cast<Node *>(p.insert(iBefore));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(iBefore);
+ QT_RETHROW;
+ }
+ return n;
+}
+template <typename T>
+inline typename QList<T>::iterator QList<T>::erase(iterator it)
+{ node_destruct(it.i);
+ return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i))); }
+template <typename T>
+inline const T &QList<T>::at(int i) const
+{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
+ return reinterpret_cast<Node *>(p.at(i))->t(); }
+template <typename T>
+inline const T &QList<T>::operator[](int i) const
+{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
+ return reinterpret_cast<Node *>(p.at(i))->t(); }
+template <typename T>
+inline T &QList<T>::operator[](int i)
+{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
+ detach(); return reinterpret_cast<Node *>(p.at(i))->t(); }
+template <typename T>
+inline void QList<T>::removeAt(int i)
+{ if(i >= 0 && i < p.size()) { detach();
+ node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i); } }
+template <typename T>
+inline T QList<T>::takeAt(int i)
+{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range");
+ detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = n->t(); node_destruct(n);
+ p.remove(i); return t; }
+template <typename T>
+inline T QList<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+template <typename T>
+inline T QList<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
+{
+ if (d->alloc < alloc) {
+ if (d->ref != 1)
+ detach_helper(alloc);
+ else
+ p.realloc(alloc);
+ }
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
+{
+ if (d->ref != 1) {
+ Node *n = detach_helper_grow(INT_MAX, 1);
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
+ } else {
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ Node *n = reinterpret_cast<Node *>(p.append());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
+ } else {
+ Node *n, copy;
+ node_construct(&copy, t); // t might be a reference to an object in the array
+ QT_TRY {
+ n = reinterpret_cast<Node *>(p.append());;
+ } QT_CATCH(...) {
+ node_destruct(&copy);
+ QT_RETHROW;
+ }
+ *n = copy;
+ }
+ }
+}
+
+template <typename T>
+inline void QList<T>::prepend(const T &t)
+{
+ if (d->ref != 1) {
+ Node *n = detach_helper_grow(0, 1);
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
+ } else {
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ Node *n = reinterpret_cast<Node *>(p.prepend());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
+ } else {
+ Node *n, copy;
+ node_construct(&copy, t); // t might be a reference to an object in the array
+ QT_TRY {
+ n = reinterpret_cast<Node *>(p.prepend());;
+ } QT_CATCH(...) {
+ node_destruct(&copy);
+ QT_RETHROW;
+ }
+ *n = copy;
+ }
+ }
+}
+
+template <typename T>
+inline void QList<T>::insert(int i, const T &t)
+{
+ if (d->ref != 1) {
+ Node *n = detach_helper_grow(i, 1);
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
+ } else {
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ Node *n = reinterpret_cast<Node *>(p.insert(i));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
+ } else {
+ Node *n, copy;
+ node_construct(&copy, t); // t might be a reference to an object in the array
+ QT_TRY {
+ n = reinterpret_cast<Node *>(p.insert(i));;
+ } QT_CATCH(...) {
+ node_destruct(&copy);
+ QT_RETHROW;
+ }
+ *n = copy;
+ }
+ }
+}
+
+template <typename T>
+inline void QList<T>::replace(int i, const T &t)
+{
+ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::replace", "index out of range");
+ detach();
+ reinterpret_cast<Node *>(p.at(i))->t() = t;
+}
+
+template <typename T>
+inline void QList<T>::swap(int i, int j)
+{
+ Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(),
+ "QList<T>::swap", "index out of range");
+ detach();
+ void *t = d->array[d->begin + i];
+ d->array[d->begin + i] = d->array[d->begin + j];
+ d->array[d->begin + j] = t;
+}
+
+template <typename T>
+inline void QList<T>::move(int from, int to)
+{
+ Q_ASSERT_X(from >= 0 && from < p.size() && to >= 0 && to < p.size(),
+ "QList<T>::move", "index out of range");
+ detach();
+ p.move(from, to);
+}
+
+template<typename T>
+Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const
+{
+ if (alength < 0 || pos + alength > size())
+ alength = size() - pos;
+ if (pos == 0 && alength == size())
+ return *this;
+ QList<T> cpy;
+ cpy.reserve(alength);
+ cpy.d->end = alength;
+ QT_TRY {
+ cpy.node_copy(reinterpret_cast<Node *>(cpy.p.begin()),
+ reinterpret_cast<Node *>(cpy.p.end()),
+ reinterpret_cast<Node *>(p.begin() + pos));
+ } QT_CATCH(...) {
+ // restore the old end
+ cpy.d->end = 0;
+ QT_RETHROW;
+ }
+ return cpy;
+}
+
+template<typename T>
+Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i) const
+{
+ if (i < 0 || i >= p.size()) {
+ return T();
+ }
+ return reinterpret_cast<Node *>(p.at(i))->t();
+}
+
+template<typename T>
+Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const
+{
+ return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t());
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i, int c)
+{
+ Node *n = reinterpret_cast<Node *>(p.begin());
+ QListData::Data *x = p.detach_grow(&i, c);
+ QT_TRY {
+ node_copy(reinterpret_cast<Node *>(p.begin()),
+ reinterpret_cast<Node *>(p.begin() + i), n);
+ } QT_CATCH(...) {
+ qFree(d);
+ d = x;
+ QT_RETHROW;
+ }
+ QT_TRY {
+ node_copy(reinterpret_cast<Node *>(p.begin() + i + c),
+ reinterpret_cast<Node *>(p.end()), n + i);
+ } QT_CATCH(...) {
+ node_destruct(reinterpret_cast<Node *>(p.begin()),
+ reinterpret_cast<Node *>(p.begin() + i));
+ qFree(d);
+ d = x;
+ QT_RETHROW;
+ }
+
+ if (!x->ref.deref())
+ free(x);
+
+ return reinterpret_cast<Node *>(p.begin() + i);
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc)
+{
+ Node *n = reinterpret_cast<Node *>(p.begin());
+ QListData::Data *x = p.detach(alloc);
+ QT_TRY {
+ node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
+ } QT_CATCH(...) {
+ qFree(d);
+ d = x;
+ QT_RETHROW;
+ }
+
+ if (!x->ref.deref())
+ free(x);
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
+{
+ detach_helper(d->alloc);
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
+{
+ if (!d->ref.deref())
+ free(d);
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const
+{
+ if (p.size() != l.p.size())
+ return false;
+ if (d == l.d)
+ return true;
+ Node *i = reinterpret_cast<Node *>(p.end());
+ Node *b = reinterpret_cast<Node *>(p.begin());
+ Node *li = reinterpret_cast<Node *>(l.p.end());
+ while (i != b) {
+ --i; --li;
+ if (!(i->t() == li->t()))
+ return false;
+ }
+ return true;
+}
+
+// ### Qt 5: rename freeData() to avoid confusion with std::free()
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data)
+{
+ node_destruct(reinterpret_cast<Node *>(data->array + data->begin),
+ reinterpret_cast<Node *>(data->array + data->end));
+ qFree(data);
+}
+
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
+{
+ *this = QList<T>();
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
+{
+ detachShared();
+ const T t = _t;
+ int removedCount=0, i=0;
+ Node *n;
+ while (i < p.size())
+ if ((n = reinterpret_cast<Node *>(p.at(i)))->t() == t) {
+ node_destruct(n);
+ p.remove(i);
+ ++removedCount;
+ } else {
+ ++i;
+ }
+ return removedCount;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t)
+{
+ detachShared();
+ int index = indexOf(_t);
+ if (index != -1) {
+ removeAt(index);
+ return true;
+ }
+ return false;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE typename QList<T>::iterator QList<T>::erase(typename QList<T>::iterator afirst,
+ typename QList<T>::iterator alast)
+{
+ for (Node *n = afirst.i; n < alast.i; ++n)
+ node_destruct(n);
+ int idx = afirst - begin();
+ p.remove(idx, alast - afirst);
+ return begin() + idx;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
+{
+ if (!l.isEmpty()) {
+ if (isEmpty()) {
+ *this = l;
+ } else {
+ Node *n = (d->ref != 1)
+ ? detach_helper_grow(INT_MAX, l.size())
+ : reinterpret_cast<Node *>(p.append2(l.p));
+ QT_TRY {
+ node_copy(n, reinterpret_cast<Node *>(p.end()),
+ reinterpret_cast<Node *>(l.p.begin()));
+ } QT_CATCH(...) {
+ // restore the old end
+ d->end -= int(reinterpret_cast<Node *>(p.end()) - n);
+ QT_RETHROW;
+ }
+ }
+ }
+ return *this;
+}
+
+template <typename T>
+inline void QList<T>::append(const QList<T> &t)
+{
+ *this += t;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE int QList<T>::indexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from = qMax(from + p.size(), 0);
+ if (from < p.size()) {
+ Node *n = reinterpret_cast<Node *>(p.at(from -1));
+ Node *e = reinterpret_cast<Node *>(p.end());
+ while (++n != e)
+ if (n->t() == t)
+ return int(n - reinterpret_cast<Node *>(p.begin()));
+ }
+ return -1;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from += p.size();
+ else if (from >= p.size())
+ from = p.size()-1;
+ if (from >= 0) {
+ Node *b = reinterpret_cast<Node *>(p.begin());
+ Node *n = reinterpret_cast<Node *>(p.at(from + 1));
+ while (n-- != b) {
+ if (n->t() == t)
+ return n - b;
+ }
+ }
+ return -1;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QBool QList<T>::contains(const T &t) const
+{
+ Node *b = reinterpret_cast<Node *>(p.begin());
+ Node *i = reinterpret_cast<Node *>(p.end());
+ while (i-- != b)
+ if (i->t() == t)
+ return QBool(true);
+ return QBool(false);
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const
+{
+ int c = 0;
+ Node *b = reinterpret_cast<Node *>(p.begin());
+ Node *i = reinterpret_cast<Node *>(p.end());
+ while (i-- != b)
+ if (i->t() == t)
+ ++c;
+ return c;
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(List)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLIST_H
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
new file mode 100644
index 0000000000..5c4085af41
--- /dev/null
+++ b/src/corelib/tools/qlocale.cpp
@@ -0,0 +1,3281 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#ifndef QT_NO_SYSTEMLOCALE
+QT_BEGIN_NAMESPACE
+class QSystemLocale;
+static QSystemLocale *QSystemLocale_globalSystemLocale();
+QT_END_NAMESPACE
+#endif
+
+#include "qplatformdefs.h"
+
+#include "qdatastream.h"
+#include "qstring.h"
+#include "qlocale.h"
+#include "qlocale_p.h"
+#include "qlocale_tools_p.h"
+#include "qdatetime_p.h"
+#include "qnamespace.h"
+#include "qdatetime.h"
+#include "qstringlist.h"
+#include "qvariant.h"
+#include "qstringbuilder.h"
+#if defined(Q_WS_WIN)
+# include "qt_windows.h"
+# include <time.h>
+#endif
+#if !defined(QWS) && defined(Q_OS_MAC)
+# include "private/qcore_mac_p.h"
+# include <CoreFoundation/CoreFoundation.h>
+#endif
+#include "private/qnumeric_p.h"
+#include "private/qsystemlibrary_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_SYMBIAN)
+void qt_symbianUpdateSystemPrivate();
+void qt_symbianInitSystemLocale();
+#endif
+
+#ifndef QT_NO_SYSTEMLOCALE
+static QSystemLocale *_systemLocale = 0;
+Q_GLOBAL_STATIC_WITH_ARGS(QSystemLocale, QSystemLocale_globalSystemLocale, (true))
+static QLocalePrivate *system_lp = 0;
+Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate)
+#endif
+
+#ifdef QT_USE_ICU
+extern bool qt_initIcu(const QString &localeName);
+#endif
+
+/******************************************************************************
+** Helpers for accessing Qt locale database
+*/
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qlocale_data_p.h"
+QT_END_INCLUDE_NAMESPACE
+
+QLocale::Language QLocalePrivate::codeToLanguage(const QString &code)
+{
+ int len = code.length();
+ if (len != 2 && len != 3)
+ return QLocale::C;
+ ushort uc1 = len-- > 0 ? code[0].toLower().unicode() : 0;
+ ushort uc2 = len-- > 0 ? code[1].toLower().unicode() : 0;
+ ushort uc3 = len-- > 0 ? code[2].toLower().unicode() : 0;
+
+ if (uc1 == 'n' && uc2 == 'o' && uc3 == 0)
+ uc2 = 'b';
+
+ 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);
+ }
+
+ return QLocale::C;
+}
+
+QLocale::Script QLocalePrivate::codeToScript(const QString &code)
+{
+ int len = code.length();
+ if (len != 4)
+ return QLocale::AnyScript;
+
+ // script is titlecased in our data
+ unsigned char c0 = code.at(0).toUpper().toLatin1();
+ unsigned char c1 = code.at(1).toLower().toLatin1();
+ unsigned char c2 = code.at(2).toLower().toLatin1();
+ unsigned char c3 = code.at(3).toLower().toLatin1();
+
+ const unsigned char *c = script_code_list;
+ for (int 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(const QString &code)
+{
+ int len = code.length();
+ if (len != 2 && len != 3)
+ return QLocale::AnyCountry;
+ ushort uc1 = len-- > 0 ? code[0].toUpper().unicode() : 0;
+ ushort uc2 = len-- > 0 ? code[1].toUpper().unicode() : 0;
+ ushort uc3 = len-- > 0 ? code[2].toUpper().unicode() : 0;
+
+ const unsigned char *c = country_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::AnyCountry;
+}
+
+QString QLocalePrivate::languageCode() const
+{
+ if (m_language_id == QLocale::AnyLanguage)
+ return QString();
+ if (m_language_id == QLocale::C)
+ return QLatin1String("C");
+
+ const unsigned char *c = language_code_list + 3*(uint(m_language_id));
+
+ QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
+
+ code[0] = ushort(c[0]);
+ code[1] = ushort(c[1]);
+ if (c[2] != 0)
+ code[2] = ushort(c[2]);
+
+ return code;
+}
+
+QString QLocalePrivate::scriptCode() const
+{
+ if (m_script_id == QLocale::AnyScript || m_script_id > QLocale::LastScript)
+ return QString();
+ const unsigned char *c = script_code_list + 4*(uint(m_script_id));
+ return QString::fromLatin1((const char *)c, 4);
+}
+
+QString QLocalePrivate::countryCode() const
+{
+ if (m_country_id == QLocale::AnyCountry)
+ return QString();
+
+ const unsigned char *c = country_code_list + 3*(uint(m_country_id));
+
+ QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
+
+ code[0] = ushort(c[0]);
+ code[1] = ushort(c[1]);
+ if (c[2] != 0)
+ code[2] = ushort(c[2]);
+
+ return code;
+}
+
+QString QLocalePrivate::bcp47Name() const
+{
+ if (m_language_id == QLocale::AnyLanguage)
+ return QString();
+ if (m_language_id == QLocale::C)
+ return QLatin1String("C");
+ const unsigned char *lang = language_code_list + 3*(uint(m_language_id));
+ const unsigned char *script =
+ (m_script_id != QLocale::AnyScript ? script_code_list + 4*(uint(m_script_id)) : 0);
+ const unsigned char *country =
+ (m_country_id != QLocale::AnyCountry ? country_code_list + 3*(uint(m_country_id)) : 0);
+ char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0);
+ QString name(len, Qt::Uninitialized);
+ QChar *uc = name.data();
+ *uc++ = ushort(lang[0]);
+ *uc++ = ushort(lang[1]);
+ if (lang[2] != 0)
+ *uc++ = ushort(lang[2]);
+ if (script) {
+ *uc++ = QLatin1Char('-');
+ *uc++ = ushort(script[0]);
+ *uc++ = ushort(script[1]);
+ *uc++ = ushort(script[2]);
+ *uc++ = ushort(script[3]);
+ }
+ if (country) {
+ *uc++ = QLatin1Char('-');
+ *uc++ = ushort(country[0]);
+ *uc++ = ushort(country[1]);
+ if (country[2] != 0)
+ *uc++ = ushort(country[2]);
+ }
+ return name;
+}
+
+const QLocalePrivate *QLocalePrivate::findLocale(QLocale::Language language, QLocale::Script script, QLocale::Country country)
+{
+ const unsigned language_id = language;
+ const unsigned script_id = script;
+ const unsigned country_id = country;
+
+ uint idx = locale_index[language_id];
+
+ const QLocalePrivate *d = locale_data + idx;
+
+ if (idx == 0) // default language has no associated country
+ return d;
+
+ if (script == QLocale::AnyScript && country == QLocale::AnyCountry)
+ return d;
+
+ Q_ASSERT(d->languageId() == language_id);
+
+ if (country == QLocale::AnyCountry) {
+ while (d->m_language_id == language_id && d->m_script_id != script_id)
+ ++d;
+ if (d->m_language_id == language_id && d->m_script_id == script_id)
+ return d;
+ } else if (script == QLocale::AnyScript) {
+ while (d->m_language_id == language_id) {
+ if (d->m_script_id == script_id && d->m_country_id == country_id)
+ return d;
+ ++d;
+ }
+ } else {
+ // both script and country are explicitly specified
+ while (d->m_language_id == language_id) {
+ if (d->m_script_id == script_id && d->m_country_id == country_id)
+ return d;
+ ++d;
+ }
+ }
+
+ return locale_data + idx;
+}
+
+static bool parse_locale_tag(const QString &input, int &i, QString *result, const QString &separators)
+{
+ *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
+ return false;
+ *pch++ = *uc++;
+ }
+ result->truncate(size);
+ return true;
+}
+
+bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry)
+{
+ const int length = name.length();
+
+ lang = script = cntry = QString();
+
+ const QString separators = QLatin1String("_-.@");
+ 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())
+ break;
+ QChar sep = i < length ? name.at(i) : QChar();
+ 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;
+ break;
+ case ScriptState: {
+ QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list));
+ 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;
+ }
+ break;
+ }
+ case CountryState:
+ cntry = value;
+ state = NoState;
+ break;
+ case NoState:
+ // shouldn't happen
+ qWarning("QLocale: This should never happen");
+ break;
+ }
+ ++i;
+ }
+ return lang.length() == 2 || lang.length() == 3;
+}
+
+void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang,
+ QLocale::Script &script, QLocale::Country &cntry)
+{
+ lang = QLocale::C;
+ script = QLocale::AnyScript;
+ cntry = QLocale::AnyCountry;
+
+ 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);
+}
+
+static const QLocalePrivate *findLocale(const QString &name)
+{
+ QLocale::Language lang;
+ QLocale::Script script;
+ QLocale::Country cntry;
+ QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
+
+ return QLocalePrivate::findLocale(lang, script, cntry);
+}
+
+QString qt_readEscapedFormatString(const QString &format, int *idx)
+{
+ int &i = *idx;
+
+ Q_ASSERT(format.at(i) == QLatin1Char('\''));
+ ++i;
+ if (i == format.size())
+ return QString();
+ if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
+ ++i;
+ return QLatin1String("'");
+ }
+
+ QString result;
+
+ while (i < format.size()) {
+ if (format.at(i).unicode() == '\'') {
+ if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') {
+ // "''" inside of a quoted string
+ result.append(QLatin1Char('\''));
+ i += 2;
+ } else {
+ break;
+ }
+ } else {
+ result.append(format.at(i++));
+ }
+ }
+ if (i < format.size())
+ ++i;
+
+ return result;
+}
+
+int qt_repeatCount(const QString &s, int i)
+{
+ QChar c = s.at(i);
+ int j = i + 1;
+ while (j < s.size() && s.at(j) == c)
+ ++j;
+ return j - i;
+}
+
+static const QLocalePrivate *default_lp = 0;
+static uint default_number_options = 0;
+
+#ifndef QT_NO_SYSTEMLOCALE
+
+
+/******************************************************************************
+** Default system locale behavior
+*/
+
+/*!
+ Constructs a QSystemLocale object. The constructor will automatically
+ install this object as the system locale and remove any earlier installed
+ system locales.
+*/
+QSystemLocale::QSystemLocale()
+{
+ delete _systemLocale;
+ _systemLocale = this;
+
+ if (system_lp)
+ system_lp->m_language_id = 0;
+}
+
+/*! \internal */
+QSystemLocale::QSystemLocale(bool)
+{ }
+
+/*!
+ Deletes the object.
+*/
+QSystemLocale::~QSystemLocale()
+{
+ if (_systemLocale == this) {
+ _systemLocale = 0;
+
+ if (system_lp)
+ system_lp->m_language_id = 0;
+ }
+}
+
+static const QSystemLocale *systemLocale()
+{
+ if (_systemLocale)
+ return _systemLocale;
+#if defined(Q_OS_SYMBIAN)
+ qt_symbianInitSystemLocale();
+#endif
+ return QSystemLocale_globalSystemLocale();
+}
+
+void QLocalePrivate::updateSystemPrivate()
+{
+ const QSystemLocale *sys_locale = systemLocale();
+ if (!system_lp)
+ system_lp = globalLocalePrivate();
+
+ // tell the object that the system locale has changed.
+ sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
+
+ *system_lp = *sys_locale->fallbackLocale().d();
+
+#if defined(Q_OS_SYMBIAN)
+ qt_symbianUpdateSystemPrivate();
+#endif
+
+ QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
+ if (!res.isNull()) {
+ system_lp->m_language_id = res.toInt();
+ system_lp->m_script_id = QLocale::AnyScript; // default for compatibility
+ }
+ res = sys_locale->query(QSystemLocale::CountryId, QVariant());
+ if (!res.isNull()) {
+ system_lp->m_country_id = res.toInt();
+ system_lp->m_script_id = QLocale::AnyScript; // default for compatibility
+ }
+ res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
+ if (!res.isNull())
+ system_lp->m_script_id = res.toInt();
+
+ res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
+ if (!res.isNull())
+ system_lp->m_decimal = res.toString().at(0).unicode();
+
+ res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
+ if (!res.isNull())
+ system_lp->m_group = res.toString().at(0).unicode();
+
+ res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
+ if (!res.isNull())
+ system_lp->m_zero = res.toString().at(0).unicode();
+
+ res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
+ if (!res.isNull())
+ system_lp->m_minus = res.toString().at(0).unicode();
+
+ res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
+ if (!res.isNull())
+ system_lp->m_plus = res.toString().at(0).unicode();
+
+#ifdef QT_USE_ICU
+ if (!default_lp)
+ qt_initIcu(system_lp->bcp47Name());
+#endif
+
+}
+#endif
+
+static const QLocalePrivate *systemPrivate()
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ // copy over the information from the fallback locale and modify
+ if (!system_lp || system_lp->m_language_id == 0)
+ QLocalePrivate::updateSystemPrivate();
+
+ return system_lp;
+#else
+ return locale_data;
+#endif
+}
+
+static const QLocalePrivate *defaultPrivate()
+{
+ if (!default_lp)
+ default_lp = systemPrivate();
+ return default_lp;
+}
+
+static QString getLocaleListData(const ushort *data, int size, int index)
+{
+ static const ushort separator = ';';
+ while (index && size > 0) {
+ while (*data != separator)
+ ++data, --size;
+ --index;
+ ++data;
+ --size;
+ }
+ const ushort *end = data;
+ while (size > 0 && *end != separator)
+ ++end, --size;
+ if (end-data == 0)
+ return QString();
+ return QString::fromRawData(reinterpret_cast<const QChar*>(data), end-data);
+}
+
+static inline QString getLocaleData(const ushort *data, int size)
+{
+ return size ? QString::fromRawData(reinterpret_cast<const QChar*>(data), size) : QString();
+}
+
+
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &ds, const QLocale &l)
+{
+ ds << l.name();
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds, QLocale &l)
+{
+ QString s;
+ ds >> s;
+ l = QLocale(s);
+ return ds;
+}
+#endif // QT_NO_DATASTREAM
+
+
+static const int locale_data_size = sizeof(locale_data)/sizeof(QLocalePrivate) - 1;
+
+static const QLocalePrivate *dataPointerHelper(quint16 index)
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ Q_ASSERT(index <= locale_data_size);
+ if (index == locale_data_size)
+ return system_lp;
+#else
+ Q_ASSERT(index < locale_data_size);
+#endif
+
+ return &locale_data[index];
+}
+
+static quint16 localePrivateIndex(const QLocalePrivate *p)
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ Q_ASSERT((p >= locale_data && p - locale_data < locale_data_size)
+ || (p != 0 && p == system_lp));
+ quint16 index = p == system_lp ? locale_data_size : p - locale_data;
+#else
+ Q_ASSERT(p >= locale_data && p - locale_data < locale_data_size);
+ quint16 index = p - locale_data;
+#endif
+
+ return index;
+}
+
+/*!
+ Constructs a QLocale object with the specified \a name,
+ which has the format
+ "language[_script][_country][.codeset][@modifier]" or "C", where:
+
+ \list
+ \i language is a lowercase, two-letter, ISO 639 language code,
+ \i script is a titlecase, four-letter, ISO 15924 script code,
+ \i country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations),
+ \i and codeset and modifier are ignored.
+ \endlist
+
+ The separator can be either underscore or a minus sign.
+
+ If the string violates the locale format, or language is not
+ a valid ISO 369 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.
+
+ 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).
+
+ This constructor is much slower than QLocale(Country, Script, Language).
+
+ \sa bcp47Name()
+*/
+
+QLocale::QLocale(const QString &name)
+ : v(0)
+{
+ p.numberOptions = 0;
+ p.index = localePrivateIndex(findLocale(name));
+}
+
+/*!
+ Constructs a QLocale object initialized with the default locale. If
+ no default locale was set using setDefaultLocale(), this locale will
+ be the same as the one returned by system().
+
+ \sa setDefault()
+*/
+
+QLocale::QLocale()
+ : v(0)
+{
+ p.numberOptions = default_number_options;
+ p.index = localePrivateIndex(defaultPrivate());
+}
+
+/*!
+ Constructs a QLocale object with the specified \a language and \a
+ country.
+
+ \list
+ \i If the language/country pair is found in the database, it is used.
+ \i 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),
+ \i 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().
+
+ \sa setDefault() language() country()
+*/
+
+QLocale::QLocale(Language language, Country country)
+ : v(0)
+{
+ const QLocalePrivate *d = QLocalePrivate::findLocale(language, QLocale::AnyScript, country);
+
+ // If not found, should default to system
+ if (d->languageId() == QLocale::C && language != QLocale::C) {
+ p.numberOptions = default_number_options;
+ p.index = localePrivateIndex(defaultPrivate());
+ } else {
+ p.numberOptions = 0;
+ p.index = localePrivateIndex(d);
+ }
+}
+\
+/*!
+ \since 4.8
+
+ Constructs a QLocale object with the specified \a language, \a script and
+ \a country.
+
+ \list
+ \i If the language/script/country is found in the database, it is used.
+ \i 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),
+ \i 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.
+ \i If neither the language nor the country are found, QLocale
+ defaults to the default locale (see setDefault()).
+ \endlist
+
+ The language, script and country that are actually used can be queried
+ using language(), script() and country().
+
+ \sa setDefault() language() script() country()
+*/
+
+QLocale::QLocale(Language language, Script script, Country country)
+ : v(0)
+{
+ const QLocalePrivate *d = QLocalePrivate::findLocale(language, script, country);
+
+ // If not found, should default to system
+ if (d->languageId() == QLocale::C && language != QLocale::C) {
+ p.numberOptions = default_number_options;
+ p.index = localePrivateIndex(defaultPrivate());
+ } else {
+ p.numberOptions = 0;
+ p.index = localePrivateIndex(d);
+ }
+}
+
+/*!
+ Constructs a QLocale object as a copy of \a other.
+*/
+
+QLocale::QLocale(const QLocale &other)
+{
+ v = other.v;
+}
+
+const QLocalePrivate *QLocale::d() const
+{
+ return dataPointerHelper(p.index);
+}
+
+/*!
+ Assigns \a other to this QLocale object and returns a reference
+ to this QLocale object.
+*/
+
+QLocale &QLocale::operator=(const QLocale &other)
+{
+ v = other.v;
+ return *this;
+}
+
+/*!
+ \since 4.2
+
+ Sets the \a options related to number conversions for this
+ QLocale instance.
+*/
+void QLocale::setNumberOptions(NumberOptions options)
+{
+ p.numberOptions = options;
+}
+
+/*!
+ \since 4.2
+
+ Returns the options related to number conversions for this
+ QLocale instance.
+
+ By default, no options are set for the standard locales.
+*/
+QLocale::NumberOptions QLocale::numberOptions() const
+{
+ return static_cast<NumberOption>(p.numberOptions);
+}
+
+/*!
+ \since 4.8
+
+ Returns \a str quoted according to the current locale using the given
+ quotation \a style.
+*/
+QString QLocale::quoteString(const QString &str, QuotationStyle style) const
+{
+ return quoteString(&str, style);
+}
+
+/*!
+ \since 4.8
+
+ \overload
+*/
+QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res;
+ if (style == QLocale::AlternateQuotation)
+ res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation, QVariant::fromValue(str));
+ if (res.isNull() || style == QLocale::StandardQuotation)
+ res = systemLocale()->query(QSystemLocale::StringToStandardQuotation, QVariant::fromValue(str));
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ if (style == QLocale::StandardQuotation)
+ return QChar(d()->m_quotation_start) % str % QChar(d()->m_quotation_end);
+ else
+ return QChar(d()->m_alternate_quotation_start) % str % QChar(d()->m_alternate_quotation_end);
+}
+
+/*!
+ \since 4.8
+
+ Returns a string that represents a join of a given \a list of strings with
+ a separator defined by the locale.
+*/
+QString QLocale::createSeparatedList(const QStringList &list) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res;
+ res = systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list));
+
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ const int size = list.size();
+ if (size == 1) {
+ return list.at(0);
+ } else if (size == 2) {
+ QString format = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_two_idx, d()->m_list_pattern_part_two_size);
+ return format.arg(list.at(0), list.at(1));
+ } else if (size > 2) {
+ QString formatStart = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_start_idx, d()->m_list_pattern_part_start_size);
+ QString formatMid = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_mid_idx, d()->m_list_pattern_part_mid_size);
+ QString formatEnd = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_end_idx, d()->m_list_pattern_part_end_size);
+ QString result = formatStart.arg(list.at(0), list.at(1));
+ for (int i = 2; i < size - 1; ++i)
+ result = formatMid.arg(result, list.at(i));
+ result = formatEnd.arg(result, list.at(size - 1));
+ return result;
+ }
+
+ return QString();
+}
+
+/*!
+ \nonreentrant
+
+ Sets the global default locale to \a locale. These
+ values are used when a QLocale object is constructed with
+ no arguments. If this function is not called, the system's
+ locale is used.
+
+ \warning In a multithreaded application, the default locale
+ should be set at application startup, before any non-GUI threads
+ are created.
+
+ \sa system() c()
+*/
+
+void QLocale::setDefault(const QLocale &locale)
+{
+ default_lp = locale.d();
+ default_number_options = locale.numberOptions();
+
+#ifdef QT_USE_ICU
+ qt_initIcu(locale.bcp47Name());
+#endif
+}
+
+/*!
+ Returns the language of this locale.
+
+ \sa script(), country(), languageToString(), bcp47Name()
+*/
+QLocale::Language QLocale::language() const
+{
+ return Language(d()->languageId());
+}
+
+/*!
+ \since 4.8
+
+ Returns the script of this locale.
+
+ \sa language(), country(), languageToString(), scriptToString(), bcp47Name()
+*/
+QLocale::Script QLocale::script() const
+{
+ return Script(d()->m_script_id);
+}
+
+/*!
+ Returns the country of this locale.
+
+ \sa language(), script(), countryToString(), bcp47Name()
+*/
+QLocale::Country QLocale::country() const
+{
+ return Country(d()->countryId());
+}
+
+/*!
+ 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.
+
+ 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.
+
+ \sa QLocale(const QString &), language(), script(), country(), bcp47Name()
+*/
+
+QString QLocale::name() const
+{
+ Language l = language();
+
+ QString result = d()->languageCode();
+
+ if (l == C)
+ return result;
+
+ Country c = country();
+ if (c == AnyCountry)
+ return result;
+
+ result.append(QLatin1Char('_'));
+ result.append(d()->countryCode());
+
+ return result;
+}
+
+/*!
+ \since 4.8
+
+ Returns the dash-separated language, script and country (and possibly other BCP47 fields)
+ of this locale as a string.
+
+ 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.
+
+ This function tries to conform the locale name to BCP47.
+
+ \sa language(), country(), script(), uiLanguages()
+*/
+QString QLocale::bcp47Name() const
+{
+ return d()->bcp47Name();
+}
+
+/*!
+ Returns a QString containing the name of \a language.
+
+ \sa countryToString(), 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]);
+}
+
+/*!
+ Returns a QString containing the name of \a country.
+
+ \sa languageToString(), scriptToString(), country(), bcp47Name()
+*/
+
+QString QLocale::countryToString(Country country)
+{
+ if (uint(country) > uint(QLocale::LastCountry))
+ return QLatin1String("Unknown");
+ return QLatin1String(country_name_list + country_name_index[country]);
+}
+
+/*!
+ \since 4.8
+
+ Returns a QString containing the name of \a script.
+
+ \sa languageToString(), countryToString(), script(), bcp47Name()
+*/
+QString QLocale::scriptToString(QLocale::Script script)
+{
+ if (uint(script) > uint(QLocale::LastScript))
+ return QLatin1String("Unknown");
+ return QLatin1String(script_name_list + script_name_index[script]);
+}
+
+/*!
+ Returns the short int represented by the localized string \a s,
+ using base \a base. If \a base is 0 the base is determined
+ automatically using the following rules: If the string begins with
+ "0x", it is assumed to be hexadecimal; if it begins with "0", it
+ is assumed to be octal; otherwise it is assumed to be decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toUShort(), toString()
+*/
+
+short QLocale::toShort(const QString &s, bool *ok, int base) const
+{
+ qlonglong i = toLongLong(s, ok, base);
+ if (i < SHRT_MIN || i > SHRT_MAX) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+ return short(i);
+}
+
+/*!
+ Returns the unsigned short int represented by the localized string
+ \a s, using base \a base. If \a base is 0 the base is determined
+ automatically using the following rules: If the string begins with
+ "0x", it is assumed to be hexadecimal; if it begins with "0", it
+ is assumed to be octal; otherwise it is assumed to be decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toShort(), toString()
+*/
+
+ushort QLocale::toUShort(const QString &s, bool *ok, int base) const
+{
+ qulonglong i = toULongLong(s, ok, base);
+ if (i > USHRT_MAX) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+ return ushort(i);
+}
+
+/*!
+ Returns the int represented by the localized string \a s, using
+ base \a base. If \a base is 0 the base is determined automatically
+ using the following rules: If the string begins with "0x", it is
+ assumed to be hexadecimal; if it begins with "0", it is assumed to
+ be octal; otherwise it is assumed to be decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toUInt(), toString()
+*/
+
+int QLocale::toInt(const QString &s, bool *ok, int base) const
+{
+ qlonglong i = toLongLong(s, ok, base);
+ if (i < INT_MIN || i > INT_MAX) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+ return int(i);
+}
+
+/*!
+ Returns the unsigned int represented by the localized string \a s,
+ using base \a base. If \a base is 0 the base is determined
+ automatically using the following rules: If the string begins with
+ "0x", it is assumed to be hexadecimal; if it begins with "0", it
+ is assumed to be octal; otherwise it is assumed to be decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toString()
+*/
+
+uint QLocale::toUInt(const QString &s, bool *ok, int base) const
+{
+ qulonglong i = toULongLong(s, ok, base);
+ if (i > UINT_MAX) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+ return uint(i);
+}
+
+/*!
+ Returns the long long int represented by the localized string \a
+ s, using base \a base. If \a base is 0 the base is determined
+ automatically using the following rules: If the string begins with
+ "0x", it is assumed to be hexadecimal; if it begins with "0", it
+ is assumed to be octal; otherwise it is assumed to be decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toULongLong(), toDouble(), toString()
+*/
+
+
+qlonglong QLocale::toLongLong(const QString &s, bool *ok, int base) const
+{
+ QLocalePrivate::GroupSeparatorMode mode
+ = p.numberOptions & RejectGroupSeparator
+ ? QLocalePrivate::FailOnGroupSeparators
+ : QLocalePrivate::ParseGroupSeparators;
+
+ return d()->stringToLongLong(s, base, ok, mode);
+}
+
+// ### Qt5: make the return type for toULongLong() qulonglong.
+
+/*!
+ Returns the unsigned long long int represented by the localized
+ string \a s, using base \a base. If \a base is 0 the base is
+ determined automatically using the following rules: If the string
+ begins with "0x", it is assumed to be hexadecimal; if it begins
+ with "0", it is assumed to be octal; otherwise it is assumed to be
+ decimal.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not 0, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toLongLong(), toInt(), toDouble(), toString()
+*/
+
+qlonglong QLocale::toULongLong(const QString &s, bool *ok, int base) const
+{
+ QLocalePrivate::GroupSeparatorMode mode
+ = p.numberOptions & RejectGroupSeparator
+ ? QLocalePrivate::FailOnGroupSeparators
+ : QLocalePrivate::ParseGroupSeparators;
+
+ return d()->stringToUnsLongLong(s, base, ok, mode);
+}
+
+/*!
+ Returns the float represented by the localized string \a s, or 0.0
+ if the conversion failed.
+
+ If \a ok is not 0, reports failure by setting
+ *ok to false and success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toDouble(), toInt(), toString()
+*/
+
+#define QT_MAX_FLOAT 3.4028234663852886e+38
+
+float QLocale::toFloat(const QString &s, bool *ok) const
+{
+ bool myOk;
+ double d = toDouble(s, &myOk);
+ if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
+ if (ok != 0)
+ *ok = false;
+ return 0.0;
+ }
+ if (ok != 0)
+ *ok = true;
+ return float(d);
+}
+
+/*!
+ Returns the double represented by the localized string \a s, or
+ 0.0 if the conversion failed.
+
+ If \a ok is not 0, reports failure by setting
+ *ok to false and success by setting *ok to true.
+
+ Unlike QString::toDouble(), this function does not fall back to
+ the "C" locale if the string cannot be interpreted in this
+ locale.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 3
+
+ Notice that the last conversion returns 1234.0, because '.' is the
+ thousands group separator in the German locale.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toFloat(), toInt(), toString()
+*/
+
+double QLocale::toDouble(const QString &s, bool *ok) const
+{
+ QLocalePrivate::GroupSeparatorMode mode
+ = p.numberOptions & RejectGroupSeparator
+ ? QLocalePrivate::FailOnGroupSeparators
+ : QLocalePrivate::ParseGroupSeparators;
+
+ return d()->stringToDouble(s, ok, mode);
+}
+
+/*!
+ Returns a localized string representation of \a i.
+
+ \sa toLongLong()
+*/
+
+QString QLocale::toString(qlonglong i) const
+{
+ int flags = p.numberOptions & OmitGroupSeparator
+ ? 0
+ : QLocalePrivate::ThousandsGroup;
+
+ return d()->longLongToString(i, -1, 10, -1, flags);
+}
+
+/*!
+ \overload
+
+ \sa toULongLong()
+*/
+
+QString QLocale::toString(qulonglong i) const
+{
+ int flags = p.numberOptions & OmitGroupSeparator
+ ? 0
+ : QLocalePrivate::ThousandsGroup;
+
+ return d()->unsLongLongToString(i, -1, 10, -1, flags);
+}
+
+/*!
+ Returns a localized string representation of the given \a date in the
+ specified \a format.
+ If \a format is an empty string, an empty string is returned.
+*/
+
+QString QLocale::toString(const QDate &date, const QString &format) const
+{
+ return d()->dateTimeToString(format, &date, 0, this);
+}
+
+/*!
+ Returns a localized string representation of the given \a date according
+ to the specified \a format.
+*/
+
+QString QLocale::toString(const QDate &date, FormatType format) const
+{
+ if (!date.isValid())
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ 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);
+}
+
+static bool timeFormatContainsAP(const QString &format)
+{
+ int i = 0;
+ while (i < format.size()) {
+ if (format.at(i).unicode() == '\'') {
+ qt_readEscapedFormatString(format, &i);
+ continue;
+ }
+
+ if (format.at(i).toLower().unicode() == 'a')
+ return true;
+
+ ++i;
+ }
+ return false;
+}
+
+static QString timeZone()
+{
+#if defined(Q_OS_WINCE)
+ TIME_ZONE_INFORMATION info;
+ DWORD res = GetTimeZoneInformation(&info);
+ if (res == TIME_ZONE_ID_UNKNOWN)
+ return QString();
+ return QString::fromWCharArray(info.StandardName);
+#elif defined(Q_OS_WIN)
+ _tzset();
+# if defined(_MSC_VER) && _MSC_VER >= 1400
+ size_t returnSize = 0;
+ char timeZoneName[512];
+ if (_get_tzname(&returnSize, timeZoneName, 512, 1))
+ return QString();
+ return QString::fromLocal8Bit(timeZoneName);
+# else
+ return QString::fromLocal8Bit(_tzname[1]);
+# endif
+#elif defined(Q_OS_VXWORKS)
+ return QString();
+#else
+ tzset();
+ return QString::fromLocal8Bit(tzname[1]);
+#endif
+}
+
+/*!
+ 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.
+*/
+QString QLocale::toString(const QTime &time, const QString &format) const
+{
+ return d()->dateTimeToString(format, 0, &time, this);
+}
+
+/*!
+ \since 4.4
+
+ 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.
+*/
+
+QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
+{
+ const QDate dt = dateTime.date();
+ const QTime tm = dateTime.time();
+ return d()->dateTimeToString(format, &dt, &tm, this);
+}
+
+/*!
+ \since 4.4
+
+ Returns a localized string representation of the given \a dateTime according
+ to the specified \a format.
+*/
+
+QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
+{
+ if (!dateTime.isValid())
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::DateTimeToStringLong
+ : QSystemLocale::DateTimeToStringShort,
+ dateTime);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ const QString format_str = dateTimeFormat(format);
+ return toString(dateTime, format_str);
+}
+
+
+/*!
+ Returns a localized string representation of the given \a time in the
+ specified \a format.
+*/
+
+QString QLocale::toString(const QTime &time, FormatType format) const
+{
+ if (!time.isValid())
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort,
+ time);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ QString format_str = timeFormat(format);
+ return toString(time, format_str);
+}
+
+/*!
+ \since 4.1
+
+ Returns the date format used for the current locale.
+
+ If \a format is LongFormat the format will be a long version.
+ Otherwise it uses a shorter version.
+
+ \sa QDate::toString(), QDate::fromString()
+*/
+
+QString QLocale::dateFormat(FormatType format) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort,
+ QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ quint32 idx, size;
+ switch (format) {
+ case LongFormat:
+ idx = d()->m_long_date_format_idx;
+ size = d()->m_long_date_format_size;
+ break;
+ default:
+ idx = d()->m_short_date_format_idx;
+ size = d()->m_short_date_format_size;
+ break;
+ }
+ return getLocaleData(date_format_data + idx, size);
+}
+
+/*!
+ \since 4.1
+
+ Returns the time format used for the current locale.
+
+ If \a format is LongFormat the format will be a long version.
+ Otherwise it uses a shorter version.
+
+ \sa QTime::toString(), QTime::fromString()
+*/
+
+QString QLocale::timeFormat(FormatType format) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort,
+ QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ quint32 idx, size;
+ switch (format) {
+ case LongFormat:
+ idx = d()->m_long_time_format_idx;
+ size = d()->m_long_time_format_size;
+ break;
+ default:
+ idx = d()->m_short_time_format_idx;
+ size = d()->m_short_time_format_size;
+ break;
+ }
+ return getLocaleData(time_format_data + idx, size);
+}
+
+/*!
+ \since 4.4
+
+ Returns the date time format used for the current locale.
+
+ If \a format is ShortFormat the format will be a short version.
+ Otherwise it uses a longer version.
+
+ \sa QDateTime::toString(), QDateTime::fromString()
+*/
+
+QString QLocale::dateTimeFormat(FormatType format) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::DateTimeFormatLong
+ : QSystemLocale::DateTimeFormatShort,
+ QVariant());
+ if (!res.isNull()) {
+ return res.toString();
+ }
+ }
+#endif
+ return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
+}
+
+/*!
+ \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()).
+
+ If the time could not be parsed, returns an invalid time.
+
+ \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
+*/
+#ifndef QT_NO_DATESTRING
+QTime QLocale::toTime(const QString &string, FormatType format) const
+{
+ return toTime(string, timeFormat(format));
+}
+#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()).
+
+ If the date could not be parsed, returns an invalid date.
+
+ \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
+*/
+#ifndef QT_NO_DATESTRING
+QDate QLocale::toDate(const QString &string, FormatType format) const
+{
+ return toDate(string, dateFormat(format));
+}
+#endif
+
+/*!
+ \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()).
+
+ If the string could not be parsed, returns an invalid QDateTime.
+
+ \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
+*/
+
+#ifndef QT_NO_DATESTRING
+QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
+{
+ return toDateTime(string, dateTimeFormat(format));
+}
+#endif
+
+/*!
+ \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.
+
+ If the time could not be parsed, returns an invalid time.
+
+ \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
+*/
+#ifndef QT_NO_DATESTRING
+QTime QLocale::toTime(const QString &string, const QString &format) const
+{
+ QTime time;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
+ dt.defaultLocale = *this;
+ if (dt.parseFormat(format))
+ dt.fromString(string, 0, &time);
+#else
+ 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.
+
+ This function searches month names and the names of the days of
+ the week in the current locale.
+
+ If the date could not be parsed, returns an invalid date.
+
+ \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
+*/
+#ifndef QT_NO_DATESTRING
+QDate QLocale::toDate(const QString &string, const QString &format) const
+{
+ QDate date;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
+ dt.defaultLocale = *this;
+ if (dt.parseFormat(format))
+ dt.fromString(string, &date, 0);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return date;
+}
+#endif
+
+/*!
+ \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.
+
+ \note The month and day names used must be given in the user's local
+ language.
+
+ If the string could not be parsed, returns an invalid QDateTime.
+
+ \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
+*/
+#ifndef QT_NO_DATESTRING
+QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
+{
+#ifndef QT_BOOTSTRAPPED
+ QTime time;
+ QDate date;
+
+ QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
+ dt.defaultLocale = *this;
+ if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
+ return QDateTime(date, time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return QDateTime(QDate(), QTime(-1, -1, -1));
+}
+#endif
+
+
+/*!
+ \since 4.1
+
+ Returns the decimal point character of this locale.
+*/
+QChar QLocale::decimalPoint() const
+{
+ return d()->decimal();
+}
+
+/*!
+ \since 4.1
+
+ Returns the group separator character of this locale.
+*/
+QChar QLocale::groupSeparator() const
+{
+ return d()->group();
+}
+
+/*!
+ \since 4.1
+
+ Returns the percent character of this locale.
+*/
+QChar QLocale::percent() const
+{
+ return d()->percent();
+}
+
+/*!
+ \since 4.1
+
+ Returns the zero digit character of this locale.
+*/
+QChar QLocale::zeroDigit() const
+{
+ return d()->zero();
+}
+
+/*!
+ \since 4.1
+
+ Returns the negative sign character of this locale.
+*/
+QChar QLocale::negativeSign() const
+{
+ return d()->minus();
+}
+
+/*!
+ \since 4.5
+
+ Returns the positive sign character of this locale.
+*/
+QChar QLocale::positiveSign() const
+{
+ return d()->plus();
+}
+
+/*!
+ \since 4.1
+
+ Returns the exponential character of this locale.
+*/
+QChar QLocale::exponential() const
+{
+ return d()->exponential();
+}
+
+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()
+*/
+
+QString QLocale::toString(double i, char f, int prec) const
+{
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ uint flags = 0;
+
+ if (qIsUpper(f))
+ flags = QLocalePrivate::CapitalEorX;
+ f = qToLower(f);
+
+ switch (f) {
+ case 'f':
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case 'e':
+ form = QLocalePrivate::DFExponent;
+ break;
+ case 'g':
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ default:
+ break;
+ }
+
+ if (!(p.numberOptions & OmitGroupSeparator))
+ flags |= QLocalePrivate::ThousandsGroup;
+ return d()->doubleToString(i, prec, form, -1, flags);
+}
+
+/*!
+ \fn QLocale QLocale::c()
+
+ Returns a QLocale object initialized to the "C" locale.
+
+ \sa system()
+*/
+
+/*!
+ 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.
+
+ \sa c()
+*/
+
+QLocale QLocale::system()
+{
+ QLocale result(C);
+ result.p.index = localePrivateIndex(systemPrivate());
+ return result;
+}
+
+
+/*!
+ \since 4.8
+
+ Returns a list of valid locale objects that match the given \a language, \a
+ script and \a country.
+
+ Getting a list of all locales:
+ QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
+*/
+QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
+ QLocale::Script script,
+ QLocale::Country country)
+{
+ if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript ||
+ uint(country) > QLocale::LastCountry)
+ return QList<QLocale>();
+
+ QList<QLocale> result;
+ const QLocalePrivate *d = locale_data;
+ if (language == QLocale::AnyLanguage && script == QLocale::AnyScript && country == QLocale::AnyCountry)
+ result.reserve(locale_data_size);
+ if (language != QLocale::C)
+ d += locale_index[language];
+ while ( (d != locale_data + locale_data_size)
+ && (language == QLocale::AnyLanguage || d->m_language_id == uint(language))) {
+ QLocale locale(QLocale::C);
+ locale.p.index = localePrivateIndex(d);
+ result.append(locale);
+ ++d;
+ }
+ return result;
+}
+
+/*!
+ \obsolete
+ \since 4.3
+
+ Returns the list of countries that have entires for \a language in Qt's locale
+ database. If the result is an empty list, then \a language is not represented in
+ Qt's locale database.
+
+ \sa matchingLocales()
+*/
+QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
+{
+ QList<Country> result;
+
+ unsigned language_id = language;
+ uint idx = locale_index[language_id];
+
+ if (language == C) {
+ result << AnyCountry;
+ return result;
+ }
+
+ const QLocalePrivate *d = locale_data + idx;
+
+ while (d->languageId() == language_id) {
+ result << static_cast<Country>(d->countryId());
+ ++d;
+ }
+
+ return result;
+}
+
+/*!
+ \since 4.2
+
+ Returns the localized name of \a month, in the format specified
+ by \a type.
+
+ \sa dayName(), standaloneMonthName()
+*/
+QString QLocale::monthName(int month, FormatType type) const
+{
+ if (month < 1 || month > 12)
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(type == LongFormat
+ ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort,
+ month);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ quint32 idx, size;
+ switch (type) {
+ case QLocale::LongFormat:
+ idx = d()->m_long_month_names_idx;
+ size = d()->m_long_month_names_size;
+ break;
+ case QLocale::ShortFormat:
+ idx = d()->m_short_month_names_idx;
+ size = d()->m_short_month_names_size;
+ break;
+ case QLocale::NarrowFormat:
+ idx = d()->m_narrow_month_names_idx;
+ size = d()->m_narrow_month_names_size;
+ break;
+ default:
+ return QString();
+ }
+ return getLocaleListData(months_data + idx, size, month - 1);
+}
+
+/*!
+ \since 4.5
+
+ Returns the localized name of \a month that is used as a
+ standalone text, in the format specified by \a type.
+
+ If the locale information doesn't specify the standalone month
+ name then return value is the same as in monthName().
+
+ \sa monthName(), standaloneDayName()
+*/
+QString QLocale::standaloneMonthName(int month, FormatType type) const
+{
+ if (month < 1 || month > 12)
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(type == LongFormat
+ ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort,
+ month);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ quint32 idx, size;
+ switch (type) {
+ case QLocale::LongFormat:
+ idx = d()->m_standalone_long_month_names_idx;
+ size = d()->m_standalone_long_month_names_size;
+ break;
+ case QLocale::ShortFormat:
+ idx = d()->m_standalone_short_month_names_idx;
+ size = d()->m_standalone_short_month_names_size;
+ break;
+ case QLocale::NarrowFormat:
+ idx = d()->m_standalone_narrow_month_names_idx;
+ size = d()->m_standalone_narrow_month_names_size;
+ break;
+ default:
+ return QString();
+ }
+ QString name = getLocaleListData(standalone_months_data + idx, size, month - 1);
+ if (name.isEmpty())
+ return monthName(month, type);
+ return name;
+}
+
+/*!
+ \since 4.2
+
+ Returns the localized name of the \a day (where 1 represents
+ Monday, 2 represents Tuesday and so on), in the format specified
+ by \a type.
+
+ \sa monthName(), standaloneDayName()
+*/
+QString QLocale::dayName(int day, FormatType type) const
+{
+ if (day < 1 || day > 7)
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(type == LongFormat
+ ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
+ day);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ if (day == 7)
+ day = 0;
+
+ quint32 idx, size;
+ switch (type) {
+ case QLocale::LongFormat:
+ idx = d()->m_long_day_names_idx;
+ size = d()->m_long_day_names_size;
+ break;
+ case QLocale::ShortFormat:
+ idx = d()->m_short_day_names_idx;
+ size = d()->m_short_day_names_size;
+ break;
+ case QLocale::NarrowFormat:
+ idx = d()->m_narrow_day_names_idx;
+ size = d()->m_narrow_day_names_size;
+ break;
+ default:
+ return QString();
+ }
+ return getLocaleListData(days_data + idx, size, day);
+}
+
+/*!
+ \since 4.5
+
+ Returns the localized name of the \a day (where 1 represents
+ Monday, 2 represents Tuesday and so on) that is used as a
+ standalone text, in the format specified by \a type.
+
+ If the locale information does not specify the standalone day
+ name then return value is the same as in dayName().
+
+ \sa dayName(), standaloneMonthName()
+*/
+QString QLocale::standaloneDayName(int day, FormatType type) const
+{
+ if (day < 1 || day > 7)
+ return QString();
+
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(type == LongFormat
+ ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
+ day);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ if (day == 7)
+ day = 0;
+
+ quint32 idx, size;
+ switch (type) {
+ case QLocale::LongFormat:
+ idx = d()->m_standalone_long_day_names_idx;
+ size = d()->m_standalone_long_day_names_size;
+ break;
+ case QLocale::ShortFormat:
+ idx = d()->m_standalone_short_day_names_idx;
+ size = d()->m_standalone_short_day_names_size;
+ break;
+ case QLocale::NarrowFormat:
+ idx = d()->m_standalone_narrow_day_names_idx;
+ size = d()->m_standalone_narrow_day_names_size;
+ break;
+ default:
+ return QString();
+ }
+ QString name = getLocaleListData(days_data + idx, size, day);
+ if (name.isEmpty())
+ return dayName(day == 0 ? 7 : day, type);
+ return name;
+}
+
+/*!
+ \since 4.8
+
+ Returns the first day of the week according to the current locale.
+*/
+Qt::DayOfWeek QLocale::firstDayOfWeek() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant());
+ if (!res.isNull())
+ return static_cast<Qt::DayOfWeek>(res.toUInt());
+ }
+#endif
+ return static_cast<Qt::DayOfWeek>(d()->m_first_day_of_week);
+}
+
+QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
+{
+ for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
+ if (ImperialMeasurementSystems[i].languageId == m_language_id
+ && ImperialMeasurementSystems[i].countryId == m_country_id) {
+ return QLocale::ImperialSystem;
+ }
+ }
+ return QLocale::MetricSystem;
+}
+
+/*!
+ \since 4.8
+
+ Returns a list of days that are considered weekdays according to the current locale.
+*/
+QList<Qt::DayOfWeek> QLocale::weekdays() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
+ if (!res.isNull())
+ return static_cast<QList<Qt::DayOfWeek> >(res.value<QList<Qt::DayOfWeek> >());
+ }
+#endif
+ QList<Qt::DayOfWeek> weekdays;
+ quint16 weekendStart = d()->m_weekend_start;
+ quint16 weekendEnd = d()->m_weekend_end;
+ for (int day = Qt::Monday; day <= Qt::Sunday; day++) {
+ if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) ||
+ (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart)))
+ weekdays << static_cast<Qt::DayOfWeek>(day);
+ }
+ return weekdays;
+}
+
+/*!
+ \since 4.4
+
+ Returns the measurement system for the locale.
+*/
+QLocale::MeasurementSystem QLocale::measurementSystem() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
+ if (!res.isNull())
+ return MeasurementSystem(res.toInt());
+ }
+#endif
+
+ return d()->measurementSystem();
+}
+
+/*!
+ \since 4.7
+
+ Returns the text direction of the language.
+*/
+Qt::LayoutDirection QLocale::textDirection() const
+{
+ Language lang = language();
+ if (lang == QLocale::Arabic ||
+ lang == QLocale::Hebrew ||
+ lang == QLocale::Persian ||
+ lang == QLocale::Urdu ||
+ lang == QLocale::Syriac)
+ return Qt::RightToLeft;
+
+ return Qt::LeftToRight;
+}
+
+
+/*!
+ \since 4.5
+
+ Returns the localized name of the "AM" suffix for times specified using
+ the conventions of the 12-hour clock.
+
+ \sa pmText()
+*/
+QString QLocale::amText() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return getLocaleData(am_data + d()->m_am_idx, d()->m_am_size);
+}
+
+/*!
+ \since 4.5
+
+ Returns the localized name of the "PM" suffix for times specified using
+ the conventions of the 12-hour clock.
+
+ \sa amText()
+*/
+QString QLocale::pmText() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return getLocaleData(pm_data + d()->m_pm_idx, d()->m_pm_size);
+}
+
+
+QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *date, const QTime *time,
+ const QLocale *q) const
+{
+ Q_ASSERT(date || time);
+ if ((date && !date->isValid()) || (time && !time->isValid()))
+ return QString();
+ const bool format_am_pm = time && timeFormatContainsAP(format);
+
+ enum { AM, PM } am_pm = AM;
+ int hour12 = time ? time->hour() : -1;
+ if (time) {
+ if (hour12 == 0) {
+ am_pm = AM;
+ hour12 = 12;
+ } else if (hour12 < 12) {
+ am_pm = AM;
+ } else if (hour12 == 12) {
+ am_pm = PM;
+ } else {
+ am_pm = PM;
+ hour12 -= 12;
+ }
+ }
+
+ QString result;
+
+ int i = 0;
+ while (i < format.size()) {
+ if (format.at(i).unicode() == '\'') {
+ result.append(qt_readEscapedFormatString(format, &i));
+ continue;
+ }
+
+ const QChar c = format.at(i);
+ int repeat = qt_repeatCount(format, i);
+ bool used = false;
+ if (date) {
+ switch (c.unicode()) {
+ case 'y':
+ used = true;
+ if (repeat >= 4)
+ repeat = 4;
+ else if (repeat >= 2)
+ repeat = 2;
+
+ switch (repeat) {
+ case 4:
+ result.append(longLongToString(date->year()));
+ break;
+ case 2:
+ result.append(longLongToString(date->year() % 100, -1, 10, 2,
+ QLocalePrivate::ZeroPadded));
+ break;
+ default:
+ repeat = 1;
+ result.append(c);
+ break;
+ }
+ break;
+
+ case 'M':
+ used = true;
+ repeat = qMin(repeat, 4);
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(date->month()));
+ break;
+ case 2:
+ result.append(longLongToString(date->month(), -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ case 3:
+ result.append(q->monthName(date->month(), QLocale::ShortFormat));
+ break;
+ case 4:
+ result.append(q->monthName(date->month(), QLocale::LongFormat));
+ break;
+ }
+ break;
+
+ case 'd':
+ used = true;
+ repeat = qMin(repeat, 4);
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(date->day()));
+ break;
+ case 2:
+ result.append(longLongToString(date->day(), -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ case 3:
+ result.append(q->dayName(date->dayOfWeek(), QLocale::ShortFormat));
+ break;
+ case 4:
+ result.append(q->dayName(date->dayOfWeek(), QLocale::LongFormat));
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (!used && time) {
+ switch (c.unicode()) {
+ case 'h': {
+ used = true;
+ repeat = qMin(repeat, 2);
+ const int hour = format_am_pm ? hour12 : time->hour();
+
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(hour));
+ break;
+ case 2:
+ result.append(longLongToString(hour, -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ }
+ break;
+ }
+ case 'H':
+ used = true;
+ repeat = qMin(repeat, 2);
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(time->hour()));
+ break;
+ case 2:
+ result.append(longLongToString(time->hour(), -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ }
+ break;
+
+ case 'm':
+ used = true;
+ repeat = qMin(repeat, 2);
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(time->minute()));
+ break;
+ case 2:
+ result.append(longLongToString(time->minute(), -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ }
+ break;
+
+ case 's':
+ used = true;
+ repeat = qMin(repeat, 2);
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(time->second()));
+ break;
+ case 2:
+ result.append(longLongToString(time->second(), -1, 10, 2, QLocalePrivate::ZeroPadded));
+ break;
+ }
+ break;
+
+ case 'a':
+ used = true;
+ if (i + 1 < format.length() && format.at(i + 1).unicode() == 'p') {
+ repeat = 2;
+ } else {
+ repeat = 1;
+ }
+ result.append(am_pm == AM ? q->amText().toLower() : q->pmText().toLower());
+ break;
+
+ case 'A':
+ used = true;
+ if (i + 1 < format.length() && format.at(i + 1).unicode() == 'P') {
+ repeat = 2;
+ } else {
+ repeat = 1;
+ }
+ result.append(am_pm == AM ? q->amText().toUpper() : q->pmText().toUpper());
+ break;
+
+ case 'z':
+ used = true;
+ if (repeat >= 3) {
+ repeat = 3;
+ } else {
+ repeat = 1;
+ }
+ switch (repeat) {
+ case 1:
+ result.append(longLongToString(time->msec()));
+ break;
+ case 3:
+ result.append(longLongToString(time->msec(), -1, 10, 3, QLocalePrivate::ZeroPadded));
+ break;
+ }
+ break;
+
+ case 't':
+ used = true;
+ repeat = 1;
+ result.append(timeZone());
+ break;
+ default:
+ break;
+ }
+ }
+ if (!used) {
+ result.append(QString(repeat, c));
+ }
+ i += repeat;
+ }
+
+ return result;
+}
+
+QString QLocalePrivate::doubleToString(double d,
+ int precision,
+ DoubleForm form,
+ int width,
+ unsigned flags) const
+{
+ return QLocalePrivate::doubleToString(zero(), plus(), minus(), exponential(),
+ group(), decimal(),
+ d, precision, form, width, flags);
+}
+
+QString QLocalePrivate::doubleToString(const QChar _zero, const QChar plus, const QChar minus,
+ const QChar exponential, const QChar group, const QChar decimal,
+ double d,
+ int precision,
+ DoubleForm form,
+ int width,
+ unsigned flags)
+{
+ if (precision == -1)
+ precision = 6;
+ if (width == -1)
+ width = 0;
+
+ bool negative = false;
+ bool special_number = false; // nan, +/-inf
+ QString num_str;
+
+ // Detect special numbers (nan, +/-inf)
+ if (qt_is_inf(d)) {
+ num_str = QString::fromLatin1("inf");
+ special_number = true;
+ negative = d < 0;
+ } else if (qt_is_nan(d)) {
+ num_str = QString::fromLatin1("nan");
+ special_number = true;
+ }
+
+ // Handle normal numbers
+ if (!special_number) {
+ int decpt, sign;
+ QString digits;
+
+#ifdef QT_QLOCALE_USES_FCVT
+ // NOT thread safe!
+ if (form == DFDecimal) {
+ digits = QLatin1String(fcvt(d, precision, &decpt, &sign));
+ } else {
+ int pr = precision;
+ if (form == DFExponent)
+ ++pr;
+ else if (form == DFSignificantDigits && pr == 0)
+ pr = 1;
+ digits = QLatin1String(ecvt(d, pr, &decpt, &sign));
+
+ // Chop trailing zeros
+ if (digits.length() > 0) {
+ int last_nonzero_idx = digits.length() - 1;
+ while (last_nonzero_idx > 0
+ && digits.unicode()[last_nonzero_idx] == QLatin1Char('0'))
+ --last_nonzero_idx;
+ digits.truncate(last_nonzero_idx + 1);
+ }
+
+ }
+
+#else
+ int mode;
+ if (form == DFDecimal)
+ mode = 3;
+ else
+ mode = 2;
+
+ /* This next bit is a bit quirky. In DFExponent form, the precision
+ is the number of digits after decpt. So that would suggest using
+ mode=3 for qdtoa. But qdtoa behaves strangely when mode=3 and
+ precision=0. So we get around this by using mode=2 and reasoning
+ that we want precision+1 significant digits, since the decimal
+ point in this mode is always after the first digit. */
+ int pr = precision;
+ if (form == DFExponent)
+ ++pr;
+
+ char *rve = 0;
+ char *buff = 0;
+ QT_TRY {
+ digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff));
+ } QT_CATCH(...) {
+ if (buff != 0)
+ free(buff);
+ QT_RETHROW;
+ }
+ if (buff != 0)
+ free(buff);
+#endif // QT_QLOCALE_USES_FCVT
+
+ if (_zero.unicode() != '0') {
+ ushort z = _zero.unicode() - '0';
+ for (int i = 0; i < digits.length(); ++i)
+ reinterpret_cast<ushort *>(digits.data())[i] += z;
+ }
+
+ bool always_show_decpt = (flags & Alternate || flags & ForcePoint);
+ switch (form) {
+ case DFExponent: {
+ num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
+ digits, decpt, precision, PMDecimalDigits,
+ always_show_decpt);
+ break;
+ }
+ case DFDecimal: {
+ num_str = decimalForm(_zero, decimal, group,
+ digits, decpt, precision, PMDecimalDigits,
+ always_show_decpt, flags & ThousandsGroup);
+ break;
+ }
+ case DFSignificantDigits: {
+ PrecisionMode mode = (flags & Alternate) ?
+ PMSignificantDigits : PMChopTrailingZeros;
+
+ if (decpt != digits.length() && (decpt <= -4 || decpt > precision))
+ num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
+ digits, decpt, precision, mode,
+ always_show_decpt);
+ else
+ num_str = decimalForm(_zero, decimal, group,
+ digits, decpt, precision, mode,
+ always_show_decpt, flags & ThousandsGroup);
+ break;
+ }
+ }
+
+ negative = sign != 0 && !isZero(d);
+ }
+
+ // pad with zeros. LeftAdjusted overrides this flag). Also, we don't
+ // pad special numbers
+ if (flags & QLocalePrivate::ZeroPadded
+ && !(flags & QLocalePrivate::LeftAdjusted)
+ && !special_number) {
+ int num_pad_chars = width - num_str.length();
+ // leave space for the sign
+ if (negative
+ || flags & QLocalePrivate::AlwaysShowSign
+ || flags & QLocalePrivate::BlankBeforePositive)
+ --num_pad_chars;
+
+ for (int i = 0; i < num_pad_chars; ++i)
+ num_str.prepend(_zero);
+ }
+
+ // add sign
+ if (negative)
+ num_str.prepend(minus);
+ else if (flags & QLocalePrivate::AlwaysShowSign)
+ num_str.prepend(plus);
+ else if (flags & QLocalePrivate::BlankBeforePositive)
+ num_str.prepend(QLatin1Char(' '));
+
+ if (flags & QLocalePrivate::CapitalEorX)
+ num_str = num_str.toUpper();
+
+ return num_str;
+}
+
+QString QLocalePrivate::longLongToString(qlonglong l, int precision,
+ int base, int width,
+ unsigned flags) const
+{
+ return QLocalePrivate::longLongToString(zero(), group(), plus(), minus(),
+ l, precision, base, width, flags);
+}
+
+QString QLocalePrivate::longLongToString(const QChar zero, const QChar group,
+ const QChar plus, const QChar 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;
+ }
+
+ 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
+ }
+
+ QString num_str;
+ if (base == 10)
+ num_str = qlltoa(l, base, zero);
+ else
+ num_str = qulltoa(l, base, zero);
+
+ uint cnt_thousand_sep = 0;
+ if (flags & ThousandsGroup && base == 10) {
+ for (int i = num_str.length() - 3; i > 0; i -= 3) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
+ }
+
+ for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
+ num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
+
+ if ((flags & Alternate || 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();
+
+ // 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 & Alternate || flags & ShowBase))
+ num_pad_chars -= 2;
+ // leave space for optional '0b' in binary form
+ else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ num_pad_chars -= 2;
+
+ for (int i = 0; i < num_pad_chars; ++i)
+ num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
+ }
+
+ if (flags & CapitalEorX)
+ num_str = num_str.toUpper();
+
+ if (base == 16 && (flags & Alternate || flags & ShowBase))
+ num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
+ if (base == 2 && (flags & Alternate || flags & ShowBase))
+ num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
+
+ // add sign
+ if (negative)
+ num_str.prepend(minus);
+ else if (flags & AlwaysShowSign)
+ num_str.prepend(plus);
+ else if (flags & BlankBeforePositive)
+ num_str.prepend(QLatin1Char(' '));
+
+ return num_str;
+}
+
+QString QLocalePrivate::unsLongLongToString(qulonglong l, int precision,
+ int base, int width,
+ unsigned flags) const
+{
+ return QLocalePrivate::unsLongLongToString(zero(), group(), plus(),
+ l, precision, base, width, flags);
+}
+
+QString QLocalePrivate::unsLongLongToString(const QChar zero, const QChar group,
+ const QChar plus,
+ qulonglong l, int precision,
+ int base, int width,
+ unsigned flags)
+{
+ bool precision_not_specified = false;
+ if (precision == -1) {
+ precision_not_specified = true;
+ precision = 1;
+ }
+
+ QString num_str = qulltoa(l, base, zero);
+
+ uint cnt_thousand_sep = 0;
+ if (flags & ThousandsGroup && base == 10) {
+ for (int i = num_str.length() - 3; i > 0; i -=3) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
+ }
+
+ for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
+ num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
+
+ if ((flags & Alternate || 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();
+
+ // leave space for optional '0x' in hex form
+ if (base == 16 && flags & Alternate)
+ num_pad_chars -= 2;
+ // leave space for optional '0b' in binary form
+ else if (base == 2 && flags & Alternate)
+ num_pad_chars -= 2;
+
+ for (int i = 0; i < num_pad_chars; ++i)
+ num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
+ }
+
+ if (flags & CapitalEorX)
+ num_str = num_str.toUpper();
+
+ if (base == 16 && (flags & Alternate || flags & ShowBase))
+ num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
+ else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
+
+ // add sign
+ if (flags & AlwaysShowSign)
+ num_str.prepend(plus);
+ else if (flags & BlankBeforePositive)
+ num_str.prepend(QLatin1Char(' '));
+
+ return num_str;
+}
+
+/*
+ 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.
+*/
+bool QLocalePrivate::numberToCLocale(const QString &num,
+ GroupSeparatorMode group_sep_mode,
+ CharBuff *result) const
+{
+ const QChar *uc = num.unicode();
+ int l = num.length();
+ int idx = 0;
+
+ // Skip whitespace
+ while (idx < l && uc[idx].isSpace())
+ ++idx;
+ if (idx == l)
+ return false;
+
+ const QChar _group = group();
+
+ while (idx < l) {
+ const QChar &in = uc[idx];
+
+ char out = digitToCLocale(in);
+ if (out == 0) {
+ if (in == list())
+ out = ';';
+ else if (in == percent())
+ out = '%';
+ // for handling base-x numbers
+ else if (in.unicode() >= 'A' && in.unicode() <= 'Z')
+ out = in.toLower().toLatin1();
+ else if (in.unicode() >= 'a' && in.unicode() <= 'z')
+ out = in.toLatin1();
+ else
+ break;
+ }
+
+ result->append(out);
+
+ ++idx;
+ }
+
+ // Check trailing whitespace
+ for (; idx < l; ++idx) {
+ if (!uc[idx].isSpace())
+ return false;
+ }
+
+ result->append('\0');
+
+ // Check separators
+ if (group_sep_mode == ParseGroupSeparators
+ && !removeGroupSeparators(result))
+ return false;
+
+
+ return true;
+}
+
+bool QLocalePrivate::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
+ int decDigits) const
+{
+ buff->clear();
+ buff->reserve(str.length());
+
+ const bool scientific = numMode == DoubleScientificMode;
+ bool lastWasE = false;
+ bool lastWasDigit = false;
+ int eCnt = 0;
+ int decPointCnt = 0;
+ bool dec = false;
+ int decDigitCnt = 0;
+
+ for (int i = 0; i < str.length(); ++i) {
+ char c = digitToCLocale(str.at(i));
+
+ 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;
+ }
+ 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 '+':
+ 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 ',':
+ //it can only be placed after a digit which is before the decimal point
+ if (!lastWasDigit || decPointCnt > 0)
+ return false;
+ 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;
+
+ default:
+ // If it's not a valid digit, it shall be Invalid.
+ return false;
+ }
+ lastWasDigit = false;
+ }
+
+ lastWasE = c == 'e';
+ if (c != ',')
+ buff->append(c);
+ }
+
+ return true;
+}
+
+double QLocalePrivate::stringToDouble(const QString &number, bool *ok,
+ GroupSeparatorMode group_sep_mode) const
+{
+ CharBuff buff;
+ if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
+ group_sep_mode, &buff)) {
+ if (ok != 0)
+ *ok = false;
+ return 0.0;
+ }
+ return bytearrayToDouble(buff.constData(), ok);
+}
+
+qlonglong QLocalePrivate::stringToLongLong(const QString &number, int base,
+ bool *ok, GroupSeparatorMode group_sep_mode) const
+{
+ CharBuff buff;
+ if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
+ group_sep_mode, &buff)) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+
+ return bytearrayToLongLong(buff.constData(), base, ok);
+}
+
+qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base,
+ bool *ok, GroupSeparatorMode group_sep_mode) const
+{
+ CharBuff buff;
+ if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
+ group_sep_mode, &buff)) {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+
+ return bytearrayToUnsLongLong(buff.constData(), base, ok);
+}
+
+
+double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
+{
+ if (ok != 0)
+ *ok = true;
+ if (overflow != 0)
+ *overflow = false;
+
+ if (*num == '\0') {
+ if (ok != 0)
+ *ok = false;
+ return 0.0;
+ }
+
+ if (qstrcmp(num, "nan") == 0)
+ return qt_snan();
+
+ if (qstrcmp(num, "+inf") == 0 || qstrcmp(num, "inf") == 0)
+ return qt_inf();
+
+ if (qstrcmp(num, "-inf") == 0)
+ return -qt_inf();
+
+ bool _ok;
+ const char *endptr;
+ double d = qstrtod(num, &endptr, &_ok);
+
+ if (!_ok) {
+ // the only way strtod can fail with *endptr != '\0' on a non-empty
+ // input string is overflow
+ if (ok != 0)
+ *ok = false;
+ if (overflow != 0)
+ *overflow = *endptr != '\0';
+ return 0.0;
+ }
+
+ if (*endptr != '\0') {
+ // we stopped at a non-digit character after converting some digits
+ if (ok != 0)
+ *ok = false;
+ if (overflow != 0)
+ *overflow = false;
+ return 0.0;
+ }
+
+ if (ok != 0)
+ *ok = true;
+ if (overflow != 0)
+ *overflow = false;
+ return d;
+}
+
+qlonglong QLocalePrivate::bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow)
+{
+ bool _ok;
+ const char *endptr;
+
+ if (*num == '\0') {
+ if (ok != 0)
+ *ok = false;
+ if (overflow != 0)
+ *overflow = false;
+ return 0;
+ }
+
+ qlonglong l = qstrtoll(num, &endptr, base, &_ok);
+
+ if (!_ok) {
+ if (ok != 0)
+ *ok = false;
+ if (overflow != 0) {
+ // the only way qstrtoll can fail with *endptr != '\0' on a non-empty
+ // input string is overflow
+ *overflow = *endptr != '\0';
+ }
+ return 0;
+ }
+
+ if (*endptr != '\0') {
+ // we stopped at a non-digit character after converting some digits
+ if (ok != 0)
+ *ok = false;
+ if (overflow != 0)
+ *overflow = false;
+ return 0;
+ }
+
+ if (ok != 0)
+ *ok = true;
+ if (overflow != 0)
+ *overflow = false;
+ return l;
+}
+
+qulonglong QLocalePrivate::bytearrayToUnsLongLong(const char *num, int base, bool *ok)
+{
+ bool _ok;
+ const char *endptr;
+ qulonglong l = qstrtoull(num, &endptr, base, &_ok);
+
+ if (!_ok || *endptr != '\0') {
+ if (ok != 0)
+ *ok = false;
+ return 0;
+ }
+
+ if (ok != 0)
+ *ok = true;
+ return l;
+}
+
+/*!
+ \since 4.8
+
+ \enum QLocale::CurrencySymbolFormat
+
+ Specifies the format of the currency symbol.
+
+ \value CurrencyIsoCode a ISO-4217 code of the currency.
+ \value CurrencySymbol a currency symbol.
+ \value CurrencyDisplayName a user readable name of the currency.
+*/
+
+/*!
+ \since 4.8
+ Returns a currency symbol according to the \a format.
+*/
+QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::CurrencySymbol, format);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ quint32 idx, size;
+ switch (format) {
+ case CurrencySymbol:
+ idx = d()->m_currency_symbol_idx;
+ size = d()->m_currency_symbol_size;
+ return getLocaleData(currency_symbol_data + idx, size);
+ case CurrencyDisplayName:
+ idx = d()->m_currency_display_name_idx;
+ size = d()->m_currency_display_name_size;
+ return getLocaleListData(currency_display_name_data + idx, size, 0);
+ case CurrencyIsoCode: {
+ int len = 0;
+ const QLocalePrivate *d = this->d();
+ for (; len < 3; ++len)
+ if (!d->m_currency_iso_code[len])
+ break;
+ return len ? QString::fromLatin1(d->m_currency_iso_code, len) : QString();
+ }
+ }
+ return QString();
+}
+
+/*!
+ \since 4.8
+
+ Returns a localized string representation of \a value as a currency.
+ If the \a symbol is provided it is used instead of the default currency symbol.
+
+ \sa currencySymbol()
+*/
+QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QSystemLocale::CurrencyToStringArgument arg(value, symbol);
+ QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ const QLocalePrivate *d = this->d();
+ quint8 idx = d->m_currency_format_idx;
+ quint8 size = d->m_currency_format_size;
+ if (d->m_currency_negative_format_size && value < 0) {
+ idx = d->m_currency_negative_format_idx;
+ size = d->m_currency_negative_format_size;
+ value = -value;
+ }
+ QString str = d->longLongToString(value);
+ QString sym = symbol.isNull() ? currencySymbol() : symbol;
+ if (sym.isEmpty())
+ sym = currencySymbol(QLocale::CurrencyIsoCode);
+ QString format = getLocaleData(currency_format_data + idx, size);
+ return format.arg(str, sym);
+}
+
+/*!
+ \since 4.8
+ \overload
+*/
+QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QSystemLocale::CurrencyToStringArgument arg(value, symbol);
+ QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ const QLocalePrivate *d = this->d();
+ quint8 idx = d->m_currency_format_idx;
+ quint8 size = d->m_currency_format_size;
+ QString str = d->unsLongLongToString(value);
+ QString sym = symbol.isNull() ? currencySymbol() : symbol;
+ if (sym.isEmpty())
+ sym = currencySymbol(QLocale::CurrencyIsoCode);
+ QString format = getLocaleData(currency_format_data + idx, size);
+ return format.arg(str, sym);
+}
+
+/*!
+ \since 4.8
+ \overload
+*/
+QString QLocale::toCurrencyString(double value, const QString &symbol) const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QSystemLocale::CurrencyToStringArgument arg(value, symbol);
+ QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ const QLocalePrivate *d = this->d();
+ quint8 idx = d->m_currency_format_idx;
+ quint8 size = d->m_currency_format_size;
+ if (d->m_currency_negative_format_size && value < 0) {
+ idx = d->m_currency_negative_format_idx;
+ size = d->m_currency_negative_format_size;
+ value = -value;
+ }
+ QString str = d->doubleToString(value, d->m_currency_digits,
+ QLocalePrivate::DFDecimal);
+ QString sym = symbol.isNull() ? currencySymbol() : symbol;
+ if (sym.isEmpty())
+ sym = currencySymbol(QLocale::CurrencyIsoCode);
+ QString format = getLocaleData(currency_format_data + idx, size);
+ return format.arg(str, sym);
+}
+
+/*!
+ \since 4.8
+
+ Returns an ordered list of locale names for translation purposes in
+ preference order.
+
+ 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
+ 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
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant());
+ if (!res.isNull()) {
+ QStringList result = res.toStringList();
+ if (!result.isEmpty())
+ return result;
+ }
+ }
+#endif
+ return QStringList(bcp47Name());
+}
+
+/*!
+ \since 4.8
+
+ Returns a native name of the language for the locale. For example
+ "Schwiizertüütsch" for Swiss-German locale.
+
+ \sa nativeCountryName(), languageToString()
+*/
+QString QLocale::nativeLanguageName() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::NativeLanguageName, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return getLocaleData(endonyms_data + d()->m_language_endonym_idx, d()->m_language_endonym_size);
+}
+
+/*!
+ \since 4.8
+
+ Returns a native name of the country for the locale. For example
+ "España" for Spanish/Spain locale.
+
+ \sa nativeLanguageName(), countryToString()
+*/
+QString QLocale::nativeCountryName() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d() == systemPrivate()) {
+ QVariant res = systemLocale()->query(QSystemLocale::NativeCountryName, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return getLocaleData(endonyms_data + d()->m_country_endonym_idx, d()->m_country_endonym_size);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
new file mode 100644
index 0000000000..9f44e3001e
--- /dev/null
+++ b/src/corelib/tools/qlocale.h
@@ -0,0 +1,818 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCALE_H
+#define QLOCALE_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QDataStream;
+class QDate;
+class QDateTime;
+class QTime;
+class QVariant;
+class QTextStream;
+class QTextStreamPrivate;
+
+class QLocale;
+
+#ifndef QT_NO_SYSTEMLOCALE
+class Q_CORE_EXPORT QSystemLocale
+{
+public:
+ QSystemLocale();
+ virtual ~QSystemLocale();
+
+ struct CurrencyToStringArgument
+ {
+ CurrencyToStringArgument() { }
+ CurrencyToStringArgument(const QVariant &v, const QString &s)
+ : value(v), symbol(s) { }
+ QVariant value;
+ QString symbol;
+ };
+
+ enum QueryType {
+ LanguageId, // uint
+ CountryId, // uint
+ DecimalPoint, // QString
+ GroupSeparator, // QString
+ ZeroDigit, // QString
+ NegativeSign, // QString
+ DateFormatLong, // QString
+ DateFormatShort, // QString
+ TimeFormatLong, // QString
+ TimeFormatShort, // QString
+ DayNameLong, // QString, in: int
+ DayNameShort, // QString, in: int
+ MonthNameLong, // QString, in: int
+ MonthNameShort, // QString, in: int
+ DateToStringLong, // QString, in: QDate
+ DateToStringShort, // QString in: QDate
+ TimeToStringLong, // QString in: QTime
+ TimeToStringShort, // QString in: QTime
+ DateTimeFormatLong, // QString
+ DateTimeFormatShort, // QString
+ DateTimeToStringLong, // QString in: QDateTime
+ DateTimeToStringShort, // QString in: QDateTime
+ MeasurementSystem, // uint
+ PositiveSign, // QString
+ AMText, // QString
+ PMText, // QString
+ FirstDayOfWeek, // Qt::DayOfWeek
+ Weekdays, // QList<Qt::DayOfWeek>
+ CurrencySymbol, // QString in: CurrencyToStringArgument
+ CurrencyToString, // QString in: qlonglong, qulonglong or double
+ UILanguages, // QStringList
+ StringToStandardQuotation, // QString in: QStringRef to quote
+ StringToAlternateQuotation, // QString in: QStringRef to quote
+ ScriptId, // uint
+ ListToSeparatedString, // QString
+ LocaleChanged, // system locale changed
+ NativeLanguageName, // QString
+ NativeCountryName // QString
+ };
+ virtual QVariant query(QueryType type, QVariant in) const;
+ virtual QLocale fallbackLocale() const;
+
+private:
+ QSystemLocale(bool);
+ friend QSystemLocale *QSystemLocale_globalSystemLocale();
+};
+#endif
+
+struct QLocalePrivate;
+class Q_CORE_EXPORT QLocale
+{
+ Q_GADGET
+ Q_ENUMS(Language)
+ Q_ENUMS(Country)
+ friend class QString;
+ friend class QByteArray;
+ friend class QIntValidator;
+ friend class QDoubleValidatorPrivate;
+ friend class QTextStream;
+ friend class QTextStreamPrivate;
+
+public:
+// GENERATED PART STARTS HERE
+// see qlocale_data_p.h for more info on generated data
+ enum Language {
+ AnyLanguage = 0,
+ C = 1,
+ Abkhazian = 2,
+ Afan = 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,
+ Bhutani = 16,
+ Bihari = 17,
+ Bislama = 18,
+ Breton = 19,
+ Bulgarian = 20,
+ Burmese = 21,
+ Byelorussian = 22,
+ Cambodian = 23,
+ Catalan = 24,
+ Chinese = 25,
+ Corsican = 26,
+ Croatian = 27,
+ Czech = 28,
+ Danish = 29,
+ Dutch = 30,
+ English = 31,
+ Esperanto = 32,
+ Estonian = 33,
+ Faroese = 34,
+ FijiLanguage = 35,
+ Finnish = 36,
+ French = 37,
+ Frisian = 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,
+ Kurundi = 68,
+ Laothian = 69,
+ Latin = 70,
+ Latvian = 71,
+ Lingala = 72,
+ Lithuanian = 73,
+ Macedonian = 74,
+ Malagasy = 75,
+ Malay = 76,
+ Malayalam = 77,
+ Maltese = 78,
+ Maori = 79,
+ Marathi = 80,
+ Moldavian = 81,
+ Mongolian = 82,
+ NauruLanguage = 83,
+ Nepali = 84,
+ Norwegian = 85,
+ Occitan = 86,
+ Oriya = 87,
+ Pashto = 88,
+ Persian = 89,
+ Polish = 90,
+ Portuguese = 91,
+ Punjabi = 92,
+ Quechua = 93,
+ RhaetoRomance = 94,
+ Romanian = 95,
+ Russian = 96,
+ Samoan = 97,
+ Sangho = 98,
+ Sanskrit = 99,
+ Serbian = 100,
+ SerboCroatian = 101,
+ Sesotho = 102,
+ Setswana = 103,
+ Shona = 104,
+ Sindhi = 105,
+ Singhalese = 106,
+ Siswati = 107,
+ Slovak = 108,
+ Slovenian = 109,
+ Somali = 110,
+ Spanish = 111,
+ Sundanese = 112,
+ Swahili = 113,
+ Swedish = 114,
+ Tagalog = 115,
+ Tajik = 116,
+ Tamil = 117,
+ Tatar = 118,
+ Telugu = 119,
+ Thai = 120,
+ Tibetan = 121,
+ Tigrinya = 122,
+ TongaLanguage = 123,
+ Tsonga = 124,
+ Turkish = 125,
+ Turkmen = 126,
+ Twi = 127,
+ Uigur = 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,
+ Nynorsk = 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,
+ Chewa = 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,
+ NorwegianBokmal = Norwegian,
+ NorwegianNynorsk = Nynorsk,
+ LastLanguage = Shambala
+ };
+
+ enum Script {
+ AnyScript = 0,
+ ArabicScript = 1,
+ CyrillicScript = 2,
+ DeseretScript = 3,
+ GurmukhiScript = 4,
+ SimplifiedHanScript = 5,
+ TraditionalHanScript = 6,
+ LatinScript = 7,
+ MongolianScript = 8,
+ TifinaghScript = 9,
+ SimplifiedChineseScript = SimplifiedHanScript,
+ TraditionalChineseScript = TraditionalHanScript,
+ LastScript = TifinaghScript
+ };
+ enum Country {
+ AnyCountry = 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,
+ BruneiDarussalam = 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,
+ DemocraticRepublicOfCongo = 49,
+ PeoplesRepublicOfCongo = 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,
+ FijiCountry = 72,
+ Finland = 73,
+ France = 74,
+ MetropolitanFrance = 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,
+ DemocraticRepublicOfKorea = 113,
+ RepublicOfKorea = 114,
+ Kuwait = 115,
+ Kyrgyzstan = 116,
+ Lao = 117,
+ Latvia = 118,
+ Lebanon = 119,
+ Lesotho = 120,
+ Liberia = 121,
+ LibyanArabJamahiriya = 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,
+ NetherlandsAntilles = 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,
+ PalestinianTerritory = 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,
+ RussianFederation = 178,
+ Rwanda = 179,
+ SaintKittsAndNevis = 180,
+ StLucia = 181,
+ StVincentAndTheGrenadines = 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,
+ StHelena = 199,
+ StPierreAndMiquelon = 200,
+ Sudan = 201,
+ Suriname = 202,
+ SvalbardAndJanMayenIslands = 203,
+ Swaziland = 204,
+ Sweden = 205,
+ Switzerland = 206,
+ SyrianArabRepublic = 207,
+ Taiwan = 208,
+ Tajikistan = 209,
+ Tanzania = 210,
+ Thailand = 211,
+ Togo = 212,
+ Tokelau = 213,
+ TongaCountry = 214,
+ TrinidadAndTobago = 215,
+ Tunisia = 216,
+ Turkey = 217,
+ Turkmenistan = 218,
+ TurksAndCaicosIslands = 219,
+ Tuvalu = 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,
+ USVirginIslands = 234,
+ WallisAndFutunaIslands = 235,
+ WesternSahara = 236,
+ Yemen = 237,
+ Yugoslavia = 238,
+ Zambia = 239,
+ Zimbabwe = 240,
+ SerbiaAndMontenegro = 241,
+ Montenegro = 242,
+ Serbia = 243,
+ SaintBarthelemy = 244,
+ SaintMartin = 245,
+ LatinAmericaAndTheCaribbean = 246,
+ LastCountry = LatinAmericaAndTheCaribbean
+ };
+// GENERATED PART ENDS HERE
+
+ enum MeasurementSystem { MetricSystem, ImperialSystem };
+
+ enum FormatType { LongFormat, ShortFormat, NarrowFormat };
+ enum NumberOption {
+ OmitGroupSeparator = 0x01,
+ RejectGroupSeparator = 0x02
+ };
+ Q_DECLARE_FLAGS(NumberOptions, NumberOption)
+
+ enum CurrencySymbolFormat {
+ CurrencyIsoCode,
+ CurrencySymbol,
+ CurrencyDisplayName
+ };
+
+ QLocale();
+ QLocale(const QString &name);
+ QLocale(Language language, Country country = AnyCountry);
+ QLocale(Language language, Script script, Country country);
+ QLocale(const QLocale &other);
+
+ QLocale &operator=(const QLocale &other);
+
+ Language language() const;
+ Script script() const;
+ Country country() const;
+ QString name() const;
+
+ QString bcp47Name() const;
+ QString nativeLanguageName() const;
+ QString nativeCountryName() const;
+
+ short toShort(const QString &s, bool *ok = 0, int base = 0) const;
+ ushort toUShort(const QString &s, bool *ok = 0, int base = 0) const;
+ int toInt(const QString &s, bool *ok = 0, int base = 0) const;
+ uint toUInt(const QString &s, bool *ok = 0, int base = 0) const;
+ qlonglong toLongLong(const QString &s, bool *ok = 0, int base = 0) const;
+ qlonglong toULongLong(const QString &s, bool *ok = 0, int base = 0) const;
+ float toFloat(const QString &s, bool *ok = 0) const;
+ double toDouble(const QString &s, bool *ok = 0) const;
+
+ QString toString(qlonglong i) const;
+ QString toString(qulonglong 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(const QDate &date, const QString &formatStr) const;
+ QString toString(const QDate &date, FormatType format = LongFormat) const;
+ QString toString(const QTime &time, const QString &formatStr) const;
+ QString toString(const QTime &time, FormatType format = LongFormat) const;
+ QString toString(const QDateTime &dateTime, FormatType format = LongFormat) const;
+ QString toString(const QDateTime &dateTime, const QString &format) const;
+
+ QString dateFormat(FormatType format = LongFormat) const;
+ QString timeFormat(FormatType format = LongFormat) const;
+ QString dateTimeFormat(FormatType format = LongFormat) const;
+#ifndef QT_NO_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;
+ QDateTime toDateTime(const QString &string, const QString &format) const;
+#endif
+
+ // ### Qt 5: We need to return QString from these function since
+ // unicode data contains several characters for these fields.
+ QChar decimalPoint() const;
+ QChar groupSeparator() const;
+ QChar percent() const;
+ QChar zeroDigit() const;
+ QChar negativeSign() const;
+ QChar positiveSign() const;
+ QChar exponential() const;
+
+ QString monthName(int, FormatType format = LongFormat) const;
+ QString standaloneMonthName(int, FormatType format = LongFormat) const;
+ QString dayName(int, FormatType format = LongFormat) const;
+ QString standaloneDayName(int, FormatType format = LongFormat) const;
+
+ Qt::DayOfWeek firstDayOfWeek() const;
+ QList<Qt::DayOfWeek> weekdays() const;
+
+ QString amText() const;
+ QString pmText() const;
+
+ MeasurementSystem measurementSystem() const;
+
+ Qt::LayoutDirection textDirection() const;
+
+ 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;
+ QString toCurrencyString(double, const QString &symbol = QString()) const;
+ inline QString toCurrencyString(float, const QString &symbol = QString()) const;
+
+ QStringList uiLanguages() const;
+
+ inline bool operator==(const QLocale &other) const;
+ inline bool operator!=(const QLocale &other) const;
+
+ static QString languageToString(Language language);
+ static QString countryToString(Country country);
+ 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<Country> countriesForLanguage(Language lang);
+
+ void setNumberOptions(NumberOptions options);
+ NumberOptions numberOptions() const;
+
+ enum QuotationStyle { StandardQuotation, AlternateQuotation };
+ QString quoteString(const QString &str, QuotationStyle style = StandardQuotation) const;
+ QString quoteString(const QStringRef &str, QuotationStyle style = StandardQuotation) const;
+
+ QString createSeparatedList(const QStringList &strl) const;
+//private: // this should be private, but can't be
+ struct Data {
+ quint16 index;
+ quint16 numberOptions;
+ };
+private:
+ friend struct QLocalePrivate;
+ // ### We now use this field to pack an index into locale_data and NumberOptions.
+ // ### Qt 5: change to a QLocaleData *d; uint numberOptions.
+ union {
+ void *v;
+ Data p;
+ };
+ const QLocalePrivate *d() const;
+};
+Q_DECLARE_TYPEINFO(QLocale, Q_MOVABLE_TYPE);
+Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::NumberOptions)
+
+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 bool QLocale::operator==(const QLocale &other) const
+ { return d() == other.d() && numberOptions() == other.numberOptions(); }
+inline bool QLocale::operator!=(const QLocale &other) const
+ { return d() != other.d() || numberOptions() != other.numberOptions(); }
+
+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); }
+inline QString QLocale::toCurrencyString(float i, const QString &symbol) const
+{ return toCurrencyString(double(i), symbol); }
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLocale &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLocale &);
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_SYSTEMLOCALE
+Q_DECLARE_METATYPE(QSystemLocale::CurrencyToStringArgument)
+#endif
+
+QT_END_HEADER
+
+#endif // QLOCALE_H
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
new file mode 100644
index 0000000000..605e3e0c56
--- /dev/null
+++ b/src/corelib/tools/qlocale.qdoc
@@ -0,0 +1,905 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QLocale
+ \brief The QLocale class converts between numbers and their
+ string representations in various languages.
+
+ \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.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 0
+
+ QLocale supports the concept of a default locale, which is
+ determined from the system's locale settings at application
+ startup. The default locale can be changed by calling the
+ static member setDefault(). Setting the default locale has the
+ following effects:
+
+ \list
+ \i If a QLocale object is constructed with the default constructor,
+ it will use the default locale's settings.
+ \i QString::toInt(), QString::toDouble(), etc., interpret the
+ string according to the default locale. If this fails, it
+ falls back on the "C" locale.
+ \i QString::arg() uses the default locale to format a number when
+ its position specifier in the format string contains an 'L',
+ e.g. "%L1".
+ \endlist
+
+ The following example illustrates how to use QLocale directly:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 1
+
+ When a language/country pair is specified in the constructor, one
+ of three things can happen:
+
+ \list
+ \i If the language/country pair is found in the database, it is used.
+ \i 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),
+ \i 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 doc/src/snippets/code/src_corelib_tools_qlocale.cpp 2
+
+ This constructor converts the locale name to a language/country
+ pair; it does not use the system locale database.
+
+ \note For the current keyboard input locale take a look at
+ QApplication::keyboardInputLocale().
+
+ QLocale's data is based on Common Locale Data Repository v1.8.1.
+
+ The double-to-string and string-to-double conversion functions are
+ covered by the following licenses:
+
+ \legalese
+ Copyright (c) 1991 by AT&T.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose without fee is hereby granted, provided that this entire notice
+ is included in all copies of any software which is or includes a copy
+ or modification of this software and in all copies of the supporting
+ documentation for such software.
+
+ THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+ REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+
+ \sa QString::arg(), QString::toInt(), QString::toDouble(),
+ QApplication::keyboardInputLocale()
+*/
+
+/*!
+ \enum QLocale::Language
+
+ This enumerated type is used to specify a language.
+
+ \value AnyLanguage
+ \value C The "C" locale is identical in behavior to English/UnitedStates.
+ \value Abkhazian
+ \value Afan
+ \value Afar
+ \value Afrikaans
+ \value Albanian
+ \value Amharic
+ \value Arabic
+ \value Armenian
+ \value Assamese
+ \value Aymara
+ \value Azerbaijani
+ \value Bashkir
+ \value Basque
+ \value Bengali
+ \value Bhutani
+ \value Bihari
+ \value Bislama
+ \value Bosnian
+ \value Breton
+ \value Bulgarian
+ \value Burmese
+ \value Byelorussian
+ \value Cambodian
+ \value Catalan
+ \value Chinese
+ \value Cornish
+ \value Corsican
+ \value Croatian
+ \value Czech
+ \value Danish
+ \value Divehi
+ \value Dutch
+ \value English
+ \value Esperanto
+ \value Estonian
+ \value Faroese
+ \value FijiLanguage
+ \value Finnish
+ \value French
+ \value Frisian
+ \value Gaelic
+ \value Galician
+ \value Georgian
+ \value German
+ \value Greek
+ \value Greenlandic
+ \value Guarani
+ \value Gujarati
+ \value Hausa
+ \value Hebrew
+ \value Hindi
+ \value Hungarian
+ \value Icelandic
+ \value Indonesian
+ \value Interlingua
+ \value Interlingue
+ \value Inuktitut
+ \value Inupiak
+ \value Irish
+ \value Italian
+ \value Japanese
+ \value Javanese
+ \value Kannada
+ \value Kashmiri
+ \value Kazakh
+ \value Kinyarwanda
+ \value Kirghiz
+ \value Korean
+ \value Kurdish
+ \value Kurundi
+ \value Laothian
+ \value Latin
+ \value Latvian
+ \value Lingala
+ \value Lithuanian
+ \value Macedonian
+ \value Malagasy
+ \value Malay
+ \value Malayalam
+ \value Maltese
+ \value Manx
+ \value Maori
+ \value Marathi
+ \value Moldavian
+ \value Mongolian
+ \value NauruLanguage
+ \value Nepali
+ \value Norwegian
+ \value NorwegianBokmal
+ \value Nynorsk Obsolete, please use NorwegianNynorsk
+ \value NorwegianNynorsk
+ \value Occitan
+ \value Oriya
+ \value Pashto
+ \value Persian
+ \value Polish
+ \value Portuguese
+ \value Punjabi
+ \value Quechua
+ \value RhaetoRomance
+ \value Romanian
+ \value Russian
+ \value Samoan
+ \value Sangho
+ \value Sanskrit
+ \value Serbian
+ \value SerboCroatian
+ \value Sesotho
+ \value Setswana
+ \value Shona
+ \value Sindhi
+ \value Singhalese
+ \value Siswati
+ \value Slovak
+ \value Slovenian
+ \value Somali
+ \value Spanish
+ \value Sundanese
+ \value Swahili
+ \value Swedish
+ \value Tagalog
+ \value Tajik
+ \value Tamil
+ \value Tatar
+ \value Telugu
+ \value Thai
+ \value Tibetan
+ \value Tigrinya
+ \value TongaLanguage
+ \value Tsonga
+ \value Turkish
+ \value Turkmen
+ \value Twi
+ \value Uigur
+ \value Ukrainian
+ \value Urdu
+ \value Uzbek
+ \value Vietnamese
+ \value Volapuk
+ \value Welsh
+ \value Wolof
+ \value Xhosa
+ \value Yiddish
+ \value Yoruba
+ \value Zhuang
+ \value Zulu
+ \value Bosnian
+ \value Divehi
+ \value Manx
+ \value Cornish
+ \value Akan
+ \value Konkani
+ \value Ga
+ \value Igbo
+ \value Kamba
+ \value Syriac
+ \value Blin
+ \value Geez
+ \value Koro
+ \value Sidamo
+ \value Atsam
+ \value Tigre
+ \value Jju
+ \value Friulian
+ \value Venda
+ \value Ewe
+ \value Walamo
+ \value Hawaiian
+ \value Tyap
+ \value Chewa
+ \value Filipino
+ \value SwissGerman
+ \value SichuanYi
+ \value Kpelle
+ \value LowGerman
+ \value SouthNdebele
+ \value NorthernSotho
+ \value NorthernSami
+ \value Taroko
+ \value Gusii
+ \value Taita
+ \value Fulah
+ \value Kikuyu
+ \value Samburu
+ \value Sena
+ \value NorthNdebele
+ \value Rombo
+ \value Tachelhit
+ \value Kabyle
+ \value Nyankole
+ \value Bena
+ \value Vunjo
+ \value Bambara
+ \value Embu
+ \value Cherokee
+ \value Morisyen
+ \value Makonde
+ \value Langi
+ \value Ganda
+ \value Bemba
+ \value Kabuverdianu
+ \value Meru
+ \value Kalenjin
+ \value Nama
+ \value Machame
+ \value Colognian
+ \value Masai
+ \value Soga
+ \value Luyia
+ \value Asu
+ \value Teso
+ \value Saho
+ \value KoyraChiini
+ \value Rwa
+ \value Luo
+ \value Chiga
+ \value CentralMoroccoTamazight
+ \value KoyraboroSenni
+ \value Shambala
+ \omitvalue LastLanguage
+
+ \sa language(), languageToString()
+*/
+
+/*!
+ \enum QLocale::Country
+
+ This enumerated type is used to specify a country.
+
+ \value AnyCountry
+ \value Afghanistan
+ \value Albania
+ \value Algeria
+ \value AmericanSamoa
+ \value Andorra
+ \value Angola
+ \value Anguilla
+ \value Antarctica
+ \value AntiguaAndBarbuda
+ \value Argentina
+ \value Armenia
+ \value Aruba
+ \value Australia
+ \value Austria
+ \value Azerbaijan
+ \value Bahamas
+ \value Bahrain
+ \value Bangladesh
+ \value Barbados
+ \value Belarus
+ \value Belgium
+ \value Belize
+ \value Benin
+ \value Bermuda
+ \value Bhutan
+ \value Bolivia
+ \value BosniaAndHerzegowina
+ \value Botswana
+ \value BouvetIsland
+ \value Brazil
+ \value BritishIndianOceanTerritory
+ \value BruneiDarussalam
+ \value Bulgaria
+ \value BurkinaFaso
+ \value Burundi
+ \value Cambodia
+ \value Cameroon
+ \value Canada
+ \value CapeVerde
+ \value CaymanIslands
+ \value CentralAfricanRepublic
+ \value Chad
+ \value Chile
+ \value China
+ \value ChristmasIsland
+ \value CocosIslands
+ \value Colombia
+ \value Comoros
+ \value DemocraticRepublicOfCongo
+ \value PeoplesRepublicOfCongo
+ \value CookIslands
+ \value CostaRica
+ \value IvoryCoast
+ \value Croatia
+ \value Cuba
+ \value Cyprus
+ \value CzechRepublic
+ \value Denmark
+ \value Djibouti
+ \value Dominica
+ \value DominicanRepublic
+ \value EastTimor
+ \value Ecuador
+ \value Egypt
+ \value ElSalvador
+ \value EquatorialGuinea
+ \value Eritrea
+ \value Estonia
+ \value Ethiopia
+ \value FalklandIslands
+ \value FaroeIslands
+ \value FijiCountry
+ \value Finland
+ \value France
+ \value MetropolitanFrance
+ \value FrenchGuiana
+ \value FrenchPolynesia
+ \value FrenchSouthernTerritories
+ \value Gabon
+ \value Gambia
+ \value Georgia
+ \value Germany
+ \value Ghana
+ \value Gibraltar
+ \value Greece
+ \value Greenland
+ \value Grenada
+ \value Guadeloupe
+ \value Guam
+ \value Guatemala
+ \value Guinea
+ \value GuineaBissau
+ \value Guyana
+ \value Haiti
+ \value HeardAndMcDonaldIslands
+ \value Honduras
+ \value HongKong
+ \value Hungary
+ \value Iceland
+ \value India
+ \value Indonesia
+ \value Iran
+ \value Iraq
+ \value Ireland
+ \value Israel
+ \value Italy
+ \value Jamaica
+ \value Japan
+ \value Jordan
+ \value Kazakhstan
+ \value Kenya
+ \value Kiribati
+ \value DemocraticRepublicOfKorea
+ \value RepublicOfKorea
+ \value Kuwait
+ \value Kyrgyzstan
+ \value Lao
+ \value Latvia
+ \value Lebanon
+ \value Lesotho
+ \value Liberia
+ \value LibyanArabJamahiriya
+ \value Liechtenstein
+ \value Lithuania
+ \value Luxembourg
+ \value Macau
+ \value Macedonia
+ \value Madagascar
+ \value Malawi
+ \value Malaysia
+ \value Maldives
+ \value Mali
+ \value Malta
+ \value MarshallIslands
+ \value Martinique
+ \value Mauritania
+ \value Mauritius
+ \value Mayotte
+ \value Mexico
+ \value Micronesia
+ \value Moldova
+ \value Monaco
+ \value Mongolia
+ \value Montserrat
+ \value Morocco
+ \value Mozambique
+ \value Myanmar
+ \value Namibia
+ \value NauruCountry
+ \value Nepal
+ \value Netherlands
+ \value NetherlandsAntilles
+ \value NewCaledonia
+ \value NewZealand
+ \value Nicaragua
+ \value Niger
+ \value Nigeria
+ \value Niue
+ \value NorfolkIsland
+ \value NorthernMarianaIslands
+ \value Norway
+ \value Oman
+ \value Pakistan
+ \value Palau
+ \value PalestinianTerritory
+ \value Panama
+ \value PapuaNewGuinea
+ \value Paraguay
+ \value Peru
+ \value Philippines
+ \value Pitcairn
+ \value Poland
+ \value Portugal
+ \value PuertoRico
+ \value Qatar
+ \value Reunion
+ \value Romania
+ \value RussianFederation
+ \value Rwanda
+ \value SaintKittsAndNevis
+ \value StLucia
+ \value StVincentAndTheGrenadines
+ \value Samoa
+ \value SanMarino
+ \value SaoTomeAndPrincipe
+ \value SaudiArabia
+ \value Senegal
+ \value SerbiaAndMontenegro
+ \value Seychelles
+ \value SierraLeone
+ \value Singapore
+ \value Slovakia
+ \value Slovenia
+ \value SolomonIslands
+ \value Somalia
+ \value SouthAfrica
+ \value SouthGeorgiaAndTheSouthSandwichIslands
+ \value Spain
+ \value SriLanka
+ \value StHelena
+ \value StPierreAndMiquelon
+ \value Sudan
+ \value Suriname
+ \value SvalbardAndJanMayenIslands
+ \value Swaziland
+ \value Sweden
+ \value Switzerland
+ \value SyrianArabRepublic
+ \value Taiwan
+ \value Tajikistan
+ \value Tanzania
+ \value Thailand
+ \value Togo
+ \value Tokelau
+ \value TongaCountry
+ \value TrinidadAndTobago
+ \value Tunisia
+ \value Turkey
+ \value Turkmenistan
+ \value TurksAndCaicosIslands
+ \value Tuvalu
+ \value Uganda
+ \value Ukraine
+ \value UnitedArabEmirates
+ \value UnitedKingdom
+ \value UnitedStates
+ \value UnitedStatesMinorOutlyingIslands
+ \value Uruguay
+ \value Uzbekistan
+ \value Vanuatu
+ \value VaticanCityState
+ \value Venezuela
+ \value VietNam
+ \value BritishVirginIslands
+ \value USVirginIslands
+ \value WallisAndFutunaIslands
+ \value WesternSahara
+ \value Yemen
+ \value Yugoslavia
+ \value Zambia
+ \value Zimbabwe
+ \value SerbiaAndMontenegro
+ \value Montenegro
+ \value Serbia
+ \value SaintBarthelemy
+ \value SaintMartin
+ \value LatinAmericaAndTheCaribbean
+ \omitvalue LastCountry
+
+ \sa country(), countryToString()
+*/
+
+/*!
+ \enum QLocale::Script
+
+ This enumerated type is used to specify a script.
+
+ \value AnyScript
+ \value ArabicScript
+ \value CyrillicScript
+ \value DeseretScript
+ \value GurmukhiScript
+ \value SimplifiedHanScript same as SimplifiedChineseScript
+ \value SimplifiedChineseScript same as SimplifiedHanScript
+ \value TraditionalHanScript same as TraditionalChineseScript
+ \value TraditionalChineseScript same as TraditionalHanScript
+ \value LatinScript
+ \value MongolianScript
+ \value TifinaghScript
+ \omitvalue LastScript
+
+ \sa script(), scriptToString(), languageToString()
+*/
+
+/*!
+ \enum QLocale::FormatType
+
+ This enum describes the types of format that can be used when
+ converting QDate and QTime objects to strings.
+
+ \value LongFormat The long version of day and month names; for
+ example, returning "January" as a month name.
+
+ \value ShortFormat The short version of day and month names; for
+ example, returning "Jan" as a month name.
+
+ \value NarrowFormat A special version of day and month names for
+ use when space is limited; for example, returning "J" as a month
+ name. Note that the narrow format might contain the same text for
+ different months and days or it can even be an empty string if the
+ locale doesn't support narrow names, so you should avoid using it
+ for date formatting. Also, for the system locale this format is
+ the same as ShortFormat.
+*/
+
+/*!
+ \enum QLocale::NumberOption
+
+ This enum defines a set of options for number-to-string and string-to-number
+ conversions. They can be retrieved with numberOptions() and set with
+ setNumberOptions().
+
+ \value OmitGroupSeparator If this option is set, the number-to-string functions
+ will not insert group separators in their return values. The default
+ is to insert group separators.
+ \value RejectGroupSeparator If this option is set, the string-to-number functions
+ will fail if they encounter group separators in their input. The default
+ is to accept numbers containing correctly placed group separators.
+
+ \sa setNumberOptions() numberOptions()
+*/
+
+/*!
+ \enum QLocale::MeasurementSystem
+
+ This enum defines which units are used for measurement.
+
+ \value MetricSystem This value indicates metric units, such as meters,
+ centimeters and millimeters.
+ \value ImperialSystem This value indicates imperial units, such as inches and
+ miles. There are several distinct imperial systems in the world; this
+ value stands for the official United States imperial units.
+
+ \since 4.4
+*/
+
+
+/*!
+ \fn bool QLocale::operator==(const QLocale &other) const
+
+ Returns true if the QLocale object is the same as the \a other
+ locale specified; otherwise returns false.
+*/
+
+/*!
+ \fn bool QLocale::operator!=(const QLocale &other) const
+
+ Returns true if the QLocale object is not the same as the \a other
+ locale specified; otherwise returns false.
+*/
+
+/*!
+ \enum QLocale::QuotationStyle
+
+ This enum defines a set of possible styles for locale specific quotation.
+
+ \value StandardQuotation If this option is set, the standard quotation marks
+ will be used to quote strings.
+ \value AlternateQuotation If this option is set, the alternate quotation marks
+ will be used to quote strings.
+
+ \since 4.8
+
+ \sa quoteString()
+*/
+
+/*!
+ \class QSystemLocale
+ \brief The QSystemLocale class can be used to finetune the system locale
+ of the user.
+ \since 4.2
+
+ \ingroup i18n
+
+ \warning This class is only useful in very rare cases. Usually QLocale offers
+ all the functionality required for application development.
+
+ QSystemLocale allows to override the values provided by the system
+ locale (QLocale::system()).
+
+ \sa QLocale
+*/
+
+/*!
+ \enum QSystemLocale::QueryType
+
+ Specifies the type of information queried by query(). For each value
+ the type of information to return from the query() method is listed.
+
+ \value LanguageId a uint specifying the language.
+ \value ScriptId a uint specifying the script.
+ \value CountryId a uint specifying the country.
+ \value DecimalPoint a QString specifying the decimal point.
+ \value GroupSeparator a QString specifying the group separator.
+ \value ZeroDigit a QString specifying the zero digit.
+ \value NegativeSign a QString specifying the minus sign.
+ \value PositiveSign a QString specifying the plus sign.
+ \value DateFormatLong a QString specifying the long date format
+ \value DateFormatShort a QString specifying the short date format
+ \value TimeFormatLong a QString specifying the long time format
+ \value TimeFormatShort a QString specifying the short time format
+ \value DayNameLong a QString specifying the name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday)
+ \value DayNameShort a QString specifying the short name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday)
+ \value MonthNameLong a QString specifying the name of a month. the in variant contains an integer between 1 and 12
+ \value MonthNameShort a QString specifying the short name of a month. the in variant contains an integer between 1 and 12
+ \value DateToStringLong converts the QDate stored in the in variant to a QString using the long date format
+ \value DateToStringShort converts the QDate stored in the in variant to a QString using the short date format
+ \value TimeToStringLong converts the QTime stored in the in variant to a QString using the long time format
+ \value TimeToStringShort converts the QTime stored in the in variant to a QString using the short time format
+ \value DateTimeFormatLong a QString specifying the long date time format
+ \value DateTimeFormatShort a QString specifying the short date time format
+ \value DateTimeToStringLong converts the QDateTime in the in variant to a QString using the long datetime format
+ \value DateTimeToStringShort converts the QDateTime in the in variant to a QString using the short datetime format
+ \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 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.
+ \value StringToStandardQuotation a QString containing a quoted version of the string ref stored in the in variant using standard quotes.
+ \value StringToAlternateQuotation a QString containing a quoted version of the string ref stored in the in variant using alternate quotes.
+ \value Weekdays a QList<Qt::DayOfWeek> specifying the regular weekdays
+ \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.
+*/
+
+/*!
+ \fn QLocale QSystemLocale::fallbackLocale() const
+
+ \since 4.6
+ Returns the fallback locale obtained from the system.
+*/
+
+/*!
+ \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
+ with \a in as input data depending on the query.
+
+ \sa QSystemLocale::QueryType
+*/
+
+/*!
+ \class QSystemLocale::CurrencyToStringArgument
+
+ A helper class that provides arguments for the QSystemLocale::query()
+ function with query type QSystemLocale::CurrencyToString.
+
+ \sa QSystemLocale::QueryType
+ \since 4.8
+*/
+
+/*!
+ \fn QSystemLocale::CurrencyToStringArgument::CurrencyToStringArgument()
+ \internal
+*/
+/*!
+ \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
+ types.
+*/
+/*!
+ \variable QSystemLocale::CurrencyToStringArgument::symbol
+
+ An optional argument containing a currency symbol to be used in the
+ currency string.
+*/
+
+
+/*!
+\fn QString QLocale::toString(short i) const
+
+\overload
+
+\sa toShort()
+*/
+
+/*!
+\fn QString QLocale::toString(ushort i) const
+
+\overload
+
+\sa toUShort()
+*/
+
+/*!
+\fn QString QLocale::toString(int i) const
+
+\overload
+
+\sa toInt()
+*/
+
+/*!
+\fn QString QLocale::toString(uint i) const
+
+\overload
+
+\sa toUInt()
+*/
+
+/*
+\fn QString QLocale::toString(long i) const
+
+\overload
+
+\sa toLong()
+*/
+
+/*
+\fn QString QLocale::toString(ulong i) const
+
+\overload
+
+\sa toULong()
+*/
+
+/*!
+\fn QString QLocale::toString(float i, char f = 'g', int prec = 6) const
+
+\overload
+
+\a f and \a prec have the same meaning as in QString::number(double, char, int).
+
+\sa toDouble()
+*/
+
+/*!
+ \fn QString QLocale::toCurrencyString(short value, const QString &symbol) const
+ \since 4.8
+ \overload
+*/
+
+/*!
+ \fn QString QLocale::toCurrencyString(ushort value, const QString &symbol) const
+ \since 4.8
+ \overload
+*/
+
+/*!
+ \fn QString QLocale::toCurrencyString(int value, const QString &symbol) const
+ \since 4.8
+ \overload
+*/
+
+/*!
+ \fn QString QLocale::toCurrencyString(uint value, const QString &symbol) const
+ \since 4.8
+ \overload
+*/
+/*!
+ \fn QString QLocale::toCurrencyString(float value, const QString &symbol) const
+ \since 4.8
+ \overload
+*/
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
new file mode 100644
index 0000000000..f3c1ed72ea
--- /dev/null
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -0,0 +1,6518 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCALE_DATA_P_H
+#define QLOCALE_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 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.
+//
+
+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
+{
+ quint16 languageId;
+ quint16 countryId;
+};
+static const CountryLanguage ImperialMeasurementSystems[] = {
+ { 31, 225 },
+ { 31, 226 },
+ { 111, 225 },
+ { 163, 225 }
+};
+static const int ImperialMeasurementSystemsCount =
+ sizeof(ImperialMeasurementSystems)/sizeof(ImperialMeasurementSystems[0]);
+
+// GENERATED PART STARTS HERE
+
+/*
+ This part of the file was generated on 2011-03-28 from the
+ Common Locale Data Repository v1.8.1
+
+ http://www.unicode.org/cldr/
+
+ Do not change it, instead edit CLDR data and regenerate this file using
+ cldr2qlocalexml.py and qlocalexml2cpp.py.
+*/
+
+
+static const quint16 locale_index[] = {
+ 0, // AnyLanguage
+ 0, // C
+ 0, // Abkhazian
+ 1, // Afan
+ 3, // Afar
+ 6, // Afrikaans
+ 8, // Albanian
+ 9, // Amharic
+ 10, // Arabic
+ 27, // Armenian
+ 28, // Assamese
+ 0, // Aymara
+ 29, // Azerbaijani
+ 0, // Bashkir
+ 34, // Basque
+ 35, // Bengali
+ 37, // Bhutani
+ 0, // Bihari
+ 0, // Bislama
+ 38, // Breton
+ 39, // Bulgarian
+ 40, // Burmese
+ 41, // Byelorussian
+ 42, // Cambodian
+ 43, // Catalan
+ 44, // Chinese
+ 0, // Corsican
+ 56, // Croatian
+ 57, // Czech
+ 58, // Danish
+ 59, // Dutch
+ 61, // English
+ 0, // Esperanto
+ 89, // Estonian
+ 90, // Faroese
+ 0, // Fiji
+ 91, // Finnish
+ 92, // French
+ 0, // Frisian
+ 0, // Gaelic
+ 111, // Galician
+ 112, // Georgian
+ 113, // German
+ 119, // Greek
+ 121, // Greenlandic
+ 0, // Guarani
+ 122, // Gujarati
+ 123, // Hausa
+ 132, // Hebrew
+ 133, // Hindi
+ 134, // Hungarian
+ 135, // Icelandic
+ 136, // Indonesian
+ 0, // Interlingua
+ 0, // Interlingue
+ 0, // Inuktitut
+ 0, // Inupiak
+ 137, // Irish
+ 138, // Italian
+ 140, // Japanese
+ 0, // Javanese
+ 141, // Kannada
+ 0, // Kashmiri
+ 142, // Kazakh
+ 144, // Kinyarwanda
+ 145, // Kirghiz
+ 146, // Korean
+ 147, // Kurdish
+ 0, // Kurundi
+ 155, // Laothian
+ 0, // Latin
+ 156, // Latvian
+ 157, // Lingala
+ 159, // Lithuanian
+ 160, // Macedonian
+ 161, // Malagasy
+ 162, // Malay
+ 164, // Malayalam
+ 165, // Maltese
+ 166, // Maori
+ 167, // Marathi
+ 0, // Moldavian
+ 168, // Mongolian
+ 0, // Nauru
+ 172, // Nepali
+ 174, // Norwegian
+ 175, // Occitan
+ 176, // Oriya
+ 177, // Pashto
+ 178, // Persian
+ 180, // Polish
+ 181, // Portuguese
+ 185, // Punjabi
+ 0, // Quechua
+ 189, // RhaetoRomance
+ 190, // Romanian
+ 192, // Russian
+ 0, // Samoan
+ 195, // Sangho
+ 196, // Sanskrit
+ 197, // Serbian
+ 212, // SerboCroatian
+ 215, // Sesotho
+ 217, // Setswana
+ 218, // Shona
+ 0, // Sindhi
+ 219, // Singhalese
+ 220, // Siswati
+ 222, // Slovak
+ 223, // Slovenian
+ 224, // Somali
+ 228, // Spanish
+ 0, // Sundanese
+ 250, // Swahili
+ 252, // Swedish
+ 0, // Tagalog
+ 254, // Tajik
+ 256, // Tamil
+ 258, // Tatar
+ 259, // Telugu
+ 260, // Thai
+ 261, // Tibetan
+ 263, // Tigrinya
+ 265, // Tonga
+ 266, // Tsonga
+ 267, // Turkish
+ 0, // Turkmen
+ 0, // Twi
+ 268, // Uigur
+ 270, // Ukrainian
+ 271, // Urdu
+ 273, // Uzbek
+ 278, // Vietnamese
+ 0, // Volapuk
+ 279, // Welsh
+ 280, // Wolof
+ 282, // Xhosa
+ 0, // Yiddish
+ 283, // Yoruba
+ 0, // Zhuang
+ 284, // Zulu
+ 285, // Nynorsk
+ 286, // Bosnian
+ 287, // Divehi
+ 288, // Manx
+ 289, // Cornish
+ 290, // Akan
+ 291, // Konkani
+ 292, // Ga
+ 293, // Igbo
+ 294, // Kamba
+ 295, // Syriac
+ 296, // Blin
+ 297, // Geez
+ 299, // Koro
+ 300, // Sidamo
+ 301, // Atsam
+ 302, // Tigre
+ 303, // Jju
+ 304, // Friulian
+ 305, // Venda
+ 306, // Ewe
+ 308, // Walamo
+ 309, // Hawaiian
+ 310, // Tyap
+ 311, // Chewa
+ 312, // Filipino
+ 313, // Swiss German
+ 314, // Sichuan Yi
+ 315, // Kpelle
+ 317, // Low German
+ 318, // South Ndebele
+ 319, // Northern Sotho
+ 320, // Northern Sami
+ 322, // Taroko
+ 323, // Gusii
+ 324, // Taita
+ 325, // Fulah
+ 326, // Kikuyu
+ 327, // Samburu
+ 328, // Sena
+ 329, // North Ndebele
+ 330, // Rombo
+ 331, // Tachelhit
+ 334, // Kabyle
+ 335, // Nyankole
+ 336, // Bena
+ 337, // Vunjo
+ 338, // Bambara
+ 339, // Embu
+ 340, // Cherokee
+ 341, // Morisyen
+ 342, // Makonde
+ 343, // Langi
+ 344, // Ganda
+ 345, // Bemba
+ 346, // Kabuverdianu
+ 347, // Meru
+ 348, // Kalenjin
+ 349, // Nama
+ 350, // Machame
+ 351, // Colognian
+ 352, // Masai
+ 354, // Soga
+ 355, // Luyia
+ 356, // Asu
+ 357, // Teso
+ 359, // Saho
+ 360, // Koyra Chiini
+ 361, // Rwa
+ 362, // Luo
+ 363, // Chiga
+ 364, // Central Morocco Tamazight
+ 366, // Koyraboro Senni
+ 367, // Shambala
+ 0 // trailing 0
+};
+
+static const QLocalePrivate locale_data[] = {
+// lang script terr dec group list prcnt zero minus plus exp quotStart quotEnd altQuotStart altQuotEnd lpStart lpMid lpEnd lpTwo sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len
+ { 1, 0, 0, 46, 44, 59, 37, 48, 45, 43, 101, 34, 34, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 0,10 , 10,17 , 0,8 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,27 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 99,14 , 0,2 , 0,2 , {0,0,0}, 0,0 , 0,7 , 0,4 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // C/AnyScript/AnyCountry
+ { 3, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 158,48 , 206,111 , 134,24 , 161,48 , 209,111 , 320,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , {69,84,66}, 0,2 , 7,24 , 4,4 , 4,0 , 0,6 , 6,10 , 2, 1, 6, 6, 7 }, // Afan/AnyScript/Ethiopia
+ { 3, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 158,48 , 206,111 , 134,24 , 161,48 , 209,111 , 320,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 0,6 , 16,8 , 2, 1, 6, 6, 7 }, // Afan/AnyScript/Kenya
+ { 4, 0, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 317,48 , 365,129 , 494,24 , 344,48 , 392,129 , 521,24 , 196,28 , 224,52 , 276,14 , 196,28 , 224,52 , 276,14 , 0,2 , 0,2 , {68,74,70}, 5,3 , 0,7 , 4,4 , 4,0 , 24,5 , 29,7 , 0, 0, 6, 6, 7 }, // Afar/AnyScript/Djibouti
+ { 4, 0, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 317,48 , 518,118 , 494,24 , 344,48 , 545,118 , 521,24 , 196,28 , 224,52 , 276,14 , 196,28 , 224,52 , 276,14 , 0,2 , 0,2 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 24,5 , 36,7 , 2, 1, 6, 6, 7 }, // Afar/AnyScript/Eritrea
+ { 4, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 317,48 , 518,118 , 494,24 , 344,48 , 545,118 , 521,24 , 196,28 , 224,52 , 276,14 , 196,28 , 224,52 , 276,14 , 0,2 , 0,2 , {69,84,66}, 0,2 , 0,7 , 4,4 , 4,0 , 24,5 , 43,7 , 2, 1, 6, 6, 7 }, // Afar/AnyScript/Ethiopia
+ { 5, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 72,10 , 82,17 , 18,7 , 25,12 , 636,48 , 684,92 , 134,24 , 663,48 , 711,92 , 320,24 , 290,21 , 311,58 , 369,14 , 290,21 , 311,58 , 369,14 , 4,3 , 4,3 , {90,65,82}, 11,1 , 31,27 , 4,4 , 4,0 , 50,9 , 59,11 , 2, 1, 1, 6, 7 }, // Afrikaans/AnyScript/SouthAfrica
+ { 5, 0, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 72,10 , 99,16 , 37,5 , 8,10 , 636,48 , 684,92 , 134,24 , 663,48 , 711,92 , 320,24 , 290,21 , 311,58 , 369,14 , 290,21 , 311,58 , 369,14 , 4,3 , 4,3 , {78,65,68}, 12,2 , 58,23 , 8,5 , 4,0 , 50,9 , 70,7 , 2, 1, 1, 6, 7 }, // Afrikaans/AnyScript/Namibia
+ { 6, 0, 2, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 115,8 , 123,18 , 42,7 , 49,12 , 776,48 , 824,78 , 902,24 , 803,48 , 851,78 , 929,24 , 383,28 , 411,58 , 469,14 , 383,28 , 411,58 , 469,14 , 7,2 , 7,2 , {65,76,76}, 14,3 , 0,7 , 4,4 , 4,0 , 77,6 , 83,9 , 0, 0, 1, 6, 7 }, // Albanian/AnyScript/Albania
+ { 7, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 926,46 , 972,62 , 1034,24 , 953,46 , 999,62 , 1061,24 , 483,27 , 510,28 , 538,14 , 483,27 , 510,28 , 538,14 , 9,3 , 9,4 , {69,84,66}, 17,2 , 81,16 , 4,4 , 13,6 , 92,4 , 96,5 , 2, 1, 6, 6, 7 }, // Amharic/AnyScript/Ethiopia
+ { 8, 0, 186, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {83,65,82}, 19,5 , 97,77 , 4,4 , 4,0 , 101,7 , 108,24 , 2, 1, 6, 4, 5 }, // Arabic/AnyScript/SaudiArabia
+ { 8, 0, 3, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 179,8 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {68,90,68}, 24,5 , 174,91 , 8,5 , 19,6 , 101,7 , 132,7 , 2, 1, 6, 4, 5 }, // Arabic/AnyScript/Algeria
+ { 8, 0, 17, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {66,72,68}, 29,5 , 265,91 , 8,5 , 19,6 , 101,7 , 139,7 , 3, 0, 6, 5, 6 }, // Arabic/AnyScript/Bahrain
+ { 8, 0, 64, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {69,71,80}, 34,5 , 356,70 , 8,5 , 19,6 , 101,7 , 146,3 , 2, 1, 6, 5, 6 }, // Arabic/AnyScript/Egypt
+ { 8, 0, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {73,81,68}, 39,5 , 426,84 , 8,5 , 19,6 , 101,7 , 149,6 , 0, 0, 6, 5, 6 }, // Arabic/AnyScript/Iraq
+ { 8, 0, 109, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1157,92 , 1157,92 , 1133,24 , 1184,92 , 1184,92 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {74,79,68}, 44,5 , 510,84 , 8,5 , 19,6 , 101,7 , 155,6 , 3, 0, 6, 5, 6 }, // Arabic/AnyScript/Jordan
+ { 8, 0, 115, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {75,87,68}, 49,5 , 594,84 , 8,5 , 19,6 , 101,7 , 161,6 , 3, 0, 6, 5, 6 }, // Arabic/AnyScript/Kuwait
+ { 8, 0, 119, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1249,92 , 1249,92 , 1133,24 , 1276,92 , 1276,92 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {76,66,80}, 54,5 , 678,84 , 8,5 , 19,6 , 101,7 , 167,5 , 0, 0, 1, 6, 7 }, // Arabic/AnyScript/Lebanon
+ { 8, 0, 122, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {76,89,68}, 59,5 , 762,77 , 8,5 , 19,6 , 101,7 , 172,5 , 3, 0, 6, 5, 6 }, // Arabic/AnyScript/LibyanArabJamahiriya
+ { 8, 0, 145, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 179,8 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {77,65,68}, 64,5 , 839,77 , 8,5 , 19,6 , 101,7 , 177,6 , 2, 1, 6, 5, 6 }, // Arabic/AnyScript/Morocco
+ { 8, 0, 162, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {79,77,82}, 69,5 , 916,77 , 8,5 , 19,6 , 101,7 , 183,5 , 3, 0, 6, 4, 5 }, // Arabic/AnyScript/Oman
+ { 8, 0, 175, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {81,65,82}, 74,5 , 993,70 , 4,4 , 4,0 , 101,7 , 188,3 , 2, 1, 6, 5, 6 }, // Arabic/AnyScript/Qatar
+ { 8, 0, 201, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {83,68,71}, 0,0 , 1063,18 , 8,5 , 19,6 , 101,7 , 191,7 , 2, 1, 6, 5, 6 }, // Arabic/AnyScript/Sudan
+ { 8, 0, 207, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1249,92 , 1249,92 , 1133,24 , 1276,92 , 1276,92 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {83,89,80}, 79,5 , 1081,70 , 4,4 , 4,0 , 101,7 , 198,5 , 0, 0, 7, 5, 6 }, // Arabic/AnyScript/SyrianArabRepublic
+ { 8, 0, 216, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 179,8 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {84,78,68}, 84,5 , 1151,77 , 4,4 , 4,0 , 101,7 , 203,4 , 3, 0, 6, 5, 6 }, // Arabic/AnyScript/Tunisia
+ { 8, 0, 223, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 670,38 , 604,52 , 656,14 , 670,38 , 604,52 , 656,14 , 12,1 , 13,1 , {65,69,68}, 89,5 , 1228,91 , 8,5 , 19,6 , 101,7 , 207,24 , 2, 1, 1, 5, 6 }, // Arabic/AnyScript/UnitedArabEmirates
+ { 8, 0, 237, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 14,6 , 14,6 , 20,8 , 28,7 , 151,10 , 161,18 , 18,7 , 61,12 , 1058,75 , 1058,75 , 1133,24 , 1085,75 , 1085,75 , 1160,24 , 552,52 , 604,52 , 656,14 , 552,52 , 604,52 , 656,14 , 12,1 , 13,1 , {89,69,82}, 94,5 , 1319,70 , 4,4 , 4,0 , 101,7 , 231,5 , 0, 0, 6, 4, 5 }, // Arabic/AnyScript/Yemen
+ { 9, 0, 11, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 187,8 , 35,18 , 37,5 , 8,10 , 1341,48 , 1389,94 , 1483,27 , 1368,48 , 1416,94 , 134,27 , 708,28 , 736,62 , 798,14 , 708,28 , 736,62 , 798,14 , 13,3 , 14,3 , {65,77,68}, 99,3 , 0,7 , 25,5 , 4,0 , 236,7 , 243,24 , 0, 0, 1, 6, 7 }, // Armenian/AnyScript/Armenia
+ { 10, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 195,8 , 203,18 , 73,8 , 81,12 , 1510,62 , 1572,88 , 1483,27 , 1510,62 , 1572,88 , 134,27 , 812,37 , 849,58 , 798,14 , 812,37 , 849,58 , 798,14 , 16,9 , 17,7 , {73,78,82}, 102,3 , 0,7 , 8,5 , 4,0 , 267,6 , 273,4 , 2, 1, 7, 7, 7 }, // Assamese/AnyScript/India
+ { 12, 0, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 229,19 , 37,5 , 8,10 , 1660,48 , 1708,77 , 1483,27 , 1660,48 , 1708,77 , 134,27 , 907,26 , 933,67 , 99,14 , 907,26 , 933,67 , 99,14 , 0,2 , 0,2 , {65,90,78}, 105,4 , 1389,41 , 8,5 , 4,0 , 277,12 , 289,10 , 2, 1, 7, 6, 7 }, // Azerbaijani/AnyScript/Azerbaijan
+ { 12, 0, 102, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 229,19 , 37,5 , 8,10 , 1660,48 , 1708,77 , 1483,27 , 1660,48 , 1708,77 , 134,27 , 907,26 , 933,67 , 99,14 , 907,26 , 933,67 , 99,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 1430,27 , 8,5 , 4,0 , 277,12 , 299,4 , 0, 0, 6, 4, 5 }, // Azerbaijani/AnyScript/Iran
+ { 12, 1, 102, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 229,19 , 37,5 , 8,10 , 1660,48 , 1708,77 , 1483,27 , 1660,48 , 1708,77 , 134,27 , 907,26 , 933,67 , 99,14 , 907,26 , 933,67 , 99,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 1430,27 , 8,5 , 4,0 , 277,12 , 299,4 , 0, 0, 6, 4, 5 }, // Azerbaijani/Arabic/Iran
+ { 12, 2, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 229,19 , 37,5 , 8,10 , 1660,48 , 1785,77 , 1483,27 , 1660,48 , 1785,77 , 134,27 , 907,26 , 1000,67 , 99,14 , 907,26 , 1000,67 , 99,14 , 0,2 , 0,2 , {65,90,78}, 109,4 , 1457,29 , 8,5 , 4,0 , 303,10 , 303,10 , 2, 1, 7, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
+ { 12, 7, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 229,19 , 37,5 , 8,10 , 1660,48 , 1708,77 , 1483,27 , 1660,48 , 1708,77 , 134,27 , 907,26 , 933,67 , 99,14 , 907,26 , 933,67 , 99,14 , 0,2 , 0,2 , {65,90,78}, 105,4 , 1389,41 , 8,5 , 4,0 , 277,12 , 289,10 , 2, 1, 7, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
+ { 14, 0, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 248,31 , 37,5 , 8,10 , 1862,48 , 1910,93 , 2003,24 , 1862,48 , 1910,93 , 2003,24 , 1067,21 , 1088,68 , 798,14 , 1067,21 , 1088,68 , 798,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 0,7 , 25,5 , 4,0 , 313,7 , 320,8 , 2, 1, 1, 6, 7 }, // Basque/AnyScript/Spain
+ { 15, 0, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 35,10 , 45,9 , 279,6 , 203,18 , 18,7 , 25,12 , 2027,90 , 2027,90 , 2117,33 , 2027,90 , 2027,90 , 2117,33 , 1156,37 , 1193,58 , 1251,18 , 1156,37 , 1193,58 , 1251,18 , 25,9 , 24,7 , {66,68,84}, 114,1 , 1486,21 , 0,4 , 30,6 , 328,5 , 333,8 , 2, 1, 1, 6, 7 }, // Bengali/AnyScript/Bangladesh
+ { 15, 0, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 35,10 , 45,9 , 279,6 , 203,18 , 18,7 , 25,12 , 2027,90 , 2027,90 , 2117,33 , 2027,90 , 2027,90 , 2117,33 , 1156,37 , 1193,58 , 1251,18 , 1156,37 , 1193,58 , 1251,18 , 25,9 , 24,7 , {73,78,82}, 115,4 , 1507,19 , 0,4 , 30,6 , 328,5 , 341,4 , 2, 1, 7, 7, 7 }, // Bengali/AnyScript/India
+ { 16, 0, 25, 46, 44, 59, 37, 48, 45, 43, 101, 34, 34, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 285,29 , 93,22 , 115,35 , 2150,75 , 2225,205 , 1483,27 , 2150,75 , 2225,205 , 134,27 , 1269,34 , 1303,79 , 798,14 , 1269,34 , 1303,79 , 798,14 , 0,2 , 0,2 , {66,84,78}, 119,3 , 1526,16 , 4,4 , 4,0 , 345,6 , 351,5 , 2, 1, 1, 6, 7 }, // Bhutani/AnyScript/Bhutan
+ { 19, 0, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1542,11 , 8,5 , 4,0 , 0,0 , 356,5 , 2, 1, 1, 6, 7 }, // Breton/AnyScript/France
+ { 20, 0, 33, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 332,8 , 340,18 , 37,5 , 8,10 , 2430,59 , 2489,82 , 2571,24 , 2430,59 , 2489,82 , 2571,24 , 1382,21 , 1403,55 , 1458,14 , 1382,21 , 1403,55 , 1458,14 , 34,7 , 31,7 , {66,71,78}, 122,3 , 1553,47 , 25,5 , 4,0 , 361,9 , 370,8 , 2, 1, 1, 6, 7 }, // Bulgarian/AnyScript/Bulgaria
+ { 21, 0, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 2595,43 , 2638,88 , 2726,24 , 2595,43 , 2638,88 , 2726,24 , 1472,25 , 1497,54 , 1551,14 , 1472,25 , 1497,54 , 1551,14 , 0,2 , 0,2 , {77,77,75}, 125,1 , 1600,18 , 8,5 , 4,0 , 378,3 , 381,6 , 0, 0, 1, 6, 7 }, // Burmese/AnyScript/Myanmar
+ { 22, 0, 20, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 358,6 , 10,17 , 150,5 , 155,10 , 2750,48 , 2798,99 , 2897,24 , 2750,48 , 2798,95 , 2893,24 , 1565,21 , 1586,56 , 1642,14 , 1565,21 , 1586,56 , 1642,14 , 41,10 , 38,13 , {66,89,82}, 0,0 , 1618,23 , 4,4 , 4,0 , 387,10 , 397,8 , 0, 0, 1, 6, 7 }, // Byelorussian/AnyScript/Belarus
+ { 23, 0, 36, 44, 46, 59, 37, 48, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 372,30 , 165,4 , 169,26 , 2921,27 , 2948,71 , 1483,27 , 2917,27 , 2944,71 , 134,27 , 1656,19 , 1675,76 , 798,14 , 1656,19 , 1675,76 , 798,14 , 51,5 , 51,5 , {75,72,82}, 126,1 , 1641,11 , 0,4 , 4,0 , 405,9 , 414,7 , 2, 1, 1, 6, 7 }, // Cambodian/AnyScript/Cambodia
+ { 24, 0, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 61,7 , 61,7 , 27,8 , 402,21 , 165,4 , 195,9 , 3019,60 , 3079,82 , 3161,24 , 3015,93 , 3108,115 , 3223,24 , 1751,21 , 1772,60 , 1832,14 , 1846,28 , 1874,60 , 1934,14 , 56,4 , 56,4 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 421,6 , 427,7 , 2, 1, 1, 6, 7 }, // Catalan/AnyScript/Spain
+ { 25, 0, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 423,6 , 429,13 , 204,6 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {67,78,89}, 127,1 , 1672,10 , 4,4 , 4,0 , 434,2 , 436,2 , 2, 1, 7, 6, 7 }, // Chinese/AnyScript/China
+ { 25, 0, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 442,7 , 429,13 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {72,75,68}, 128,1 , 1682,9 , 4,4 , 13,6 , 434,2 , 438,14 , 2, 1, 7, 6, 7 }, // Chinese/AnyScript/HongKong
+ { 25, 0, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 442,7 , 449,15 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {77,79,80}, 129,4 , 1691,10 , 4,4 , 4,0 , 434,2 , 452,14 , 2, 1, 7, 6, 7 }, // Chinese/AnyScript/Macau
+ { 25, 0, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 27,8 , 429,13 , 232,7 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {83,71,68}, 133,2 , 1701,11 , 4,4 , 4,0 , 434,2 , 466,3 , 2, 1, 7, 6, 7 }, // Chinese/AnyScript/Singapore
+ { 25, 0, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 464,6 , 429,13 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {84,87,68}, 135,3 , 1712,10 , 4,4 , 4,0 , 434,2 , 469,2 , 2, 1, 7, 6, 7 }, // Chinese/AnyScript/Taiwan
+ { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 423,6 , 429,13 , 204,6 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {67,78,89}, 127,1 , 1672,10 , 4,4 , 4,0 , 471,6 , 436,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
+ { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 423,6 , 429,13 , 204,6 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {72,75,68}, 128,1 , 1682,9 , 4,4 , 4,0 , 471,6 , 477,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/HongKong
+ { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 423,6 , 429,13 , 204,6 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {77,79,80}, 129,4 , 1722,10 , 4,4 , 4,0 , 471,6 , 486,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
+ { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 68,5 , 68,5 , 73,5 , 73,5 , 27,8 , 429,13 , 232,7 , 210,11 , 3185,38 , 3185,38 , 3223,39 , 3247,39 , 3247,39 , 3247,39 , 1948,21 , 1969,28 , 1997,14 , 1948,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {83,71,68}, 133,2 , 1701,11 , 4,4 , 4,0 , 471,6 , 466,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
+ { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 442,7 , 429,13 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {72,75,68}, 128,1 , 1682,9 , 4,4 , 13,6 , 495,4 , 438,14 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/HongKong
+ { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 442,7 , 449,15 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {77,79,80}, 129,4 , 1691,10 , 4,4 , 4,0 , 495,4 , 452,14 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
+ { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 73,5 , 73,5 , 464,6 , 429,13 , 204,6 , 221,11 , 3185,38 , 3185,38 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 2011,21 , 1969,28 , 1997,14 , 2011,21 , 1969,28 , 1997,14 , 60,2 , 60,2 , {84,87,68}, 135,3 , 1712,10 , 4,4 , 4,0 , 495,4 , 469,2 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
+ { 27, 0, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 61,7 , 61,7 , 470,13 , 483,19 , 37,5 , 8,10 , 3262,49 , 3311,94 , 3405,39 , 3286,49 , 3335,98 , 3433,39 , 2032,28 , 2060,58 , 2118,14 , 2032,28 , 2060,58 , 2118,14 , 0,2 , 0,2 , {72,82,75}, 138,2 , 1732,27 , 25,5 , 4,0 , 499,8 , 507,8 , 2, 1, 1, 6, 7 }, // Croatian/AnyScript/Croatia
+ { 28, 0, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 78,7 , 78,7 , 358,6 , 502,18 , 165,4 , 195,9 , 3405,39 , 3444,82 , 3526,24 , 134,27 , 3472,84 , 3556,24 , 2132,21 , 2153,49 , 2202,14 , 2132,21 , 2153,49 , 2202,14 , 62,4 , 62,4 , {67,90,75}, 140,2 , 1759,19 , 25,5 , 4,0 , 515,7 , 522,15 , 2, 1, 1, 6, 7 }, // Czech/AnyScript/CzechRepublic
+ { 29, 0, 58, 44, 46, 44, 37, 48, 45, 43, 101, 8221, 8221, 8221, 8221, 0,6 , 0,6 , 85,8 , 85,8 , 27,8 , 520,23 , 150,5 , 155,10 , 3550,48 , 3598,84 , 134,24 , 3580,59 , 3639,84 , 320,24 , 2216,28 , 2244,51 , 2295,14 , 2216,28 , 2244,51 , 2295,14 , 66,4 , 66,4 , {68,75,75}, 142,2 , 1778,42 , 25,5 , 4,0 , 537,5 , 542,7 , 2, 1, 1, 6, 7 }, // Danish/AnyScript/Denmark
+ { 30, 0, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 543,8 , 99,16 , 37,5 , 8,10 , 3682,48 , 3730,88 , 134,24 , 3723,59 , 3782,88 , 320,24 , 2309,21 , 2330,59 , 2389,14 , 2309,21 , 2330,59 , 2389,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1820,19 , 8,5 , 19,6 , 549,10 , 559,9 , 2, 1, 1, 6, 7 }, // Dutch/AnyScript/Netherlands
+ { 30, 0, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 551,7 , 99,16 , 37,5 , 8,10 , 3682,48 , 3730,88 , 134,24 , 3723,59 , 3782,88 , 320,24 , 2309,21 , 2330,59 , 2389,14 , 2309,21 , 2330,59 , 2389,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1820,19 , 25,5 , 4,0 , 568,6 , 574,6 , 2, 1, 1, 6, 7 }, // Dutch/AnyScript/Belgium
+ { 31, 0, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 580,12 , 592,13 , 2, 1, 7, 6, 7 }, // English/AnyScript/UnitedStates
+ { 31, 0, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 612,14 , 2, 1, 7, 6, 7 }, // English/AnyScript/AmericanSamoa
+ { 31, 0, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 551,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 128,1 , 1874,59 , 4,4 , 4,0 , 626,18 , 644,9 , 2, 1, 1, 6, 7 }, // English/AnyScript/Australia
+ { 31, 0, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 27,8 , 99,16 , 37,5 , 239,24 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1933,20 , 25,5 , 4,0 , 605,7 , 653,7 , 2, 1, 1, 6, 7 }, // English/AnyScript/Belgium
+ { 31, 0, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 27,8 , 564,12 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,90,68}, 128,1 , 1953,47 , 4,4 , 4,0 , 605,7 , 660,6 , 2, 1, 1, 6, 7 }, // English/AnyScript/Belize
+ { 31, 0, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 27,8 , 82,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,87,80}, 144,1 , 2000,50 , 4,4 , 4,0 , 605,7 , 666,8 , 2, 1, 7, 6, 7 }, // English/AnyScript/Botswana
+ { 31, 0, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 115,8 , 203,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {67,65,68}, 128,1 , 2050,53 , 4,4 , 13,6 , 674,16 , 690,6 , 2, 1, 7, 6, 7 }, // English/AnyScript/Canada
+ { 31, 0, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 696,4 , 2, 1, 7, 6, 7 }, // English/AnyScript/Guam
+ { 31, 0, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 279,6 , 203,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {72,75,68}, 128,1 , 2103,56 , 4,4 , 13,6 , 605,7 , 700,19 , 2, 1, 7, 6, 7 }, // English/AnyScript/HongKong
+ { 31, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 27,8 , 99,16 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {73,78,82}, 145,2 , 2159,44 , 8,5 , 4,0 , 605,7 , 719,5 , 2, 1, 7, 7, 7 }, // English/AnyScript/India
+ { 31, 0, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 141,10 , 99,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 56,4 , 56,4 , {69,85,82}, 113,1 , 1933,20 , 4,4 , 4,0 , 605,7 , 724,7 , 2, 1, 7, 6, 7 }, // English/AnyScript/Ireland
+ { 31, 0, 107, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 279,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {74,77,68}, 128,1 , 2203,53 , 4,4 , 4,0 , 605,7 , 731,7 , 2, 1, 7, 6, 7 }, // English/AnyScript/Jamaica
+ { 31, 0, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 141,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1933,20 , 4,4 , 4,0 , 605,7 , 738,5 , 2, 1, 7, 6, 7 }, // English/AnyScript/Malta
+ { 31, 0, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 743,16 , 2, 1, 7, 6, 7 }, // English/AnyScript/MarshallIslands
+ { 31, 0, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,85,82}, 147,4 , 2256,53 , 4,4 , 13,6 , 605,7 , 759,9 , 0, 0, 1, 6, 7 }, // English/AnyScript/Mauritius
+ { 31, 0, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,65,68}, 128,1 , 2309,53 , 4,4 , 4,0 , 605,7 , 768,7 , 2, 1, 1, 6, 7 }, // English/AnyScript/Namibia
+ { 31, 0, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 551,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 128,1 , 2362,62 , 4,4 , 4,0 , 605,7 , 775,11 , 2, 1, 7, 6, 7 }, // English/AnyScript/NewZealand
+ { 31, 0, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 786,24 , 2, 1, 7, 6, 7 }, // English/AnyScript/NorthernMarianaIslands
+ { 31, 0, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 27,8 , 99,16 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {80,75,82}, 151,1 , 2424,53 , 8,5 , 4,0 , 605,7 , 810,8 , 0, 0, 7, 6, 7 }, // English/AnyScript/Pakistan
+ { 31, 0, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {80,72,80}, 152,1 , 2477,42 , 4,4 , 13,6 , 605,7 , 818,11 , 2, 1, 7, 6, 7 }, // English/AnyScript/Philippines
+ { 31, 0, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 279,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,71,68}, 128,1 , 2519,56 , 4,4 , 13,6 , 605,7 , 829,9 , 2, 1, 7, 6, 7 }, // English/AnyScript/Singapore
+ { 31, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 576,10 , 82,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 2575,61 , 4,4 , 4,0 , 605,7 , 838,12 , 2, 1, 1, 6, 7 }, // English/AnyScript/SouthAfrica
+ { 31, 0, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {84,84,68}, 128,1 , 2636,86 , 4,4 , 4,0 , 605,7 , 850,19 , 2, 1, 7, 6, 7 }, // English/AnyScript/TrinidadAndTobago
+ { 31, 0, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 93,10 , 103,9 , 141,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,66,80}, 153,1 , 2722,74 , 4,4 , 4,0 , 869,15 , 884,14 , 2, 1, 1, 6, 7 }, // English/AnyScript/UnitedKingdom
+ { 31, 0, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 898,27 , 2, 1, 7, 6, 7 }, // English/AnyScript/UnitedStatesMinorOutlyingIslands
+ { 31, 0, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 605,7 , 925,19 , 2, 1, 7, 6, 7 }, // English/AnyScript/USVirginIslands
+ { 31, 0, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 364,8 , 82,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 320,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 4,0 , 605,7 , 944,8 , 2, 1, 7, 6, 7 }, // English/AnyScript/Zimbabwe
+ { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 93,10 , 103,9 , 558,6 , 35,18 , 18,7 , 25,12 , 3818,80 , 3898,154 , 4052,36 , 3870,80 , 3950,154 , 4104,36 , 2403,49 , 2452,85 , 2537,21 , 2403,49 , 2452,85 , 2537,21 , 70,4 , 70,4 , {85,83,68}, 128,1 , 1839,35 , 4,4 , 13,6 , 580,12 , 952,25 , 2, 1, 7, 6, 7 }, // English/Deseret/UnitedStates
+ { 33, 0, 68, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 112,8 , 112,8 , 332,8 , 502,18 , 165,4 , 263,9 , 4088,59 , 4147,91 , 4238,24 , 4140,59 , 4199,91 , 4290,24 , 2558,14 , 2572,63 , 2558,14 , 2558,14 , 2572,63 , 2558,14 , 74,14 , 74,16 , {69,69,75}, 142,2 , 2796,41 , 25,5 , 4,0 , 977,5 , 982,5 , 2, 1, 1, 6, 7 }, // Estonian/AnyScript/Estonia
+ { 34, 0, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 85,8 , 85,8 , 543,8 , 82,17 , 37,5 , 8,10 , 4262,48 , 4310,83 , 134,24 , 4314,48 , 4362,83 , 320,24 , 2635,28 , 2663,74 , 2737,14 , 2635,28 , 2663,74 , 2737,14 , 0,2 , 0,2 , {68,75,75}, 142,2 , 2837,42 , 4,4 , 36,5 , 987,8 , 995,7 , 2, 1, 7, 6, 7 }, // Faroese/AnyScript/FaroeIslands
+ { 36, 0, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 112,8 , 112,8 , 586,8 , 594,17 , 272,4 , 276,9 , 4393,69 , 4462,105 , 4567,24 , 4445,129 , 4445,129 , 4574,24 , 2751,21 , 2772,67 , 2839,14 , 2751,21 , 2853,81 , 2839,14 , 88,3 , 90,3 , {69,85,82}, 113,1 , 2879,20 , 25,5 , 4,0 , 1002,5 , 1007,5 , 2, 1, 1, 6, 7 }, // Finnish/AnyScript/Finland
+ { 37, 0, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1020,6 , 2, 1, 1, 6, 7 }, // French/AnyScript/France
+ { 37, 0, 21, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 551,7 , 99,16 , 37,5 , 285,23 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1026,8 , 2, 1, 1, 6, 7 }, // French/AnyScript/Belgium
+ { 37, 0, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,65,70}, 154,3 , 2899,56 , 25,5 , 4,0 , 1012,8 , 1034,8 , 0, 0, 1, 6, 7 }, // French/AnyScript/Cameroon
+ { 37, 0, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 115,8 , 99,16 , 37,5 , 239,24 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {67,65,68}, 128,1 , 2955,54 , 25,5 , 41,7 , 1042,17 , 690,6 , 2, 1, 7, 6, 7 }, // French/AnyScript/Canada
+ { 37, 0, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,65,70}, 154,3 , 2899,56 , 25,5 , 4,0 , 1012,8 , 1059,25 , 0, 0, 1, 6, 7 }, // French/AnyScript/CentralAfricanRepublic
+ { 37, 0, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3009,59 , 25,5 , 4,0 , 1012,8 , 1084,13 , 0, 0, 1, 6, 7 }, // French/AnyScript/IvoryCoast
+ { 37, 0, 88, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1097,10 , 2, 1, 1, 6, 7 }, // French/AnyScript/Guadeloupe
+ { 37, 0, 91, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {71,78,70}, 160,3 , 3068,48 , 25,5 , 4,0 , 1012,8 , 1107,6 , 0, 0, 1, 6, 7 }, // French/AnyScript/Guinea
+ { 37, 0, 125, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1113,10 , 2, 1, 1, 6, 7 }, // French/AnyScript/Luxembourg
+ { 37, 0, 128, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {77,71,65}, 0,0 , 3116,54 , 25,5 , 4,0 , 1012,8 , 1123,10 , 0, 0, 1, 6, 7 }, // French/AnyScript/Madagascar
+ { 37, 0, 132, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3009,59 , 25,5 , 4,0 , 1012,8 , 1133,4 , 0, 0, 1, 6, 7 }, // French/AnyScript/Mali
+ { 37, 0, 135, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1137,10 , 2, 1, 1, 6, 7 }, // French/AnyScript/Martinique
+ { 37, 0, 142, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1147,6 , 2, 1, 1, 6, 7 }, // French/AnyScript/Monaco
+ { 37, 0, 156, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3009,59 , 25,5 , 4,0 , 1012,8 , 1153,5 , 0, 0, 1, 6, 7 }, // French/AnyScript/Niger
+ { 37, 0, 176, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1158,7 , 2, 1, 1, 6, 7 }, // French/AnyScript/Reunion
+ { 37, 0, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3009,59 , 25,5 , 4,0 , 1012,8 , 1165,7 , 0, 0, 1, 6, 7 }, // French/AnyScript/Senegal
+ { 37, 0, 206, 46, 39, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 120,8 , 120,8 , 332,8 , 10,17 , 37,5 , 308,14 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {67,72,70}, 163,3 , 3170,45 , 8,5 , 48,5 , 1172,15 , 1187,6 , 2, 5, 1, 6, 7 }, // French/AnyScript/Switzerland
+ { 37, 0, 244, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1193,16 , 2, 1, 1, 6, 7 }, // French/AnyScript/Saint Barthelemy
+ { 37, 0, 245, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 120,8 , 120,8 , 27,8 , 99,16 , 37,5 , 8,10 , 4591,63 , 4654,85 , 134,24 , 4598,63 , 4661,85 , 320,24 , 2934,35 , 2969,52 , 3021,14 , 2934,35 , 2969,52 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1652,20 , 25,5 , 4,0 , 1012,8 , 1209,12 , 2, 1, 1, 6, 7 }, // French/AnyScript/Saint Martin
+ { 40, 0, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 82,17 , 37,5 , 8,10 , 4739,48 , 4787,87 , 4874,24 , 4746,48 , 4794,87 , 4881,24 , 3035,28 , 3063,49 , 3112,14 , 3035,28 , 3063,49 , 3112,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1933,20 , 25,5 , 4,0 , 1221,6 , 1227,6 , 2, 1, 1, 6, 7 }, // Galician/AnyScript/Spain
+ { 41, 0, 81, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 4898,48 , 4946,99 , 5045,24 , 4905,48 , 4953,99 , 5052,24 , 3126,28 , 3154,62 , 3216,14 , 3126,28 , 3154,62 , 3216,14 , 0,2 , 0,2 , {71,69,76}, 0,0 , 3215,19 , 8,5 , 4,0 , 1233,7 , 1240,10 , 2, 1, 7, 6, 7 }, // Georgian/AnyScript/Georgia
+ { 42, 0, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 502,18 , 37,5 , 8,10 , 5069,52 , 5121,83 , 134,24 , 5076,48 , 5124,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3325,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {69,85,82}, 113,1 , 3234,19 , 25,5 , 4,0 , 1250,7 , 1257,11 , 2, 1, 1, 6, 7 }, // German/AnyScript/Germany
+ { 42, 0, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 611,19 , 37,5 , 8,10 , 5069,52 , 5204,83 , 134,24 , 5207,48 , 5255,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3325,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {69,85,82}, 113,1 , 3234,19 , 8,5 , 4,0 , 1268,24 , 1292,10 , 2, 1, 1, 6, 7 }, // German/AnyScript/Austria
+ { 42, 0, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 128,9 , 128,9 , 551,7 , 99,16 , 37,5 , 239,24 , 5069,52 , 5121,83 , 134,24 , 5076,48 , 5124,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3353,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {69,85,82}, 113,1 , 3234,19 , 25,5 , 4,0 , 1250,7 , 1302,7 , 2, 1, 1, 6, 7 }, // German/AnyScript/Belgium
+ { 42, 0, 123, 46, 39, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 502,18 , 37,5 , 8,10 , 5069,52 , 5121,83 , 134,24 , 5076,48 , 5124,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3325,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {67,72,70}, 0,0 , 3253,41 , 8,5 , 4,0 , 1250,7 , 1309,13 , 2, 5, 1, 6, 7 }, // German/AnyScript/Liechtenstein
+ { 42, 0, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 502,18 , 37,5 , 8,10 , 5069,52 , 5121,83 , 134,24 , 5076,48 , 5124,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3325,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {69,85,82}, 113,1 , 3234,19 , 25,5 , 4,0 , 1250,7 , 1322,9 , 2, 1, 1, 6, 7 }, // German/AnyScript/Luxembourg
+ { 42, 0, 206, 46, 39, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 502,18 , 37,5 , 8,10 , 5069,52 , 5121,83 , 134,24 , 5076,48 , 5124,83 , 320,24 , 3230,21 , 3251,60 , 3311,14 , 3325,28 , 3251,60 , 3311,14 , 91,5 , 93,6 , {67,72,70}, 0,0 , 3253,41 , 8,5 , 48,5 , 1331,21 , 1352,7 , 2, 5, 1, 6, 7 }, // German/AnyScript/Switzerland
+ { 43, 0, 85, 44, 46, 44, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 137,9 , 137,9 , 279,6 , 10,17 , 18,7 , 25,12 , 5287,50 , 5337,115 , 5452,24 , 5338,50 , 5388,115 , 5503,24 , 3381,28 , 3409,55 , 3464,14 , 3381,28 , 3409,55 , 3464,14 , 96,4 , 99,4 , {69,85,82}, 113,1 , 3294,19 , 25,5 , 4,0 , 1359,8 , 1367,6 , 2, 1, 1, 6, 7 }, // Greek/AnyScript/Greece
+ { 43, 0, 56, 44, 46, 44, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 137,9 , 137,9 , 279,6 , 10,17 , 18,7 , 25,12 , 5287,50 , 5337,115 , 5452,24 , 5338,50 , 5388,115 , 5503,24 , 3381,28 , 3409,55 , 3464,14 , 3381,28 , 3409,55 , 3464,14 , 96,4 , 99,4 , {69,85,82}, 113,1 , 3294,19 , 4,4 , 4,0 , 1359,8 , 1373,6 , 2, 1, 1, 6, 7 }, // Greek/AnyScript/Cyprus
+ { 44, 0, 86, 44, 46, 59, 37, 48, 8722, 43, 101, 187, 171, 8250, 8249, 146,11 , 0,6 , 0,6 , 146,11 , 72,10 , 82,17 , 18,7 , 25,12 , 3550,48 , 5476,96 , 134,24 , 5527,48 , 5575,96 , 320,24 , 3478,28 , 3506,98 , 3604,14 , 3478,28 , 3506,98 , 3604,14 , 0,2 , 0,2 , {68,75,75}, 142,2 , 3313,24 , 4,4 , 36,5 , 1379,11 , 1390,16 , 2, 1, 7, 6, 7 }, // Greenlandic/AnyScript/Greenland
+ { 46, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 157,9 , 157,9 , 630,7 , 203,18 , 322,8 , 330,13 , 5572,67 , 5639,87 , 5726,31 , 5671,67 , 5738,87 , 5825,31 , 3618,32 , 3650,53 , 3703,19 , 3618,32 , 3650,53 , 3703,19 , 100,14 , 103,14 , {73,78,82}, 166,2 , 0,7 , 8,5 , 4,0 , 1406,7 , 1413,4 , 2, 1, 7, 7, 7 }, // Gujarati/AnyScript/India
+ { 47, 0, 83, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {71,72,83}, 168,3 , 0,7 , 8,5 , 4,0 , 1417,5 , 1422,4 , 2, 1, 1, 6, 7 }, // Hausa/AnyScript/Ghana
+ { 47, 0, 156, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3337,36 , 8,5 , 4,0 , 1417,5 , 1426,5 , 0, 0, 1, 6, 7 }, // Hausa/AnyScript/Niger
+ { 47, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 3373,12 , 8,5 , 4,0 , 1417,5 , 1431,8 , 2, 1, 1, 6, 7 }, // Hausa/AnyScript/Nigeria
+ { 47, 0, 201, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5914,55 , 5969,99 , 5890,24 , 6013,55 , 6068,99 , 5989,24 , 3809,31 , 3840,57 , 3795,14 , 3809,31 , 3840,57 , 3795,14 , 0,2 , 0,2 , {83,68,71}, 0,0 , 3385,20 , 8,5 , 4,0 , 1417,5 , 1439,5 , 2, 1, 6, 5, 6 }, // Hausa/AnyScript/Sudan
+ { 47, 1, 157, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5914,55 , 5969,99 , 5890,24 , 6013,55 , 6068,99 , 5989,24 , 3809,31 , 3840,57 , 3795,14 , 3809,31 , 3840,57 , 3795,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 3405,13 , 8,5 , 4,0 , 1417,5 , 1431,8 , 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
+ { 47, 1, 201, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5914,55 , 5969,99 , 5890,24 , 6013,55 , 6068,99 , 5989,24 , 3809,31 , 3840,57 , 3795,14 , 3809,31 , 3840,57 , 3795,14 , 0,2 , 0,2 , {83,68,71}, 0,0 , 3385,20 , 8,5 , 4,0 , 1417,5 , 1439,5 , 2, 1, 6, 5, 6 }, // Hausa/Arabic/Sudan
+ { 47, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {71,72,83}, 168,3 , 0,7 , 8,5 , 4,0 , 1417,5 , 1422,4 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
+ { 47, 7, 156, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 3337,36 , 8,5 , 4,0 , 1417,5 , 1426,5 , 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
+ { 47, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 203,18 , 37,5 , 8,10 , 5757,48 , 5805,85 , 5890,24 , 5856,48 , 5904,85 , 5989,24 , 3722,21 , 3743,52 , 3795,14 , 3722,21 , 3743,52 , 3795,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 3373,12 , 8,5 , 4,0 , 1417,5 , 1431,8 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
+ { 48, 0, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 637,18 , 37,5 , 8,10 , 6068,58 , 6126,72 , 1483,27 , 6167,48 , 6215,72 , 134,27 , 3897,46 , 3943,65 , 4008,14 , 3897,46 , 3943,65 , 4008,14 , 114,6 , 117,5 , {73,76,83}, 172,1 , 3418,21 , 25,5 , 4,0 , 1444,5 , 1449,5 , 2, 1, 7, 5, 6 }, // Hebrew/AnyScript/Israel
+ { 49, 0, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 166,8 , 166,8 , 655,6 , 10,17 , 18,7 , 25,12 , 6198,75 , 6198,75 , 6273,30 , 6287,75 , 6287,75 , 6362,30 , 4022,38 , 4060,57 , 4117,19 , 4022,38 , 4060,57 , 4117,19 , 120,9 , 122,7 , {73,78,82}, 173,3 , 3439,19 , 8,5 , 4,0 , 1454,6 , 1460,4 , 2, 1, 7, 7, 7 }, // Hindi/AnyScript/India
+ { 50, 0, 98, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8222, 8221, 0,6 , 0,6 , 174,8 , 174,8 , 661,11 , 672,19 , 165,4 , 195,9 , 6303,64 , 6367,98 , 6465,25 , 6392,64 , 6456,98 , 6554,25 , 4136,19 , 4155,52 , 4207,17 , 4136,19 , 4155,52 , 4207,17 , 129,3 , 129,3 , {72,85,70}, 176,2 , 3458,20 , 25,5 , 4,0 , 1464,6 , 1470,12 , 0, 0, 1, 6, 7 }, // Hungarian/AnyScript/Hungary
+ { 51, 0, 99, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 85,8 , 85,8 , 586,8 , 502,18 , 37,5 , 8,10 , 6490,48 , 6538,82 , 6620,24 , 6579,48 , 6627,82 , 6709,24 , 4224,28 , 4252,81 , 4333,14 , 4224,28 , 4252,81 , 4347,14 , 132,4 , 132,4 , {73,83,75}, 142,2 , 3478,48 , 25,5 , 4,0 , 1482,8 , 1490,6 , 0, 0, 7, 6, 7 }, // Icelandic/AnyScript/Iceland
+ { 52, 0, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 182,11 , 193,9 , 27,8 , 123,18 , 150,5 , 276,9 , 6644,48 , 6692,87 , 134,24 , 6733,48 , 6781,87 , 320,24 , 4361,28 , 4389,43 , 4432,14 , 4361,28 , 4389,43 , 4432,14 , 0,2 , 0,2 , {73,68,82}, 178,2 , 3526,23 , 4,4 , 4,0 , 1496,16 , 1512,9 , 0, 0, 1, 6, 7 }, // Indonesian/AnyScript/Indonesia
+ { 57, 0, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 99,16 , 37,5 , 8,10 , 6779,62 , 6841,107 , 6948,24 , 6868,62 , 6930,107 , 7037,24 , 4446,37 , 4483,75 , 4558,14 , 4446,37 , 4483,75 , 4558,14 , 56,4 , 56,4 , {69,85,82}, 113,1 , 3549,11 , 4,4 , 4,0 , 1521,7 , 1528,4 , 2, 1, 7, 6, 7 }, // Irish/AnyScript/Ireland
+ { 58, 0, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 202,8 , 210,7 , 27,8 , 99,16 , 37,5 , 8,10 , 6972,48 , 7020,94 , 7114,24 , 7061,48 , 7109,94 , 7203,24 , 4572,28 , 4600,57 , 4657,14 , 4572,28 , 4671,57 , 4657,14 , 136,2 , 136,2 , {69,85,82}, 113,1 , 3549,11 , 8,5 , 4,0 , 1532,8 , 1540,6 , 2, 1, 1, 6, 7 }, // Italian/AnyScript/Italy
+ { 58, 0, 206, 46, 39, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 202,8 , 210,7 , 332,8 , 10,17 , 37,5 , 308,14 , 6972,48 , 7020,94 , 7114,24 , 7061,48 , 7109,94 , 7203,24 , 4572,28 , 4600,57 , 4657,14 , 4572,28 , 4671,57 , 4657,14 , 136,2 , 136,2 , {67,72,70}, 0,0 , 3560,22 , 8,5 , 48,5 , 1532,8 , 1546,8 , 2, 5, 1, 6, 7 }, // Italian/AnyScript/Switzerland
+ { 59, 0, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 68,5 , 68,5 , 68,5 , 68,5 , 221,8 , 429,13 , 165,4 , 343,10 , 3223,39 , 3223,39 , 1483,27 , 3247,39 , 3247,39 , 134,27 , 4728,14 , 4742,28 , 4728,14 , 4728,14 , 4742,28 , 4728,14 , 138,2 , 138,2 , {74,80,89}, 127,1 , 3582,10 , 4,4 , 4,0 , 1554,3 , 1557,2 , 0, 0, 7, 6, 7 }, // Japanese/AnyScript/Japan
+ { 61, 0, 100, 46, 44, 59, 37, 3302, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 217,11 , 217,11 , 655,6 , 99,16 , 322,8 , 330,13 , 7138,86 , 7138,86 , 7224,31 , 7227,86 , 7227,86 , 7313,31 , 4770,28 , 4798,53 , 4851,19 , 4770,28 , 4798,53 , 4851,19 , 140,2 , 140,2 , {73,78,82}, 180,2 , 0,7 , 8,5 , 4,0 , 1559,5 , 1564,4 , 2, 1, 7, 7, 7 }, // Kannada/AnyScript/India
+ { 63, 0, 110, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 332,8 , 691,22 , 37,5 , 8,10 , 7255,61 , 7316,83 , 1483,27 , 7344,61 , 7405,83 , 134,27 , 4870,28 , 4898,54 , 798,14 , 4870,28 , 4898,54 , 798,14 , 0,2 , 0,2 , {75,90,84}, 182,4 , 0,7 , 25,5 , 4,0 , 1568,5 , 1573,9 , 2, 1, 1, 6, 7 }, // Kazakh/AnyScript/Kazakhstan
+ { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 332,8 , 691,22 , 37,5 , 8,10 , 7255,61 , 7316,83 , 1483,27 , 7344,61 , 7405,83 , 134,27 , 4870,28 , 4898,54 , 798,14 , 4870,28 , 4898,54 , 798,14 , 0,2 , 0,2 , {75,90,84}, 182,4 , 0,7 , 25,5 , 4,0 , 1568,5 , 1573,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
+ { 64, 0, 179, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 7399,60 , 7459,101 , 1483,27 , 7488,60 , 7548,101 , 134,27 , 4952,35 , 4987,84 , 798,14 , 4952,35 , 4987,84 , 798,14 , 0,2 , 0,2 , {82,87,70}, 186,2 , 0,7 , 8,5 , 4,0 , 1582,11 , 1593,6 , 0, 0, 1, 6, 7 }, // Kinyarwanda/AnyScript/Rwanda
+ { 65, 0, 116, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {75,71,83}, 188,3 , 0,7 , 8,5 , 4,0 , 1599,6 , 1605,10 , 2, 1, 7, 6, 7 }, // Kirghiz/AnyScript/Kyrgyzstan
+ { 66, 0, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 713,9 , 722,16 , 353,7 , 360,13 , 7560,39 , 7560,39 , 7560,39 , 7649,39 , 7649,39 , 7649,39 , 5071,14 , 5085,28 , 5071,14 , 5071,14 , 5085,28 , 5071,14 , 142,2 , 142,2 , {75,82,87}, 191,1 , 3592,13 , 4,4 , 4,0 , 1615,3 , 1618,4 , 0, 0, 7, 6, 7 }, // Korean/AnyScript/RepublicOfKorea
+ { 67, 0, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 5113,42 , 5113,42 , 5155,14 , 5113,42 , 5113,42 , 5155,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 1622,5 , 0,0 , 0, 0, 6, 4, 5 }, // Kurdish/AnyScript/Iran
+ { 67, 0, 103, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 5113,42 , 5113,42 , 5155,14 , 5113,42 , 5113,42 , 5155,14 , 0,2 , 0,2 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 1622,5 , 1627,5 , 0, 0, 6, 5, 6 }, // Kurdish/AnyScript/Iraq
+ { 67, 0, 207, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 7599,41 , 7640,51 , 7691,27 , 7688,41 , 7729,51 , 7780,27 , 5169,20 , 5189,39 , 5228,14 , 5169,20 , 5189,39 , 5228,14 , 0,2 , 0,2 , {83,89,80}, 192,3 , 0,7 , 8,5 , 4,0 , 1632,5 , 0,0 , 0, 0, 7, 5, 6 }, // Kurdish/AnyScript/SyrianArabRepublic
+ { 67, 0, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 7599,41 , 7640,51 , 7691,27 , 7688,41 , 7729,51 , 7780,27 , 5169,20 , 5189,39 , 5228,14 , 5169,20 , 5189,39 , 5228,14 , 0,2 , 0,2 , {84,82,89}, 195,2 , 0,7 , 8,5 , 4,0 , 1632,5 , 1637,7 , 2, 1, 1, 6, 7 }, // Kurdish/AnyScript/Turkey
+ { 67, 1, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 5113,42 , 5113,42 , 5155,14 , 5113,42 , 5113,42 , 5155,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 1622,5 , 0,0 , 0, 0, 6, 4, 5 }, // Kurdish/Arabic/Iran
+ { 67, 1, 103, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 5113,42 , 5113,42 , 5155,14 , 5113,42 , 5113,42 , 5155,14 , 0,2 , 0,2 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 1622,5 , 1627,5 , 0, 0, 6, 5, 6 }, // Kurdish/Arabic/Iraq
+ { 67, 7, 207, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 7599,41 , 7640,51 , 7691,27 , 7688,41 , 7729,51 , 7780,27 , 5169,20 , 5189,39 , 5228,14 , 5169,20 , 5189,39 , 5228,14 , 0,2 , 0,2 , {83,89,80}, 192,3 , 0,7 , 8,5 , 4,0 , 1632,5 , 0,0 , 0, 0, 7, 5, 6 }, // Kurdish/Latin/SyrianArabRepublic
+ { 67, 7, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 7599,41 , 7640,51 , 7691,27 , 7688,41 , 7729,51 , 7780,27 , 5169,20 , 5189,39 , 5228,14 , 5169,20 , 5189,39 , 5228,14 , 0,2 , 0,2 , {84,82,89}, 195,2 , 0,7 , 8,5 , 4,0 , 1632,5 , 1637,7 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
+ { 69, 0, 117, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 738,18 , 165,4 , 373,21 , 7718,63 , 7781,75 , 1483,27 , 7807,63 , 7870,75 , 134,27 , 5242,24 , 5266,57 , 798,14 , 5242,24 , 5266,57 , 798,14 , 0,2 , 0,2 , {76,65,75}, 197,1 , 3605,10 , 4,4 , 48,5 , 1644,3 , 1644,3 , 0, 0, 7, 6, 7 }, // Laothian/AnyScript/Lao
+ { 71, 0, 118, 44, 160, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 332,8 , 756,26 , 37,5 , 8,10 , 7856,65 , 7921,101 , 134,24 , 7945,65 , 8010,101 , 320,24 , 5323,21 , 5344,72 , 5416,14 , 5323,21 , 5344,72 , 5416,14 , 144,14 , 144,11 , {76,86,76}, 198,2 , 3615,20 , 25,5 , 4,0 , 1647,8 , 1655,7 , 2, 1, 1, 6, 7 }, // Latvian/AnyScript/Latvia
+ { 72, 0, 49, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 8022,39 , 8061,203 , 1483,27 , 8111,39 , 8150,203 , 134,27 , 5430,23 , 5453,98 , 798,14 , 5430,23 , 5453,98 , 798,14 , 0,2 , 0,2 , {67,68,70}, 200,1 , 3635,22 , 8,5 , 4,0 , 1662,7 , 1669,13 , 2, 1, 1, 6, 7 }, // Lingala/AnyScript/DemocraticRepublicOfCongo
+ { 72, 0, 50, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 8022,39 , 8061,203 , 1483,27 , 8111,39 , 8150,203 , 134,27 , 5430,23 , 5453,98 , 798,14 , 5430,23 , 5453,98 , 798,14 , 0,2 , 0,2 , {88,65,70}, 201,4 , 0,7 , 8,5 , 4,0 , 1662,7 , 1682,17 , 0, 0, 1, 6, 7 }, // Lingala/AnyScript/PeoplesRepublicOfCongo
+ { 73, 0, 124, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 236,8 , 236,8 , 72,10 , 782,26 , 37,5 , 8,10 , 8264,69 , 8333,96 , 8429,24 , 8353,48 , 8401,96 , 8497,24 , 5551,17 , 5568,89 , 5657,14 , 5671,21 , 5568,89 , 5657,14 , 158,9 , 155,6 , {76,84,76}, 205,2 , 3657,54 , 25,5 , 4,0 , 1699,8 , 1707,7 , 2, 1, 1, 6, 7 }, // Lithuanian/AnyScript/Lithuania
+ { 74, 0, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 808,7 , 123,18 , 37,5 , 8,10 , 8453,63 , 8516,85 , 8601,24 , 8521,63 , 8584,85 , 8669,24 , 5692,34 , 5726,54 , 1458,14 , 5692,34 , 5726,54 , 1458,14 , 167,10 , 161,8 , {77,75,68}, 0,0 , 3711,23 , 8,5 , 4,0 , 1714,10 , 1724,10 , 2, 1, 1, 6, 7 }, // Macedonian/AnyScript/Macedonia
+ { 75, 0, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 8625,48 , 8673,92 , 134,24 , 8693,48 , 8741,92 , 320,24 , 5780,34 , 5814,60 , 5874,14 , 5780,34 , 5814,60 , 5874,14 , 0,2 , 0,2 , {77,71,65}, 0,0 , 3734,13 , 4,4 , 4,0 , 1734,8 , 1742,12 , 0, 0, 1, 6, 7 }, // Malagasy/AnyScript/Madagascar
+ { 76, 0, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 815,16 , 394,4 , 25,12 , 8765,49 , 8814,82 , 1483,27 , 8833,49 , 8882,82 , 134,27 , 5888,28 , 5916,43 , 798,14 , 5888,28 , 5916,43 , 798,14 , 0,2 , 0,2 , {77,89,82}, 207,2 , 3747,23 , 4,4 , 13,6 , 1754,13 , 1767,8 , 2, 1, 1, 6, 7 }, // Malay/AnyScript/Malaysia
+ { 76, 0, 32, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 564,12 , 165,4 , 398,14 , 8765,49 , 8814,82 , 1483,27 , 8833,49 , 8882,82 , 134,27 , 5888,28 , 5916,43 , 798,14 , 5888,28 , 5916,43 , 798,14 , 0,2 , 0,2 , {66,78,68}, 128,1 , 0,7 , 8,5 , 4,0 , 1754,13 , 1775,6 , 2, 1, 1, 6, 7 }, // Malay/AnyScript/BruneiDarussalam
+ { 77, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 244,12 , 244,12 , 27,8 , 831,18 , 18,7 , 25,12 , 8896,66 , 8962,101 , 9063,31 , 8964,66 , 9030,101 , 9131,31 , 5959,47 , 6006,70 , 6076,22 , 5959,47 , 6006,70 , 6076,22 , 177,6 , 169,10 , {73,78,82}, 209,2 , 3770,46 , 0,4 , 4,0 , 1781,6 , 1787,6 , 2, 1, 7, 7, 7 }, // Malayalam/AnyScript/India
+ { 78, 0, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 849,23 , 37,5 , 8,10 , 9094,48 , 9142,86 , 9228,24 , 9162,48 , 9210,86 , 9296,24 , 6098,28 , 6126,63 , 6189,14 , 6098,28 , 6126,63 , 6189,14 , 183,2 , 179,2 , {69,85,82}, 113,1 , 3816,11 , 4,4 , 4,0 , 1793,5 , 738,5 , 2, 1, 7, 6, 7 }, // Maltese/AnyScript/Malta
+ { 79, 0, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9252,83 , 9252,83 , 1483,27 , 9320,83 , 9320,83 , 134,27 , 6203,48 , 6203,48 , 798,14 , 6203,48 , 6203,48 , 798,14 , 0,2 , 0,2 , {78,90,68}, 211,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Maori/AnyScript/NewZealand
+ { 80, 0, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 256,11 , 267,9 , 655,6 , 99,16 , 412,7 , 419,12 , 9335,86 , 9335,86 , 9421,32 , 9403,86 , 9403,86 , 9489,32 , 6251,32 , 6283,53 , 4117,19 , 6251,32 , 6283,53 , 4117,19 , 140,2 , 140,2 , {73,78,82}, 180,2 , 0,7 , 8,5 , 4,0 , 1798,5 , 1460,4 , 2, 1, 7, 7, 7 }, // Marathi/AnyScript/India
+ { 82, 0, 143, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9453,48 , 9501,66 , 1483,27 , 9521,48 , 9569,66 , 134,27 , 6336,21 , 6357,43 , 798,14 , 6336,21 , 6357,43 , 798,14 , 0,2 , 0,2 , {77,78,84}, 214,1 , 0,7 , 8,5 , 4,0 , 1803,6 , 1809,10 , 0, 0, 7, 6, 7 }, // Mongolian/AnyScript/Mongolia
+ { 82, 0, 44, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9453,48 , 9501,66 , 1483,27 , 9521,48 , 9569,66 , 134,27 , 6336,21 , 6357,43 , 798,14 , 6336,21 , 6357,43 , 798,14 , 0,2 , 0,2 , {67,78,89}, 215,3 , 0,7 , 8,5 , 4,0 , 1803,6 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/AnyScript/China
+ { 82, 2, 143, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9453,48 , 9501,66 , 1483,27 , 9521,48 , 9569,66 , 134,27 , 6336,21 , 6357,43 , 798,14 , 6336,21 , 6357,43 , 798,14 , 0,2 , 0,2 , {77,78,84}, 214,1 , 0,7 , 8,5 , 4,0 , 1803,6 , 1809,10 , 0, 0, 7, 6, 7 }, // Mongolian/Cyrillic/Mongolia
+ { 82, 8, 44, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9453,48 , 9501,66 , 1483,27 , 9521,48 , 9569,66 , 134,27 , 6336,21 , 6357,43 , 798,14 , 6336,21 , 6357,43 , 798,14 , 0,2 , 0,2 , {67,78,89}, 215,3 , 0,7 , 8,5 , 4,0 , 1803,6 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
+ { 84, 0, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9567,56 , 9623,85 , 9708,27 , 9635,56 , 9691,85 , 9776,27 , 6400,33 , 6433,54 , 6487,14 , 6400,33 , 6433,54 , 6487,14 , 185,14 , 181,14 , {78,80,82}, 218,4 , 0,7 , 8,5 , 4,0 , 1819,6 , 1825,5 , 2, 1, 1, 6, 7 }, // Nepali/AnyScript/Nepal
+ { 84, 0, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9567,56 , 9735,80 , 9708,27 , 9635,56 , 9803,80 , 9776,27 , 6400,33 , 6501,54 , 6487,14 , 6400,33 , 6501,54 , 6487,14 , 120,9 , 122,7 , {73,78,82}, 145,2 , 3827,49 , 8,5 , 4,0 , 1819,6 , 1460,4 , 2, 1, 7, 7, 7 }, // Nepali/AnyScript/India
+ { 85, 0, 161, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 85,8 , 85,8 , 332,8 , 594,17 , 37,5 , 431,16 , 9815,59 , 9874,83 , 134,24 , 9883,59 , 9942,83 , 320,24 , 6555,28 , 2244,51 , 2295,14 , 6583,35 , 2244,51 , 2295,14 , 0,2 , 0,2 , {78,79,75}, 142,2 , 3876,44 , 8,5 , 4,0 , 1830,12 , 1842,5 , 2, 1, 1, 6, 7 }, // Norwegian/AnyScript/Norway
+ { 86, 0, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 9957,83 , 9957,83 , 1483,27 , 10025,83 , 10025,83 , 134,27 , 6618,57 , 6618,57 , 798,14 , 6618,57 , 6618,57 , 798,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 1542,11 , 8,5 , 4,0 , 1847,7 , 1854,6 , 2, 1, 1, 6, 7 }, // Occitan/AnyScript/France
+ { 87, 0, 100, 46, 44, 59, 37, 2918, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 655,6 , 10,17 , 18,7 , 25,12 , 10040,89 , 10040,89 , 10129,32 , 10108,89 , 10108,89 , 10197,32 , 6675,33 , 6708,54 , 6762,18 , 6675,33 , 6708,54 , 6762,18 , 140,2 , 140,2 , {73,78,82}, 145,2 , 3920,11 , 8,5 , 4,0 , 1860,5 , 1865,4 , 2, 1, 7, 7, 7 }, // Oriya/AnyScript/India
+ { 88, 0, 1, 1643, 1644, 59, 1642, 1776, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 179,8 , 872,20 , 165,4 , 447,11 , 10161,68 , 10161,68 , 1483,27 , 10229,68 , 10229,68 , 134,27 , 6780,49 , 6780,49 , 798,14 , 6780,49 , 6780,49 , 798,14 , 199,4 , 195,4 , {65,70,78}, 222,1 , 3931,13 , 25,5 , 4,0 , 1869,4 , 1873,9 , 0, 0, 6, 4, 5 }, // Pashto/AnyScript/Afghanistan
+ { 89, 0, 102, 1643, 1644, 1563, 1642, 1776, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 558,6 , 35,18 , 165,4 , 447,11 , 10229,71 , 10300,70 , 10370,25 , 10297,71 , 10368,73 , 10441,25 , 6780,49 , 6780,49 , 6829,14 , 6780,49 , 6780,49 , 6829,14 , 203,10 , 199,10 , {73,82,82}, 223,1 , 3944,17 , 25,5 , 53,8 , 1882,5 , 1887,5 , 0, 0, 6, 4, 5 }, // Persian/AnyScript/Iran
+ { 89, 0, 1, 1643, 1644, 1563, 1642, 1776, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 558,6 , 35,18 , 165,4 , 447,11 , 10395,63 , 10300,70 , 10458,24 , 10466,63 , 10529,68 , 10597,24 , 6780,49 , 6780,49 , 6829,14 , 6780,49 , 6780,49 , 6829,14 , 203,10 , 199,10 , {65,70,78}, 222,1 , 3961,23 , 25,5 , 53,8 , 1892,3 , 1873,9 , 0, 0, 6, 4, 5 }, // Persian/AnyScript/Afghanistan
+ { 90, 0, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8222, 8221, 0,6 , 0,6 , 61,7 , 61,7 , 892,10 , 10,17 , 37,5 , 8,10 , 10482,48 , 10530,97 , 10627,24 , 10621,48 , 10669,99 , 10768,24 , 6843,34 , 6877,59 , 6936,14 , 6843,34 , 6877,59 , 6936,14 , 0,2 , 0,2 , {80,76,78}, 224,2 , 3984,60 , 25,5 , 4,0 , 1895,6 , 1901,6 , 2, 1, 1, 6, 7 }, // Polish/AnyScript/Poland
+ { 91, 0, 173, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 202,8 , 210,7 , 27,8 , 902,27 , 37,5 , 458,19 , 10651,48 , 10699,89 , 134,24 , 10792,48 , 10840,89 , 320,24 , 6950,28 , 6978,79 , 7057,14 , 6950,28 , 6978,79 , 7057,14 , 213,17 , 209,18 , {69,85,82}, 113,1 , 1933,20 , 25,5 , 4,0 , 1907,17 , 1924,8 , 2, 1, 1, 6, 7 }, // Portuguese/AnyScript/Portugal
+ { 91, 0, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,7 , 210,7 , 27,8 , 902,27 , 37,5 , 458,19 , 10788,48 , 10836,89 , 134,24 , 10929,48 , 10977,89 , 320,24 , 6950,28 , 7071,79 , 7057,14 , 6950,28 , 7071,79 , 7057,14 , 0,2 , 0,2 , {66,82,76}, 226,2 , 4044,54 , 4,4 , 13,6 , 1932,19 , 1951,6 , 2, 1, 1, 6, 7 }, // Portuguese/AnyScript/Brazil
+ { 91, 0, 92, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,7 , 210,7 , 27,8 , 902,27 , 37,5 , 458,19 , 10788,48 , 10836,89 , 134,24 , 10929,48 , 10977,89 , 320,24 , 6950,28 , 7071,79 , 7057,14 , 6950,28 , 7071,79 , 7057,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 4098,62 , 4,4 , 13,6 , 1957,9 , 1966,12 , 0, 0, 1, 6, 7 }, // Portuguese/AnyScript/GuineaBissau
+ { 91, 0, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,7 , 210,7 , 27,8 , 902,27 , 37,5 , 458,19 , 10788,48 , 10836,89 , 134,24 , 10929,48 , 10977,89 , 320,24 , 6950,28 , 7071,79 , 7057,14 , 6950,28 , 7071,79 , 7057,14 , 0,2 , 0,2 , {77,90,78}, 228,3 , 4160,72 , 4,4 , 13,6 , 1957,9 , 1978,10 , 2, 1, 1, 6, 7 }, // Portuguese/AnyScript/Mozambique
+ { 92, 0, 100, 46, 44, 59, 37, 2662, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 123,18 , 18,7 , 25,12 , 10925,68 , 10925,68 , 10993,27 , 11066,68 , 11066,68 , 11134,27 , 7150,38 , 7188,55 , 7243,23 , 7150,38 , 7188,55 , 7243,23 , 230,5 , 227,4 , {73,78,82}, 231,3 , 4232,12 , 8,5 , 4,0 , 1988,6 , 1994,4 , 2, 1, 7, 7, 7 }, // Punjabi/AnyScript/India
+ { 92, 0, 163, 46, 44, 59, 37, 1632, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 123,18 , 18,7 , 25,12 , 11020,67 , 11020,67 , 10993,27 , 11161,67 , 11161,67 , 11134,27 , 7150,38 , 7266,37 , 7243,23 , 7150,38 , 7266,37 , 7243,23 , 230,5 , 227,4 , {80,75,82}, 234,1 , 4244,13 , 8,5 , 4,0 , 1998,5 , 2003,6 , 0, 0, 7, 6, 7 }, // Punjabi/AnyScript/Pakistan
+ { 92, 1, 163, 46, 44, 59, 37, 1632, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 123,18 , 18,7 , 25,12 , 11020,67 , 11020,67 , 10993,27 , 11161,67 , 11161,67 , 11134,27 , 7150,38 , 7266,37 , 7243,23 , 7150,38 , 7266,37 , 7243,23 , 230,5 , 227,4 , {80,75,82}, 234,1 , 4244,13 , 8,5 , 4,0 , 1998,5 , 2003,6 , 0, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
+ { 92, 4, 100, 46, 44, 59, 37, 2662, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 123,18 , 18,7 , 25,12 , 10925,68 , 10925,68 , 10993,27 , 11066,68 , 11066,68 , 11134,27 , 7150,38 , 7188,55 , 7243,23 , 7150,38 , 7188,55 , 7243,23 , 230,5 , 227,4 , {73,78,82}, 231,3 , 4232,12 , 8,5 , 4,0 , 1988,6 , 1994,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
+ { 94, 0, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 332,8 , 502,18 , 37,5 , 8,10 , 11087,67 , 11154,92 , 11246,24 , 11228,67 , 11295,92 , 11387,24 , 7303,23 , 7326,56 , 7382,14 , 7303,23 , 7326,56 , 7382,14 , 140,2 , 231,2 , {67,72,70}, 0,0 , 4257,20 , 25,5 , 4,0 , 2009,9 , 2018,6 , 2, 5, 1, 6, 7 }, // RhaetoRomance/AnyScript/Switzerland
+ { 95, 0, 141, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 929,10 , 10,17 , 37,5 , 8,10 , 11270,60 , 11330,98 , 11428,24 , 11411,60 , 11471,98 , 11569,24 , 7396,21 , 7417,48 , 3021,14 , 7396,21 , 7417,48 , 3021,14 , 0,2 , 0,2 , {77,68,76}, 0,0 , 4277,54 , 25,5 , 4,0 , 2024,6 , 2030,17 , 2, 1, 1, 6, 7 }, // Romanian/AnyScript/Moldova
+ { 95, 0, 177, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 929,10 , 10,17 , 37,5 , 8,10 , 11270,60 , 11330,98 , 11428,24 , 11411,60 , 11471,98 , 11569,24 , 7396,21 , 7417,48 , 3021,14 , 7396,21 , 7417,48 , 3021,14 , 0,2 , 0,2 , {82,79,78}, 235,3 , 4331,16 , 25,5 , 4,0 , 2024,6 , 2047,7 , 2, 1, 1, 6, 7 }, // Romanian/AnyScript/Romania
+ { 96, 0, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 54,7 , 54,7 , 332,8 , 939,22 , 165,4 , 195,9 , 11452,62 , 11514,80 , 11594,24 , 11593,63 , 11656,82 , 11738,24 , 7465,21 , 7486,62 , 7548,14 , 7465,21 , 7562,62 , 7548,14 , 0,2 , 0,2 , {82,85,66}, 238,4 , 4347,89 , 25,5 , 4,0 , 2054,7 , 2061,6 , 2, 1, 1, 6, 7 }, // Russian/AnyScript/RussianFederation
+ { 96, 0, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 54,7 , 54,7 , 332,8 , 939,22 , 165,4 , 195,9 , 11452,62 , 11514,80 , 11594,24 , 11593,63 , 11656,82 , 11738,24 , 7465,21 , 7486,62 , 7548,14 , 7465,21 , 7562,62 , 7548,14 , 0,2 , 0,2 , {77,68,76}, 0,0 , 4436,21 , 25,5 , 4,0 , 2054,7 , 2067,7 , 2, 1, 1, 6, 7 }, // Russian/AnyScript/Moldova
+ { 96, 0, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 54,7 , 54,7 , 332,8 , 939,22 , 37,5 , 8,10 , 11452,62 , 11514,80 , 11594,24 , 11593,63 , 11656,82 , 11738,24 , 7465,21 , 7486,62 , 7548,14 , 7465,21 , 7562,62 , 7548,14 , 0,2 , 0,2 , {85,65,72}, 242,1 , 4457,24 , 25,5 , 4,0 , 2054,7 , 2074,7 , 2, 1, 1, 6, 7 }, // Russian/AnyScript/Ukraine
+ { 98, 0, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 11618,48 , 11666,91 , 11757,24 , 11762,48 , 11810,91 , 11901,24 , 7624,28 , 7652,66 , 7718,14 , 7624,28 , 7652,66 , 7718,14 , 235,2 , 233,2 , {88,65,70}, 201,4 , 4481,25 , 4,4 , 48,5 , 2081,5 , 2086,22 , 0, 0, 1, 6, 7 }, // Sangho/AnyScript/CentralAfricanRepublic
+ { 99, 0, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 630,7 , 99,16 , 322,8 , 330,13 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {73,78,82}, 180,2 , 0,7 , 4,4 , 4,0 , 2108,12 , 2120,6 , 2, 1, 7, 7, 7 }, // Sanskrit/AnyScript/India
+ { 100, 0, 241, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2126,6 , 2132,18 , 2, 1, 1, 6, 7 }, // Serbian/AnyScript/SerbiaAndMontenegro
+ { 100, 0, 27, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 115,8 , 968,20 , 37,5 , 477,40 , 11781,48 , 11910,83 , 8601,24 , 11925,48 , 12054,83 , 8669,24 , 7826,28 , 7854,54 , 7812,14 , 7826,28 , 7854,54 , 7812,14 , 237,9 , 235,7 , {66,65,77}, 243,3 , 4506,195 , 25,5 , 4,0 , 2150,6 , 2156,19 , 2, 1, 1, 6, 7 }, // Serbian/AnyScript/BosniaAndHerzegowina
+ { 100, 0, 238, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2126,6 , 0,0 , 2, 1, 1, 6, 7 }, // Serbian/AnyScript/Yugoslavia
+ { 100, 0, 242, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {69,85,82}, 113,1 , 4701,27 , 8,5 , 4,0 , 2175,6 , 2181,9 , 2, 1, 1, 6, 7 }, // Serbian/AnyScript/Montenegro
+ { 100, 0, 243, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {82,83,68}, 246,4 , 4728,71 , 25,5 , 4,0 , 2126,6 , 2190,6 , 0, 0, 1, 6, 7 }, // Serbian/AnyScript/Serbia
+ { 100, 2, 27, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 115,8 , 968,20 , 37,5 , 477,40 , 11781,48 , 11910,83 , 8601,24 , 11925,48 , 12054,83 , 8669,24 , 7826,28 , 7854,54 , 7812,14 , 7826,28 , 7854,54 , 7812,14 , 237,9 , 235,7 , {66,65,77}, 243,3 , 4506,195 , 25,5 , 4,0 , 2150,6 , 2156,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/BosniaAndHerzegowina
+ { 100, 2, 238, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2126,6 , 0,0 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Yugoslavia
+ { 100, 2, 241, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2126,6 , 2132,18 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/SerbiaAndMontenegro
+ { 100, 2, 242, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {69,85,82}, 113,1 , 4799,27 , 25,5 , 4,0 , 2126,6 , 2196,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
+ { 100, 2, 243, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 54,7 , 54,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11781,48 , 11829,81 , 8601,24 , 11925,48 , 11973,81 , 8669,24 , 7732,28 , 7760,52 , 7812,14 , 7732,28 , 7760,52 , 7812,14 , 237,9 , 235,7 , {82,83,68}, 246,4 , 4728,71 , 25,5 , 4,0 , 2126,6 , 2190,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
+ { 100, 7, 27, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {66,65,77}, 250,2 , 4826,218 , 25,5 , 4,0 , 2175,6 , 2205,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/BosniaAndHerzegowina
+ { 100, 7, 238, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2175,6 , 0,0 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Yugoslavia
+ { 100, 7, 241, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2175,6 , 2224,18 , 2, 1, 1, 6, 7 }, // Serbian/Latin/SerbiaAndMontenegro
+ { 100, 7, 242, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {69,85,82}, 113,1 , 4701,27 , 8,5 , 4,0 , 2175,6 , 2181,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
+ { 100, 7, 243, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {82,83,68}, 252,4 , 5044,71 , 25,5 , 4,0 , 2175,6 , 2242,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
+ { 101, 0, 241, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2248,14 , 2224,18 , 2, 1, 1, 6, 7 }, // SerboCroatian/AnyScript/SerbiaAndMontenegro
+ { 101, 0, 27, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {66,65,77}, 250,2 , 4826,218 , 25,5 , 4,0 , 2248,14 , 2205,19 , 2, 1, 1, 6, 7 }, // SerboCroatian/AnyScript/BosniaAndHerzegowina
+ { 101, 0, 238, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 61,7 , 61,7 , 961,7 , 968,20 , 150,5 , 155,10 , 11993,48 , 12041,81 , 12122,24 , 12137,48 , 12185,81 , 12266,24 , 7908,28 , 7936,54 , 2118,14 , 7908,28 , 7936,54 , 2118,14 , 246,9 , 242,7 , {0,0,0}, 0,0 , 4506,0 , 25,5 , 4,0 , 2248,14 , 0,0 , 2, 1, 1, 6, 7 }, // SerboCroatian/AnyScript/Yugoslavia
+ { 102, 0, 120, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 12146,48 , 12194,105 , 1483,27 , 12290,48 , 12338,105 , 134,27 , 7990,27 , 8017,61 , 798,14 , 7990,27 , 8017,61 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2262,7 , 0,0 , 2, 1, 1, 6, 7 }, // Sesotho/AnyScript/Lesotho
+ { 102, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 12146,48 , 12194,105 , 1483,27 , 12290,48 , 12338,105 , 134,27 , 7990,27 , 8017,61 , 798,14 , 7990,27 , 8017,61 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2262,7 , 0,0 , 2, 1, 1, 6, 7 }, // Sesotho/AnyScript/SouthAfrica
+ { 103, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 12299,48 , 12347,117 , 1483,27 , 12443,48 , 12491,117 , 134,27 , 8078,27 , 8105,64 , 798,14 , 8078,27 , 8105,64 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2269,8 , 0,0 , 2, 1, 1, 6, 7 }, // Setswana/AnyScript/SouthAfrica
+ { 104, 0, 240, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8221, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 12464,47 , 12511,100 , 12611,24 , 12608,47 , 12655,100 , 12755,24 , 8169,32 , 8201,55 , 8256,14 , 8169,32 , 8201,55 , 8256,14 , 0,2 , 0,2 , {85,83,68}, 256,3 , 5115,22 , 4,4 , 13,6 , 2277,8 , 944,8 , 2, 1, 7, 6, 7 }, // Shona/AnyScript/Zimbabwe
+ { 106, 0, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 576,10 , 988,17 , 18,7 , 25,12 , 12635,54 , 12689,92 , 12781,32 , 12779,54 , 12833,92 , 12925,32 , 8270,30 , 8300,62 , 8362,19 , 8270,30 , 8300,62 , 8362,19 , 255,5 , 249,4 , {76,75,82}, 259,5 , 5137,19 , 4,4 , 13,6 , 2285,5 , 2290,11 , 2, 1, 1, 6, 7 }, // Singhalese/AnyScript/SriLanka
+ { 107, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 12813,48 , 12861,114 , 1483,27 , 12957,48 , 13005,114 , 134,27 , 8381,27 , 8408,68 , 798,14 , 8381,27 , 8408,68 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2301,7 , 0,0 , 2, 1, 1, 6, 7 }, // Siswati/AnyScript/SouthAfrica
+ { 107, 0, 204, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 12813,48 , 12861,114 , 1483,27 , 12957,48 , 13005,114 , 134,27 , 8381,27 , 8408,68 , 798,14 , 8381,27 , 8408,68 , 798,14 , 0,2 , 0,2 , {83,90,76}, 264,1 , 0,7 , 4,4 , 4,0 , 2301,7 , 0,0 , 2, 1, 1, 6, 7 }, // Siswati/AnyScript/Swaziland
+ { 108, 0, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8218, 8216, 8222, 8220, 0,6 , 0,6 , 78,7 , 78,7 , 586,8 , 502,18 , 165,4 , 195,9 , 12975,48 , 13023,82 , 12122,24 , 13119,48 , 13167,89 , 12266,24 , 8476,21 , 8497,52 , 8549,14 , 8476,21 , 8497,52 , 8549,14 , 260,10 , 253,9 , {69,85,82}, 113,1 , 3549,11 , 25,5 , 4,0 , 2308,10 , 2318,19 , 2, 1, 1, 6, 7 }, // Slovak/AnyScript/Slovakia
+ { 109, 0, 192, 44, 46, 59, 37, 48, 45, 43, 101, 187, 171, 8222, 8220, 0,6 , 0,6 , 276,8 , 276,8 , 1005,9 , 611,19 , 37,5 , 8,10 , 11993,48 , 13105,86 , 12122,24 , 12137,48 , 13256,86 , 12266,24 , 8563,28 , 8591,52 , 8643,14 , 8563,28 , 8591,52 , 8643,14 , 62,4 , 262,4 , {69,85,82}, 113,1 , 5156,28 , 25,5 , 4,0 , 2337,11 , 2348,9 , 2, 1, 1, 6, 7 }, // Slovenian/AnyScript/Slovenia
+ { 110, 0, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 13191,48 , 13239,189 , 13428,24 , 13342,48 , 13390,189 , 13579,24 , 8657,28 , 8685,47 , 8732,14 , 8657,28 , 8685,47 , 8732,14 , 270,3 , 266,3 , {83,79,83}, 265,3 , 5184,22 , 4,4 , 4,0 , 2357,8 , 2365,10 , 0, 0, 6, 6, 7 }, // Somali/AnyScript/Somalia
+ { 110, 0, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 13191,48 , 13239,189 , 13428,24 , 13342,48 , 13390,189 , 13579,24 , 8657,28 , 8685,47 , 8732,14 , 8657,28 , 8685,47 , 8732,14 , 270,3 , 266,3 , {68,74,70}, 5,3 , 5206,21 , 4,4 , 4,0 , 2357,8 , 2375,7 , 0, 0, 6, 6, 7 }, // Somali/AnyScript/Djibouti
+ { 110, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 13191,48 , 13239,189 , 13428,24 , 13342,48 , 13390,189 , 13579,24 , 8657,28 , 8685,47 , 8732,14 , 8657,28 , 8685,47 , 8732,14 , 270,3 , 266,3 , {69,84,66}, 0,2 , 5227,22 , 4,4 , 4,0 , 2357,8 , 2382,8 , 2, 1, 6, 6, 7 }, // Somali/AnyScript/Ethiopia
+ { 110, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 13191,48 , 13239,189 , 13428,24 , 13342,48 , 13390,189 , 13579,24 , 8657,28 , 8685,47 , 8732,14 , 8657,28 , 8685,47 , 8732,14 , 270,3 , 266,3 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 2357,8 , 2390,7 , 2, 1, 6, 6, 7 }, // Somali/AnyScript/Kenya
+ { 111, 0, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {69,85,82}, 113,1 , 1652,20 , 8,5 , 4,0 , 2397,17 , 1227,6 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Spain
+ { 111, 0, 10, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 517,14 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {65,82,83}, 128,1 , 5249,51 , 8,5 , 4,0 , 2414,7 , 2421,9 , 2, 1, 7, 6, 7 }, // Spanish/AnyScript/Argentina
+ { 111, 0, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {66,79,66}, 268,2 , 5300,35 , 8,5 , 4,0 , 2414,7 , 2430,7 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Bolivia
+ { 111, 0, 43, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 543,8 , 1014,26 , 165,4 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {67,76,80}, 128,1 , 5335,45 , 4,4 , 48,5 , 2414,7 , 2437,5 , 0, 0, 1, 6, 7 }, // Spanish/AnyScript/Chile
+ { 111, 0, 47, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 551,7 , 1014,26 , 165,4 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {67,79,80}, 128,1 , 5380,54 , 8,5 , 4,0 , 2414,7 , 2442,8 , 0, 0, 1, 6, 7 }, // Spanish/AnyScript/Colombia
+ { 111, 0, 52, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {67,82,67}, 270,1 , 5434,67 , 8,5 , 4,0 , 2414,7 , 2450,10 , 0, 0, 1, 6, 7 }, // Spanish/AnyScript/CostaRica
+ { 111, 0, 61, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {68,79,80}, 271,3 , 5501,54 , 8,5 , 4,0 , 2414,7 , 2460,20 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/DominicanRepublic
+ { 111, 0, 63, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 165,4 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {85,83,68}, 128,1 , 5555,70 , 4,4 , 48,5 , 2414,7 , 2480,7 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Ecuador
+ { 111, 0, 65, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {85,83,68}, 256,3 , 5555,70 , 8,5 , 4,0 , 2414,7 , 2487,11 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/ElSalvador
+ { 111, 0, 66, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {88,65,70}, 201,4 , 5625,22 , 8,5 , 4,0 , 2414,7 , 2498,17 , 0, 0, 1, 6, 7 }, // Spanish/AnyScript/EquatorialGuinea
+ { 111, 0, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 551,7 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {71,84,81}, 274,1 , 5647,70 , 8,5 , 4,0 , 2414,7 , 2515,9 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Guatemala
+ { 111, 0, 96, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1040,27 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {72,78,76}, 275,1 , 5717,60 , 8,5 , 4,0 , 2414,7 , 2524,8 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Honduras
+ { 111, 0, 139, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {77,88,78}, 128,1 , 5777,48 , 8,5 , 4,0 , 2414,7 , 2532,6 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Mexico
+ { 111, 0, 155, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {78,73,79}, 276,2 , 5825,81 , 8,5 , 4,0 , 2414,7 , 2538,9 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Nicaragua
+ { 111, 0, 166, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 187,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {80,65,66}, 278,3 , 5906,54 , 8,5 , 4,0 , 2414,7 , 2547,6 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Panama
+ { 111, 0, 168, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {80,89,71}, 281,1 , 5960,61 , 8,5 , 61,6 , 2414,7 , 2553,8 , 0, 0, 1, 6, 7 }, // Spanish/AnyScript/Paraguay
+ { 111, 0, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 551,7 , 1014,26 , 37,5 , 531,15 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {80,69,78}, 282,3 , 6021,62 , 8,5 , 4,0 , 2414,7 , 2561,4 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Peru
+ { 111, 0, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 187,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {85,83,68}, 128,1 , 5555,70 , 8,5 , 4,0 , 2414,7 , 2565,11 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/PuertoRico
+ { 111, 0, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 558,6 , 1014,26 , 18,7 , 25,12 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {85,83,68}, 128,1 , 5555,70 , 8,5 , 4,0 , 2414,7 , 2576,14 , 2, 1, 7, 6, 7 }, // Spanish/AnyScript/UnitedStates
+ { 111, 0, 227, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {85,89,85}, 128,1 , 6083,48 , 8,5 , 67,7 , 2414,7 , 2590,7 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Uruguay
+ { 111, 0, 231, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {86,69,70}, 285,5 , 6131,86 , 4,4 , 48,5 , 2414,7 , 2597,9 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/Venezuela
+ { 111, 0, 246, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 284,7 , 284,7 , 27,8 , 1014,26 , 37,5 , 8,10 , 13452,48 , 13500,89 , 13589,24 , 13603,48 , 13651,89 , 13740,24 , 8746,28 , 8774,53 , 3021,14 , 8746,28 , 8774,53 , 3021,14 , 56,4 , 56,4 , {0,0,0}, 0,0 , 4506,0 , 8,5 , 4,0 , 2606,23 , 2629,25 , 2, 1, 1, 6, 7 }, // Spanish/AnyScript/LatinAmericaAndTheCaribbean
+ { 113, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 13661,84 , 134,24 , 13764,48 , 13812,84 , 320,24 , 8827,22 , 8849,60 , 8909,14 , 8827,22 , 8849,60 , 8909,14 , 273,7 , 269,7 , {75,69,83}, 2,3 , 6217,24 , 4,4 , 4,0 , 2654,9 , 2663,5 , 2, 1, 6, 6, 7 }, // Swahili/AnyScript/Kenya
+ { 113, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 13661,84 , 134,24 , 13764,48 , 13812,84 , 320,24 , 8827,22 , 8849,60 , 8909,14 , 8827,22 , 8849,60 , 8909,14 , 273,7 , 269,7 , {84,90,83}, 290,3 , 6241,27 , 25,5 , 4,0 , 2654,9 , 2668,8 , 0, 0, 1, 6, 7 }, // Swahili/AnyScript/Tanzania
+ { 114, 0, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 291,9 , 291,9 , 72,10 , 1067,30 , 37,5 , 431,16 , 3550,48 , 13745,86 , 134,24 , 5527,48 , 13896,86 , 320,24 , 8923,29 , 8952,50 , 2295,14 , 8923,29 , 8952,50 , 2295,14 , 280,2 , 276,2 , {83,69,75}, 142,2 , 6268,45 , 25,5 , 4,0 , 2676,7 , 2683,7 , 2, 1, 1, 6, 7 }, // Swedish/AnyScript/Sweden
+ { 114, 0, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 291,9 , 291,9 , 72,10 , 1067,30 , 37,5 , 431,16 , 3550,48 , 13745,86 , 134,24 , 5527,48 , 13896,86 , 320,24 , 8923,29 , 8952,50 , 2295,14 , 8923,29 , 8952,50 , 2295,14 , 280,2 , 276,2 , {69,85,82}, 113,1 , 6313,19 , 25,5 , 4,0 , 2676,7 , 2690,7 , 2, 1, 1, 6, 7 }, // Swedish/AnyScript/Finland
+ { 116, 0, 209, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 171, 8222, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 13831,48 , 13879,71 , 1483,27 , 13982,48 , 14030,71 , 134,27 , 9002,28 , 9030,55 , 798,14 , 9002,28 , 9030,55 , 798,14 , 0,2 , 0,2 , {84,74,83}, 188,3 , 6332,13 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tajik/AnyScript/Tajikistan
+ { 116, 2, 209, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 171, 8222, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 13831,48 , 13879,71 , 1483,27 , 13982,48 , 14030,71 , 134,27 , 9002,28 , 9030,55 , 798,14 , 9002,28 , 9030,55 , 798,14 , 0,2 , 0,2 , {84,74,83}, 188,3 , 6332,13 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
+ { 117, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 300,13 , 300,13 , 655,6 , 203,18 , 18,7 , 25,12 , 13950,58 , 14008,88 , 14096,31 , 14101,58 , 14159,88 , 14247,31 , 9085,20 , 9105,49 , 9085,20 , 9085,20 , 9105,49 , 9085,20 , 140,2 , 140,2 , {73,78,82}, 293,2 , 6345,13 , 8,5 , 4,0 , 2697,5 , 2702,7 , 2, 1, 7, 7, 7 }, // Tamil/AnyScript/India
+ { 117, 0, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 300,13 , 300,13 , 655,6 , 203,18 , 18,7 , 25,12 , 13950,58 , 14008,88 , 14096,31 , 14101,58 , 14159,88 , 14247,31 , 9085,20 , 9105,49 , 9085,20 , 9085,20 , 9105,49 , 9085,20 , 140,2 , 140,2 , {76,75,82}, 295,4 , 0,7 , 8,5 , 4,0 , 2697,5 , 2709,6 , 2, 1, 1, 6, 7 }, // Tamil/AnyScript/SriLanka
+ { 118, 0, 178, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 929,10 , 1097,11 , 165,4 , 25,12 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {82,85,66}, 0,0 , 0,7 , 0,4 , 4,0 , 2715,5 , 2061,6 , 2, 1, 1, 6, 7 }, // Tatar/AnyScript/RussianFederation
+ { 119, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 313,12 , 325,11 , 543,8 , 99,16 , 18,7 , 25,12 , 14127,86 , 14127,86 , 14213,30 , 14278,86 , 14278,86 , 14364,30 , 9154,32 , 9186,60 , 9246,18 , 9154,32 , 9186,60 , 9246,18 , 282,1 , 278,2 , {73,78,82}, 299,3 , 6358,13 , 8,5 , 4,0 , 2720,6 , 2726,9 , 2, 1, 7, 7, 7 }, // Telugu/AnyScript/India
+ { 120, 0, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 336,5 , 336,5 , 341,8 , 349,7 , 364,8 , 1108,19 , 165,4 , 546,27 , 14243,63 , 14306,98 , 14243,63 , 14394,63 , 14457,98 , 14555,24 , 9264,23 , 9287,68 , 9355,14 , 9264,23 , 9287,68 , 9355,14 , 283,10 , 280,10 , {84,72,66}, 302,1 , 6371,13 , 4,4 , 48,5 , 2735,3 , 2735,3 , 2, 1, 7, 6, 7 }, // Thai/AnyScript/Thailand
+ { 121, 0, 44, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 14404,63 , 14467,158 , 1483,27 , 14579,63 , 14642,158 , 134,27 , 9369,49 , 9418,77 , 9495,21 , 9369,49 , 9418,77 , 9495,21 , 293,7 , 290,8 , {67,78,89}, 215,3 , 6384,13 , 8,5 , 4,0 , 2738,8 , 2746,6 , 2, 1, 7, 6, 7 }, // Tibetan/AnyScript/China
+ { 121, 0, 100, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 14404,63 , 14467,158 , 1483,27 , 14579,63 , 14642,158 , 134,27 , 9369,49 , 9418,77 , 9495,21 , 9369,49 , 9418,77 , 9495,21 , 293,7 , 290,8 , {73,78,82}, 145,2 , 6397,22 , 8,5 , 4,0 , 2738,8 , 2752,7 , 2, 1, 7, 7, 7 }, // Tibetan/AnyScript/India
+ { 122, 0, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1127,23 , 18,7 , 25,12 , 14625,46 , 14671,54 , 1034,24 , 14800,46 , 14846,54 , 1061,24 , 9516,29 , 9516,29 , 9545,14 , 9516,29 , 9516,29 , 9545,14 , 300,7 , 298,7 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 2759,4 , 0,0 , 2, 1, 6, 6, 7 }, // Tigrinya/AnyScript/Eritrea
+ { 122, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1150,23 , 18,7 , 25,12 , 926,46 , 972,62 , 1034,24 , 953,46 , 999,62 , 1061,24 , 9559,29 , 9559,29 , 9545,14 , 9559,29 , 9559,29 , 9545,14 , 300,7 , 298,7 , {69,84,66}, 0,2 , 81,16 , 4,4 , 4,0 , 2759,4 , 0,0 , 2, 1, 6, 6, 7 }, // Tigrinya/AnyScript/Ethiopia
+ { 123, 0, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 99,16 , 37,5 , 8,10 , 14725,51 , 14776,87 , 14863,24 , 14900,51 , 14951,87 , 15038,24 , 9588,29 , 9617,60 , 9677,14 , 9588,29 , 9617,60 , 9677,14 , 0,2 , 0,2 , {84,79,80}, 303,2 , 0,7 , 8,5 , 4,0 , 2763,13 , 2776,5 , 2, 1, 1, 6, 7 }, // Tonga/AnyScript/Tonga
+ { 124, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 14887,48 , 14935,122 , 1483,27 , 15062,48 , 15110,122 , 134,27 , 9691,27 , 9718,72 , 798,14 , 9691,27 , 9718,72 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2781,8 , 0,0 , 2, 1, 1, 6, 7 }, // Tsonga/AnyScript/SouthAfrica
+ { 125, 0, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 356,8 , 356,8 , 929,10 , 1173,17 , 37,5 , 8,10 , 15057,48 , 15105,75 , 15180,24 , 15232,48 , 15280,75 , 15355,24 , 9790,28 , 9818,54 , 9872,14 , 9790,28 , 9818,54 , 9872,14 , 0,2 , 0,2 , {84,82,89}, 195,2 , 6419,18 , 25,5 , 4,0 , 2789,6 , 2795,7 , 2, 1, 1, 6, 7 }, // Turkish/AnyScript/Turkey
+ { 128, 0, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {67,78,89}, 215,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Uigur/AnyScript/China
+ { 128, 1, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {67,78,89}, 215,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Uigur/Arabic/China
+ { 129, 0, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 364,8 , 364,8 , 332,8 , 1190,22 , 37,5 , 8,10 , 15204,48 , 15252,95 , 15347,24 , 15379,67 , 15446,87 , 15533,24 , 9886,21 , 9907,56 , 9963,14 , 9886,21 , 9907,56 , 9963,14 , 307,2 , 305,2 , {85,65,72}, 242,1 , 6437,49 , 25,5 , 4,0 , 2802,10 , 2812,7 , 2, 1, 1, 6, 7 }, // Ukrainian/AnyScript/Ukraine
+ { 130, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 1212,18 , 18,7 , 25,12 , 15371,67 , 15371,67 , 10458,24 , 15557,67 , 15557,67 , 10597,24 , 9977,36 , 9977,36 , 10013,14 , 9977,36 , 9977,36 , 10013,14 , 0,2 , 0,2 , {73,78,82}, 145,2 , 6486,18 , 8,5 , 4,0 , 2819,4 , 2823,5 , 2, 1, 7, 7, 7 }, // Urdu/AnyScript/India
+ { 130, 0, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 1212,18 , 18,7 , 25,12 , 15371,67 , 15371,67 , 10458,24 , 15557,67 , 15557,67 , 10597,24 , 9977,36 , 9977,36 , 10013,14 , 9977,36 , 9977,36 , 10013,14 , 0,2 , 0,2 , {80,75,82}, 305,4 , 6504,21 , 4,4 , 4,0 , 2819,4 , 2828,7 , 0, 0, 7, 6, 7 }, // Urdu/AnyScript/Pakistan
+ { 131, 0, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 13831,48 , 15438,115 , 11594,24 , 13982,48 , 15624,115 , 11738,24 , 10027,28 , 10055,53 , 10108,14 , 10027,28 , 10055,53 , 10108,14 , 0,2 , 0,2 , {85,90,83}, 309,3 , 6525,21 , 8,5 , 4,0 , 2835,5 , 2840,10 , 0, 0, 7, 6, 7 }, // Uzbek/AnyScript/Uzbekistan
+ { 131, 0, 1, 1643, 1644, 59, 1642, 1776, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 179,8 , 1230,33 , 165,4 , 447,11 , 15553,48 , 15601,68 , 11594,24 , 15739,48 , 10529,68 , 11738,24 , 10122,21 , 6780,49 , 10108,14 , 10122,21 , 6780,49 , 10108,14 , 0,2 , 0,2 , {65,70,78}, 312,2 , 6546,13 , 25,5 , 4,0 , 2850,6 , 1873,9 , 0, 0, 6, 4, 5 }, // Uzbek/AnyScript/Afghanistan
+ { 131, 1, 1, 1643, 1644, 59, 1642, 1776, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 179,8 , 1230,33 , 165,4 , 447,11 , 15553,48 , 15601,68 , 11594,24 , 15739,48 , 10529,68 , 11738,24 , 10122,21 , 6780,49 , 10108,14 , 10122,21 , 6780,49 , 10108,14 , 0,2 , 0,2 , {65,70,78}, 312,2 , 6546,13 , 25,5 , 4,0 , 2850,6 , 1873,9 , 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
+ { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 13831,48 , 15438,115 , 11594,24 , 13982,48 , 15624,115 , 11738,24 , 10027,28 , 10055,53 , 10108,14 , 10027,28 , 10055,53 , 10108,14 , 0,2 , 0,2 , {85,90,83}, 309,3 , 6525,21 , 8,5 , 4,0 , 2835,5 , 2840,10 , 0, 0, 7, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
+ { 131, 7, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 15669,52 , 15438,115 , 15721,24 , 15787,52 , 15624,115 , 15839,24 , 10143,34 , 10177,61 , 10238,14 , 10143,34 , 10177,61 , 10238,14 , 0,2 , 0,2 , {85,90,83}, 314,4 , 6559,23 , 8,5 , 4,0 , 2856,9 , 2865,11 , 0, 0, 7, 6, 7 }, // Uzbek/Latin/Uzbekistan
+ { 132, 0, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 372,8 , 372,8 , 141,10 , 1263,31 , 37,5 , 8,10 , 15745,75 , 15820,130 , 1483,27 , 15863,75 , 15938,130 , 134,27 , 10252,33 , 10285,55 , 10340,21 , 10252,33 , 10285,55 , 10340,21 , 309,2 , 307,2 , {86,78,68}, 318,1 , 6582,11 , 25,5 , 4,0 , 2876,10 , 2886,8 , 0, 0, 1, 6, 7 }, // Vietnamese/AnyScript/VietNam
+ { 134, 0, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 123,18 , 18,7 , 25,12 , 15950,53 , 16003,87 , 16090,24 , 16068,62 , 16130,86 , 16216,24 , 10361,29 , 10390,77 , 10467,14 , 10481,30 , 10390,77 , 10467,14 , 0,2 , 0,2 , {71,66,80}, 153,1 , 6593,28 , 4,4 , 4,0 , 2894,7 , 2901,12 , 2, 1, 1, 6, 7 }, // Welsh/AnyScript/UnitedKingdom
+ { 135, 0, 187, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Wolof/AnyScript/Senegal
+ { 135, 7, 187, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
+ { 136, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 16114,48 , 16162,91 , 1483,27 , 16240,48 , 16288,91 , 134,27 , 10511,28 , 10539,61 , 798,14 , 10511,28 , 10539,61 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2913,8 , 0,0 , 2, 1, 1, 6, 7 }, // Xhosa/AnyScript/SouthAfrica
+ { 138, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 16253,73 , 16326,121 , 1483,27 , 16379,73 , 16452,121 , 134,27 , 10600,44 , 10644,69 , 798,14 , 10600,44 , 10644,69 , 798,14 , 311,5 , 309,5 , {78,71,78}, 171,1 , 6621,34 , 4,4 , 13,6 , 2921,10 , 2931,18 , 2, 1, 1, 6, 7 }, // Yoruba/AnyScript/Nigeria
+ { 140, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 82,17 , 18,7 , 25,12 , 16447,48 , 16495,104 , 134,24 , 16573,48 , 16621,90 , 320,24 , 10713,28 , 10741,68 , 10809,14 , 10713,28 , 10741,68 , 10809,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 2949,7 , 2956,17 , 2, 1, 1, 6, 7 }, // Zulu/AnyScript/SouthAfrica
+ { 141, 0, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 85,8 , 85,8 , 332,8 , 594,17 , 37,5 , 431,16 , 4262,48 , 9874,83 , 134,24 , 4314,48 , 9942,83 , 320,24 , 10823,28 , 10851,51 , 2295,14 , 10823,28 , 10851,51 , 2295,14 , 316,9 , 314,11 , {78,79,75}, 142,2 , 6655,42 , 25,5 , 4,0 , 2973,7 , 2980,5 , 2, 1, 1, 6, 7 }, // Nynorsk/AnyScript/Norway
+ { 142, 0, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 16599,48 , 16647,83 , 1483,27 , 16711,48 , 16759,83 , 134,27 , 10902,28 , 10930,58 , 798,14 , 10902,28 , 10930,58 , 798,14 , 0,2 , 0,2 , {66,65,77}, 250,2 , 6697,26 , 8,5 , 4,0 , 2985,8 , 2205,19 , 2, 1, 1, 6, 7 }, // Bosnian/AnyScript/BosniaAndHerzegowina
+ { 143, 0, 131, 46, 44, 44, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 655,6 , 99,16 , 322,8 , 330,13 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {77,86,82}, 319,2 , 0,7 , 8,5 , 4,0 , 2993,10 , 3003,13 , 2, 1, 5, 6, 7 }, // Divehi/AnyScript/Maldives
+ { 144, 0, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 82,17 , 37,5 , 8,10 , 16730,102 , 16832,140 , 1483,27 , 16842,102 , 16944,140 , 134,27 , 10988,30 , 11018,57 , 798,14 , 10988,30 , 11018,57 , 798,14 , 56,4 , 56,4 , {71,66,80}, 153,1 , 0,7 , 4,4 , 4,0 , 3016,5 , 3021,14 , 2, 1, 1, 6, 7 }, // Manx/AnyScript/UnitedKingdom
+ { 145, 0, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 99,16 , 37,5 , 8,10 , 16972,46 , 17018,124 , 1483,27 , 17084,46 , 17130,124 , 134,27 , 11075,28 , 11103,60 , 798,14 , 11075,28 , 11103,60 , 798,14 , 56,4 , 56,4 , {71,66,80}, 153,1 , 0,7 , 4,4 , 4,0 , 3035,8 , 3021,14 , 2, 1, 1, 6, 7 }, // Cornish/AnyScript/UnitedKingdom
+ { 146, 0, 83, 46, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 17142,48 , 17190,192 , 1483,27 , 17254,48 , 17302,192 , 134,27 , 11163,28 , 11191,49 , 11240,14 , 11163,28 , 11191,49 , 11240,14 , 325,2 , 325,2 , {71,72,83}, 168,3 , 0,7 , 4,4 , 4,0 , 3043,4 , 3047,5 , 2, 1, 1, 6, 7 }, // Akan/AnyScript/Ghana
+ { 147, 0, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 655,6 , 99,16 , 18,7 , 25,12 , 17382,87 , 17382,87 , 1483,27 , 17494,87 , 17494,87 , 134,27 , 6251,32 , 11254,55 , 798,14 , 6251,32 , 11254,55 , 798,14 , 327,5 , 327,5 , {73,78,82}, 180,2 , 0,7 , 8,5 , 4,0 , 3052,6 , 1460,4 , 2, 1, 7, 7, 7 }, // Konkani/AnyScript/India
+ { 148, 0, 83, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 34, 34, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 17469,48 , 17517,94 , 1483,27 , 17581,48 , 17629,94 , 134,27 , 11309,26 , 11335,34 , 798,14 , 11309,26 , 11335,34 , 798,14 , 0,2 , 0,2 , {71,72,83}, 168,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ga/AnyScript/Ghana
+ { 149, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 17611,48 , 17659,86 , 1483,27 , 17723,48 , 17771,86 , 134,27 , 11369,29 , 11398,57 , 798,14 , 11369,29 , 11398,57 , 798,14 , 332,4 , 332,4 , {78,71,78}, 171,1 , 6723,12 , 4,4 , 13,6 , 3058,4 , 3062,7 , 2, 1, 1, 6, 7 }, // Igbo/AnyScript/Nigeria
+ { 150, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 17745,48 , 17793,189 , 17982,24 , 17857,48 , 17905,189 , 18094,24 , 11455,28 , 11483,74 , 11557,14 , 11455,28 , 11483,74 , 11557,14 , 336,9 , 336,7 , {75,69,83}, 2,3 , 6735,23 , 4,4 , 13,6 , 3069,7 , 2663,5 , 2, 1, 6, 6, 7 }, // Kamba/AnyScript/Kenya
+ { 151, 0, 207, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 1294,13 , 394,4 , 25,12 , 18006,65 , 18006,65 , 1483,27 , 18118,65 , 18118,65 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {83,89,80}, 79,5 , 0,7 , 8,5 , 19,6 , 3076,6 , 3076,6 , 0, 0, 7, 5, 6 }, // Syriac/AnyScript/SyrianArabRepublic
+ { 152, 0, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1307,22 , 18,7 , 25,12 , 18071,47 , 18118,77 , 18195,24 , 18183,47 , 18230,77 , 18307,24 , 11571,26 , 11597,43 , 11640,14 , 11571,26 , 11597,43 , 11640,14 , 0,2 , 0,2 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 3082,3 , 3085,4 , 2, 1, 6, 6, 7 }, // Blin/AnyScript/Eritrea
+ { 153, 0, 67, 46, 4808, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1329,23 , 18,7 , 25,12 , 18219,49 , 18219,49 , 18268,24 , 18331,49 , 18331,49 , 18380,24 , 11654,29 , 11654,29 , 11683,14 , 11654,29 , 11654,29 , 11683,14 , 0,2 , 0,2 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 3089,4 , 3085,4 , 2, 1, 6, 6, 7 }, // Geez/AnyScript/Eritrea
+ { 153, 0, 69, 46, 4808, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1329,23 , 18,7 , 25,12 , 18219,49 , 18219,49 , 18268,24 , 18331,49 , 18331,49 , 18380,24 , 11654,29 , 11654,29 , 11683,14 , 11654,29 , 11654,29 , 11683,14 , 0,2 , 0,2 , {69,84,66}, 0,2 , 81,16 , 4,4 , 4,0 , 3089,4 , 96,5 , 2, 1, 6, 6, 7 }, // Geez/AnyScript/Ethiopia
+ { 154, 0, 53, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 18292,48 , 18340,124 , 1483,27 , 18404,48 , 18452,124 , 134,27 , 11697,28 , 11725,54 , 798,14 , 11697,28 , 11725,54 , 798,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Koro/AnyScript/IvoryCoast
+ { 155, 0, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 11779,28 , 11807,51 , 11858,14 , 11779,28 , 11807,51 , 11858,14 , 0,2 , 0,2 , {69,84,66}, 0,2 , 0,7 , 4,4 , 4,0 , 3093,11 , 3104,11 , 2, 1, 6, 6, 7 }, // Sidamo/AnyScript/Ethiopia
+ { 156, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 18464,59 , 18523,129 , 1483,27 , 18576,59 , 18635,129 , 134,27 , 11872,35 , 11907,87 , 798,14 , 11872,35 , 11907,87 , 798,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 6758,11 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Atsam/AnyScript/Nigeria
+ { 157, 0, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1352,21 , 18,7 , 25,12 , 926,46 , 972,62 , 1034,24 , 953,46 , 999,62 , 1061,24 , 11994,27 , 12021,41 , 12062,14 , 11994,27 , 12021,41 , 12062,14 , 0,2 , 0,2 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 3115,3 , 3085,4 , 2, 1, 6, 6, 7 }, // Tigre/AnyScript/Eritrea
+ { 158, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 18652,57 , 18709,178 , 1483,27 , 18764,57 , 18821,178 , 134,27 , 12076,28 , 12104,44 , 798,14 , 12076,28 , 12104,44 , 798,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 6769,14 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/AnyScript/Nigeria
+ { 159, 0, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1373,27 , 37,5 , 8,10 , 18887,48 , 18935,77 , 19012,24 , 18999,48 , 19047,77 , 19124,24 , 12148,28 , 12176,50 , 3021,14 , 12148,28 , 12176,50 , 3021,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 3549,11 , 8,5 , 4,0 , 3118,6 , 3124,6 , 2, 1, 1, 6, 7 }, // Friulian/AnyScript/Italy
+ { 160, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 19036,48 , 19084,111 , 1483,27 , 19148,48 , 19196,111 , 134,27 , 12226,27 , 12253,70 , 798,14 , 12226,27 , 12253,70 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 3130,9 , 0,0 , 2, 1, 1, 6, 7 }, // Venda/AnyScript/SouthAfrica
+ { 161, 0, 83, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 19195,48 , 19243,87 , 19330,24 , 19307,48 , 19355,87 , 19442,24 , 12323,32 , 12355,44 , 12399,14 , 12323,32 , 12355,44 , 12399,14 , 325,2 , 325,2 , {71,72,83}, 168,3 , 0,7 , 4,4 , 13,6 , 3139,6 , 3145,7 , 2, 1, 1, 6, 7 }, // Ewe/AnyScript/Ghana
+ { 161, 0, 212, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 19195,48 , 19243,87 , 19330,24 , 19307,48 , 19355,87 , 19442,24 , 12323,32 , 12355,44 , 12399,14 , 12323,32 , 12355,44 , 12399,14 , 325,2 , 325,2 , {88,79,70}, 157,3 , 6783,11 , 4,4 , 13,6 , 3139,6 , 3152,6 , 0, 0, 1, 6, 7 }, // Ewe/AnyScript/Togo
+ { 162, 0, 69, 46, 8217, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1400,22 , 18,7 , 25,12 , 926,46 , 972,62 , 1034,24 , 953,46 , 999,62 , 1061,24 , 12413,27 , 12413,27 , 12440,14 , 12413,27 , 12413,27 , 12440,14 , 0,2 , 0,2 , {69,84,66}, 0,2 , 81,16 , 4,4 , 4,0 , 3158,5 , 96,5 , 2, 1, 6, 6, 7 }, // Walamo/AnyScript/Ethiopia
+ { 163, 0, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 279,6 , 10,17 , 18,7 , 25,12 , 19354,59 , 19413,95 , 1483,27 , 19466,59 , 19525,95 , 134,27 , 12454,21 , 12475,57 , 798,14 , 12454,21 , 12475,57 , 798,14 , 0,2 , 0,2 , {85,83,68}, 256,3 , 0,7 , 4,4 , 13,6 , 3163,14 , 3177,19 , 2, 1, 7, 6, 7 }, // Hawaiian/AnyScript/UnitedStates
+ { 164, 0, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 221,8 , 314,18 , 37,5 , 8,10 , 19508,48 , 19556,153 , 1483,27 , 19620,48 , 19668,153 , 134,27 , 12532,28 , 12560,42 , 798,14 , 12532,28 , 12560,42 , 798,14 , 0,2 , 0,2 , {78,71,78}, 171,1 , 6794,11 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/AnyScript/Nigeria
+ { 165, 0, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 19709,48 , 19757,91 , 1483,27 , 19821,48 , 19869,91 , 134,27 , 12602,28 , 12630,67 , 798,14 , 12602,28 , 12630,67 , 798,14 , 0,2 , 0,2 , {77,87,75}, 0,0 , 6805,22 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chewa/AnyScript/Malawi
+ { 166, 0, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 380,8 , 380,8 , 558,6 , 1422,18 , 37,5 , 8,10 , 19848,48 , 19896,88 , 19984,24 , 19960,48 , 20008,88 , 20096,24 , 12697,28 , 12725,55 , 12780,14 , 12794,28 , 12725,55 , 12780,14 , 0,2 , 0,2 , {80,72,80}, 152,1 , 6827,22 , 8,5 , 4,0 , 3196,8 , 3204,9 , 2, 1, 7, 6, 7 }, // Filipino/AnyScript/Philippines
+ { 167, 0, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 128,9 , 128,9 , 332,8 , 502,18 , 37,5 , 8,10 , 20008,48 , 20056,86 , 134,24 , 5076,48 , 20120,86 , 320,24 , 12822,28 , 12850,63 , 3311,14 , 12822,28 , 12850,63 , 3311,14 , 91,5 , 343,4 , {67,72,70}, 0,0 , 6849,39 , 25,5 , 4,0 , 3213,16 , 3229,7 , 2, 5, 1, 6, 7 }, // Swiss German/AnyScript/Switzerland
+ { 168, 0, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 20142,38 , 1483,27 , 134,27 , 20206,38 , 134,27 , 12913,21 , 12934,28 , 12962,14 , 12913,21 , 12934,28 , 12962,14 , 345,2 , 347,2 , {67,78,89}, 215,3 , 0,7 , 8,5 , 4,0 , 3236,3 , 3239,2 , 2, 1, 7, 6, 7 }, // Sichuan Yi/AnyScript/China
+ { 169, 0, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {71,78,70}, 321,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Kpelle/AnyScript/Guinea
+ { 169, 0, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {76,82,68}, 128,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kpelle/AnyScript/Liberia
+ { 170, 0, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 1483,27 , 1483,27 , 1483,27 , 134,27 , 134,27 , 134,27 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 798,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 0,7 , 25,5 , 4,0 , 3241,12 , 3253,11 , 2, 1, 1, 6, 7 }, // Low German/AnyScript/Germany
+ { 171, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 20180,48 , 20228,100 , 1483,27 , 20244,48 , 20292,100 , 134,27 , 12976,27 , 13003,66 , 798,14 , 12976,27 , 13003,66 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 3264,10 , 0,0 , 2, 1, 1, 6, 7 }, // South Ndebele/AnyScript/SouthAfrica
+ { 172, 0, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 20328,48 , 20376,94 , 1483,27 , 20392,48 , 20440,94 , 134,27 , 13069,27 , 13096,63 , 798,14 , 13069,27 , 13096,63 , 798,14 , 0,2 , 0,2 , {90,65,82}, 11,1 , 0,7 , 4,4 , 4,0 , 3274,16 , 0,0 , 2, 1, 1, 6, 7 }, // Northern Sotho/AnyScript/SouthAfrica
+ { 173, 0, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 112,8 , 112,8 , 72,10 , 314,18 , 37,5 , 8,10 , 20470,85 , 20555,145 , 20700,24 , 20534,85 , 20619,145 , 20764,24 , 13159,33 , 13192,65 , 13257,14 , 13159,33 , 13192,65 , 13257,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 6888,23 , 25,5 , 4,0 , 3290,15 , 3305,6 , 2, 1, 1, 6, 7 }, // Northern Sami/AnyScript/Finland
+ { 173, 0, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 112,8 , 112,8 , 72,10 , 314,18 , 37,5 , 8,10 , 20724,59 , 20555,145 , 20700,24 , 20788,59 , 20619,145 , 20764,24 , 13159,33 , 13271,75 , 13346,14 , 13159,33 , 13271,75 , 13346,14 , 0,2 , 0,2 , {78,79,75}, 323,3 , 6911,21 , 25,5 , 4,0 , 3290,15 , 3311,5 , 2, 1, 1, 6, 7 }, // Northern Sami/AnyScript/Norway
+ { 174, 0, 208, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 72,10 , 314,18 , 37,5 , 8,10 , 20783,48 , 20831,142 , 20973,24 , 20847,48 , 20895,142 , 21037,24 , 13360,28 , 13388,172 , 13560,14 , 13360,28 , 13388,172 , 13560,14 , 0,2 , 0,2 , {84,87,68}, 135,3 , 6932,18 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Taroko/AnyScript/Taiwan
+ { 175, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 8216, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 20997,48 , 21045,88 , 21133,24 , 21061,48 , 21109,88 , 21197,24 , 13574,28 , 13602,62 , 13664,14 , 13574,28 , 13602,62 , 13664,14 , 347,5 , 349,10 , {75,69,83}, 2,3 , 6950,24 , 4,4 , 13,6 , 3316,8 , 2663,5 , 2, 1, 6, 6, 7 }, // Gusii/AnyScript/Kenya
+ { 176, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 21157,48 , 21205,221 , 21426,24 , 21221,48 , 21269,221 , 21490,24 , 13678,28 , 13706,106 , 13812,14 , 13678,28 , 13706,106 , 13812,14 , 352,10 , 359,10 , {75,69,83}, 2,3 , 6950,24 , 4,4 , 13,6 , 3324,7 , 2663,5 , 2, 1, 6, 6, 7 }, // Taita/AnyScript/Kenya
+ { 177, 0, 187, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 21450,48 , 21498,77 , 21575,24 , 21514,48 , 21562,77 , 21639,24 , 13826,28 , 13854,59 , 13913,14 , 13826,28 , 13854,59 , 13913,14 , 362,6 , 369,7 , {88,79,70}, 157,3 , 6974,26 , 25,5 , 4,0 , 3331,6 , 3337,8 , 0, 0, 1, 6, 7 }, // Fulah/AnyScript/Senegal
+ { 178, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 21599,48 , 21647,185 , 21832,24 , 21663,48 , 21711,185 , 21896,24 , 13927,28 , 13955,63 , 14018,14 , 13927,28 , 13955,63 , 14018,14 , 368,6 , 376,8 , {75,69,83}, 2,3 , 7000,23 , 4,4 , 13,6 , 3345,6 , 2663,5 , 2, 1, 6, 6, 7 }, // Kikuyu/AnyScript/Kenya
+ { 179, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 21856,48 , 21904,173 , 22077,24 , 21920,48 , 21968,173 , 22141,24 , 14032,28 , 14060,105 , 14165,14 , 14032,28 , 14060,105 , 14165,14 , 374,7 , 384,5 , {75,69,83}, 2,3 , 7023,25 , 4,4 , 13,6 , 3351,8 , 2663,5 , 2, 1, 6, 6, 7 }, // Samburu/AnyScript/Kenya
+ { 180, 0, 146, 44, 46, 59, 37, 48, 45, 43, 101, 39, 39, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 902,27 , 37,5 , 8,10 , 22101,48 , 22149,88 , 134,24 , 22165,48 , 22213,88 , 320,24 , 14179,28 , 14207,55 , 14262,14 , 14179,28 , 14207,55 , 14262,14 , 0,2 , 0,2 , {77,90,78}, 228,3 , 0,7 , 0,4 , 4,0 , 3359,4 , 1978,10 , 2, 1, 1, 6, 7 }, // Sena/AnyScript/Mozambique
+ { 181, 0, 240, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 22237,48 , 22285,112 , 22397,24 , 22301,48 , 22349,112 , 22461,24 , 14276,28 , 14304,50 , 14354,14 , 14276,28 , 14304,50 , 14354,14 , 0,2 , 0,2 , {85,83,68}, 256,3 , 7048,24 , 4,4 , 13,6 , 3264,10 , 944,8 , 2, 1, 7, 6, 7 }, // North Ndebele/AnyScript/Zimbabwe
+ { 182, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 22421,39 , 22460,194 , 22654,24 , 22485,39 , 22524,194 , 22718,24 , 14368,28 , 14396,65 , 14461,14 , 14368,28 , 14396,65 , 14461,14 , 381,8 , 389,7 , {84,90,83}, 290,3 , 7072,25 , 4,4 , 4,0 , 3363,9 , 2668,8 , 0, 0, 1, 6, 7 }, // Rombo/AnyScript/Tanzania
+ { 183, 0, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 22678,48 , 22726,81 , 22807,24 , 22742,48 , 22790,81 , 22871,24 , 14475,30 , 14505,48 , 798,14 , 14475,30 , 14505,48 , 798,14 , 389,6 , 396,8 , {77,65,68}, 0,0 , 7097,21 , 0,4 , 4,0 , 3372,9 , 3381,6 , 2, 1, 6, 5, 6 }, // Tachelhit/AnyScript/Morocco
+ { 183, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 22678,48 , 22726,81 , 22807,24 , 22742,48 , 22790,81 , 22871,24 , 14475,30 , 14505,48 , 798,14 , 14475,30 , 14505,48 , 798,14 , 389,6 , 396,8 , {77,65,68}, 0,0 , 7097,21 , 0,4 , 4,0 , 3372,9 , 3381,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Latin/Morocco
+ { 183, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 22831,48 , 22879,81 , 22960,24 , 22895,48 , 22943,81 , 23024,24 , 14553,30 , 14583,47 , 798,14 , 14553,30 , 14583,47 , 798,14 , 395,6 , 404,8 , {77,65,68}, 0,0 , 7118,21 , 0,4 , 4,0 , 3387,8 , 3395,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Tifinagh/Morocco
+ { 184, 0, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 22984,48 , 23032,84 , 23116,24 , 23048,48 , 23096,84 , 23180,24 , 14630,30 , 14660,51 , 14711,14 , 14630,30 , 14660,51 , 14711,14 , 401,7 , 412,9 , {68,90,68}, 326,2 , 7139,21 , 0,4 , 4,0 , 3401,9 , 3410,8 , 2, 1, 6, 4, 5 }, // Kabyle/AnyScript/Algeria
+ { 185, 0, 221, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8222, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 23140,48 , 23188,152 , 134,24 , 23204,48 , 23252,152 , 320,24 , 14725,28 , 14753,74 , 14827,14 , 14725,28 , 14753,74 , 14827,14 , 0,2 , 0,2 , {85,71,88}, 328,3 , 7160,26 , 4,4 , 74,5 , 3418,10 , 3428,6 , 0, 0, 1, 6, 7 }, // Nyankole/AnyScript/Uganda
+ { 186, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 23340,48 , 23388,254 , 23642,24 , 23404,48 , 23452,254 , 23706,24 , 14841,28 , 14869,82 , 14951,14 , 14841,28 , 14869,82 , 14951,14 , 408,7 , 421,7 , {84,90,83}, 290,3 , 7186,29 , 0,4 , 4,0 , 3434,6 , 3440,10 , 0, 0, 1, 6, 7 }, // Bena/AnyScript/Tanzania
+ { 187, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 23666,87 , 134,24 , 13764,48 , 23730,87 , 320,24 , 14965,28 , 14993,62 , 15055,14 , 14965,28 , 14993,62 , 15055,14 , 415,5 , 428,9 , {84,90,83}, 290,3 , 7215,27 , 4,4 , 4,0 , 3450,8 , 2668,8 , 0, 0, 1, 6, 7 }, // Vunjo/AnyScript/Tanzania
+ { 188, 0, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 23753,47 , 23800,92 , 23892,24 , 23817,47 , 23864,92 , 23956,24 , 15069,28 , 15097,44 , 15141,14 , 15069,28 , 15097,44 , 15141,14 , 0,2 , 0,2 , {88,79,70}, 157,3 , 7242,24 , 4,4 , 13,6 , 3458,9 , 1133,4 , 0, 0, 1, 6, 7 }, // Bambara/AnyScript/Mali
+ { 189, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 23916,48 , 23964,207 , 24171,24 , 23980,48 , 24028,207 , 24235,24 , 15155,28 , 15183,64 , 15247,14 , 15155,28 , 15183,64 , 15247,14 , 420,2 , 437,2 , {75,69,83}, 2,3 , 6950,24 , 4,4 , 13,6 , 3467,6 , 2663,5 , 2, 1, 6, 6, 7 }, // Embu/AnyScript/Kenya
+ { 190, 0, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 558,6 , 35,18 , 18,7 , 25,12 , 24195,36 , 24231,58 , 24289,24 , 24259,36 , 24295,58 , 24353,24 , 15261,28 , 15289,49 , 15338,14 , 15261,28 , 15289,49 , 15338,14 , 422,3 , 439,6 , {85,83,68}, 128,1 , 7266,19 , 4,4 , 13,6 , 3473,3 , 3476,4 , 2, 1, 7, 6, 7 }, // Cherokee/AnyScript/UnitedStates
+ { 191, 0, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 24313,47 , 24360,68 , 24428,24 , 24377,47 , 24424,68 , 24492,24 , 15352,27 , 15379,48 , 15427,14 , 15352,27 , 15379,48 , 15427,14 , 0,2 , 0,2 , {77,85,82}, 147,4 , 7285,21 , 8,5 , 4,0 , 3480,14 , 3494,5 , 0, 0, 1, 6, 7 }, // Morisyen/AnyScript/Mauritius
+ { 192, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 24452,264 , 134,24 , 13764,48 , 24516,264 , 320,24 , 15441,28 , 15469,133 , 14461,14 , 15441,28 , 15469,133 , 14461,14 , 425,4 , 445,5 , {84,90,83}, 290,3 , 7215,27 , 4,4 , 13,6 , 3499,10 , 2668,8 , 0, 0, 1, 6, 7 }, // Makonde/AnyScript/Tanzania
+ { 193, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 24716,83 , 24799,111 , 24910,24 , 24780,83 , 24863,111 , 24974,24 , 15602,36 , 15638,63 , 15701,14 , 15602,36 , 15638,63 , 15701,14 , 429,3 , 450,3 , {84,90,83}, 290,3 , 7306,29 , 8,5 , 4,0 , 3509,8 , 3517,9 , 0, 0, 1, 6, 7 }, // Langi/AnyScript/Tanzania
+ { 194, 0, 221, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 24934,48 , 24982,97 , 134,24 , 24998,48 , 25046,97 , 320,24 , 15715,28 , 15743,66 , 15809,14 , 15715,28 , 15743,66 , 15809,14 , 0,2 , 0,2 , {85,71,88}, 328,3 , 7335,26 , 0,4 , 4,0 , 3526,7 , 3533,7 , 0, 0, 1, 6, 7 }, // Ganda/AnyScript/Uganda
+ { 195, 0, 239, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 25079,48 , 25127,83 , 25210,24 , 25143,48 , 25191,83 , 25274,24 , 15823,80 , 15823,80 , 798,14 , 15823,80 , 15823,80 , 798,14 , 432,8 , 453,7 , {90,77,75}, 331,2 , 0,7 , 4,4 , 13,6 , 3540,9 , 3549,6 , 0, 0, 1, 6, 7 }, // Bemba/AnyScript/Zambia
+ { 196, 0, 39, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 902,27 , 37,5 , 8,10 , 25234,48 , 25282,86 , 134,24 , 25298,48 , 25346,86 , 320,24 , 15903,28 , 15931,73 , 16004,14 , 15903,28 , 15931,73 , 16004,14 , 140,2 , 140,2 , {67,86,69}, 333,3 , 7361,25 , 0,4 , 4,0 , 3555,12 , 3567,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/AnyScript/CapeVerde
+ { 197, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 25368,48 , 25416,86 , 25502,24 , 25432,48 , 25480,86 , 25566,24 , 16018,28 , 16046,51 , 16097,14 , 16018,28 , 16046,51 , 16097,14 , 440,2 , 460,2 , {75,69,83}, 2,3 , 6950,24 , 4,4 , 13,6 , 3577,6 , 2663,5 , 2, 1, 6, 6, 7 }, // Meru/AnyScript/Kenya
+ { 198, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 25526,48 , 25574,111 , 25685,24 , 25590,48 , 25638,111 , 25749,24 , 16111,28 , 16139,93 , 16232,14 , 16111,28 , 16139,93 , 16232,14 , 442,4 , 462,4 , {75,69,83}, 2,3 , 7386,26 , 4,4 , 13,6 , 3583,8 , 3591,12 , 2, 1, 6, 6, 7 }, // Kalenjin/AnyScript/Kenya
+ { 199, 0, 148, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 0,48 , 25709,136 , 134,24 , 0,48 , 25773,136 , 320,24 , 16246,23 , 16269,92 , 16361,14 , 16246,23 , 16269,92 , 16361,14 , 446,7 , 466,5 , {78,65,68}, 12,2 , 7412,22 , 4,4 , 4,0 , 3603,13 , 3616,8 , 2, 1, 1, 6, 7 }, // Nama/AnyScript/Namibia
+ { 200, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 23666,87 , 134,24 , 13764,48 , 23730,87 , 320,24 , 14965,28 , 14993,62 , 15055,14 , 14965,28 , 14993,62 , 15055,14 , 415,5 , 428,9 , {84,90,83}, 290,3 , 7215,27 , 4,4 , 4,0 , 3624,9 , 2668,8 , 0, 0, 1, 6, 7 }, // Machame/AnyScript/Tanzania
+ { 201, 0, 82, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 228,8 , 228,8 , 1440,10 , 1450,23 , 37,5 , 8,10 , 25845,59 , 25904,87 , 134,24 , 25909,59 , 25968,87 , 320,24 , 16375,28 , 16403,72 , 3311,14 , 16375,28 , 16403,72 , 3311,14 , 0,2 , 0,2 , {69,85,82}, 113,1 , 3549,11 , 25,5 , 4,0 , 0,0 , 3633,11 , 2, 1, 1, 6, 7 }, // Colognian/AnyScript/Germany
+ { 202, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8221, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 25991,51 , 26042,132 , 1483,27 , 26055,51 , 26106,132 , 134,27 , 14965,28 , 16475,58 , 14461,14 , 14965,28 , 16475,58 , 14461,14 , 453,9 , 471,6 , {75,69,83}, 2,3 , 7434,25 , 4,4 , 13,6 , 3644,3 , 2663,5 , 2, 1, 6, 6, 7 }, // Masai/AnyScript/Kenya
+ { 202, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8221, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 25991,51 , 26042,132 , 1483,27 , 26055,51 , 26106,132 , 134,27 , 14965,28 , 16475,58 , 14461,14 , 14965,28 , 16475,58 , 14461,14 , 453,9 , 471,6 , {84,90,83}, 290,3 , 7459,28 , 4,4 , 13,6 , 3644,3 , 3647,8 , 0, 0, 1, 6, 7 }, // Masai/AnyScript/Tanzania
+ { 203, 0, 221, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8222, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 24934,48 , 24982,97 , 134,24 , 24998,48 , 25046,97 , 320,24 , 16533,35 , 16568,65 , 16633,14 , 16533,35 , 16568,65 , 16633,14 , 462,6 , 477,6 , {85,71,88}, 328,3 , 7335,26 , 25,5 , 4,0 , 3655,7 , 3533,7 , 0, 0, 1, 6, 7 }, // Soga/AnyScript/Uganda
+ { 204, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26174,48 , 13661,84 , 134,24 , 26238,48 , 13812,84 , 320,24 , 16647,21 , 16668,75 , 85,14 , 16647,21 , 16668,75 , 85,14 , 56,4 , 56,4 , {75,69,83}, 2,3 , 7487,23 , 4,4 , 79,6 , 3662,7 , 2663,5 , 2, 1, 6, 6, 7 }, // Luyia/AnyScript/Kenya
+ { 205, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26222,48 , 13661,84 , 134,24 , 26286,48 , 13812,84 , 320,24 , 16743,28 , 8849,60 , 15055,14 , 16743,28 , 8849,60 , 15055,14 , 468,9 , 483,8 , {84,90,83}, 290,3 , 7510,28 , 25,5 , 4,0 , 3669,6 , 3675,8 , 0, 0, 1, 6, 7 }, // Asu/AnyScript/Tanzania
+ { 206, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 39, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26270,48 , 26318,94 , 26412,24 , 26334,48 , 26382,94 , 26476,24 , 16771,28 , 16799,69 , 16868,14 , 16771,28 , 16799,69 , 16868,14 , 477,9 , 491,6 , {75,69,83}, 2,3 , 7538,27 , 4,4 , 13,6 , 3683,6 , 3689,5 , 2, 1, 6, 6, 7 }, // Teso/AnyScript/Kenya
+ { 206, 0, 221, 46, 44, 59, 37, 48, 45, 43, 101, 39, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26270,48 , 26318,94 , 26412,24 , 26334,48 , 26382,94 , 26476,24 , 16771,28 , 16799,69 , 16868,14 , 16771,28 , 16799,69 , 16868,14 , 477,9 , 491,6 , {85,71,88}, 328,3 , 7565,28 , 4,4 , 13,6 , 3683,6 , 3428,6 , 0, 0, 1, 6, 7 }, // Teso/AnyScript/Uganda
+ { 207, 0, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 53,19 , 18,7 , 25,12 , 317,48 , 518,118 , 494,24 , 344,48 , 545,118 , 521,24 , 16882,28 , 16910,56 , 16966,14 , 16882,28 , 16910,56 , 16966,14 , 0,2 , 0,2 , {69,82,78}, 8,3 , 0,7 , 4,4 , 4,0 , 0,0 , 36,7 , 2, 1, 6, 6, 7 }, // Saho/AnyScript/Eritrea
+ { 208, 0, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 26436,46 , 26482,88 , 26570,24 , 26500,46 , 26546,88 , 26634,24 , 16980,28 , 17008,53 , 17061,14 , 16980,28 , 17008,53 , 17061,14 , 486,6 , 497,6 , {88,79,70}, 157,3 , 7593,23 , 0,4 , 4,0 , 3694,11 , 3705,5 , 0, 0, 1, 6, 7 }, // Koyra Chiini/AnyScript/Mali
+ { 209, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 23666,87 , 134,24 , 13764,48 , 23730,87 , 320,24 , 14965,28 , 14993,62 , 15055,14 , 14965,28 , 14993,62 , 15055,14 , 415,5 , 428,9 , {84,90,83}, 290,3 , 7215,27 , 0,4 , 4,0 , 3710,6 , 2668,8 , 0, 0, 1, 6, 7 }, // Rwa/AnyScript/Tanzania
+ { 210, 0, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26594,48 , 26642,186 , 26828,24 , 26658,48 , 26706,186 , 26892,24 , 17075,28 , 17103,69 , 17172,14 , 17075,28 , 17103,69 , 17172,14 , 492,2 , 503,2 , {75,69,83}, 2,3 , 7616,23 , 0,4 , 4,0 , 3716,6 , 2663,5 , 2, 1, 6, 6, 7 }, // Luo/AnyScript/Kenya
+ { 211, 0, 221, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8222, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 23140,48 , 23188,152 , 134,24 , 23204,48 , 23252,152 , 320,24 , 14725,28 , 14753,74 , 14827,14 , 14725,28 , 14753,74 , 14827,14 , 0,2 , 0,2 , {85,71,88}, 328,3 , 7160,26 , 4,4 , 74,5 , 3722,6 , 3428,6 , 0, 0, 1, 6, 7 }, // Chiga/AnyScript/Uganda
+ { 212, 0, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26852,48 , 26900,86 , 26986,24 , 26916,48 , 26964,86 , 27050,24 , 17186,28 , 17214,48 , 17262,14 , 17186,28 , 17214,48 , 17262,14 , 494,9 , 505,10 , {77,65,68}, 0,0 , 7639,22 , 25,5 , 4,0 , 3728,8 , 3736,6 , 2, 1, 6, 5, 6 }, // Central Morocco Tamazight/AnyScript/Morocco
+ { 212, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 26852,48 , 26900,86 , 26986,24 , 26916,48 , 26964,86 , 27050,24 , 17186,28 , 17214,48 , 17262,14 , 17186,28 , 17214,48 , 17262,14 , 494,9 , 505,10 , {77,65,68}, 0,0 , 7639,22 , 25,5 , 4,0 , 3728,8 , 3736,6 , 2, 1, 6, 5, 6 }, // Central Morocco Tamazight/Latin/Morocco
+ { 213, 0, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 364,8 , 99,16 , 37,5 , 8,10 , 26436,46 , 26482,88 , 26570,24 , 26500,46 , 26546,88 , 26634,24 , 17276,28 , 17304,54 , 17061,14 , 17276,28 , 17304,54 , 17061,14 , 486,6 , 497,6 , {88,79,70}, 157,3 , 7593,23 , 0,4 , 4,0 , 3742,15 , 3705,5 , 0, 0, 1, 6, 7 }, // Koyraboro Senni/AnyScript/Mali
+ { 214, 0, 210, 46, 44, 59, 37, 48, 45, 43, 101, 39, 39, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 141,10 , 10,17 , 18,7 , 25,12 , 13613,48 , 27010,84 , 134,24 , 13764,48 , 27074,84 , 320,24 , 17358,28 , 17386,63 , 8909,14 , 17358,28 , 17386,63 , 8909,14 , 503,5 , 515,8 , {84,90,83}, 290,3 , 6241,27 , 0,4 , 4,0 , 3757,9 , 2668,8 , 0, 0, 1, 6, 7 }, // Shambala/AnyScript/Tanzania
+ { 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 0s
+};
+
+static const ushort list_pattern_part_data[] = {
+0x25, 0x31, 0x2c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x98f,
+0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 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, 0x6a, 0x61, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x65, 0x74, 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, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9, 0x73, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69,
+0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x20,
+0x906, 0x923, 0x93f, 0x20, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x923, 0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69,
+0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 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, 0x2c, 0x20, 0xc2e, 0xc30, 0xc3f,
+0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76,
+0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x442, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32
+};
+
+static const ushort date_format_data[] = {
+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, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 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, 0x79, 0x79, 0x2d, 0x4d, 0x4d,
+0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f, 0x4d, 0x200f, 0x2f, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2c, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x27, 0x65,
+0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x72, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x64, 0x27, 0x61, 0x27, 0x64,
+0x2f, 0x4d, 0x2f, 0x79, 0x79, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79, 0x79, 0x79, 0x79, 0x20, 0xf5f, 0xfb3,
+0xf0b, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79,
+0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e,
+0x4d, 0x2e, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x1790, 0x17d2, 0x1784,
+0x17c3, 0x20, 0x64, 0x20, 0x1781, 0x17c2, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1786, 0x17d2, 0x1793, 0x17b6, 0x17c6, 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, 0x79, 0x79, 0x2d, 0x4d, 0x2d, 0x64, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64,
+0x64, 0x64, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x4d, 0x6708, 0x64, 0x64, 0x65e5,
+0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 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, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x4d, 0x2f,
+0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64,
+0x2e, 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, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x64, 0x20, 0x5d1, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x2e, 0x20,
+0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20, 0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x64, 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, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20,
+0x64, 0x64, 0x20, 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, 0x64, 0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 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, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64,
+0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0xa0, 0x27, 0x433, 0x27,
+0x2e, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 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, 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, 0x27, 0x65, 0x6e, 0x27, 0x20, 0x27, 0x64, 0x65, 0x6e,
+0x27, 0x20, 0x64, 0x3a, 0x27, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 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, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2c,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 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, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x6e, 0x67, 0xe0, 0x79, 0x27, 0x20, 0x64, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x6e, 0x103, 0x6d, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x130d, 0x122d, 0x130b, 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, 0x1361, 0x20, 0x64, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x12ee, 0x121d, 0x20, 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, 0x1365, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x130b, 0x120b, 0x1233, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x2e, 0x20, 0x4d, 0x2e, 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
+};
+
+static const ushort time_format_data[] = {
+0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x3a,
+0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x3a,
+0x6d, 0x6d, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x2e, 0x41, 0x50, 0x20,
+0x74, 0x74, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x20, 0x41,
+0x50, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 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, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c,
+0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf46,
+0xf71, 0xf0b, 0x20, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d,
+0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x48, 0x20, 0x1798, 0x17c9, 0x17c4, 0x1784, 0x20, 0x6d, 0x20, 0x1793, 0x17b6,
+0x1791, 0x17b8, 0x20, 0x73, 0x73, 0x20, 0x179c, 0x17b7, 0x1793, 0x17b6, 0x1791, 0x17b8, 0x200b, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x3a,
+0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x74, 0x41, 0x50, 0x68, 0x65f6, 0x6d, 0x6d, 0x5206, 0x73, 0x73,
+0x79d2, 0x74, 0x41, 0x50, 0x68, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x41, 0x50, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 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, 0x3a, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d,
+0x2e, 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, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27,
+0x20, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41,
+0x50, 0x20, 0x74, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d,
+0x41, 0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20, 0x74, 0x48, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0xe99,
+0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x68, 0x3a,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x41, 0x50, 0x20, 0x74, 0x68, 0x2d, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68,
+0x2d, 0x6d, 0x6d, 0x2d, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x48, 0x48,
+0x27, 0x68, 0x27, 0x6d, 0x6d, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x73, 0x73, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x20,
+0x27, 0x447, 0x430, 0x441, 0x43e, 0x432, 0x430, 0x27, 0x2c, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x43c, 0x438, 0x43d, 0x443, 0x442, 0x430,
+0x27, 0x2c, 0x20, 0x73, 0x73, 0x20, 0x27, 0x441, 0x435, 0x43a, 0x443, 0x43d, 0x434, 0x438, 0x27, 0x20, 0x74, 0x48, 0x48, 0x27,
+0x68, 0x27, 0x27, 0x27, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x48, 0x27, 0x48, 0x27, 0x6d, 0x6d, 0x27, 0x27,
+0x73, 0x73, 0x27, 0x27, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34, 0xe01, 0xe32, 0x20, 0x6d, 0x20, 0xe19, 0xe32, 0xe17,
+0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x74
+};
+
+static const ushort months_data[] = {
+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, 0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b,
+0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
+0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 0x51, 0x75, 0x6e, 0x78, 0x61, 0x20, 0x47, 0x61,
+0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4e, 0x61, 0x68, 0x61, 0x72, 0x73, 0x69, 0x20, 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, 0x73, 0x6f, 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,
+0x3b, 0x51, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x43, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x4c, 0x3b, 0x57, 0x3b, 0x44,
+0x3b, 0x58, 0x3b, 0x4b, 0x3b, 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, 0x3b, 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, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f,
+0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50, 0x72, 0x69, 0x3b, 0x4d,
+0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x54,
+0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b, 0x44, 0x68, 0x6a, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x51,
+0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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,
+0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b, 0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6,
+0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 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, 0x3b,
+0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b,
+0x628, 0x3b, 0x62f, 0x3b, 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, 0x3b, 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, 0x646, 0x648, 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, 0x3b, 0x540, 0x576, 0x57e, 0x3b, 0x553, 0x57f, 0x57e, 0x3b, 0x544, 0x580, 0x57f, 0x3b,
+0x531, 0x57a, 0x580, 0x3b, 0x544, 0x575, 0x57d, 0x3b, 0x540, 0x576, 0x57d, 0x3b, 0x540, 0x56c, 0x57d, 0x3b, 0x555, 0x563, 0x57d, 0x3b,
+0x54d, 0x565, 0x57a, 0x3b, 0x540, 0x578, 0x56f, 0x3b, 0x546, 0x578, 0x575, 0x3b, 0x534, 0x565, 0x56f, 0x3b, 0x540, 0x578, 0x582, 0x576,
+0x57e, 0x561, 0x580, 0x3b, 0x553, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x544, 0x561, 0x580, 0x57f, 0x3b, 0x531, 0x57a, 0x580,
+0x56b, 0x56c, 0x3b, 0x544, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x540, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x540, 0x578, 0x582, 0x56c,
+0x56b, 0x57d, 0x3b, 0x555, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x54d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580,
+0x3b, 0x540, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x546, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b,
+0x534, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 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, 0x3b, 0x99c, 0x9c1,
+0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd,
+0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x3b, 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, 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, 0x3b,
+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, 0x3b, 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, 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, 0x44, 0x65,
+0x6b, 0x61, 0x62, 0x72, 0x3b, 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, 0x3b, 0x75, 0x72, 0x74, 0x3b, 0x6f, 0x74, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x69, 0x3b, 0x6d, 0x61,
+0x69, 0x3b, 0x65, 0x6b, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x3b, 0x61, 0x62, 0x75, 0x3b, 0x69, 0x72, 0x61, 0x3b, 0x75, 0x72,
+0x72, 0x3b, 0x61, 0x7a, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x3b, 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, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49,
+0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20,
+0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf25, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0x20, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf28, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0x20, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0x20, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf66,
+0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
+0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
+0xf5d, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf63, 0xf94,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
+0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d,
+0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0x44f, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b,
+0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b,
+0x438, 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, 0x3b, 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, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c,
+0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 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, 0x3b, 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, 0x3b, 0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b,
+0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x3b, 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, 0x3b, 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, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a,
+0x3b, 0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x17e1, 0x3b, 0x17e2,
+0x3b, 0x17e3, 0x3b, 0x17e4, 0x3b, 0x17e5, 0x3b, 0x17e6, 0x3b, 0x17e7, 0x3b, 0x17e8, 0x3b, 0x17e9, 0x3b, 0x17e1, 0x17e0, 0x3b, 0x17e1, 0x17e1,
+0x3b, 0x17e1, 0x17e2, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b7, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x6c, 0x3b, 0xfa, 0x3b,
+0x62, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x10d, 0x3b, 0x10d, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x159, 0x3b, 0x6c, 0x3b, 0x70, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x4d, 0x3b,
+0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 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,
+0x3b, 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, 0x3b, 0x58, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62,
+0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x58, 0x75, 0xf1, 0x3b, 0x58, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65,
+0x74, 0x3b, 0x4f, 0x75, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 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,
+0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b,
+0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x399, 0x3b1,
+0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x3ca, 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, 0x3b, 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, 0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3,
+0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x3b, 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, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x69, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69,
+0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 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, 0x3b, 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, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7,
+0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59,
+0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e1, 0x3b, 0x5d0,
+0x5e4, 0x5e8, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x3b, 0x5e1,
+0x5e4, 0x5d8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8,
+0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e1, 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, 0x3b, 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, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x92e, 0x94d, 0x92c,
+0x930, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0xc1, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a,
+0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a,
+0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0xe1, 0x67, 0xfa, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
+0xf3, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x45, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e,
+0x3b, 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, 0x3b, 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, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcc0, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0,
+0xcc0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8e, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc6, 0x3b,
+0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 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, 0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe,
+0x3b, 0xc8e, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b, 0xc9c, 0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8,
+0x3b, 0xca1, 0xcbf, 0x3b, 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, 0x442, 0x2e, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0xe7, 0x69, 0x6c, 0x3b, 0x73, 0x69, 0x62, 0x3b, 0x61, 0x64, 0x72, 0x3b,
+0x6e, 0xee, 0x73, 0x3b, 0x67, 0x75, 0x6c, 0x3b, 0x68, 0x65, 0x7a, 0x3b, 0x74, 0xee, 0x72, 0x3b, 0x38, 0x3b, 0x39, 0x3b,
+0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0xe7, 0x69, 0x6c, 0x65, 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, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b,
+0xe7, 0x3b, 0x73, 0x3b, 0x61, 0x3b, 0x6e, 0x3b, 0x67, 0x3b, 0x68, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30,
+0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb5, 0x2e,
+0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x73, 0x31, 0x3b, 0x73, 0x32, 0x3b, 0x73, 0x33, 0x3b,
+0x73, 0x34, 0x3b, 0x73, 0x35, 0x3b, 0x73, 0x36, 0x3b, 0x73, 0x37, 0x3b, 0x73, 0x38, 0x3b, 0x73, 0x39, 0x3b, 0x73, 0x31,
+0x30, 0x3b, 0x73, 0x31, 0x31, 0x3b, 0x73, 0x31, 0x32, 0x3b, 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, 0x3b, 0x53, 0x61, 0x75, 0x3b, 0x56, 0x61, 0x73,
+0x3b, 0x4b, 0x6f, 0x76, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x47, 0x65, 0x67, 0x3b, 0x42, 0x69, 0x72, 0x3b, 0x4c, 0x69, 0x65,
+0x3b, 0x52, 0x67, 0x70, 0x3b, 0x52, 0x67, 0x73, 0x3b, 0x53, 0x70, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x3b, 0x47, 0x72, 0x64,
+0x3b, 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, 0x3b, 0x53, 0x3b, 0x56,
+0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47,
+0x3b, 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,
+0x435, 0x43c, 0x2e, 0x3b, 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, 0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458,
+0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69,
+0x73, 0x3b, 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, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e, 0xd30, 0xd4d, 0x200d,
+0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 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, 0x3b, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c,
+0xd4d, 0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd30, 0xd4d, 0x200d, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d,
+0xd30, 0xd3f, 0xd32, 0xd4d, 0x200d, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 0x3b, 0xd1c, 0xd42, 0xd32,
+0xd48, 0x3b, 0xd06, 0xd17, 0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c,
+0xd30, 0xd4d, 0x200d, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd30, 0xd4d,
+0x200d, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f,
+0x3b, 0xd2e, 0xd47, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21,
+0xd3f, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x120, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+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, 0x3b, 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, 0x3b, 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,
+0x3b, 0x445, 0x443, 0x43b, 0x3b, 0x4af, 0x445, 0x44d, 0x3b, 0x431, 0x430, 0x440, 0x3b, 0x442, 0x443, 0x443, 0x3b, 0x43b, 0x443, 0x443,
+0x3b, 0x43c, 0x43e, 0x433, 0x3b, 0x43c, 0x43e, 0x440, 0x3b, 0x445, 0x43e, 0x43d, 0x3b, 0x431, 0x438, 0x447, 0x3b, 0x442, 0x430, 0x445,
+0x3b, 0x43d, 0x43e, 0x445, 0x3b, 0x433, 0x430, 0x445, 0x3b, 0x425, 0x443, 0x43b, 0x433, 0x430, 0x43d, 0x430, 0x3b, 0x4ae, 0x445, 0x44d,
+0x440, 0x3b, 0x411, 0x430, 0x440, 0x3b, 0x422, 0x443, 0x443, 0x43b, 0x430, 0x439, 0x3b, 0x41b, 0x443, 0x443, 0x3b, 0x41c, 0x43e, 0x433,
+0x43e, 0x439, 0x3b, 0x41c, 0x43e, 0x440, 0x44c, 0x3b, 0x425, 0x43e, 0x43d, 0x44c, 0x3b, 0x411, 0x438, 0x447, 0x3b, 0x422, 0x430, 0x445,
+0x438, 0x430, 0x3b, 0x41d, 0x43e, 0x445, 0x43e, 0x439, 0x3b, 0x413, 0x430, 0x445, 0x430, 0x439, 0x3b, 0x91c, 0x928, 0x3b, 0x92b, 0x947,
+0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b,
+0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x3b, 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, 0x924, 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, 0x3b, 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, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
+0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x947, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908,
+0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 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, 0x926, 0x93f, 0x938, 0x92e, 0x94d,
+0x92c, 0x930, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0xb1c, 0xb3e, 0xb28, 0xb41, 0xb06, 0xb30, 0xb40, 0x3b, 0xb2b, 0xb47, 0xb2c, 0xb4d,
+0xb30, 0xb41, 0xb5f, 0xb3e, 0xb30, 0xb40, 0x3b, 0xb2e, 0xb3e, 0xb30, 0xb4d, 0xb1a, 0xb4d, 0xb1a, 0x3b, 0xb05, 0xb2a, 0xb4d, 0xb30, 0xb47,
+0xb32, 0x3b, 0xb2e, 0xb47, 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, 0x3b, 0xb1c, 0xb3e, 0x3b,
+0xb2b, 0xb47, 0x3b, 0xb2e, 0xb3e, 0x3b, 0xb05, 0x3b, 0xb2e, 0xb47, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb05, 0x3b, 0xb38,
+0xb47, 0x3b, 0xb05, 0x3b, 0xb28, 0x3b, 0xb21, 0xb3f, 0x3b, 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, 0x6cc, 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, 0x3b, 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, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 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, 0x3b, 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, 0x6cc, 0x3b, 0x62c, 0x648, 0x646,
+0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x622, 0x6af, 0x648, 0x633, 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,
+0x3b, 0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x6cc, 0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, 0x3b, 0x633, 0x3b,
+0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x654, 0x3b, 0x645, 0x627, 0x631,
+0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x640, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 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, 0x645, 0x3b, 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, 0x3b, 0x62c, 0x3b, 0x641,
+0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f,
+0x3b, 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, 0x3b, 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, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b,
+0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x3b, 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, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x75, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b,
+0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61,
+0x72, 0xe7, 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, 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, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72,
+0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f,
+0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 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, 0x3b, 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, 0x3b, 0xa1c, 0x3b, 0xa2b, 0x3b, 0xa2e, 0xa3e,
+0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x46,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49,
+0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435,
+0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438,
+0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, 0x43b, 0x44f, 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, 0x3b, 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, 0x3b, 0x42f, 0x3b,
+0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b,
+0x414, 0x3b, 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, 0x3b, 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,
+0x3b, 0x4e, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4e,
+0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 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, 0x3b, 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, 0x3b, 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, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b,
+0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x64, 0x69, 0x3b, 0x4b, 0x75, 0x6b, 0x3b, 0x4b, 0x75, 0x72, 0x3b,
+0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x3b, 0x4e, 0x79, 0x61, 0x3b,
+0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x3b, 0x5a, 0x76, 0x69, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0xda2,
+0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0x3b,
+0xdb8, 0xdd0, 0xdba, 0x3b, 0xda2, 0xdd6, 0xdb1, 0x3b, 0xda2, 0xdd6, 0xdbd, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0x3b,
+0xd94, 0xd9a, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0x3b, 0xdb4,
+0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd,
+0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 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, 0x3b, 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, 0xddc, 0x3b, 0xdaf, 0xdd9, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x53, 0x68,
+0x61, 0x3b, 0x4c, 0x69, 0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53, 0x69, 0x64, 0x3b, 0x53, 0x61, 0x67, 0x3b, 0x54, 0x6f,
+0x62, 0x3b, 0x4b, 0x49, 0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 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, 0x3b, 0x4b,
+0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b,
+0x3b, 0x4c, 0x3b, 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, 0x3b, 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, 0x3b,
+0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
+0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0xbc6, 0xbae, 0xbcd, 0xbaa, 0xbcd, 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, 0x3b, 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, 0x3b, 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, 0xc42, 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, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0x3b, 0xc0e, 0x3b, 0xc2e, 0xc46, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc1c,
+0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0x3b, 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, 0x3b, 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, 0x3b, 0xe21, 0x3b, 0xe01, 0x3b, 0xe21,
+0x3b, 0xe21, 0x3b, 0xe1e, 0x3b, 0xe21, 0x3b, 0xe01, 0x3b, 0xe2a, 0x3b, 0xe01, 0x3b, 0xe15, 0x3b, 0xe1e, 0x3b, 0xe18, 0x3b, 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, 0x3b, 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, 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, 0x3b,
+0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x3b, 0x1218, 0x130b, 0x1262, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x3b, 0x130d, 0x1295, 0x1266, 0x3b, 0x1230,
+0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x3b, 0x1325, 0x1245, 0x121d, 0x3b, 0x1215, 0x12f3,
+0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x53, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x54, 0x3b, 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, 0x27, 0x77, 0x3b, 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, 0x27,
+0x77, 0x65, 0x6e, 0x64, 0x7a, 0x61, 0x6d, 0x68, 0x61, 0x6c, 0x61, 0x3b, 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, 0x3b,
+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, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d,
+0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a,
+0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x62c, 0x646, 0x648,
+0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x20, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x64a, 0x644,
+0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 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, 0x3b, 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, 0x3b, 0x62c,
+0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631, 0x3b, 0x645, 0x640, 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, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b,
+0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49, 0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76,
+0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x3b, 0x44, 0x65, 0x6b, 0x3b, 0x59,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
+0x3b, 0x44, 0x3b, 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, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1ed9, 0x74, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x68, 0x61, 0x69, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x62, 0x61, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x74, 0x1b0, 0x3b, 0x74, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x6e, 0x103, 0x6d, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x73, 0xe1, 0x75, 0x3b, 0x74, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x62, 0x1ea3, 0x79, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x74, 0xe1, 0x6d, 0x3b, 0x74, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x63, 0x68, 0xed, 0x6e, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x20, 0x6d, 0x1ed9, 0x74, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d,
+0x1b0, 0x1edd, 0x69, 0x20, 0x68, 0x61, 0x69, 0x3b, 0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x3b, 0x4d, 0x61,
+0x77, 0x72, 0x74, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x69, 0x6c, 0x6c, 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, 0x3b, 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, 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, 0x3b, 0x49, 0x3b, 0x43, 0x3b,
+0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x3b,
+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, 0x3b, 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, 0x3b, 0x1e62,
+0x1eb9, 0x301, 0x72, 0x1eb9, 0x323, 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, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1e62, 0x1eb8, 0x301, 0x72,
+0x1eb9, 0x301, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1eb8, 0x72, 0x1eb9,
+0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1eb8, 0x300, 0x62,
+0x69, 0x62, 0x69, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x41, 0x67,
+0x1eb9, 0x6d, 0x1ecd, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x4f, 0x77, 0x65,
+0x77, 0x65, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x42, 0xe9,
+0x6c, 0xfa, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x41, 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,
+0x3b, 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, 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, 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, 0x3b, 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,
+0x76, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41,
+0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41,
+0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 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, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61,
+0x72, 0x3b, 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, 0x2e, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2e, 0x4e, 0x6f, 0x6c, 0x6c,
+0x69, 0x63, 0x6b, 0x3b, 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, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x57, 0x68, 0x65, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x45, 0x62, 0x72, 0x3b,
+0x4d, 0x65, 0x3b, 0x45, 0x66, 0x6e, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48,
+0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72,
+0x3b, 0x4d, 0x79, 0x73, 0x20, 0x57, 0x68, 0x65, 0x76, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x72,
+0x74, 0x68, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x3b,
+0x4d, 0x79, 0x73, 0x20, 0x45, 0x66, 0x61, 0x6e, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72,
+0x65, 0x6e, 0x3b, 0x4d, 0x79, 0x65, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x67,
+0x61, 0x6c, 0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x44, 0x75,
+0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, 0x75, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x913,
+0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x913, 0x915, 0x94d, 0x91f, 0x94b,
+0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930,
+0x3b, 0x41, 0x68, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x3b, 0x4f, 0x63, 0x68, 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, 0x3b, 0x41, 0x68, 0x61, 0x72, 0x61, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x4f,
+0x66, 0x6c, 0x6f, 0x3b, 0x4f, 0x63, 0x68, 0x6f, 0x6b, 0x72, 0x69, 0x6b, 0x72, 0x69, 0x3b, 0x41, 0x62, 0x65, 0x69, 0x62,
+0x65, 0x65, 0x3b, 0x41, 0x67, 0x62, 0x65, 0x69, 0x6e, 0x61, 0x61, 0x3b, 0x4f, 0x74, 0x75, 0x6b, 0x77, 0x61, 0x64, 0x61,
+0x6e, 0x3b, 0x4d, 0x61, 0x61, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x6e, 0x79, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x3b, 0x47, 0x62,
+0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x6f, 0x6e, 0x3b, 0x41, 0x6c, 0x65, 0x6d, 0x6c, 0x65, 0x3b, 0x41, 0x66, 0x75, 0x61, 0x62,
+0x65, 0x65, 0x3b, 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, 0x3b, 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, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x70f, 0x71f,
+0x722, 0x20, 0x70f, 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, 0x70f, 0x72c, 0x72b, 0x20, 0x70f, 0x710, 0x3b, 0x70f, 0x72c, 0x72b, 0x20, 0x70f, 0x712, 0x3b, 0x70f, 0x71f, 0x722, 0x20,
+0x70f, 0x710, 0x3b, 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, 0x3b, 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, 0x3b, 0x120d, 0x3b, 0x12ab, 0x3b, 0x12ad, 0x3b, 0x134b, 0x3b, 0x12ad, 0x3b, 0x121d, 0x3b, 0x12b0,
+0x3b, 0x121b, 0x3b, 0x12eb, 0x3b, 0x1218, 0x3b, 0x121d, 0x3b, 0x1270, 0x3b, 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, 0x3b,
+0x1320, 0x3b, 0x12a8, 0x3b, 0x1218, 0x3b, 0x12a0, 0x3b, 0x130d, 0x3b, 0x1220, 0x3b, 0x1210, 0x3b, 0x1290, 0x3b, 0x12a8, 0x3b, 0x1320, 0x3b,
+0x1280, 0x3b, 0x1280, 0x3b, 0x57, 0x65, 0x79, 0x3b, 0x46, 0x61, 0x6e, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x6e, 0x3b,
+0x54, 0x75, 0x79, 0x3b, 0x54, 0x73, 0x6f, 0x3b, 0x54, 0x61, 0x66, 0x3b, 0x57, 0x61, 0x72, 0x3b, 0x4b, 0x75, 0x6e, 0x3b,
+0x42, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x53, 0x61, 0x75, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x57, 0x65, 0x79, 0x65,
+0x6e, 0x65, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x46, 0x61, 0x6e, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x74, 0x61,
+0x6b, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x6e, 0x67, 0x72, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x75,
+0x79, 0x6f, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x73, 0x6f, 0x79, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x66,
+0x61, 0x6b, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x57, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20,
+0x4b, 0x75, 0x6e, 0x6f, 0x62, 0x6f, 0x6b, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x42, 0x61, 0x6e, 0x73, 0x6f, 0x6b, 0x3b, 0x46,
+0x61, 0x69, 0x20, 0x4b, 0x6f, 0x6d, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x53, 0x61, 0x75, 0x6b, 0x3b, 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, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x44,
+0x79, 0x6f, 0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x42, 0x61, 0x27, 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, 0x3b, 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,
+0x3b, 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, 0x27, 0x61, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b,
+0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20, 0x42, 0x27, 0x61, 0x331, 0x68, 0x77, 0x61, 0x3b, 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, 0x3b, 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, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x50, 0x68, 0x61, 0x3b, 0x4c, 0x75, 0x68, 0x3b, 0x1e70, 0x68, 0x61, 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, 0x3b, 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, 0x3b, 0x44, 0x7a, 0x76, 0x3b, 0x44, 0x7a, 0x64, 0x3b, 0x54, 0x65, 0x64, 0x3b, 0x41,
+0x66, 0x254, 0x3b, 0x44, 0x61, 0x6d, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x53, 0x69, 0x61, 0x3b, 0x44, 0x65, 0x61, 0x3b, 0x41,
+0x6e, 0x79, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x41, 0x64, 0x65, 0x3b, 0x44, 0x7a, 0x6d, 0x3b, 0x44, 0x7a, 0x6f, 0x76, 0x65,
+0x3b, 0x44, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x54, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x41, 0x66, 0x254, 0x66, 0x69,
+0x25b, 0x3b, 0x44, 0x61, 0x6d, 0x61, 0x3b, 0x4d, 0x61, 0x73, 0x61, 0x3b, 0x53, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b,
+0x44, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x41, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x4b,
+0x65, 0x6c, 0x65, 0x3b, 0x41, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x6d,
+0x65, 0x3b, 0x44, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x41, 0x3b,
+0x4b, 0x3b, 0x41, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x45, 0x3b, 0x50, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x74, 0x3b, 0x41, 0x70, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x66, 0x3b, 0x44, 0x69, 0x73, 0x3b,
+0x4a, 0x61, 0x6e, 0x61, 0x77, 0x61, 0x72, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x65, 0x72, 0x77, 0x61, 0x72, 0x65, 0x3b, 0x4d,
+0x61, 0x74, 0x161, 0x68, 0x65, 0x3b, 0x41, 0x70, 0x6f, 0x72, 0x65, 0x6c, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75,
+0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x65, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x73, 0x65, 0x3b, 0x53, 0x65,
+0x74, 0x65, 0x6d, 0x65, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x6f, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x66, 0x65,
+0x6d, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x72, 0x65, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61,
+0x67, 0x65, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x76, 0x61, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x3b, 0x63, 0x75, 0x6f,
+0x14b, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x3b, 0x73, 0x75, 0x6f,
+0x69, 0x64, 0x6e, 0x65, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x3b, 0x67, 0x6f, 0x6c,
+0x67, 0x67, 0x6f, 0x74, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0x61, 0x3b, 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, 0x3b, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b,
+0x10c, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b, 0x44,
+0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44,
+0x3b, 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, 0x3b, 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, 0x3b, 0x43, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x3b, 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, 0x3b, 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, 0x3b, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 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, 0x3b, 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, 0x3b, 0x73,
+0x3b, 0x63, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a,
+0x3b, 0x62, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b,
+0x47, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b,
+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, 0x3b, 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, 0x27,
+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,
+0x3b, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54,
+0x3b, 0x54, 0x3b, 0x54, 0x3b, 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, 0x3b, 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,
+0x3b, 0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77,
+0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x3b, 0x4d, 0x66, 0x75,
+0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4d, 0x70, 0x61, 0x3b, 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,
+0x3b, 0x5a, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d,
+0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 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, 0x3b, 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, 0x3b, 0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d,
+0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b,
+0x2d5b, 0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x3b, 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, 0x3b, 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, 0x3b,
+0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b,
+0x4e, 0x3b, 0x44, 0x3b, 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, 0x4e, 0x3b,
+0x4b, 0x4b, 0x4d, 0x3b, 0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x53, 0x3b,
+0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 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, 0x3b, 0x7a, 0x61, 0x6e,
+0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6e, 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, 0x3b, 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, 0x3b, 0x5a, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 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, 0x13a4, 0x13cd, 0x3b, 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, 0x13a4, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7,
+0x3b, 0x13a0, 0x3b, 0x13d5, 0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a4, 0x3b, 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, 0x3b, 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, 0x3b, 0x7a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b,
+0x6d, 0x3b, 0x7a, 0x3b, 0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b,
+0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x75,
+0x76, 0x3b, 0x44, 0x69, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x76, 0x65, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b,
+0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x3b, 0x4b, 0x69,
+0x70, 0x3b, 0x49, 0x77, 0x61, 0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x57, 0x61, 0x6b, 0x3b, 0x52, 0x6f, 0x70, 0x3b, 0x4b, 0x6f,
+0x67, 0x3b, 0x42, 0x75, 0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x41, 0x65, 0x6e, 0x3b, 0x4d, 0x75,
+0x6c, 0x67, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x27, 0x61, 0x74, 0x79, 0x61, 0x74, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61,
+0x6d, 0x6f, 0x3b, 0x49, 0x77, 0x61, 0x74, 0x20, 0x6b, 0x75, 0x74, 0x3b, 0x4e, 0x67, 0x27, 0x65, 0x69, 0x79, 0x65, 0x74,
+0x3b, 0x57, 0x61, 0x6b, 0x69, 0x3b, 0x52, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x6b, 0x6f, 0x67, 0x61,
+0x67, 0x61, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75,
+0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x74, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e,
+0x65, 0x62, 0x6f, 0x20, 0x61, 0x65, 0x6e, 0x67, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x4e, 0x3b, 0x57,
+0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d,
+0x61, 0x72, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0xe4, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75,
+0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f,
+0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 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, 0xe4, 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, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76,
+0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4f, 0x72, 0x61, 0x72, 0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67, 0x27,
+0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67, 0x27, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f,
+0x64, 0x6f, 0x6b, 0x27, 0x6b, 0x69, 0x6e, 0x67, 0x27, 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, 0x3b, 0x52, 0x3b, 0x4d, 0x3b,
+0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50, 0x3b,
+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, 0x3b, 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, 0x3b, 0x17d, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x27,
+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, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e, 0x3b,
+0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 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, 0x3b, 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, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b,
+0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b
+};
+
+static const ushort standalone_months_data[] = {
+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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x51, 0x75, 0x6e, 0x78, 0x61, 0x20, 0x47, 0x61, 0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4e,
+0x61, 0x68, 0x61, 0x72, 0x73, 0x69, 0x20, 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, 0x73, 0x6f, 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, 0x3b, 0x51, 0x3b, 0x4e, 0x3b, 0x43, 0x3b,
+0x41, 0x3b, 0x43, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x4c, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x58, 0x3b, 0x4b, 0x3b, 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, 0x3b, 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, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x65, 0x73, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x3b,
+0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b,
+0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x54, 0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b,
+0x44, 0x68, 0x6a, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x51, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b,
+0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b,
+0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 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, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623,
+0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 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, 0x3b, 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, 0x646, 0x648,
+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,
+0x3b, 0x540, 0x576, 0x57e, 0x3b, 0x553, 0x57f, 0x57e, 0x3b, 0x544, 0x580, 0x57f, 0x3b, 0x531, 0x57a, 0x580, 0x3b, 0x544, 0x575, 0x57d,
+0x3b, 0x540, 0x576, 0x57d, 0x3b, 0x540, 0x56c, 0x57d, 0x3b, 0x555, 0x563, 0x57d, 0x3b, 0x54d, 0x565, 0x57a, 0x3b, 0x540, 0x578, 0x56f,
+0x3b, 0x546, 0x578, 0x575, 0x3b, 0x534, 0x565, 0x56f, 0x3b, 0x540, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b, 0x553, 0x565, 0x57f,
+0x580, 0x57e, 0x561, 0x580, 0x3b, 0x544, 0x561, 0x580, 0x57f, 0x3b, 0x531, 0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x544, 0x561, 0x575, 0x56b,
+0x57d, 0x3b, 0x540, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x540, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x555, 0x563, 0x578, 0x57d,
+0x57f, 0x578, 0x57d, 0x3b, 0x54d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x578, 0x56f, 0x57f, 0x565, 0x574,
+0x562, 0x565, 0x580, 0x3b, 0x546, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x534, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562,
+0x565, 0x580, 0x3b, 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, 0x3b, 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, 0x3b, 0x99c, 0x9c1,
+0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd,
+0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x3b, 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, 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, 0x3b,
+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, 0x3b, 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, 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, 0x44, 0x65,
+0x6b, 0x61, 0x62, 0x72, 0x3b, 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, 0x3b, 0x75, 0x72, 0x74, 0x3b, 0x6f, 0x74, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x69, 0x3b, 0x6d, 0x61,
+0x69, 0x3b, 0x65, 0x6b, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x3b, 0x61, 0x62, 0x75, 0x3b, 0x69, 0x72, 0x61, 0x3b, 0x75, 0x72,
+0x72, 0x3b, 0x61, 0x7a, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x3b, 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, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49,
+0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20,
+0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf25, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0x20, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf28, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0x20, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0x20, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf66,
+0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
+0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
+0xf5d, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf63, 0xf94,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
+0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d,
+0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0x44f, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b,
+0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b,
+0x438, 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, 0x3b, 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, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c,
+0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 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, 0x3b, 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, 0x3b, 0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b,
+0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430,
+0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x442, 0x440, 0x430, 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, 0x3b, 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, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 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, 0x3b, 0x441, 0x3b, 0x43b,
+0x3b, 0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441,
+0x3b, 0x17e1, 0x3b, 0x17e2, 0x3b, 0x17e3, 0x3b, 0x17e4, 0x3b, 0x17e5, 0x3b, 0x17e6, 0x3b, 0x17e7, 0x3b, 0x17e8, 0x3b, 0x17e9, 0x3b, 0x17e1,
+0x17e0, 0x3b, 0x17e1, 0x17e1, 0x3b, 0x17e1, 0x17e2, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b,
+0x1798, 0x17b7, 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, 0x3b, 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, 0x3b, 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,
+0x3b, 0x67, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f,
+0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x6c, 0x3b, 0xfa, 0x3b, 0x62, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x10d, 0x3b, 0x10d, 0x3b,
+0x73, 0x3b, 0x7a, 0x3b, 0x159, 0x3b, 0x6c, 0x3b, 0x70, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b,
+0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48,
+0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 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, 0x3b, 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, 0x3b, 0x58,
+0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x58,
+0x75, 0xf1, 0x3b, 0x58, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x75, 0x74, 0x3b, 0x4e,
+0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 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, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0,
+0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d,
+0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
+0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a,
+0x3b, 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, 0x3b, 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, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391,
+0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x3ca, 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, 0x3b, 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, 0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b,
+0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x3b, 0x6a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x69, 0x3b,
+0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c,
+0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 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, 0x3b, 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, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa1, 0xabf, 0xab8,
+0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5f3, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8,
+0x5e1, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5f3,
+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, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de,
+0x5e8, 0x5e1, 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, 0x3b, 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, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935,
+0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41,
+0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0xe1, 0x67,
+0xfa, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0xf3, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 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, 0x3b,
+0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0xe1, 0x3b, 0x73, 0x3b, 0x6f, 0x3b,
+0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b,
+0x49, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 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, 0x3b,
+0x47, 0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x4d, 0x61, 0x72,
+0x7a, 0x6f, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x4d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x47, 0x69, 0x75,
+0x67, 0x6e, 0x6f, 0x3b, 0x4c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65,
+0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xc9c, 0xca8,
+0xcb5, 0xcb0, 0xcc0, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcc0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b,
+0xc8e, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc6, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8,
+0x3b, 0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 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, 0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8e, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b,
+0xc9c, 0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x3b, 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, 0x442, 0x2e, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 0xe7,
+0x69, 0x6c, 0x3b, 0x73, 0x69, 0x62, 0x3b, 0x61, 0x64, 0x72, 0x3b, 0x6e, 0xee, 0x73, 0x3b, 0x67, 0x75, 0x6c, 0x3b, 0x68,
+0x65, 0x7a, 0x3b, 0x74, 0xee, 0x72, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b,
+0xe7, 0x69, 0x6c, 0x65, 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, 0x37, 0x3b, 0x38, 0x3b,
+0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0xe7, 0x3b, 0x73, 0x3b, 0x61, 0x3b, 0x6e, 0x3b, 0x67,
+0x3b, 0x68, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0xea1, 0x2e,
+0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb5, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 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,
+0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 0x73, 0x31, 0x3b, 0x73, 0x32, 0x3b, 0x73, 0x33, 0x3b, 0x73, 0x34, 0x3b, 0x73, 0x35, 0x3b, 0x73, 0x36, 0x3b,
+0x73, 0x37, 0x3b, 0x73, 0x38, 0x3b, 0x73, 0x39, 0x3b, 0x73, 0x31, 0x30, 0x3b, 0x73, 0x31, 0x31, 0x3b, 0x73, 0x31, 0x32,
+0x3b, 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, 0x3b, 0x53, 0x61, 0x75, 0x73, 0x2e, 0x3b, 0x56, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x3b, 0x42,
+0x61, 0x6c, 0x2e, 0x3b, 0x47, 0x65, 0x67, 0x2e, 0x3b, 0x42, 0x69, 0x72, 0x2e, 0x3b, 0x4c, 0x69, 0x65, 0x70, 0x2e, 0x3b,
+0x52, 0x75, 0x67, 0x70, 0x6a, 0x2e, 0x3b, 0x52, 0x75, 0x67, 0x73, 0x2e, 0x3b, 0x53, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x4c,
+0x61, 0x70, 0x6b, 0x72, 0x2e, 0x3b, 0x47, 0x72, 0x75, 0x6f, 0x64, 0x2e, 0x3b, 0x53, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b,
+0x56, 0x61, 0x73, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x4b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x64,
+0x69, 0x73, 0x3b, 0x47, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x3b, 0x42, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x4c,
+0x69, 0x65, 0x70, 0x61, 0x3b, 0x52, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x52, 0x75, 0x67, 0x73, 0x117,
+0x6a, 0x69, 0x73, 0x3b, 0x53, 0x70, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x4c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73,
+0x3b, 0x47, 0x72, 0x75, 0x6f, 0x64, 0x69, 0x73, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42,
+0x3b, 0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x3b, 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, 0x435, 0x43c, 0x2e, 0x3b, 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,
+0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e,
+0x3b, 0x43d, 0x3b, 0x434, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x73, 0x3b, 0x53, 0x65,
+0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 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, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b,
+0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e,
+0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 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, 0x3b, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e,
+0xd3e, 0xd30, 0xd4d, 0x200d, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd32, 0xd4d, 0x200d, 0x3b, 0xd2e, 0xd47,
+0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd06, 0xd17, 0xd38, 0xd4d, 0xd31, 0xd4d,
+0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f,
+0xd4b, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd30,
+0xd4d, 0x200d, 0x3b, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd47, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd1c,
+0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x120, 0x3b,
+0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 0x445, 0x443, 0x43b, 0x3b, 0x4af, 0x445, 0x44d,
+0x3b, 0x431, 0x430, 0x440, 0x3b, 0x442, 0x443, 0x443, 0x3b, 0x43b, 0x443, 0x443, 0x3b, 0x43c, 0x43e, 0x433, 0x3b, 0x43c, 0x43e, 0x440,
+0x3b, 0x445, 0x43e, 0x43d, 0x3b, 0x431, 0x438, 0x447, 0x3b, 0x442, 0x430, 0x445, 0x3b, 0x43d, 0x43e, 0x445, 0x3b, 0x433, 0x430, 0x445,
+0x3b, 0x425, 0x443, 0x43b, 0x433, 0x430, 0x43d, 0x430, 0x3b, 0x4ae, 0x445, 0x44d, 0x440, 0x3b, 0x411, 0x430, 0x440, 0x3b, 0x422, 0x443,
+0x443, 0x43b, 0x430, 0x439, 0x3b, 0x41b, 0x443, 0x443, 0x3b, 0x41c, 0x43e, 0x433, 0x43e, 0x439, 0x3b, 0x41c, 0x43e, 0x440, 0x44c, 0x3b,
+0x425, 0x43e, 0x43d, 0x44c, 0x3b, 0x411, 0x438, 0x447, 0x3b, 0x422, 0x430, 0x445, 0x438, 0x430, 0x3b, 0x41d, 0x43e, 0x445, 0x43e, 0x439,
+0x3b, 0x413, 0x430, 0x445, 0x430, 0x439, 0x3b, 0x91c, 0x928, 0x3b, 0x92b, 0x947, 0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b,
+0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x3b, 0x905, 0x917,
+0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f,
+0x938, 0x947, 0x3b, 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, 0x924, 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, 0x3b, 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, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940,
+0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x947, 0x932, 0x3b,
+0x92e, 0x908, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 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, 0x926, 0x93f, 0x938, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0xb1c, 0xb3e, 0xb28, 0xb41, 0xb06, 0xb30, 0xb40, 0x3b, 0xb2b, 0xb47, 0xb2c, 0xb4d, 0xb30, 0xb41, 0xb5f, 0xb3e, 0xb30, 0xb40, 0x3b, 0xb2e,
+0xb3e, 0xb30, 0xb4d, 0xb1a, 0xb4d, 0xb1a, 0x3b, 0xb05, 0xb2a, 0xb4d, 0xb30, 0xb47, 0xb32, 0x3b, 0xb2e, 0xb47, 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, 0x3b, 0xb1c, 0xb3e, 0x3b, 0xb2b, 0xb47, 0x3b, 0xb2e, 0xb3e, 0x3b, 0xb05, 0x3b,
+0xb2e, 0xb47, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb05, 0x3b, 0xb38, 0xb47, 0x3b, 0xb05, 0x3b, 0xb28, 0x3b, 0xb21, 0xb3f,
+0x3b, 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, 0x6cc, 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, 0x3b, 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, 0x6cc, 0x3b, 0x62c, 0x648,
+0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 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, 0x3b,
+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, 0x3b, 0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x6cc,
+0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641,
+0x648, 0x631, 0x6cc, 0x647, 0x654, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x640, 0x6cc,
+0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 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, 0x645, 0x3b, 0x62c, 0x3b,
+0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b,
+0x62f, 0x3b, 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, 0x3b, 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, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c,
+0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x3b, 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,
+0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x75, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a,
+0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72,
+0xe7, 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, 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, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b,
+0x73, 0x65, 0x74, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 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, 0x3b, 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, 0x3b, 0xa1c, 0x3b, 0xa2b, 0x3b, 0xa2e, 0xa3e, 0x3b,
+0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x46, 0x3b,
+0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b,
+0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4b,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b,
+0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x64, 0x69, 0x3b, 0x4b, 0x75, 0x6b, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x4b, 0x75, 0x62, 0x3b,
+0x43, 0x68, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b,
+0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x3b, 0x5a, 0x76, 0x69, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43,
+0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9,
+0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0x3b, 0xdb8, 0xdd0, 0xdba, 0x3b,
+0xda2, 0xdd6, 0xdb1, 0x3b, 0xda2, 0xdd6, 0xdbd, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0x3b, 0xd94, 0xd9a, 0x3b, 0xdb1,
+0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0,
+0xdcf, 0xdbb, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0,
+0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 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,
+0x3b, 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, 0xddc, 0x3b, 0xdaf, 0xdd9, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53,
+0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4c, 0x69, 0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53,
+0x69, 0x64, 0x3b, 0x53, 0x61, 0x67, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x4b, 0x49, 0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 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, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b,
+0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 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, 0x3b,
+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, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0xbc6, 0xbae, 0xbcd, 0xbaa, 0xbcd, 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, 0x3b, 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, 0x3b, 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, 0xc42, 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, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0x3b,
+0xc0e, 0x3b, 0xc2e, 0xc46, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b,
+0xc21, 0xc3f, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 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, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x3b, 0x1218, 0x130b, 0x1262, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x3b,
+0x130d, 0x1295, 0x1266, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x3b, 0x1325,
+0x1245, 0x121d, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 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, 0x27, 0x77, 0x3b, 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, 0x27, 0x77, 0x65, 0x6e, 0x64, 0x7a, 0x61, 0x6d, 0x68, 0x61, 0x6c, 0x61, 0x3b, 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, 0x3b, 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, 0x3b,
+0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x45, 0x3b, 0x45, 0x3b,
+0x4b, 0x3b, 0x41, 0x3b, 0x421, 0x456, 0x447, 0x3b, 0x41b, 0x44e, 0x442, 0x3b, 0x411, 0x435, 0x440, 0x3b, 0x41a, 0x432, 0x456, 0x3b,
+0x422, 0x440, 0x430, 0x3b, 0x427, 0x435, 0x440, 0x3b, 0x41b, 0x438, 0x43f, 0x3b, 0x421, 0x435, 0x440, 0x3b, 0x412, 0x435, 0x440, 0x3b,
+0x416, 0x43e, 0x432, 0x3b, 0x41b, 0x438, 0x441, 0x3b, 0x413, 0x440, 0x443, 0x3b, 0x421, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x41b,
+0x44e, 0x442, 0x438, 0x439, 0x3b, 0x411, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x41a, 0x432, 0x456, 0x442, 0x435, 0x43d,
+0x44c, 0x3b, 0x422, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x427, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x41b, 0x438,
+0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x412, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d,
+0x44c, 0x3b, 0x416, 0x43e, 0x432, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x41b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b, 0x413,
+0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b,
+0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648,
+0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x20, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648,
+0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 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, 0x3b, 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, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631,
+0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631, 0x3b, 0x645, 0x640, 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,
+0x3b, 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, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49, 0x79, 0x75, 0x6c, 0x3b,
+0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x3b, 0x44, 0x65, 0x6b,
+0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b,
+0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1ed9, 0x74, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x68, 0x61, 0x69, 0x3b,
+0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x62, 0x61, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x74, 0x1b0, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x6e, 0x103, 0x6d, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x73, 0xe1, 0x75, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x62, 0x1ea3, 0x79, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x74, 0xe1, 0x6d, 0x3b, 0x74, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x63, 0x68, 0xed, 0x6e, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x3b,
+0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x20, 0x6d, 0x1ed9, 0x74, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67,
+0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x20, 0x68, 0x61, 0x69, 0x3b, 0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 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, 0x3b, 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, 0x3b, 0x49, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b,
+0x4d, 0x3b, 0x47, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x3b, 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, 0x3b, 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, 0x3b, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x323, 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, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1e62, 0x1eb8, 0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0x4f, 0x1e62, 0xf9,
+0x20, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x1e62,
+0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0x4f, 0x1e62,
+0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0x4f, 0x1e62,
+0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x4f, 0x1e62, 0xf9,
+0x20, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x4f, 0x1e62, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x1e62, 0xf9,
+0x20, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x41,
+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, 0x3b, 0x75, 0x4a, 0x61, 0x6e, 0x75,
+0x77, 0x61, 0x72, 0x69, 0x3b, 0x75, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x75, 0x4d, 0x61, 0x73,
+0x68, 0x69, 0x3b, 0x75, 0x2d, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x75, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x75, 0x4a,
+0x75, 0x6e, 0x69, 0x3b, 0x75, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x75, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b,
+0x75, 0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x75, 0x2d, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61,
+0x3b, 0x75, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x75, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 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, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
+0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x4a, 0x75, 0x6e,
+0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 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, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 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, 0x2e, 0x48, 0x6f, 0x75, 0x6e, 0x65,
+0x79, 0x3b, 0x4d, 0x2e, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 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, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x57, 0x68, 0x65, 0x3b,
+0x4d, 0x65, 0x72, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x45, 0x66, 0x6e, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45,
+0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x4d, 0x79,
+0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x57, 0x68, 0x65, 0x76, 0x72, 0x65, 0x6c,
+0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x72, 0x74, 0x68, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c,
+0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x45, 0x66, 0x61, 0x6e, 0x3b, 0x4d, 0x79, 0x73,
+0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x4d, 0x79, 0x65, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x4d,
+0x79, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72,
+0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x44, 0x75, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68,
+0x75, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x913, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902,
+0x92c, 0x930, 0x3b, 0x913, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930,
+0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x41, 0x68, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x3b, 0x4f, 0x63, 0x68,
+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, 0x3b, 0x41, 0x68, 0x61,
+0x72, 0x61, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x6f, 0x3b, 0x4f, 0x63, 0x68, 0x6f, 0x6b, 0x72, 0x69, 0x6b,
+0x72, 0x69, 0x3b, 0x41, 0x62, 0x65, 0x69, 0x62, 0x65, 0x65, 0x3b, 0x41, 0x67, 0x62, 0x65, 0x69, 0x6e, 0x61, 0x61, 0x3b,
+0x4f, 0x74, 0x75, 0x6b, 0x77, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x61, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x6e, 0x79,
+0x61, 0x77, 0x61, 0x6c, 0x65, 0x3b, 0x47, 0x62, 0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x6f, 0x6e, 0x3b, 0x41, 0x6c, 0x65, 0x6d,
+0x6c, 0x65, 0x3b, 0x41, 0x66, 0x75, 0x61, 0x62, 0x65, 0x65, 0x3b, 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, 0x3b, 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, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b,
+0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x70f, 0x71f, 0x722, 0x20, 0x70f, 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, 0x70f, 0x72c, 0x72b, 0x20, 0x70f, 0x710, 0x3b, 0x70f, 0x72c, 0x72b,
+0x20, 0x70f, 0x712, 0x3b, 0x70f, 0x71f, 0x722, 0x20, 0x70f, 0x710, 0x3b, 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, 0x3b, 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, 0x3b, 0x120d, 0x3b, 0x12ab, 0x3b, 0x12ad,
+0x3b, 0x134b, 0x3b, 0x12ad, 0x3b, 0x121d, 0x3b, 0x12b0, 0x3b, 0x121b, 0x3b, 0x12eb, 0x3b, 0x1218, 0x3b, 0x121d, 0x3b, 0x1270, 0x3b, 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, 0x3b, 0x1320, 0x3b, 0x12a8, 0x3b, 0x1218, 0x3b, 0x12a0, 0x3b, 0x130d, 0x3b, 0x1220, 0x3b,
+0x1210, 0x3b, 0x1290, 0x3b, 0x12a8, 0x3b, 0x1320, 0x3b, 0x1280, 0x3b, 0x1280, 0x3b, 0x57, 0x65, 0x79, 0x3b, 0x46, 0x61, 0x6e, 0x3b,
+0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x75, 0x79, 0x3b, 0x54, 0x73, 0x6f, 0x3b, 0x54, 0x61, 0x66, 0x3b,
+0x57, 0x61, 0x72, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x42, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x53, 0x61, 0x75, 0x3b,
+0x46, 0x61, 0x69, 0x20, 0x57, 0x65, 0x79, 0x65, 0x6e, 0x65, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x46, 0x61, 0x6e, 0x69, 0x3b,
+0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x74, 0x61, 0x6b, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x6e, 0x67, 0x72,
+0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x75, 0x79, 0x6f, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x73, 0x6f, 0x79, 0x69,
+0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x66, 0x61, 0x6b, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x57, 0x61, 0x72, 0x61,
+0x63, 0x68, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4b, 0x75, 0x6e, 0x6f, 0x62, 0x6f, 0x6b, 0x3b, 0x46, 0x61, 0x69, 0x20,
+0x42, 0x61, 0x6e, 0x73, 0x6f, 0x6b, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4b, 0x6f, 0x6d, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x53,
+0x61, 0x75, 0x6b, 0x3b, 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, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x44, 0x79, 0x6f, 0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x42, 0x61, 0x27, 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, 0x3b, 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, 0x3b, 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, 0x27,
+0x61, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20, 0x42,
+0x27, 0x61, 0x331, 0x68, 0x77, 0x61, 0x3b, 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, 0x3b, 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, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x50, 0x68, 0x61, 0x3b,
+0x4c, 0x75, 0x68, 0x3b, 0x1e70, 0x68, 0x61, 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, 0x3b, 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, 0x3b, 0x44, 0x7a, 0x76, 0x3b, 0x44,
+0x7a, 0x64, 0x3b, 0x54, 0x65, 0x64, 0x3b, 0x41, 0x66, 0x254, 0x3b, 0x44, 0x61, 0x6d, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x53,
+0x69, 0x61, 0x3b, 0x44, 0x65, 0x61, 0x3b, 0x41, 0x6e, 0x79, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x41, 0x64, 0x65, 0x3b, 0x44,
+0x7a, 0x6d, 0x3b, 0x44, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x54, 0x65, 0x64, 0x6f,
+0x78, 0x65, 0x3b, 0x41, 0x66, 0x254, 0x66, 0x69, 0x25b, 0x3b, 0x44, 0x61, 0x6d, 0x61, 0x3b, 0x4d, 0x61, 0x73, 0x61, 0x3b,
+0x53, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x44, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x41,
+0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x4b, 0x65, 0x6c, 0x65, 0x3b, 0x41, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70,
+0x254, 0x78, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x6d, 0x65, 0x3b, 0x44, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x44, 0x3b,
+0x4d, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x74, 0x3b,
+0x41, 0x70, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b,
+0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x66, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x61,
+0x77, 0x61, 0x72, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x65, 0x72, 0x77, 0x61, 0x72, 0x65, 0x3b, 0x4d, 0x61, 0x74, 0x161, 0x68,
+0x65, 0x3b, 0x41, 0x70, 0x6f, 0x72, 0x65, 0x6c, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x65, 0x3b, 0x4a,
+0x75, 0x6c, 0x61, 0x65, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x73, 0x65, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x65,
+0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x6f, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x66, 0x65, 0x6d, 0x65, 0x72, 0x65,
+0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x72, 0x65, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x3b, 0x67,
+0x75, 0x6f, 0x76, 0x76, 0x61, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x6f, 0x3b, 0x6d,
+0x69, 0x65, 0x73, 0x73, 0x65, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x64, 0x6e, 0x65,
+0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f, 0x74,
+0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0x61, 0x3b, 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, 0x3b,
+0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c, 0x3b, 0x47, 0x3b,
+0x53, 0x3b, 0x4a, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x53,
+0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x43, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b,
+0x57, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 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, 0x3b, 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, 0x3b, 0x73, 0x3b, 0x63, 0x3b, 0x6d,
+0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b, 0x3b,
+0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x27, 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, 0x3b, 0x4f, 0x3b, 0x57,
+0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54,
+0x3b, 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, 0x3b, 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, 0x3b, 0x5a, 0x69, 0x62,
+0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77, 0x3b, 0x4e, 0x68, 0x6c,
+0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65,
+0x3b, 0x4d, 0x70, 0x61, 0x3b, 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, 0x3b, 0x5a, 0x3b, 0x4e,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d,
+0x3b, 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, 0x3b,
+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, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 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, 0x3b, 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, 0x3b, 0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79,
+0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b,
+0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b, 0x2d3d, 0x3b,
+0x2d4f, 0x3b, 0x2d37, 0x3b, 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, 0x3b, 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, 0x3b, 0x59, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+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, 0x4e, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b,
+0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 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, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62,
+0x3b, 0x6e, 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, 0x3b,
+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, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47,
+0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 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, 0x13a4, 0x13cd, 0x3b, 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, 0x13a4, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5,
+0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a4, 0x3b, 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, 0x3b,
+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, 0x3b, 0x7a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b,
+0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69,
+0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x76, 0x65, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
+0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x3b, 0x4b, 0x69, 0x70, 0x3b, 0x49, 0x77,
+0x61, 0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x57, 0x61, 0x6b, 0x3b, 0x52, 0x6f, 0x70, 0x3b, 0x4b, 0x6f, 0x67, 0x3b, 0x42, 0x75,
+0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x41, 0x65, 0x6e, 0x3b, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c,
+0x3b, 0x4e, 0x67, 0x27, 0x61, 0x74, 0x79, 0x61, 0x74, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x6d, 0x6f, 0x3b, 0x49,
+0x77, 0x61, 0x74, 0x20, 0x6b, 0x75, 0x74, 0x3b, 0x4e, 0x67, 0x27, 0x65, 0x69, 0x79, 0x65, 0x74, 0x3b, 0x57, 0x61, 0x6b,
+0x69, 0x3b, 0x52, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x6b, 0x6f, 0x67, 0x61, 0x67, 0x61, 0x3b, 0x42,
+0x75, 0x72, 0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x6e, 0x64, 0x65, 0x20,
+0x6e, 0x65, 0x74, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20,
+0x61, 0x65, 0x6e, 0x67, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x4e, 0x3b, 0x57, 0x3b, 0x52, 0x3b, 0x4b,
+0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 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, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b,
+0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0xe4, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f,
+0x75, 0x67, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44,
+0x65, 0x7a, 0x2e, 0x3b, 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, 0xe4, 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, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4f, 0x72,
+0x61, 0x72, 0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67, 0x27, 0x3b, 0x4f, 0x64, 0x75,
+0x6e, 0x67, 0x27, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f, 0x64, 0x6f, 0x6b, 0x27,
+0x6b, 0x69, 0x6e, 0x67, 0x27, 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, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50, 0x3b, 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, 0x3b, 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, 0x3b, 0x17d, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b, 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, 0x27, 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, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b,
+0x42, 0x3b, 0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 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, 0x3b,
+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, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b,
+0x194, 0x3b, 0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 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, 0x3b
+};
+
+static const ushort days_data[] = {
+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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x37,
+0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x41, 0x3b, 0x45, 0x3b,
+0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x69, 0x3b, 0x57,
+0x6f, 0x3b, 0x44, 0x6f, 0x3b, 0x56, 0x72, 0x3b, 0x53, 0x61, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56,
+0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x44, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50,
+0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x12a5, 0x3b,
+0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1245, 0x3b, 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, 0x3b, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x625, 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, 0x3b, 0x62d, 0x3b, 0x646, 0x3b,
+0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x3b, 0x623, 0x62d, 0x62f, 0x3b, 0x625, 0x62b, 0x646, 0x64a, 0x646, 0x3b,
+0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x62c,
+0x645, 0x639, 0x629, 0x3b, 0x633, 0x628, 0x62a, 0x3b, 0x53f, 0x56b, 0x580, 0x3b, 0x535, 0x580, 0x56f, 0x3b, 0x535, 0x580, 0x584, 0x3b,
+0x549, 0x578, 0x580, 0x3b, 0x540, 0x576, 0x563, 0x3b, 0x548, 0x582, 0x580, 0x3b, 0x547, 0x561, 0x562, 0x3b, 0x53f, 0x56b, 0x580, 0x561,
+0x56f, 0x56b, 0x3b, 0x535, 0x580, 0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x535, 0x580, 0x565, 0x584, 0x577, 0x561,
+0x562, 0x569, 0x56b, 0x3b, 0x549, 0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x540, 0x56b, 0x576, 0x563, 0x577,
+0x561, 0x562, 0x569, 0x56b, 0x3b, 0x548, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x547, 0x561, 0x562, 0x561, 0x569, 0x3b, 0x31, 0x3b,
+0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x9f0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b,
+0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6,
+0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 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, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, 0x3b,
+0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b,
+0xc7, 0x2e, 0x3b, 0x43, 0x2e, 0x41, 0x2e, 0x3b, 0x43, 0x3b, 0x15e, 0x2e, 0x3b, 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, 0x3b,
+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, 0x3b, 0x69, 0x67, 0x3b, 0x61, 0x6c, 0x3b, 0x61, 0x73, 0x3b, 0x61, 0x7a, 0x3b, 0x6f,
+0x67, 0x3b, 0x6f, 0x72, 0x3b, 0x6c, 0x72, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0,
+0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1,
+0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6, 0x3b, 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, 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, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58,
+0xf0b, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b,
+0x441, 0x431, 0x3b, 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, 0x3b, 0x43d, 0x3b,
+0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x1014, 0x103d, 0x1031, 0x3b, 0x101c, 0x102c, 0x3b, 0x1002,
+0x102b, 0x3b, 0x101f, 0x1030, 0x1038, 0x3b, 0x1010, 0x1031, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c, 0x3b, 0x1014, 0x1031, 0x3b, 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, 0x3b, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000,
+0x3b, 0x101e, 0x3b, 0x1005, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b,
+0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 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, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x17a2, 0x17b6, 0x3b, 0x1785,
+0x3b, 0x17a2, 0x3b, 0x1796, 0x17bb, 0x3b, 0x1796, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17bb, 0x3b, 0x179f, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x17a2,
+0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x200b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x1790, 0x17d2,
+0x1784, 0x17c3, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1790, 0x17d2, 0x1784,
+0x17c3, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x179f, 0x17bb, 0x1780, 0x17d2,
+0x179a, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x64, 0x67, 0x3b, 0x64, 0x6c, 0x3b, 0x64, 0x74, 0x3b,
+0x64, 0x63, 0x3b, 0x64, 0x6a, 0x3b, 0x64, 0x76, 0x3b, 0x64, 0x73, 0x3b, 0x44, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65,
+0x3b, 0x44, 0x69, 0x6c, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x44, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x44, 0x69, 0x6d,
+0x65, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x44, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x44, 0x69, 0x76, 0x65, 0x6e, 0x64, 0x72,
+0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65, 0x3b, 0x67, 0x3b, 0x6c, 0x3b, 0x74, 0x3b, 0x63, 0x3b,
+0x6a, 0x3b, 0x76, 0x3b, 0x73, 0x3b, 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, 0x3b, 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, 0x3b, 0x47, 0x3b, 0x6c, 0x3b, 0x54, 0x3b,
+0x43, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x5468, 0x65e5, 0x3b, 0x5468, 0x4e00, 0x3b, 0x5468, 0x4e8c, 0x3b, 0x5468, 0x4e09, 0x3b,
+0x5468, 0x56db, 0x3b, 0x5468, 0x4e94, 0x3b, 0x5468, 0x516d, 0x3b, 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, 0x3b, 0x65e5, 0x3b, 0x4e00,
+0x3b, 0x4e8c, 0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94, 0x3b, 0x516d, 0x3b, 0x9031, 0x65e5, 0x3b, 0x9031, 0x4e00, 0x3b, 0x9031, 0x4e8c, 0x3b,
+0x9031, 0x4e09, 0x3b, 0x9031, 0x56db, 0x3b, 0x9031, 0x4e94, 0x3b, 0x9031, 0x516d, 0x3b, 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, 0x3b,
+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, 0x3b, 0x6e, 0x3b,
+0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74,
+0x3b, 0x73, 0x74, 0x3b, 0x10d, 0x74, 0x3b, 0x70, 0xe1, 0x3b, 0x73, 0x6f, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0xda, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54,
+0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x7a, 0x6f, 0x3b, 0x6d, 0x61, 0x3b, 0x64, 0x69, 0x3b, 0x77, 0x6f,
+0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b, 0x7a, 0x61, 0x3b, 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, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56,
+0x3b, 0x5a, 0x3b, 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, 0x3b, 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, 0x3b, 0xd801, 0xdc1d, 0x3b,
+0xd801, 0xdc23, 0x3b, 0xd801, 0xdc13, 0x3b, 0xd801, 0xdc0e, 0x3b, 0xd801, 0xdc1b, 0x3b, 0xd801, 0xdc19, 0x3b, 0xd801, 0xdc1d, 0x3b, 0x50, 0x3b,
+0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d,
+0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b,
+0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x3b, 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, 0x3b, 0x53,
+0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 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, 0x3b, 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, 0x3b, 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,
+0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c,
+0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0xe9, 0x72, 0x3b, 0x58, 0x6f, 0x76, 0x3b, 0x56, 0x65, 0x6e, 0x3b, 0x53,
+0xe1, 0x62, 0x3b, 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, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b,
+0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x10d9, 0x3b, 0x10dd, 0x3b,
+0x10e1, 0x3b, 0x10dd, 0x3b, 0x10ee, 0x3b, 0x10de, 0x3b, 0x10e8, 0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x44, 0x69, 0x3b, 0x4d,
+0x69, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x44,
+0x3b, 0x46, 0x3b, 0x53, 0x3b, 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, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x6f, 0x6e,
+0x3b, 0x44, 0x69, 0x65, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6d,
+0x3b, 0x39a, 0x3c5, 0x3c1, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1, 0x3b9, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3b, 0x3a0, 0x3b5, 0x3bc,
+0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b, 0x3a3, 0x3b1, 0x3b2, 0x3b, 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, 0x3b, 0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4, 0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b, 0x3a3, 0x3b, 0x73, 0x61,
+0x62, 0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x69, 0x6e, 0x3b, 0x73, 0x69, 0x73, 0x3b, 0x74, 0x61,
+0x6c, 0x3b, 0x61, 0x72, 0x66, 0x3b, 0x73, 0x61, 0x62, 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, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82, 0x3b, 0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b, 0xab6, 0xac1, 0x3b,
+0xab6, 0x3b, 0x4c, 0x68, 0x3b, 0x4c, 0x69, 0x3b, 0x54, 0x61, 0x3b, 0x4c, 0x72, 0x3b, 0x41, 0x6c, 0x3b, 0x4a, 0x75, 0x3b,
+0x41, 0x73, 0x3b, 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, 0x27, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x54,
+0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 0x5d0, 0x3b, 0x5d1, 0x3b, 0x5d2, 0x3b, 0x5d3, 0x3b, 0x5d4, 0x3b, 0x5d5, 0x3b,
+0x5e9, 0x3b, 0x930, 0x935, 0x93f, 0x2e, 0x3b, 0x938, 0x94b, 0x92e, 0x2e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x2e, 0x3b, 0x92c, 0x941,
+0x927, 0x2e, 0x3b, 0x92c, 0x943, 0x939, 0x2e, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x2e, 0x3b, 0x936, 0x928, 0x93f, 0x2e, 0x3b,
+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, 0x92c, 0x943, 0x939, 0x938, 0x94d, 0x92a, 0x924, 0x93f, 0x935, 0x93e, 0x930,
+0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938,
+0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0x56, 0x3b, 0x48, 0x3b,
+0x4b, 0x3b, 0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b, 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, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b, 0x50,
+0x3b, 0x53, 0x7a, 0x3b, 0x73, 0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0xfe, 0x72, 0x69, 0x3b, 0x6d, 0x69, 0xf0, 0x3b,
+0x66, 0x69, 0x6d, 0x3b, 0x66, 0xf6, 0x73, 0x3b, 0x6c, 0x61, 0x75, 0x3b, 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, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0xfe, 0x3b, 0x6d,
+0x3b, 0x66, 0x3b, 0x66, 0x3b, 0x6c, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c,
+0x3b, 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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b,
+0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x44, 0x3b,
+0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 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, 0x3b,
+0x44, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x4d, 0x61, 0x72, 0x74,
+0x65, 0x64, 0xec, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x47, 0x69, 0x6f, 0x76, 0x65, 0x64,
+0xec, 0x3b, 0x56, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x44, 0x3b, 0x4c,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 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, 0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b,
+0x571f, 0x3b, 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, 0x3b, 0xcb0, 0x2e, 0x3b, 0xcb8, 0xccb, 0x2e, 0x3b, 0xcae, 0xc82, 0x2e,
+0x3b, 0xcac, 0xcc1, 0x2e, 0x3b, 0xc97, 0xcc1, 0x2e, 0x3b, 0xcb6, 0xcc1, 0x2e, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x2e, 0x3b, 0xcb0, 0xcb5,
+0xcbf, 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, 0x3b, 0xcb0, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82, 0x3b, 0xcac,
+0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x3b, 0x436, 0x441, 0x2e, 0x3b, 0x434, 0x441, 0x2e, 0x3b, 0x441, 0x441,
+0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x431, 0x441, 0x2e, 0x3b, 0x436, 0x43c, 0x2e, 0x3b, 0x441, 0x4bb, 0x2e, 0x3b, 0x436, 0x435,
+0x43a, 0x441, 0x435, 0x43d, 0x456, 0x3b, 0x434, 0x443, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435,
+0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456,
+0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 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, 0x3b, 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, 0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9,
+0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 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, 0x3b, 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, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633,
+0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x79, 0x15f, 0x3b, 0x64, 0x15f, 0x3b, 0x73, 0x15f, 0x3b, 0xe7, 0x15f,
+0x3b, 0x70, 0x15f, 0x3b, 0xee, 0x6e, 0x3b, 0x15f, 0x3b, 0x79, 0x65, 0x6b, 0x15f, 0x65, 0x6d, 0x3b, 0x64, 0x75, 0x15f, 0x65,
+0x6d, 0x3b, 0x15f, 0xea, 0x3b, 0xe7, 0x61, 0x72, 0x15f, 0x65, 0x6d, 0x3b, 0x70, 0xea, 0x6e, 0x63, 0x15f, 0x65, 0x6d, 0x3b,
+0xee, 0x6e, 0x3b, 0x15f, 0x65, 0x6d, 0xee, 0x3b, 0x79, 0x3b, 0x64, 0x3b, 0x73, 0x3b, 0xe7, 0x3b, 0x70, 0x3b, 0xee, 0x3b,
+0x15f, 0x3b, 0xead, 0xeb2, 0x2e, 0x3b, 0xe88, 0x2e, 0x3b, 0xead, 0x2e, 0x3b, 0xe9e, 0x2e, 0x3b, 0xe9e, 0xeab, 0x2e, 0x3b, 0xeaa,
+0xe81, 0x2e, 0x3b, 0xeaa, 0x2e, 0x3b, 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, 0x3b, 0x53, 0x76, 0x3b, 0x50, 0x72, 0x3b, 0x4f, 0x74, 0x3b, 0x54, 0x72, 0x3b, 0x43, 0x65, 0x3b, 0x50, 0x6b,
+0x3b, 0x53, 0x65, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x50, 0x3b,
+0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x6d, 0x31, 0x3b, 0x6d, 0x32, 0x3b,
+0x6d, 0x33, 0x3b, 0x6d, 0x34, 0x3b, 0x6d, 0x35, 0x3b, 0x6d, 0x70, 0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b,
+0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x6f, 0x73, 0xf3, 0x3b, 0x6d, 0x6f, 0x6b,
+0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254,
+0x20, 0x79, 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, 0x3b, 0x53, 0x6b, 0x3b, 0x50, 0x69, 0x3b, 0x41, 0x3b, 0x54,
+0x3b, 0x4b, 0x3b, 0x50, 0x65, 0x3b, 0x160, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x50,
+0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x3b, 0x53, 0x6b, 0x3b, 0x50, 0x72, 0x3b, 0x41, 0x6e, 0x3b,
+0x54, 0x72, 0x3b, 0x4b, 0x74, 0x3b, 0x50, 0x6e, 0x3b, 0x160, 0x74, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x54, 0x3b,
+0x41, 0x3b, 0x41, 0x3b, 0x5a, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 0xd1e,
+0xd3e, 0xd2f, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd4d, 0x200d, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35,
+0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd4d, 0x200d, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33,
+0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15,
+0xd33, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28,
+0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33,
+0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24,
+0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 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, 0x3b, 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, 0x3b, 0x126, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x126, 0x3b, 0x120,
+0x3b, 0x53, 0x3b, 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, 0x48, 0x101, 0x74, 0x61, 0x72, 0x65, 0x69, 0x3b, 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, 0x3b, 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, 0x3b, 0x41d, 0x44f, 0x3b, 0x414,
+0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b, 0x411, 0x44f, 0x3b, 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, 0x3b,
+0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x93f,
+0x939, 0x940, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 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, 0x940, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b,
+0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b, 0x96b, 0x3b, 0x96c, 0x3b, 0x96d,
+0x3b, 0x906, 0x907, 0x924, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932,
+0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x940, 0x935, 0x93e, 0x930, 0x3b, 0x936,
+0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d,
+0x61, 0x2e, 0x3b, 0x74, 0x69, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c,
+0xf8, 0x2e, 0x3b, 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, 0x3b, 0x44, 0x69,
+0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b, 0x64, 0x69, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0xe7, 0x3b,
+0x64, 0x69, 0x6d, 0xe8, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6a, 0xf2, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0xe8,
+0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65, 0x3b, 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, 0x3b, 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, 0x3b, 0xb30, 0x3b, 0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x3b,
+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, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c,
+0x3b, 0x634, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x50, 0x3b,
+0x57, 0x3b, 0x15a, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65,
+0x72, 0x3b, 0x71, 0x75, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x3b, 0x73, 0x65, 0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x44, 0x6f,
+0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
+0x54, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x51, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66,
+0x65, 0x69, 0x72, 0x61, 0x3b, 0x51, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x53, 0x65,
+0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x53,
+0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 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, 0x3b, 0xa10, 0xa24, 0x2e, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x2e, 0x3b, 0xa2e,
+0xa70, 0xa17, 0xa32, 0x2e, 0x3b, 0xa2c, 0xa41, 0xa27, 0x2e, 0x3b, 0xa35, 0xa40, 0xa30, 0x2e, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa15, 0xa30,
+0x2e, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa40, 0x2e, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30,
+0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 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, 0xa40, 0xa1a, 0xa30, 0xa35,
+0xa3e, 0xa30, 0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, 0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c,
+0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x3b, 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, 0x3b, 0x64, 0x75, 0x3b, 0x67, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b,
+0x76, 0x65, 0x3b, 0x73, 0x6f, 0x3b, 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, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x75, 0x3b, 0x4c,
+0x75, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x6f, 0x3b, 0x56, 0x69, 0x3b, 0x53, 0xe2, 0x3b, 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, 0x3b, 0x412, 0x441, 0x3b, 0x41f, 0x43d, 0x3b, 0x412, 0x442, 0x3b, 0x421, 0x440, 0x3b, 0x427, 0x442, 0x3b,
+0x41f, 0x442, 0x3b, 0x421, 0x431, 0x3b, 0x412, 0x43e, 0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x41f, 0x43e,
+0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x3b, 0x412, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x421, 0x440,
+0x435, 0x434, 0x430, 0x3b, 0x427, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0x3b, 0x41f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b,
+0x421, 0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x412, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b,
+0x421, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b,
+0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x59, 0x3b, 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, 0x3b,
+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, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b,
+0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 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, 0x3b, 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,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x54, 0x73,
+0x68, 0x3b, 0x4d, 0x6f, 0x73, 0x3b, 0x42, 0x65, 0x64, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, 0x54, 0x6c, 0x61,
+0x3b, 0x4d, 0x61, 0x74, 0x3b, 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, 0x3b, 0x53, 0x76, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x69,
+0x70, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x3b, 0x4d, 0x75, 0x67,
+0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b,
+0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0xd89, 0xdbb, 0xdd2, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0x3b, 0xd85, 0xd9f,
+0x3b, 0xdb6, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0x3b,
+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, 0x3b, 0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3, 0xdd2, 0x3b, 0xdc3, 0xdd9,
+0x3b, 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, 0x3b, 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, 0x3b, 0x6e, 0x65, 0x3b, 0x70,
+0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b, 0x70, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x160, 0x3b, 0x50,
+0x3b, 0x53, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d,
+0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 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, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x41, 0x78, 0x64,
+0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x69, 0x6d,
+0x3b, 0x53, 0x61, 0x62, 0x3b, 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, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b,
+0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b, 0x41,
+0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x3b, 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, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x41, 0x3b, 0x49,
+0x3b, 0x31, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b,
+0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0xc06, 0x3b, 0xc38, 0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2d, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36,
+0xc41, 0x3b, 0xc36, 0x3b, 0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e,
+0x3b, 0xe28, 0x2e, 0x3b, 0xe2a, 0x2e, 0x3b, 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, 0x3b, 0xe2d, 0x3b, 0xe08, 0x3b, 0xe2d,
+0x3b, 0xe1e, 0x3b, 0xe1e, 0x3b, 0xe28, 0x3b, 0xe2a, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf67, 0xfb3, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62,
+0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 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, 0xf67, 0xfb3, 0xf42, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xf44,
+0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf49, 0xf72, 0x3b, 0xf5f, 0xfb3,
+0x3b, 0xf58, 0xf72, 0x3b, 0xf67, 0xfb3, 0x3b, 0xf55, 0xf74, 0x3b, 0xf66, 0x3b, 0xf66, 0xfa4, 0xf7a, 0x3b, 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, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x1228, 0x3b, 0x1283, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d,
+0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x54, 0x3b, 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, 0x3b, 0x53, 0x6f,
+0x6e, 0x74, 0x6f, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0xc7, 0x3b,
+0x50, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x41d, 0x434, 0x3b, 0x41f, 0x43d, 0x3b, 0x412, 0x442, 0x3b, 0x421, 0x440, 0x3b, 0x427, 0x442,
+0x3b, 0x41f, 0x442, 0x3b, 0x421, 0x431, 0x3b, 0x41d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x41f, 0x43e, 0x43d, 0x435, 0x434, 0x456,
+0x43b, 0x43e, 0x43a, 0x3b, 0x412, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x421, 0x435, 0x440, 0x435, 0x434, 0x430, 0x3b,
+0x427, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x41f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f, 0x3b, 0x421, 0x443, 0x431, 0x43e,
+0x442, 0x430, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, 0x627, 0x62a, 0x648,
+0x627, 0x631, 0x3b, 0x67e, 0x64a, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x62f, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x631,
+0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b, 0x627, 0x3b, 0x67e, 0x3b, 0x645, 0x3b, 0x628,
+0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x6c1, 0x3b, 0x42f, 0x43a, 0x448, 0x3b, 0x414, 0x443, 0x448, 0x3b, 0x421, 0x435, 0x448, 0x3b, 0x427,
+0x43e, 0x440, 0x3b, 0x41f, 0x430, 0x439, 0x3b, 0x416, 0x443, 0x43c, 0x3b, 0x428, 0x430, 0x43d, 0x3b, 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, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b,
+0x428, 0x3b, 0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b, 0x67e, 0x2e, 0x3b, 0x62c, 0x2e, 0x3b,
+0x634, 0x2e, 0x3b, 0x59, 0x61, 0x6b, 0x73, 0x68, 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, 0x3b, 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, 0x3b, 0x59, 0x3b,
+0x44, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 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, 0x3b, 0x43, 0x68, 0x1ee7, 0x20, 0x6e, 0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x68, 0x61,
+0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x62, 0x61, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x74, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20,
+0x6e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x73, 0xe1, 0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x62, 0x1ea3, 0x79, 0x3b,
+0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b, 0x54, 0x35, 0x3b, 0x54, 0x36, 0x3b, 0x54, 0x37,
+0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 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,
+0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x4c, 0x77,
+0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b,
+0x75, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48,
+0x3b, 0x4d, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x65, 0x64, 0x3b, 0x50, 0x6f, 0x6e, 0x3b, 0x55, 0x74, 0x6f, 0x3b, 0x53, 0x72, 0x69, 0x3b, 0x10c, 0x65,
+0x74, 0x3b, 0x50, 0x65, 0x74, 0x3b, 0x53, 0x75, 0x62, 0x3b, 0x4e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x50,
+0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x55, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x53, 0x72,
+0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10c, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x50, 0x65, 0x74, 0x61, 0x6b,
+0x3b, 0x53, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x44, 0x65, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x65, 0x20, 0x4c, 0x75, 0x6e, 0x3b, 0x44, 0x65, 0x20,
+0x4d, 0x65, 0x72, 0x74, 0x68, 0x3b, 0x44, 0x65, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x20, 0x59,
+0x6f, 0x77, 0x3b, 0x44, 0x65, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x20, 0x53, 0x61, 0x64, 0x6f,
+0x72, 0x6e, 0x3b, 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, 0x3b, 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, 0x3b,
+0x4b, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x906, 0x926, 0x93f, 0x924, 0x94d, 0x92f,
+0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 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, 0x935, 0x93e,
+0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x48, 0x6f, 0x3b, 0x44, 0x7a, 0x75, 0x3b, 0x44, 0x7a, 0x66, 0x3b,
+0x53, 0x68, 0x6f, 0x3b, 0x53, 0x6f, 0x6f, 0x3b, 0x53, 0x6f, 0x68, 0x3b, 0x48, 0x6f, 0x3b, 0x48, 0x6f, 0x67, 0x62, 0x61,
+0x61, 0x3b, 0x44, 0x7a, 0x75, 0x3b, 0x44, 0x7a, 0x75, 0x66, 0x6f, 0x3b, 0x53, 0x68, 0x6f, 0x3b, 0x53, 0x6f, 0x6f, 0x3b,
+0x53, 0x6f, 0x68, 0x61, 0x61, 0x3b, 0x48, 0x6f, 0x3b, 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, 0x3b, 0x4d, 0x62,
+0x1ecd, 0x73, 0x1ecb, 0x20, 0x1ee4, 0x6b, 0x61, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x59, 0x3b, 0x57,
+0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b,
+0x1230, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1208, 0x3b, 0x12a3, 0x3b, 0x12a3, 0x3b, 0x1230, 0x3b, 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, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x122b, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x4c, 0x61, 0x68,
+0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x47, 0x62, 0x61, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x59, 0x65, 0x69, 0x3b, 0x4b, 0x6f, 0x79,
+0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x4a, 0x65, 0x2d, 0x4b, 0x75, 0x62, 0x61, 0x63,
+0x68, 0x61, 0x3b, 0x4a, 0x65, 0x2d, 0x47, 0x62, 0x61, 0x69, 0x3b, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x74, 0x69, 0x3b, 0x4a,
+0x65, 0x2d, 0x59, 0x65, 0x69, 0x3b, 0x4a, 0x65, 0x2d, 0x4b, 0x6f, 0x79, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x69, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b,
+0x53, 0x3b, 0x4d, 0x3b, 0x52, 0x3b, 0x48, 0x3b, 0x41, 0x3b, 0x51, 0x3b, 0x59, 0x6f, 0x6b, 0x3b, 0x54, 0x75, 0x6e, 0x67,
+0x3b, 0x54, 0x2e, 0x20, 0x54, 0x75, 0x6e, 0x67, 0x3b, 0x54, 0x73, 0x61, 0x6e, 0x3b, 0x4e, 0x61, 0x73, 0x3b, 0x4e, 0x61,
+0x74, 0x3b, 0x43, 0x68, 0x69, 0x72, 0x3b, 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, 0x3b, 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,
+0x3b, 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, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1273, 0x3b, 0x12a3, 0x3b, 0x12a8, 0x3b, 0x1305, 0x3b, 0x1230, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x254, 0x73, 0x20, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x3b, 0x42, 0x72, 0x61, 0x3b, 0x4b,
+0x75, 0x256, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x256, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, 0x254, 0x73, 0x69, 0x256,
+0x61, 0x3b, 0x44, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x42, 0x72, 0x61, 0x256, 0x61, 0x3b, 0x4b, 0x75, 0x256, 0x61, 0x3b, 0x59,
+0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b, 0x46, 0x69, 0x256, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x6c, 0x65, 0x256, 0x61, 0x3b, 0x4b,
+0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4b, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 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, 0x3b,
+0x12c8, 0x3b, 0x1233, 0x3b, 0x121b, 0x3b, 0x12a0, 0x3b, 0x1203, 0x3b, 0x12a0, 0x3b, 0x1244, 0x3b, 0x4c, 0x50, 0x3b, 0x50, 0x31, 0x3b,
+0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+0x4c, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x42, 0x3b, 0x53, 0x3b, 0x4c, 0x69, 0x6e, 0x3b, 0x4c, 0x75,
+0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x79, 0x65, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x79, 0x65, 0x3b, 0x53, 0x61,
+0x62, 0x3b, 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, 0x3b, 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, 0x3b, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f,
+0xa44d, 0x3b, 0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0x3b, 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, 0x3b, 0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315, 0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x6f, 0x73, 0x3b, 0x42, 0x65, 0x64,
+0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x53, 0x6f, 0x6e, 0x74,
+0x61, 0x67, 0x61, 0x3b, 0x4d, 0x6f, 0x73, 0x75, 0x70, 0x61, 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, 0x3b, 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, 0x3b, 0x61, 0x65, 0x6a, 0x6c, 0x65, 0x67, 0x65, 0x3b,
+0x6d, 0xe5, 0x61, 0x6e, 0x74, 0x61, 0x3b, 0x64, 0xe4, 0x6a, 0x73, 0x74, 0x61, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x65, 0x76,
+0x61, 0x68, 0x6b, 0x6f, 0x65, 0x3b, 0x64, 0xe5, 0x61, 0x72, 0x73, 0x74, 0x61, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61,
+0x64, 0x61, 0x68, 0x6b, 0x65, 0x3b, 0x6c, 0x61, 0x61, 0x76, 0x61, 0x64, 0x61, 0x68, 0x6b, 0x65, 0x3b, 0x53, 0x3b, 0x4d,
+0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b,
+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, 0x3b, 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, 0x3b,
+0x45, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 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, 0x3b, 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, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x45, 0x3b, 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, 0x3b, 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, 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, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 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, 0x3b, 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, 0x3b, 0x64, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6e,
+0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b,
+0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 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, 0x3b,
+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, 0x27, 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, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 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, 0x3b, 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, 0x3b, 0x44, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x53, 0x3b,
+0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x49, 0x6a, 0x70, 0x3b, 0x49, 0x6a, 0x74, 0x3b, 0x49, 0x6a, 0x6e, 0x3b,
+0x49, 0x6a, 0x74, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 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,
+0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x31, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61,
+0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61, 0x6b, 0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x3b,
+0x41, 0x73, 0x69, 0x1e0d, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b,
+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, 0x3b, 0x59, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4d,
+0x3b, 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, 0x3b, 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, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x48,
+0x3b, 0x57, 0x3b, 0x4a, 0x3b, 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, 0x3b, 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, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 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, 0x3b, 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,
+0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4e,
+0x3b, 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, 0x3b, 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, 0x3b, 0x13c6, 0x3b,
+0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x3b, 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, 0x3b, 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, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x76, 0x3b, 0x73,
+0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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,
+0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c,
+0x3b, 0x4c, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x64, 0x3b, 0x73, 0x3b, 0x74, 0x3b, 0x6b, 0x3b, 0x6b, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 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, 0x3b, 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, 0x3b, 0x4b, 0x3b, 0x4d,
+0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x41,
+0x65, 0x6e, 0x3b, 0x53, 0x6f, 0x6d, 0x3b, 0x41, 0x6e, 0x67, 0x3b, 0x4d, 0x75, 0x74, 0x3b, 0x4c, 0x6f, 0x68, 0x3b, 0x42,
+0x65, 0x74, 0x75, 0x74, 0x61, 0x62, 0x20, 0x74, 0x69, 0x73, 0x61, 0x70, 0x3b, 0x42, 0x65, 0x74, 0x75, 0x74, 0x20, 0x6e,
+0x65, 0x74, 0x61, 0x69, 0x3b, 0x42, 0x65, 0x74, 0x75, 0x74, 0x61, 0x62, 0x20, 0x61, 0x65, 0x6e, 0x67, 0x27, 0x3b, 0x42,
+0x65, 0x74, 0x75, 0x74, 0x61, 0x62, 0x20, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x42, 0x65, 0x74, 0x75, 0x74, 0x61, 0x62,
+0x20, 0x61, 0x6e, 0x67, 0x27, 0x77, 0x61, 0x6e, 0x3b, 0x42, 0x65, 0x74, 0x75, 0x74, 0x61, 0x62, 0x20, 0x6d, 0x75, 0x74,
+0x3b, 0x42, 0x65, 0x74, 0x75, 0x74, 0x61, 0x62, 0x20, 0x6c, 0x6f, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b, 0x44,
+0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x3b, 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,
+0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 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, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x6f, 0x6f, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x53,
+0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b, 0x41,
+0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x27, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61, 0x6b,
+0x61, 0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b, 0x3b,
+0x53, 0x3b, 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, 0x3b, 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, 0x3b, 0x4e, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x43, 0x3b, 0x4a, 0x3b, 0x51, 0x3b,
+0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b,
+0x41, 0x6c, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x3b, 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,
+0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 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, 0x3b, 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, 0x27, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20,
+0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65, 0x73, 0x6f, 0x3b, 0x4a, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x54, 0x3b,
+0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 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, 0x3b, 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, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b
+};
+
+static const ushort am_data[] = {
+0x41, 0x4d, 0x57, 0x44, 0x76, 0x6d, 0x2e, 0x50, 0x44, 0x1321, 0x12cb, 0x1275, 0x635, 0x531, 0x57c, 0x2024, 0x9aa, 0x9c2, 0x9f0, 0x9cd,
+0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x9aa, 0x9c2, 0x9b0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x43f, 0x440, 0x2e, 0x20, 0x43e, 0x431,
+0x2e, 0x434, 0x430, 0x20, 0x43f, 0x430, 0x43b, 0x443, 0x434, 0x43d, 0x44f, 0x1796, 0x17d2, 0x179a, 0x17b9, 0x1780, 0x61, 0x2e, 0x6d, 0x2e,
+0x4e0a, 0x5348, 0x64, 0x6f, 0x70, 0x2e, 0x66, 0x2e, 0x6d, 0x2e, 0xd801, 0xdc08, 0xd801, 0xdc23, 0x65, 0x6e, 0x6e, 0x65, 0x20, 0x6b,
+0x65, 0x73, 0x6b, 0x70, 0xe4, 0x65, 0x76, 0x61, 0x61, 0x70, 0x2e, 0x76, 0x6f, 0x72, 0x6d, 0x2e, 0x3c0, 0x2e, 0x3bc, 0x2e,
+0xaaa, 0xac2, 0xab0, 0xacd, 0xab5, 0x20, 0xaae, 0xaa7, 0xacd, 0xaaf, 0xabe, 0xab9, 0xacd, 0xaa8, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6,
+0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x6d, 0x2e, 0x5348, 0x524d,
+0x61, 0x6d, 0xc624, 0xc804, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x70, 0x72,
+0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0xd30, 0xd3e, 0xd35,
+0xd3f, 0xd32, 0xd46, 0x51, 0x4e, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x20, 0x92e, 0x927, 0x94d, 0x92f, 0x93e, 0x928, 0x94d, 0x939, 0x63a,
+0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x20, 0x627, 0x632, 0x20, 0x638, 0x647, 0x631, 0x41, 0x6e, 0x74, 0x65, 0x73, 0x20, 0x64,
+0x6f, 0x20, 0x6d, 0x65, 0x69, 0x6f, 0x2d, 0x64, 0x69, 0x61, 0xa38, 0xa35, 0xa47, 0xa30, 0xa47, 0x4e, 0x44, 0x43f, 0x440, 0x435,
+0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e,
+0x64, 0x6f, 0x70, 0x6f, 0x6c, 0x75, 0x64, 0x6e, 0x69, 0x61, 0x73, 0x6e, 0x2e, 0x61, 0x73, 0x75, 0x62, 0x75, 0x68, 0x69,
+0x66, 0x6d, 0xc09, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b,
+0x1295, 0x1309, 0x1206, 0x20, 0x1230, 0x12d3, 0x1270, 0x434, 0x43f, 0x53, 0x41, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0x66, 0x6f, 0x72, 0x6d,
+0x69, 0x64, 0x64, 0x61, 0x67, 0x41, 0x4e, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x41, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x6b,
+0x77, 0x61, 0x6b, 0x79, 0x61, 0xa3b8, 0xa111, 0x4d, 0x61, 0x2f, 0x4d, 0x6f, 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, 0x27, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30, 0x2d61,
+0x2d5c, 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, 0x42, 0x65, 0x65, 0x74, 0x1c1, 0x67, 0x6f, 0x61, 0x67, 0x61, 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
+};
+
+static const ushort pm_data[] = {
+0x50, 0x4d, 0x57, 0x42, 0x6e, 0x6d, 0x2e, 0x4d, 0x44, 0x12a8, 0x1233, 0x12d3, 0x1275, 0x645, 0x53f, 0x565, 0x2024, 0x985, 0x9aa, 0x9f0,
+0x9be, 0x9b9, 0x9cd, 0x9a3, 0x985, 0x9aa, 0x9b0, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x441, 0x43b, 0x2e, 0x20, 0x43e, 0x431, 0x2e, 0x43f, 0x430,
+0x441, 0x43b, 0x44f, 0x20, 0x43f, 0x430, 0x43b, 0x443, 0x434, 0x43d, 0x44f, 0x179b, 0x17d2, 0x1784, 0x17b6, 0x1785, 0x70, 0x2e, 0x6d, 0x2e,
+0x4e0b, 0x5348, 0x6f, 0x64, 0x70, 0x2e, 0x65, 0x2e, 0x6d, 0x2e, 0xd801, 0xdc11, 0xd801, 0xdc23, 0x70, 0xe4, 0x72, 0x61, 0x73, 0x74,
+0x20, 0x6b, 0x65, 0x73, 0x6b, 0x70, 0xe4, 0x65, 0x76, 0x61, 0x69, 0x70, 0x2e, 0x6e, 0x61, 0x63, 0x68, 0x6d, 0x2e, 0x3bc,
+0x2e, 0x3bc, 0x2e, 0xa89, 0xaa4, 0xacd, 0xaa4, 0xab0, 0x20, 0xaae, 0xaa7, 0xacd, 0xaaf, 0xabe, 0xab9, 0xacd, 0xaa8, 0x5d0, 0x5d7, 0x5d4,
+0x5f4, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, 0x2e, 0x65, 0x2e, 0x68, 0x2e, 0x70, 0x2e, 0x5348, 0x5f8c,
+0x70, 0x6d, 0xc624, 0xd6c4, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x70, 0x6f, 0x70, 0x69, 0x65,
+0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0xd35, 0xd48, 0xd15, 0xd41, 0xd28, 0xd4d, 0xd28, 0xd47, 0xd30, 0xd02, 0x57,
+0x4e, 0x909, 0x924, 0x94d, 0x924, 0x930, 0x20, 0x92e, 0x927, 0x94d, 0x92f, 0x93e, 0x928, 0x94d, 0x939, 0x63a, 0x2e, 0x648, 0x2e, 0x628,
+0x639, 0x62f, 0x20, 0x627, 0x632, 0x20, 0x638, 0x647, 0x631, 0x44, 0x65, 0x70, 0x6f, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x20, 0x6d,
+0x65, 0x69, 0x6f, 0x2d, 0x64, 0x69, 0x61, 0xa38, 0xa3c, 0xa3e, 0xa2e, 0x73, 0x6d, 0x4c, 0x4b, 0x43f, 0x43e, 0x43f, 0x43e, 0x434,
+0x43d, 0x435, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x6f, 0x6c, 0x75, 0x64,
+0x6e, 0xed, 0x70, 0x6f, 0x70, 0x2e, 0x67, 0x6e, 0x2e, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x72, 0x69, 0x65, 0x6d, 0xc38, 0xc3e,
+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, 0x43f, 0x43f, 0x43, 0x48, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x65, 0x74, 0x74, 0x65, 0x72, 0x6d,
+0x69, 0x64, 0x64, 0x61, 0x67, 0x45, 0x57, 0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x50, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x77,
+0x129, 0x6f, 0x6f, 0x6e, 0x61, 0x6d, 0x2e, 0xa06f, 0xa2d2, 0x4d, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x2f, 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, 0x74, 0x61, 0x64, 0x67,
+0x67, 0x2b7, 0x61, 0x74, 0x2d5c, 0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c, 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, 0x4b, 0x65, 0x6d, 0x6f, 0x1c3, 0x75, 0x69, 0x61, 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
+};
+
+static const ushort currency_symbol_data[] = {
+0x42, 0x72, 0x4b, 0x73, 0x68, 0x46, 0x64, 0x6a, 0x4e, 0x66, 0x6b, 0x52, 0x4e, 0x24, 0x4c, 0x65, 0x6b, 0x1265, 0x122d, 0x631,
+0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62c, 0x2e, 0x200f, 0x62f, 0x2e, 0x628, 0x2e, 0x200f, 0x62c, 0x2e, 0x645, 0x2e, 0x200f, 0x62f,
+0x2e, 0x639, 0x2e, 0x200f, 0x62f, 0x2e, 0x623, 0x2e, 0x200f, 0x62f, 0x2e, 0x643, 0x2e, 0x200f, 0x644, 0x2e, 0x644, 0x2e, 0x200f, 0x62f,
+0x2e, 0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631, 0x2e, 0x639, 0x2e, 0x200f, 0x631, 0x2e, 0x642, 0x2e, 0x200f, 0x644,
+0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e, 0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f, 0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0x564,
+0x580, 0x2e, 0x99f, 0x995, 0x9be, 0x6d, 0x61, 0x6e, 0x2e, 0x43c, 0x430, 0x43d, 0x2e, 0x20ac, 0x9f3, 0x99f, 0x9be, 0x995, 0x9be, 0x4e,
+0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x4b, 0x17db, 0xffe5, 0x24, 0x4d, 0x4f, 0x50, 0x24, 0x53, 0x24, 0x4e, 0x54, 0x24, 0x6b, 0x6e,
+0x4b, 0x10d, 0x6b, 0x72, 0x50, 0x52, 0x73, 0x4d, 0x55, 0x52, 0x73, 0x20a8, 0x20b1, 0xa3, 0x58, 0x41, 0x46, 0x43, 0x46, 0x41,
+0x47, 0x4e, 0x46, 0x43, 0x48, 0x46, 0xab0, 0xac1, 0x47, 0x48, 0x20b5, 0x20a6, 0x20aa, 0x930, 0x941, 0x2e, 0x46, 0x74, 0x52, 0x70,
+0x930, 0x941, 0x442, 0x4a3, 0x433, 0x2e, 0x52, 0x46, 0x441, 0x43e, 0x43c, 0x20a9, 0x53, 0x59, 0xa3, 0x54, 0x4c, 0x20ad, 0x4c, 0x73,
+0x46, 0x46, 0x43, 0x46, 0x41, 0x4c, 0x74, 0x52, 0x4d, 0xd30, 0xd42, 0x4e, 0x5a, 0x24, 0x20ae, 0x43, 0x4e, 0xa5, 0x928, 0x947,
+0x930, 0x942, 0x60b, 0xfdfc, 0x7a, 0x142, 0x52, 0x24, 0x4d, 0x54, 0x6e, 0xa30, 0xa41, 0x2e, 0x631, 0x52, 0x4f, 0x4e, 0x440, 0x443,
+0x431, 0x2e, 0x20b4, 0x41a, 0x41c, 0x2e, 0x434, 0x438, 0x43d, 0x2e, 0x4b, 0x4d, 0x64, 0x69, 0x6e, 0x2e, 0x55, 0x53, 0x24, 0x53,
+0x4c, 0x20, 0x52, 0x65, 0x45, 0x53, 0x73, 0x68, 0x42, 0x73, 0x20a1, 0x52, 0x44, 0x24, 0x51, 0x4c, 0x43, 0x24, 0x42, 0x2f,
+0x2e, 0x20b2, 0x53, 0x2f, 0x2e, 0x42, 0x73, 0x2e, 0x46, 0x2e, 0x54, 0x53, 0x68, 0xbb0, 0xbc2, 0x53, 0x4c, 0x52, 0x73, 0xc30,
+0xc42, 0x2e, 0xe3f, 0x54, 0x24, 0x631, 0x648, 0x67e, 0x6d2, 0x441, 0x45e, 0x43c, 0x41, 0x66, 0x73, 0x6f, 0x2bf, 0x6d, 0x20ab, 0x783,
+0x2e, 0x46, 0x47, 0x4e, 0x6b, 0x72, 0x44, 0x41, 0x55, 0x53, 0x68, 0x5a, 0x4b, 0x43, 0x56, 0x24
+};
+
+static const ushort currency_display_name_data[] = {
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x74, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x20, 0x42, 0x69,
+0x72, 0x72, 0x69, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x3b, 0x3b, 0x4e, 0x61,
+0x6d, 0x69, 0x62, 0x69, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x12e8, 0x12a2, 0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 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, 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, 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, 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, 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,
+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, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647,
+0x20, 0x645, 0x635, 0x631, 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, 0x3b, 0x62f, 0x64a,
+0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 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, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 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, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62c, 0x646,
+0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646,
+0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644,
+0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646,
+0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646,
+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, 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, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 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, 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, 0x20, 0x645,
+0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 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, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 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, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637,
+0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a,
+0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a,
+0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a,
+0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x62a, 0x648, 0x646, 0x633,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x62a, 0x648,
+0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
+0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646,
+0x627, 0x631, 0x62a, 0x648, 0x646, 0x633, 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, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 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, 0x3b, 0x631,
+0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20,
+0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
+0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x130, 0x72, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x61, 0x6c, 0x131,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x130, 0x72, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x61, 0x6c, 0x131, 0x3b, 0x43c, 0x430, 0x43d,
+0x430, 0x442, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d,
+0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf51, 0xf44, 0xf74, 0xf63, 0xf0b, 0xf40, 0xfb2, 0xf58, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b,
+0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x20, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x431, 0x435,
+0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x52, 0x69, 0x65, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
+0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x81fa, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x6b, 0x75,
+0x6e, 0x61, 0x3b, 0x3b, 0x6b, 0x75, 0x6e, 0x65, 0x3b, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4b,
+0x6f, 0x72, 0x75, 0x6e, 0x61, 0x20, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x61,
+0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f,
+0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b,
+0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 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, 0x3b, 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, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 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, 0x3b,
+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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x50, 0x65, 0x73,
+0x6f, 0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x3b,
+0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x3b, 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, 0x3b, 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, 0x3b, 0x54, 0x72, 0x69, 0x6e,
+0x69, 0x64, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 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, 0x61, 0x6e, 0x64, 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, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x73, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x65, 0x72,
+0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20,
+0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x45, 0x65, 0x73, 0x74,
+0x69, 0x20, 0x6b, 0x72, 0x6f, 0x6f, 0x6e, 0x3b, 0x3b, 0x45, 0x65, 0x73, 0x74, 0x69, 0x20, 0x6b, 0x72, 0x6f, 0x6f, 0x6e,
+0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x65, 0x73, 0x74, 0x69, 0x20, 0x6b, 0x72, 0x6f, 0x6f, 0x6e, 0x69, 0x3b, 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, 0x6f, 0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 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, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3,
+0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
+0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a,
+0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63, 0x68, 0x77,
+0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x395, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b,
+0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x69, 0x6e,
+0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6d, 0x20, 0x6b, 0x69, 0x6e, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x646, 0x64e, 0x64a, 0x652, 0x631, 0x64e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5f4,
+0x5d7, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x92d,
+0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61,
+0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xcd, 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, 0x75, 0x20, 0x6b,
+0x72, 0xf3, 0x6e, 0x75, 0x72, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73,
+0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x61, 0x74, 0x76, 0x69,
+0x6a, 0x61, 0x73, 0x20, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x61, 0x6c, 0xe1, 0x6e,
+0x67, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0xe9, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x74,
+0x61, 0x73, 0x3b, 0x3b, 0x4c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x73, 0x3b, 0x3b,
+0x4c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x69, 0x3b, 0x3b, 0x4c, 0x69, 0x65, 0x74,
+0x75, 0x76, 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x69, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a,
+0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79,
+0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd28, 0xd4d, 0x200d, 0x20,
+0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd28, 0xd4d, 0x200d, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b,
+0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd28, 0xd4d, 0x200d, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x45, 0x77, 0x72, 0x6f,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 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, 0x3b,
+0xb1f, 0xb19, 0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b,
+0x69, 0x63, 0x68, 0x3b, 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, 0x3b, 0x46, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e,
+0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x46,
+0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b,
+0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75,
+0x65, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62,
+0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x65,
+0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0xa30, 0xa41, 0xa2a, 0xa3f, 0xa2f, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x648, 0x67e, 0x626, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65, 0x75,
+0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 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, 0x3b, 0x6c, 0x65, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65,
+0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443,
+0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b,
+0x44c, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b,
+0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x420, 0x43e,
+0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x41c, 0x43e, 0x43b, 0x434,
+0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x423, 0x43a, 0x440,
+0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x66, 0x61, 0x72, 0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20,
+0x41c, 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, 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, 0x430, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 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,
+0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x65, 0x76,
+0x72, 0x61, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 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, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x434, 0x438,
+0x43d, 0x430, 0x440, 0x430, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x438, 0x3b, 0x415,
+0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x435, 0x432, 0x440, 0x430,
+0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x48, 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, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f,
+0x2d, 0x48, 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, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73,
+0x6b, 0x6f, 0x2d, 0x48, 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, 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, 0x3b, 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, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61,
+0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x69, 0x3b, 0x44, 0x6f, 0x72, 0x61, 0x20,
+0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xdbd, 0xd82, 0xd9a,
+0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0xdca, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61, 0x62, 0x62, 0x75, 0x75, 0x74, 0x69,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69,
+0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b,
+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, 0x3b, 0x70, 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, 0x3b,
+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, 0x3b, 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,
+0x3b, 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, 0x3b, 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, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x20, 0x67, 0x75, 0x61, 0x74, 0x65,
+0x6d, 0x61, 0x6c, 0x74, 0x65, 0x63, 0x6f, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x20, 0x67, 0x75, 0x61,
+0x74, 0x65, 0x6d, 0x61, 0x6c, 0x74, 0x65, 0x63, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c,
+0x65, 0x73, 0x20, 0x67, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x74, 0x65, 0x63, 0x6f, 0x73, 0x3b, 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, 0x3b, 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, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6f, 0x72, 0x6f, 0x20, 0x6e, 0x69, 0x63,
+0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6f,
+0x72, 0x6f, 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, 0x6f, 0x72, 0x6f, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc,
+0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 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, 0x3b,
+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,
+0x3b, 0x6e, 0x75, 0x65, 0x76, 0x6f, 0x20, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b,
+0x6e, 0x75, 0x65, 0x76, 0x6f, 0x20, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b,
+0x3b, 0x6e, 0x75, 0x65, 0x76, 0x6f, 0x73, 0x20, 0x73, 0x6f, 0x6c, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e,
+0x6f, 0x73, 0x3b, 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, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x66,
+0x75, 0x65, 0x72, 0x74, 0x65, 0x20, 0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f,
+0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x66, 0x75, 0x65, 0x72, 0x74, 0x65, 0x20, 0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c,
+0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x65, 0x73, 0x20, 0x66, 0x75, 0x65,
+0x72, 0x74, 0x65, 0x73, 0x20, 0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x73, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x3b, 0x3b, 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, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x421, 0x43e, 0x43c, 0x43e, 0x43d, 0x4e3, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30, 0xc42,
+0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf62, 0xf92, 0xfb1,
+0xf0b, 0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0xf58, 0xf7c, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x54,
+0xfc, 0x72, 0x6b, 0x20, 0x4c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x423, 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, 0x3b, 0x627, 0x646, 0x688, 0x6cc, 0x646, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4f,
+0x2bf, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2bf, 0x6d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x111, 0x1ed3, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x75, 0x6e, 0x74, 0x20, 0x53, 0x74,
+0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20,
+0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b,
+0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 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, 0x3b, 0x4b, 0x6f, 0x6e,
+0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e,
+0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6d,
+0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x331, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x53, 0x65, 0x66, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x72, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x65,
+0x73, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46,
+0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72,
+0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72,
+0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x69, 0x6c, 0x61, 0x20, 0x54, 0x61, 0x69,
+0x77, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
+0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75,
+0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x43, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x4e, 0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65, 0x6e, 0x79,
+0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x73, 0x65, 0x20, 0x41, 0x6d,
+0x65, 0x6c, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x68, 0x65, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x73,
+0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x64, 0x72,
+0x69, 0x6d, 0x20, 0x6e, 0x20, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x2d30, 0x2d37,
+0x2d54, 0x2d49, 0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41,
+0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79, 0x72, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x48, 0x75,
+0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x13a4, 0x13c3, 0x13cd, 0x13d7, 0x3b, 0x3b, 0x13a4, 0x13c3, 0x13cd, 0x13d7, 0x3b, 0x3b, 0x3b, 0x3b,
+0x13e7, 0x13c3, 0x13cd, 0x13d7, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0xed, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54,
+0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e,
+0x67, 0x69, 0x20, 0x65, 0x79, 0x61, 0x20, 0x59, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x6b, 0x75, 0x64, 0x75, 0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x74, 0x61, 0x62, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20,
+0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79,
+0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49,
+0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x72, 0x69, 0x6e, 0x6a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65,
+0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
+0x61, 0x20, 0x54, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6e,
+0x67, 0x6f, 0x27, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x27, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6e, 0x67, 0x6f, 0x27, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x27, 0x20,
+0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61,
+0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44,
+0x65, 0x72, 0x68, 0x65, 0x6d, 0x20, 0x55, 0x6d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b
+};
+
+static const ushort currency_format_data[] = {
+0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25,
+0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x28, 0x25, 0x31, 0x25, 0x32, 0x29, 0x25, 0x32, 0x2212, 0x25,
+0x31, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x25, 0x32, 0x2d, 0x25, 0x31, 0x202a, 0x2212, 0x25, 0x31, 0x202c, 0xa0, 0x25,
+0x32, 0x25, 0x32, 0xa0, 0x2d, 0x25, 0x31, 0x28, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x29, 0x2d, 0x25, 0x31, 0x25, 0x32, 0x25,
+0x32, 0x2d, 0xa0, 0x25, 0x31
+};
+static const ushort 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, 0x51, 0x61, 0x66, 0x61, 0x72, 0x59, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x45, 0x72, 0x65, 0x74,
+0x72, 0x69, 0x61, 0x4f, 0x74, 0x6f, 0x62, 0x62, 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, 0x73, 0x68, 0x71,
+0x69, 0x70, 0x65, 0x53, 0x68, 0x71, 0x69, 0x70, 0xeb, 0x72, 0x69, 0x61, 0x12a0, 0x121b, 0x122d, 0x129b, 0x12a2, 0x1275, 0x12ee, 0x1335,
+0x12eb, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 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, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x627,
+0x644, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x645, 0x635, 0x631, 0x627, 0x644, 0x639, 0x631, 0x627, 0x642, 0x627, 0x644, 0x623, 0x631, 0x62f,
+0x646, 0x627, 0x644, 0x643, 0x648, 0x64a, 0x62a, 0x644, 0x628, 0x646, 0x627, 0x646, 0x644, 0x64a, 0x628, 0x64a, 0x627, 0x627, 0x644, 0x645,
+0x63a, 0x631, 0x628, 0x639, 0x64f, 0x645, 0x627, 0x646, 0x642, 0x637, 0x631, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x633, 0x648,
+0x631, 0x64a, 0x627, 0x62a, 0x648, 0x646, 0x633, 0x627, 0x644, 0x627, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x627, 0x644, 0x639, 0x631,
+0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x645, 0x62a, 0x62d, 0x62f, 0x629, 0x627, 0x644, 0x64a, 0x645, 0x646, 0x540, 0x561, 0x575, 0x565,
+0x580, 0x567, 0x576, 0x540, 0x561, 0x575, 0x561, 0x57d, 0x57f, 0x561, 0x576, 0x56b, 0x20, 0x540, 0x561, 0x576, 0x580, 0x561, 0x57a, 0x565,
+0x57f, 0x578, 0x582, 0x569, 0x56b, 0x582, 0x576, 0x985, 0x9b8, 0x9ae, 0x9c0, 0x9df, 0x9be, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x61, 0x7a, 0x259,
+0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x63, 0x61, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x130,
+0x72, 0x61, 0x6e, 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, 0x46, 0x72, 0x61, 0xf1,
+0x73, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1017, 0x1019,
+0x102c, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b,
+0x430, 0x440, 0x443, 0x441, 0x44c, 0x1797, 0x17b6, 0x179f, 0x17b6, 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, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d, 0x83ef,
+0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x6fb3,
+0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x65b0, 0x52a0, 0x5761, 0x53f0, 0x7063, 0x4e2d, 0x6587, 0xff08, 0x7b80, 0x4f53, 0xff09, 0x4e2d, 0x56fd, 0x9999,
+0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d, 0x56fd, 0x6fb3, 0x95e8, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x7e41, 0x9ad4, 0x4e2d, 0x6587, 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, 0xe1, 0x20, 0x72, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x6b, 0x61, 0x64, 0x61, 0x6e,
+0x73, 0x6b, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e,
+0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x56, 0x6c, 0x61, 0x61, 0x6d, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0xeb,
+0x55, 0x2e, 0x53, 0x2e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53,
+0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e,
+0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67,
+0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d,
+0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69,
+0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x47, 0x75, 0x61, 0x6d,
+0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x49,
+0x6e, 0x64, 0x69, 0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 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, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x4e, 0x65, 0x77, 0x20, 0x5a,
+0x65, 0x61, 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, 0x68,
+0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x53, 0x6f,
+0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x61,
+0x6e, 0x64, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 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, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 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, 0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 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, 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, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x71, 0x75, 0x65, 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, 0x43, 0xf4, 0x74, 0x65, 0x20, 0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x47, 0x75, 0x61,
+0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f,
+0x75, 0x72, 0x67, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x69, 0x4d, 0x61, 0x72,
+0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x52, 0xe9,
+0x75, 0x6e, 0x69, 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, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42,
+0x61, 0x72, 0x74, 0x68, 0xe9, 0x6c, 0xe9, 0x6d, 0x79, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69,
+0x6e, 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, 0xd6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69,
+0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 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, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 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, 0x47, 0x61, 0x6e, 0x61, 0x4e, 0x69, 0x6a, 0x61, 0x72, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x53,
+0x75, 0x64, 0x61, 0x6e, 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, 0x42, 0x61, 0x68, 0x61,
+0x73, 0x61, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69,
+0x61, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67, 0x65, 0xc9, 0x69, 0x72, 0x65, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x6f,
+0x49, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x61, 0x65e5, 0x672c, 0x8a9e, 0x65e5, 0x672c, 0xc95,
+0xca8, 0xccd, 0xca8, 0xca1, 0xcad, 0xcbe, 0xcb0, 0xca4, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442,
+0x430, 0x43d, 0x4b, 0x69, 0x6e, 0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x41a,
+0x44b, 0x440, 0x433, 0x44b, 0x437, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c,
+0xbbfc, 0xad6d, 0x643, 0x648, 0x631, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x6b, 0x75, 0x72, 0x64, 0xee, 0x54, 0x69, 0x72,
+0x6b, 0x69, 0x79, 0x65, 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, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x2d, 0x4b, 0x69, 0x6e, 0x73, 0xe1,
+0x73, 0xe1, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 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, 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, 0x42, 0x61, 0x68, 0x61, 0x73, 0x61,
+0x20, 0x4d, 0x65, 0x6c, 0x61, 0x79, 0x75, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x42, 0x72, 0x75, 0x6e, 0x65,
+0x69, 0xd2e, 0xd32, 0xd2f, 0xd3e, 0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x92e, 0x930,
+0x93e, 0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x20, 0x443, 0x43b, 0x441, 0x928,
+0x947, 0x92a, 0x93e, 0x932, 0x940, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d,
+0xe5, 0x6c, 0x4e, 0x6f, 0x72, 0x67, 0x65, 0x6f, 0x63, 0x63, 0x69, 0x74, 0x61, 0x6e, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61,
+0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a, 0x627, 0x646, 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, 0x20, 0x65, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea,
+0x73, 0x20, 0x64, 0x6f, 0x20, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x70, 0x6f, 0x72,
+0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x4d, 0x6f,
+0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e, 0x646,
+0x62c, 0x627, 0x628, 0x67e, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x72, 0x75, 0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76,
+0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20,
+0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x52, 0x6f, 0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438,
+0x439, 0x420, 0x43e, 0x441, 0x441, 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, 0x938, 0x902, 0x938, 0x94d, 0x915, 0x943, 0x924, 0x20, 0x92d, 0x93e, 0x937, 0x93e,
+0x92d, 0x93e, 0x930, 0x924, 0x92e, 0x94d, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x20, 0x438,
+0x20, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x411, 0x43e, 0x441, 0x43d,
+0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430, 0x53, 0x72, 0x70, 0x73, 0x6b,
+0x69, 0x43, 0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x426, 0x440, 0x43d, 0x430,
+0x20, 0x413, 0x43e, 0x440, 0x430, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f,
+0x76, 0x69, 0x6e, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x20, 0x69, 0x20, 0x43, 0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f,
+0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x53, 0x72, 0x70, 0x73, 0x6b, 0x6f, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73,
+0x6b, 0x69, 0x53, 0x65, 0x73, 0x6f, 0x74, 0x68, 0x6f, 0x53, 0x65, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x63, 0x68, 0x69,
+0x53, 0x68, 0x6f, 0x6e, 0x61, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf,
+0xdc0, 0x53, 0x69, 0x73, 0x77, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c,
+0x6f, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0xe1, 0x20, 0x72, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x6b, 0x61, 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, 0x4b, 0x69, 0x69, 0x6e, 0x69, 0x79, 0x61, 0x65, 0x73, 0x70,
+0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f,
+0x6c, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x43, 0x68, 0x69,
+0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x20, 0x52, 0x69, 0x63, 0x61,
+0x52, 0x65, 0x70, 0xfa, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61,
+0x45, 0x63, 0x75, 0x61, 0x64, 0x6f, 0x72, 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, 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, 0x50, 0x65, 0x72, 0xfa, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 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, 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, 0x20, 0x79, 0x20, 0x65, 0x6c, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x65, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68,
+0x69, 0x6c, 0x69, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x73, 0x76, 0x65, 0x6e,
+0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69, 0x67, 0x65, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0xba4, 0xbae, 0xbbf,
+0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x422, 0x430, 0x442, 0x430, 0x440,
+0xc24, 0xc46, 0xc32, 0xc41, 0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0x20, 0xc26, 0xc47, 0xc36, 0xc02, 0xe44, 0xe17, 0xe22, 0xf54, 0xf7c,
+0xf51, 0xf0b, 0xf66, 0xf90, 0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275,
+0x130d, 0x122d, 0x129b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x6f, 0x6e, 0x67,
+0x61, 0x58, 0x69, 0x74, 0x73, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69,
+0x79, 0x65, 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, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x40e, 0x437, 0x431, 0x435, 0x43a,
+0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x627, 0x6c9, 0x632, 0x628, 0x6d0, 0x6a9, 0x6f, 0x27, 0x7a, 0x62,
+0x65, 0x6b, 0x63, 0x68, 0x61, 0x4f, 0x2bf, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x54, 0x69, 0x1ebf, 0x6e,
+0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65,
+0x67, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x20, 0x46, 0x61, 0x77, 0x72, 0x69, 0x73, 0x69, 0x58, 0x68, 0x6f, 0x73,
+0x61, 0xc8, 0x64, 0xe8, 0x20, 0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65,
+0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 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, 0x78b, 0x7a8, 0x788, 0x7ac, 0x780, 0x7a8, 0x784,
+0x7a6, 0x790, 0x7b0, 0x78b, 0x7a8, 0x788, 0x7ac, 0x780, 0x7a8, 0x20, 0x783, 0x7a7, 0x787, 0x7b0, 0x796, 0x7ac, 0x47, 0x61, 0x65, 0x6c,
+0x67, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e, 0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x6b, 0x65, 0x72, 0x6e, 0x65,
+0x77, 0x65, 0x6b, 0x41, 0x6b, 0x61, 0x6e, 0x47, 0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902, 0x915, 0x923, 0x940, 0x49, 0x67,
+0x62, 0x6f, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0x723, 0x718, 0x72a, 0x71d,
+0x71d, 0x710, 0x1265, 0x120a, 0x1295, 0x12a4, 0x122d, 0x1275, 0x122b, 0x130d, 0x12d5, 0x12dd, 0x129b, 0x53, 0x69, 0x64, 0x61, 0x61, 0x6d, 0x75,
+0x20, 0x41, 0x66, 0x6f, 0x49, 0x74, 0x69, 0x79, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x1275, 0x130d, 0x1228, 0x66, 0x75,
+0x72, 0x6c, 0x61, 0x6e, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x54, 0x73, 0x68, 0x69, 0x76, 0x65, 0x6e, 0x1e13, 0x61, 0x45,
+0x28b, 0x65, 0x67, 0x62, 0x65, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x54, 0x6f, 0x67, 0x6f, 0x64, 0x75, 0x12c8, 0x120b,
+0x12ed, 0x1273, 0x1271, 0x2bb, 0x14d, 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, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0xa188, 0xa320, 0xa259, 0xa34f,
+0xa1e9, 0x50, 0x6c, 0x61, 0x74, 0x74, 0x64, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x44, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68,
+0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62, 0x65, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x6f, 0x74, 0x68,
+0x6f, 0x20, 0x73, 0x61, 0x20, 0x4c, 0x65, 0x62, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1, 0x6d, 0x65, 0x67,
+0x69, 0x65, 0x6c, 0x6c, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x4e, 0x6f, 0x72, 0x67, 0x61, 0x45, 0x6b, 0x65, 0x67,
+0x75, 0x73, 0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61, 0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x53, 0x65, 0x6e,
+0x65, 0x67, 0x61, 0x61, 0x6c, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75, 0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x73,
+0x65, 0x6e, 0x61, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62, 0x6f, 0x74, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x67, 0x68,
+0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56, 0x2d5c, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49,
+0x2d31, 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, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 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, 0x13a0, 0x13b9, 0x13f0, 0x13df,
+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, 0x5a, 0x61, 0x6d, 0x62, 0x69, 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, 0x44, 0x6f, 0xfc, 0x74, 0x73, 0x63, 0x68,
+0x6c, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x61, 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, 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
+};
+
+static const char language_name_list[] =
+"Default\0"
+"C\0"
+"Abkhazian\0"
+"Afan\0"
+"Afar\0"
+"Afrikaans\0"
+"Albanian\0"
+"Amharic\0"
+"Arabic\0"
+"Armenian\0"
+"Assamese\0"
+"Aymara\0"
+"Azerbaijani\0"
+"Bashkir\0"
+"Basque\0"
+"Bengali\0"
+"Bhutani\0"
+"Bihari\0"
+"Bislama\0"
+"Breton\0"
+"Bulgarian\0"
+"Burmese\0"
+"Byelorussian\0"
+"Cambodian\0"
+"Catalan\0"
+"Chinese\0"
+"Corsican\0"
+"Croatian\0"
+"Czech\0"
+"Danish\0"
+"Dutch\0"
+"English\0"
+"Esperanto\0"
+"Estonian\0"
+"Faroese\0"
+"Fiji\0"
+"Finnish\0"
+"French\0"
+"Frisian\0"
+"Gaelic\0"
+"Galician\0"
+"Georgian\0"
+"German\0"
+"Greek\0"
+"Greenlandic\0"
+"Guarani\0"
+"Gujarati\0"
+"Hausa\0"
+"Hebrew\0"
+"Hindi\0"
+"Hungarian\0"
+"Icelandic\0"
+"Indonesian\0"
+"Interlingua\0"
+"Interlingue\0"
+"Inuktitut\0"
+"Inupiak\0"
+"Irish\0"
+"Italian\0"
+"Japanese\0"
+"Javanese\0"
+"Kannada\0"
+"Kashmiri\0"
+"Kazakh\0"
+"Kinyarwanda\0"
+"Kirghiz\0"
+"Korean\0"
+"Kurdish\0"
+"Kurundi\0"
+"Laothian\0"
+"Latin\0"
+"Latvian\0"
+"Lingala\0"
+"Lithuanian\0"
+"Macedonian\0"
+"Malagasy\0"
+"Malay\0"
+"Malayalam\0"
+"Maltese\0"
+"Maori\0"
+"Marathi\0"
+"Moldavian\0"
+"Mongolian\0"
+"Nauru\0"
+"Nepali\0"
+"Norwegian\0"
+"Occitan\0"
+"Oriya\0"
+"Pashto\0"
+"Persian\0"
+"Polish\0"
+"Portuguese\0"
+"Punjabi\0"
+"Quechua\0"
+"RhaetoRomance\0"
+"Romanian\0"
+"Russian\0"
+"Samoan\0"
+"Sangho\0"
+"Sanskrit\0"
+"Serbian\0"
+"SerboCroatian\0"
+"Sesotho\0"
+"Setswana\0"
+"Shona\0"
+"Sindhi\0"
+"Singhalese\0"
+"Siswati\0"
+"Slovak\0"
+"Slovenian\0"
+"Somali\0"
+"Spanish\0"
+"Sundanese\0"
+"Swahili\0"
+"Swedish\0"
+"Tagalog\0"
+"Tajik\0"
+"Tamil\0"
+"Tatar\0"
+"Telugu\0"
+"Thai\0"
+"Tibetan\0"
+"Tigrinya\0"
+"Tonga\0"
+"Tsonga\0"
+"Turkish\0"
+"Turkmen\0"
+"Twi\0"
+"Uigur\0"
+"Ukrainian\0"
+"Urdu\0"
+"Uzbek\0"
+"Vietnamese\0"
+"Volapuk\0"
+"Welsh\0"
+"Wolof\0"
+"Xhosa\0"
+"Yiddish\0"
+"Yoruba\0"
+"Zhuang\0"
+"Zulu\0"
+"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"
+"Chewa\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"
+;
+
+static const quint16 language_name_index[] = {
+ 0, // AnyLanguage
+ 8, // C
+ 10, // Abkhazian
+ 20, // Afan
+ 25, // Afar
+ 30, // Afrikaans
+ 40, // Albanian
+ 49, // Amharic
+ 57, // Arabic
+ 64, // Armenian
+ 73, // Assamese
+ 82, // Aymara
+ 89, // Azerbaijani
+ 101, // Bashkir
+ 109, // Basque
+ 116, // Bengali
+ 124, // Bhutani
+ 132, // Bihari
+ 139, // Bislama
+ 147, // Breton
+ 154, // Bulgarian
+ 164, // Burmese
+ 172, // Byelorussian
+ 185, // Cambodian
+ 195, // Catalan
+ 203, // Chinese
+ 211, // Corsican
+ 220, // Croatian
+ 229, // Czech
+ 235, // Danish
+ 242, // Dutch
+ 248, // English
+ 256, // Esperanto
+ 266, // Estonian
+ 275, // Faroese
+ 283, // Fiji
+ 288, // Finnish
+ 296, // French
+ 303, // Frisian
+ 311, // Gaelic
+ 318, // Galician
+ 327, // Georgian
+ 336, // German
+ 343, // Greek
+ 349, // Greenlandic
+ 361, // Guarani
+ 369, // Gujarati
+ 378, // Hausa
+ 384, // Hebrew
+ 391, // Hindi
+ 397, // Hungarian
+ 407, // Icelandic
+ 417, // Indonesian
+ 428, // Interlingua
+ 440, // Interlingue
+ 452, // Inuktitut
+ 462, // Inupiak
+ 470, // Irish
+ 476, // Italian
+ 484, // Japanese
+ 493, // Javanese
+ 502, // Kannada
+ 510, // Kashmiri
+ 519, // Kazakh
+ 526, // Kinyarwanda
+ 538, // Kirghiz
+ 546, // Korean
+ 553, // Kurdish
+ 561, // Kurundi
+ 569, // Laothian
+ 578, // Latin
+ 584, // Latvian
+ 592, // Lingala
+ 600, // Lithuanian
+ 611, // Macedonian
+ 622, // Malagasy
+ 631, // Malay
+ 637, // Malayalam
+ 647, // Maltese
+ 655, // Maori
+ 661, // Marathi
+ 669, // Moldavian
+ 679, // Mongolian
+ 689, // Nauru
+ 695, // Nepali
+ 702, // Norwegian
+ 712, // Occitan
+ 720, // Oriya
+ 726, // Pashto
+ 733, // Persian
+ 741, // Polish
+ 748, // Portuguese
+ 759, // Punjabi
+ 767, // Quechua
+ 775, // RhaetoRomance
+ 789, // Romanian
+ 798, // Russian
+ 806, // Samoan
+ 813, // Sangho
+ 820, // Sanskrit
+ 829, // Serbian
+ 837, // SerboCroatian
+ 851, // Sesotho
+ 859, // Setswana
+ 868, // Shona
+ 874, // Sindhi
+ 881, // Singhalese
+ 892, // Siswati
+ 900, // Slovak
+ 907, // Slovenian
+ 917, // Somali
+ 924, // Spanish
+ 932, // Sundanese
+ 942, // Swahili
+ 950, // Swedish
+ 958, // Tagalog
+ 966, // Tajik
+ 972, // Tamil
+ 978, // Tatar
+ 984, // Telugu
+ 991, // Thai
+ 996, // Tibetan
+ 1004, // Tigrinya
+ 1013, // Tonga
+ 1019, // Tsonga
+ 1026, // Turkish
+ 1034, // Turkmen
+ 1042, // Twi
+ 1046, // Uigur
+ 1052, // Ukrainian
+ 1062, // Urdu
+ 1067, // Uzbek
+ 1073, // Vietnamese
+ 1084, // Volapuk
+ 1092, // Welsh
+ 1098, // Wolof
+ 1104, // Xhosa
+ 1110, // Yiddish
+ 1118, // Yoruba
+ 1125, // Zhuang
+ 1132, // Zulu
+ 1137, // Nynorsk
+ 1145, // Bosnian
+ 1153, // Divehi
+ 1160, // Manx
+ 1165, // Cornish
+ 1173, // Akan
+ 1178, // Konkani
+ 1186, // Ga
+ 1189, // Igbo
+ 1194, // Kamba
+ 1200, // Syriac
+ 1207, // Blin
+ 1212, // Geez
+ 1217, // Koro
+ 1222, // Sidamo
+ 1229, // Atsam
+ 1235, // Tigre
+ 1241, // Jju
+ 1245, // Friulian
+ 1254, // Venda
+ 1260, // Ewe
+ 1264, // Walamo
+ 1271, // Hawaiian
+ 1280, // Tyap
+ 1285, // Chewa
+ 1291, // Filipino
+ 1300, // Swiss German
+ 1313, // Sichuan Yi
+ 1324, // Kpelle
+ 1331, // Low German
+ 1342, // South Ndebele
+ 1356, // Northern Sotho
+ 1371, // Northern Sami
+ 1385, // Taroko
+ 1392, // Gusii
+ 1398, // Taita
+ 1404, // Fulah
+ 1410, // Kikuyu
+ 1417, // Samburu
+ 1425, // Sena
+ 1430, // North Ndebele
+ 1444, // Rombo
+ 1450, // Tachelhit
+ 1460, // Kabyle
+ 1467, // Nyankole
+ 1476, // Bena
+ 1481, // Vunjo
+ 1487, // Bambara
+ 1495, // Embu
+ 1500, // Cherokee
+ 1509, // Morisyen
+ 1518, // Makonde
+ 1526, // Langi
+ 1532, // Ganda
+ 1538, // Bemba
+ 1544, // Kabuverdianu
+ 1557, // Meru
+ 1562, // Kalenjin
+ 1571, // Nama
+ 1576, // Machame
+ 1584, // Colognian
+ 1594, // Masai
+ 1600, // Soga
+ 1605, // Luyia
+ 1611, // Asu
+ 1615, // Teso
+ 1620, // Saho
+ 1625, // Koyra Chiini
+ 1638, // Rwa
+ 1642, // Luo
+ 1646, // Chiga
+ 1652, // Central Morocco Tamazight
+ 1678, // Koyraboro Senni
+ 1694, // Shambala
+};
+
+static const char script_name_list[] =
+"Default\0"
+"Arabic\0"
+"Cyrillic\0"
+"Deseret\0"
+"Gurmukhi\0"
+"Simplified Han\0"
+"Traditional Han\0"
+"Latin\0"
+"Mongolian\0"
+"Tifinagh\0"
+;
+
+static const 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
+};
+
+static const char country_name_list[] =
+"Default\0"
+"Afghanistan\0"
+"Albania\0"
+"Algeria\0"
+"AmericanSamoa\0"
+"Andorra\0"
+"Angola\0"
+"Anguilla\0"
+"Antarctica\0"
+"AntiguaAndBarbuda\0"
+"Argentina\0"
+"Armenia\0"
+"Aruba\0"
+"Australia\0"
+"Austria\0"
+"Azerbaijan\0"
+"Bahamas\0"
+"Bahrain\0"
+"Bangladesh\0"
+"Barbados\0"
+"Belarus\0"
+"Belgium\0"
+"Belize\0"
+"Benin\0"
+"Bermuda\0"
+"Bhutan\0"
+"Bolivia\0"
+"BosniaAndHerzegowina\0"
+"Botswana\0"
+"BouvetIsland\0"
+"Brazil\0"
+"BritishIndianOceanTerritory\0"
+"BruneiDarussalam\0"
+"Bulgaria\0"
+"BurkinaFaso\0"
+"Burundi\0"
+"Cambodia\0"
+"Cameroon\0"
+"Canada\0"
+"CapeVerde\0"
+"CaymanIslands\0"
+"CentralAfricanRepublic\0"
+"Chad\0"
+"Chile\0"
+"China\0"
+"ChristmasIsland\0"
+"CocosIslands\0"
+"Colombia\0"
+"Comoros\0"
+"DemocraticRepublicOfCongo\0"
+"PeoplesRepublicOfCongo\0"
+"CookIslands\0"
+"CostaRica\0"
+"IvoryCoast\0"
+"Croatia\0"
+"Cuba\0"
+"Cyprus\0"
+"CzechRepublic\0"
+"Denmark\0"
+"Djibouti\0"
+"Dominica\0"
+"DominicanRepublic\0"
+"EastTimor\0"
+"Ecuador\0"
+"Egypt\0"
+"ElSalvador\0"
+"EquatorialGuinea\0"
+"Eritrea\0"
+"Estonia\0"
+"Ethiopia\0"
+"FalklandIslands\0"
+"FaroeIslands\0"
+"Fiji\0"
+"Finland\0"
+"France\0"
+"MetropolitanFrance\0"
+"FrenchGuiana\0"
+"FrenchPolynesia\0"
+"FrenchSouthernTerritories\0"
+"Gabon\0"
+"Gambia\0"
+"Georgia\0"
+"Germany\0"
+"Ghana\0"
+"Gibraltar\0"
+"Greece\0"
+"Greenland\0"
+"Grenada\0"
+"Guadeloupe\0"
+"Guam\0"
+"Guatemala\0"
+"Guinea\0"
+"GuineaBissau\0"
+"Guyana\0"
+"Haiti\0"
+"HeardAndMcDonaldIslands\0"
+"Honduras\0"
+"HongKong\0"
+"Hungary\0"
+"Iceland\0"
+"India\0"
+"Indonesia\0"
+"Iran\0"
+"Iraq\0"
+"Ireland\0"
+"Israel\0"
+"Italy\0"
+"Jamaica\0"
+"Japan\0"
+"Jordan\0"
+"Kazakhstan\0"
+"Kenya\0"
+"Kiribati\0"
+"DemocraticRepublicOfKorea\0"
+"RepublicOfKorea\0"
+"Kuwait\0"
+"Kyrgyzstan\0"
+"Lao\0"
+"Latvia\0"
+"Lebanon\0"
+"Lesotho\0"
+"Liberia\0"
+"LibyanArabJamahiriya\0"
+"Liechtenstein\0"
+"Lithuania\0"
+"Luxembourg\0"
+"Macau\0"
+"Macedonia\0"
+"Madagascar\0"
+"Malawi\0"
+"Malaysia\0"
+"Maldives\0"
+"Mali\0"
+"Malta\0"
+"MarshallIslands\0"
+"Martinique\0"
+"Mauritania\0"
+"Mauritius\0"
+"Mayotte\0"
+"Mexico\0"
+"Micronesia\0"
+"Moldova\0"
+"Monaco\0"
+"Mongolia\0"
+"Montserrat\0"
+"Morocco\0"
+"Mozambique\0"
+"Myanmar\0"
+"Namibia\0"
+"Nauru\0"
+"Nepal\0"
+"Netherlands\0"
+"NetherlandsAntilles\0"
+"NewCaledonia\0"
+"NewZealand\0"
+"Nicaragua\0"
+"Niger\0"
+"Nigeria\0"
+"Niue\0"
+"NorfolkIsland\0"
+"NorthernMarianaIslands\0"
+"Norway\0"
+"Oman\0"
+"Pakistan\0"
+"Palau\0"
+"PalestinianTerritory\0"
+"Panama\0"
+"PapuaNewGuinea\0"
+"Paraguay\0"
+"Peru\0"
+"Philippines\0"
+"Pitcairn\0"
+"Poland\0"
+"Portugal\0"
+"PuertoRico\0"
+"Qatar\0"
+"Reunion\0"
+"Romania\0"
+"RussianFederation\0"
+"Rwanda\0"
+"SaintKittsAndNevis\0"
+"StLucia\0"
+"StVincentAndTheGrenadines\0"
+"Samoa\0"
+"SanMarino\0"
+"SaoTomeAndPrincipe\0"
+"SaudiArabia\0"
+"Senegal\0"
+"Seychelles\0"
+"SierraLeone\0"
+"Singapore\0"
+"Slovakia\0"
+"Slovenia\0"
+"SolomonIslands\0"
+"Somalia\0"
+"SouthAfrica\0"
+"SouthGeorgiaAndTheSouthSandwichIslands\0"
+"Spain\0"
+"SriLanka\0"
+"StHelena\0"
+"StPierreAndMiquelon\0"
+"Sudan\0"
+"Suriname\0"
+"SvalbardAndJanMayenIslands\0"
+"Swaziland\0"
+"Sweden\0"
+"Switzerland\0"
+"SyrianArabRepublic\0"
+"Taiwan\0"
+"Tajikistan\0"
+"Tanzania\0"
+"Thailand\0"
+"Togo\0"
+"Tokelau\0"
+"Tonga\0"
+"TrinidadAndTobago\0"
+"Tunisia\0"
+"Turkey\0"
+"Turkmenistan\0"
+"TurksAndCaicosIslands\0"
+"Tuvalu\0"
+"Uganda\0"
+"Ukraine\0"
+"UnitedArabEmirates\0"
+"UnitedKingdom\0"
+"UnitedStates\0"
+"UnitedStatesMinorOutlyingIslands\0"
+"Uruguay\0"
+"Uzbekistan\0"
+"Vanuatu\0"
+"VaticanCityState\0"
+"Venezuela\0"
+"VietNam\0"
+"BritishVirginIslands\0"
+"USVirginIslands\0"
+"WallisAndFutunaIslands\0"
+"WesternSahara\0"
+"Yemen\0"
+"Yugoslavia\0"
+"Zambia\0"
+"Zimbabwe\0"
+"SerbiaAndMontenegro\0"
+"Montenegro\0"
+"Serbia\0"
+"Saint Barthelemy\0"
+"Saint Martin\0"
+"LatinAmericaAndTheCaribbean\0"
+;
+
+static const quint16 country_name_index[] = {
+ 0, // AnyCountry
+ 8, // Afghanistan
+ 20, // Albania
+ 28, // Algeria
+ 36, // AmericanSamoa
+ 50, // Andorra
+ 58, // Angola
+ 65, // Anguilla
+ 74, // Antarctica
+ 85, // AntiguaAndBarbuda
+ 103, // Argentina
+ 113, // Armenia
+ 121, // Aruba
+ 127, // Australia
+ 137, // Austria
+ 145, // Azerbaijan
+ 156, // Bahamas
+ 164, // Bahrain
+ 172, // Bangladesh
+ 183, // Barbados
+ 192, // Belarus
+ 200, // Belgium
+ 208, // Belize
+ 215, // Benin
+ 221, // Bermuda
+ 229, // Bhutan
+ 236, // Bolivia
+ 244, // BosniaAndHerzegowina
+ 265, // Botswana
+ 274, // BouvetIsland
+ 287, // Brazil
+ 294, // BritishIndianOceanTerritory
+ 322, // BruneiDarussalam
+ 339, // Bulgaria
+ 348, // BurkinaFaso
+ 360, // Burundi
+ 368, // Cambodia
+ 377, // Cameroon
+ 386, // Canada
+ 393, // CapeVerde
+ 403, // CaymanIslands
+ 417, // CentralAfricanRepublic
+ 440, // Chad
+ 445, // Chile
+ 451, // China
+ 457, // ChristmasIsland
+ 473, // CocosIslands
+ 486, // Colombia
+ 495, // Comoros
+ 503, // DemocraticRepublicOfCongo
+ 529, // PeoplesRepublicOfCongo
+ 552, // CookIslands
+ 564, // CostaRica
+ 574, // IvoryCoast
+ 585, // Croatia
+ 593, // Cuba
+ 598, // Cyprus
+ 605, // CzechRepublic
+ 619, // Denmark
+ 627, // Djibouti
+ 636, // Dominica
+ 645, // DominicanRepublic
+ 663, // EastTimor
+ 673, // Ecuador
+ 681, // Egypt
+ 687, // ElSalvador
+ 698, // EquatorialGuinea
+ 715, // Eritrea
+ 723, // Estonia
+ 731, // Ethiopia
+ 740, // FalklandIslands
+ 756, // FaroeIslands
+ 769, // Fiji
+ 774, // Finland
+ 782, // France
+ 789, // MetropolitanFrance
+ 808, // FrenchGuiana
+ 821, // FrenchPolynesia
+ 837, // FrenchSouthernTerritories
+ 863, // Gabon
+ 869, // Gambia
+ 876, // Georgia
+ 884, // Germany
+ 892, // Ghana
+ 898, // Gibraltar
+ 908, // Greece
+ 915, // Greenland
+ 925, // Grenada
+ 933, // Guadeloupe
+ 944, // Guam
+ 949, // Guatemala
+ 959, // Guinea
+ 966, // GuineaBissau
+ 979, // Guyana
+ 986, // Haiti
+ 992, // HeardAndMcDonaldIslands
+ 1016, // Honduras
+ 1025, // HongKong
+ 1034, // Hungary
+ 1042, // Iceland
+ 1050, // India
+ 1056, // Indonesia
+ 1066, // Iran
+ 1071, // Iraq
+ 1076, // Ireland
+ 1084, // Israel
+ 1091, // Italy
+ 1097, // Jamaica
+ 1105, // Japan
+ 1111, // Jordan
+ 1118, // Kazakhstan
+ 1129, // Kenya
+ 1135, // Kiribati
+ 1144, // DemocraticRepublicOfKorea
+ 1170, // RepublicOfKorea
+ 1186, // Kuwait
+ 1193, // Kyrgyzstan
+ 1204, // Lao
+ 1208, // Latvia
+ 1215, // Lebanon
+ 1223, // Lesotho
+ 1231, // Liberia
+ 1239, // LibyanArabJamahiriya
+ 1260, // Liechtenstein
+ 1274, // Lithuania
+ 1284, // Luxembourg
+ 1295, // Macau
+ 1301, // Macedonia
+ 1311, // Madagascar
+ 1322, // Malawi
+ 1329, // Malaysia
+ 1338, // Maldives
+ 1347, // Mali
+ 1352, // Malta
+ 1358, // MarshallIslands
+ 1374, // Martinique
+ 1385, // Mauritania
+ 1396, // Mauritius
+ 1406, // Mayotte
+ 1414, // Mexico
+ 1421, // Micronesia
+ 1432, // Moldova
+ 1440, // Monaco
+ 1447, // Mongolia
+ 1456, // Montserrat
+ 1467, // Morocco
+ 1475, // Mozambique
+ 1486, // Myanmar
+ 1494, // Namibia
+ 1502, // Nauru
+ 1508, // Nepal
+ 1514, // Netherlands
+ 1526, // NetherlandsAntilles
+ 1546, // NewCaledonia
+ 1559, // NewZealand
+ 1570, // Nicaragua
+ 1580, // Niger
+ 1586, // Nigeria
+ 1594, // Niue
+ 1599, // NorfolkIsland
+ 1613, // NorthernMarianaIslands
+ 1636, // Norway
+ 1643, // Oman
+ 1648, // Pakistan
+ 1657, // Palau
+ 1663, // PalestinianTerritory
+ 1684, // Panama
+ 1691, // PapuaNewGuinea
+ 1706, // Paraguay
+ 1715, // Peru
+ 1720, // Philippines
+ 1732, // Pitcairn
+ 1741, // Poland
+ 1748, // Portugal
+ 1757, // PuertoRico
+ 1768, // Qatar
+ 1774, // Reunion
+ 1782, // Romania
+ 1790, // RussianFederation
+ 1808, // Rwanda
+ 1815, // SaintKittsAndNevis
+ 1834, // StLucia
+ 1842, // StVincentAndTheGrenadines
+ 1868, // Samoa
+ 1874, // SanMarino
+ 1884, // SaoTomeAndPrincipe
+ 1903, // SaudiArabia
+ 1915, // Senegal
+ 1923, // Seychelles
+ 1934, // SierraLeone
+ 1946, // Singapore
+ 1956, // Slovakia
+ 1965, // Slovenia
+ 1974, // SolomonIslands
+ 1989, // Somalia
+ 1997, // SouthAfrica
+ 2009, // SouthGeorgiaAndTheSouthSandwichIslands
+ 2048, // Spain
+ 2054, // SriLanka
+ 2063, // StHelena
+ 2072, // StPierreAndMiquelon
+ 2092, // Sudan
+ 2098, // Suriname
+ 2107, // SvalbardAndJanMayenIslands
+ 2134, // Swaziland
+ 2144, // Sweden
+ 2151, // Switzerland
+ 2163, // SyrianArabRepublic
+ 2182, // Taiwan
+ 2189, // Tajikistan
+ 2200, // Tanzania
+ 2209, // Thailand
+ 2218, // Togo
+ 2223, // Tokelau
+ 2231, // Tonga
+ 2237, // TrinidadAndTobago
+ 2255, // Tunisia
+ 2263, // Turkey
+ 2270, // Turkmenistan
+ 2283, // TurksAndCaicosIslands
+ 2305, // Tuvalu
+ 2312, // Uganda
+ 2319, // Ukraine
+ 2327, // UnitedArabEmirates
+ 2346, // UnitedKingdom
+ 2360, // UnitedStates
+ 2373, // UnitedStatesMinorOutlyingIslands
+ 2406, // Uruguay
+ 2414, // Uzbekistan
+ 2425, // Vanuatu
+ 2433, // VaticanCityState
+ 2450, // Venezuela
+ 2460, // VietNam
+ 2468, // BritishVirginIslands
+ 2489, // USVirginIslands
+ 2505, // WallisAndFutunaIslands
+ 2528, // WesternSahara
+ 2542, // Yemen
+ 2548, // Yugoslavia
+ 2559, // Zambia
+ 2566, // Zimbabwe
+ 2575, // SerbiaAndMontenegro
+ 2595, // Montenegro
+ 2606, // Serbia
+ 2613, // Saint Barthelemy
+ 2630, // Saint Martin
+ 2643, // LatinAmericaAndTheCaribbean
+};
+
+static const unsigned char language_code_list[] =
+" \0" // AnyLanguage
+" \0" // C
+"ab\0" // Abkhazian
+"om\0" // Afan
+"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" // Bhutani
+"bh\0" // Bihari
+"bi\0" // Bislama
+"br\0" // Breton
+"bg\0" // Bulgarian
+"my\0" // Burmese
+"be\0" // Byelorussian
+"km\0" // Cambodian
+"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" // Fiji
+"fi\0" // Finnish
+"fr\0" // French
+"fy\0" // 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" // Kurundi
+"lo\0" // Laothian
+"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
+"mo\0" // Moldavian
+"mn\0" // Mongolian
+"na\0" // Nauru
+"ne\0" // Nepali
+"nb\0" // Norwegian
+"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" // RhaetoRomance
+"ro\0" // Romanian
+"ru\0" // Russian
+"sm\0" // Samoan
+"sg\0" // Sangho
+"sa\0" // Sanskrit
+"sr\0" // Serbian
+"sh\0" // SerboCroatian
+"st\0" // Sesotho
+"tn\0" // Setswana
+"sn\0" // Shona
+"sd\0" // Sindhi
+"si\0" // Singhalese
+"ss\0" // Siswati
+"sk\0" // Slovak
+"sl\0" // Slovenian
+"so\0" // Somali
+"es\0" // Spanish
+"su\0" // Sundanese
+"sw\0" // Swahili
+"sv\0" // Swedish
+"tl\0" // Tagalog
+"tg\0" // Tajik
+"ta\0" // Tamil
+"tt\0" // Tatar
+"te\0" // Telugu
+"th\0" // Thai
+"bo\0" // Tibetan
+"ti\0" // Tigrinya
+"to\0" // Tonga
+"ts\0" // Tsonga
+"tr\0" // Turkish
+"tk\0" // Turkmen
+"tw\0" // Twi
+"ug\0" // Uigur
+"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" // 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" // Chewa
+"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
+;
+
+static const unsigned char script_code_list[] =
+"\0\0\0\0" // AnyScript
+"Arab" // Arabic
+"Cyrl" // Cyrillic
+"Dsrt" // Deseret
+"Guru" // Gurmukhi
+"Hans" // Simplified Han
+"Hant" // Traditional Han
+"Latn" // Latin
+"Mong" // Mongolian
+"Tfng" // Tifinagh
+;
+static const unsigned char country_code_list[] =
+" \0" // AnyCountry
+"AF\0" // Afghanistan
+"AL\0" // Albania
+"DZ\0" // Algeria
+"AS\0" // AmericanSamoa
+"AD\0" // Andorra
+"AO\0" // Angola
+"AI\0" // Anguilla
+"AQ\0" // Antarctica
+"AG\0" // AntiguaAndBarbuda
+"AR\0" // Argentina
+"AM\0" // Armenia
+"AW\0" // Aruba
+"AU\0" // Australia
+"AT\0" // Austria
+"AZ\0" // Azerbaijan
+"BS\0" // Bahamas
+"BH\0" // Bahrain
+"BD\0" // Bangladesh
+"BB\0" // Barbados
+"BY\0" // Belarus
+"BE\0" // Belgium
+"BZ\0" // Belize
+"BJ\0" // Benin
+"BM\0" // Bermuda
+"BT\0" // Bhutan
+"BO\0" // Bolivia
+"BA\0" // BosniaAndHerzegowina
+"BW\0" // Botswana
+"BV\0" // BouvetIsland
+"BR\0" // Brazil
+"IO\0" // BritishIndianOceanTerritory
+"BN\0" // BruneiDarussalam
+"BG\0" // Bulgaria
+"BF\0" // BurkinaFaso
+"BI\0" // Burundi
+"KH\0" // Cambodia
+"CM\0" // Cameroon
+"CA\0" // Canada
+"CV\0" // CapeVerde
+"KY\0" // CaymanIslands
+"CF\0" // CentralAfricanRepublic
+"TD\0" // Chad
+"CL\0" // Chile
+"CN\0" // China
+"CX\0" // ChristmasIsland
+"CC\0" // CocosIslands
+"CO\0" // Colombia
+"KM\0" // Comoros
+"CD\0" // DemocraticRepublicOfCongo
+"CG\0" // PeoplesRepublicOfCongo
+"CK\0" // CookIslands
+"CR\0" // CostaRica
+"CI\0" // IvoryCoast
+"HR\0" // Croatia
+"CU\0" // Cuba
+"CY\0" // Cyprus
+"CZ\0" // CzechRepublic
+"DK\0" // Denmark
+"DJ\0" // Djibouti
+"DM\0" // Dominica
+"DO\0" // DominicanRepublic
+"TL\0" // EastTimor
+"EC\0" // Ecuador
+"EG\0" // Egypt
+"SV\0" // ElSalvador
+"GQ\0" // EquatorialGuinea
+"ER\0" // Eritrea
+"EE\0" // Estonia
+"ET\0" // Ethiopia
+"FK\0" // FalklandIslands
+"FO\0" // FaroeIslands
+"FJ\0" // Fiji
+"FI\0" // Finland
+"FR\0" // France
+"FX\0" // MetropolitanFrance
+"GF\0" // FrenchGuiana
+"PF\0" // FrenchPolynesia
+"TF\0" // FrenchSouthernTerritories
+"GA\0" // Gabon
+"GM\0" // Gambia
+"GE\0" // Georgia
+"DE\0" // Germany
+"GH\0" // Ghana
+"GI\0" // Gibraltar
+"GR\0" // Greece
+"GL\0" // Greenland
+"GD\0" // Grenada
+"GP\0" // Guadeloupe
+"GU\0" // Guam
+"GT\0" // Guatemala
+"GN\0" // Guinea
+"GW\0" // GuineaBissau
+"GY\0" // Guyana
+"HT\0" // Haiti
+"HM\0" // HeardAndMcDonaldIslands
+"HN\0" // Honduras
+"HK\0" // HongKong
+"HU\0" // Hungary
+"IS\0" // Iceland
+"IN\0" // India
+"ID\0" // Indonesia
+"IR\0" // Iran
+"IQ\0" // Iraq
+"IE\0" // Ireland
+"IL\0" // Israel
+"IT\0" // Italy
+"JM\0" // Jamaica
+"JP\0" // Japan
+"JO\0" // Jordan
+"KZ\0" // Kazakhstan
+"KE\0" // Kenya
+"KI\0" // Kiribati
+"KP\0" // DemocraticRepublicOfKorea
+"KR\0" // RepublicOfKorea
+"KW\0" // Kuwait
+"KG\0" // Kyrgyzstan
+"LA\0" // Lao
+"LV\0" // Latvia
+"LB\0" // Lebanon
+"LS\0" // Lesotho
+"LR\0" // Liberia
+"LY\0" // LibyanArabJamahiriya
+"LI\0" // Liechtenstein
+"LT\0" // Lithuania
+"LU\0" // Luxembourg
+"MO\0" // Macau
+"MK\0" // Macedonia
+"MG\0" // Madagascar
+"MW\0" // Malawi
+"MY\0" // Malaysia
+"MV\0" // Maldives
+"ML\0" // Mali
+"MT\0" // Malta
+"MH\0" // MarshallIslands
+"MQ\0" // Martinique
+"MR\0" // Mauritania
+"MU\0" // Mauritius
+"YT\0" // Mayotte
+"MX\0" // Mexico
+"FM\0" // Micronesia
+"MD\0" // Moldova
+"MC\0" // Monaco
+"MN\0" // Mongolia
+"MS\0" // Montserrat
+"MA\0" // Morocco
+"MZ\0" // Mozambique
+"MM\0" // Myanmar
+"NA\0" // Namibia
+"NR\0" // Nauru
+"NP\0" // Nepal
+"NL\0" // Netherlands
+"AN\0" // NetherlandsAntilles
+"NC\0" // NewCaledonia
+"NZ\0" // NewZealand
+"NI\0" // Nicaragua
+"NE\0" // Niger
+"NG\0" // Nigeria
+"NU\0" // Niue
+"NF\0" // NorfolkIsland
+"MP\0" // NorthernMarianaIslands
+"NO\0" // Norway
+"OM\0" // Oman
+"PK\0" // Pakistan
+"PW\0" // Palau
+"PS\0" // PalestinianTerritory
+"PA\0" // Panama
+"PG\0" // PapuaNewGuinea
+"PY\0" // Paraguay
+"PE\0" // Peru
+"PH\0" // Philippines
+"PN\0" // Pitcairn
+"PL\0" // Poland
+"PT\0" // Portugal
+"PR\0" // PuertoRico
+"QA\0" // Qatar
+"RE\0" // Reunion
+"RO\0" // Romania
+"RU\0" // RussianFederation
+"RW\0" // Rwanda
+"KN\0" // SaintKittsAndNevis
+"LC\0" // StLucia
+"VC\0" // StVincentAndTheGrenadines
+"WS\0" // Samoa
+"SM\0" // SanMarino
+"ST\0" // SaoTomeAndPrincipe
+"SA\0" // SaudiArabia
+"SN\0" // Senegal
+"SC\0" // Seychelles
+"SL\0" // SierraLeone
+"SG\0" // Singapore
+"SK\0" // Slovakia
+"SI\0" // Slovenia
+"SB\0" // SolomonIslands
+"SO\0" // Somalia
+"ZA\0" // SouthAfrica
+"GS\0" // SouthGeorgiaAndTheSouthSandwichIslands
+"ES\0" // Spain
+"LK\0" // SriLanka
+"SH\0" // StHelena
+"PM\0" // StPierreAndMiquelon
+"SD\0" // Sudan
+"SR\0" // Suriname
+"SJ\0" // SvalbardAndJanMayenIslands
+"SZ\0" // Swaziland
+"SE\0" // Sweden
+"CH\0" // Switzerland
+"SY\0" // SyrianArabRepublic
+"TW\0" // Taiwan
+"TJ\0" // Tajikistan
+"TZ\0" // Tanzania
+"TH\0" // Thailand
+"TG\0" // Togo
+"TK\0" // Tokelau
+"TO\0" // Tonga
+"TT\0" // TrinidadAndTobago
+"TN\0" // Tunisia
+"TR\0" // Turkey
+"TM\0" // Turkmenistan
+"TC\0" // TurksAndCaicosIslands
+"TV\0" // Tuvalu
+"UG\0" // Uganda
+"UA\0" // Ukraine
+"AE\0" // UnitedArabEmirates
+"GB\0" // UnitedKingdom
+"US\0" // UnitedStates
+"UM\0" // UnitedStatesMinorOutlyingIslands
+"UY\0" // Uruguay
+"UZ\0" // Uzbekistan
+"VU\0" // Vanuatu
+"VA\0" // VaticanCityState
+"VE\0" // Venezuela
+"VN\0" // VietNam
+"VG\0" // BritishVirginIslands
+"VI\0" // USVirginIslands
+"WF\0" // WallisAndFutunaIslands
+"EH\0" // WesternSahara
+"YE\0" // Yemen
+"YU\0" // Yugoslavia
+"ZM\0" // Zambia
+"ZW\0" // Zimbabwe
+"CS\0" // SerbiaAndMontenegro
+"ME\0" // Montenegro
+"RS\0" // Serbia
+"BL\0" // Saint Barthelemy
+"MF\0" // Saint Martin
+"419" // LatinAmericaAndTheCaribbean
+;
+
+// GENERATED PART ENDS HERE
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp
new file mode 100644
index 0000000000..0e283dd0bb
--- /dev/null
+++ b/src/corelib/tools/qlocale_icu.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+#include "qlibrary.h"
+#include "qdebug.h"
+
+#include "unicode/uversion.h"
+#include "unicode/ucol.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status);
+typedef void (*Ptr_ucol_close)(UCollator *coll);
+typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength);
+typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode);
+
+static Ptr_ucol_open ptr_ucol_open = 0;
+static Ptr_ucol_strcoll ptr_ucol_strcoll = 0;
+static Ptr_ucol_close ptr_ucol_close = 0;
+static Ptr_u_strToCase ptr_u_strToUpper = 0;
+static Ptr_u_strToCase ptr_u_strToLower = 0;
+
+enum LibLoadStatus
+{
+ ErrorLoading = -1,
+ NotLoaded = 0,
+ Loaded = 1
+};
+
+static LibLoadStatus status = NotLoaded;
+
+static UCollator *icuCollator = 0;
+
+#define STRINGIFY2(x) #x
+#define STRINGIFY(x) STRINGIFY2(x)
+
+bool qt_initIcu(const QString &localeString)
+{
+ if (status == ErrorLoading)
+ return false;
+
+ if (status == NotLoaded) {
+
+ // resolve libicui18n
+ QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT));
+ if (!lib.load()) {
+ qWarning() << "Unable to load library icui18n" << lib.errorString();
+ status = ErrorLoading;
+ return false;
+ }
+
+ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open");
+ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close");
+ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll");
+
+ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+ // try again with decorated symbol names
+ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ }
+
+ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+ ptr_ucol_open = 0;
+ ptr_ucol_close = 0;
+ ptr_ucol_strcoll = 0;
+
+ qWarning("Unable to find symbols in icui18n");
+ status = ErrorLoading;
+ return false;
+ }
+
+ // resolve libicuuc
+ QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT));
+ if (!ucLib.load()) {
+ qWarning() << "Unable to load library icuuc" << ucLib.errorString();
+ status = ErrorLoading;
+ return false;
+ }
+
+ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper");
+ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower");
+
+ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ }
+
+ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+ ptr_u_strToUpper = 0;
+ ptr_u_strToLower = 0;
+
+ qWarning("Unable to find symbols in icuuc");
+ status = ErrorLoading;
+ return false;
+ }
+
+ // success :)
+ status = Loaded;
+ }
+
+ if (icuCollator) {
+ ptr_ucol_close(icuCollator);
+ icuCollator = 0;
+ }
+
+ UErrorCode icuStatus = U_ZERO_ERROR;
+ icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus);
+
+ if (!icuCollator) {
+ qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus);
+ return false;
+ }
+
+ return true;
+}
+
+bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result)
+{
+ Q_ASSERT(result);
+ Q_ASSERT(source);
+ Q_ASSERT(target);
+
+ if (!icuCollator)
+ return false;
+
+ *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength),
+ reinterpret_cast<const UChar *>(target), int32_t(targetLength));
+
+ return true;
+}
+
+// caseFunc can either be u_strToUpper or u_strToLower
+static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc)
+{
+ Q_ASSERT(out);
+
+ if (!icuCollator)
+ return false;
+
+ QString result(str.size(), Qt::Uninitialized);
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+ reinterpret_cast<const UChar *>(str.constData()), str.size(),
+ locale.bcp47Name().toLatin1().constData(), &status);
+
+ if (U_FAILURE(status))
+ return false;
+
+ if (size < result.size()) {
+ result.resize(size);
+ } else if (size > result.size()) {
+ // the resulting string is larger than our source string
+ result.resize(size);
+
+ status = U_ZERO_ERROR;
+ size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+ reinterpret_cast<const UChar *>(str.constData()), str.size(),
+ locale.bcp47Name().toLatin1().constData(), &status);
+
+ if (U_FAILURE(status))
+ return false;
+
+ // if the sizes don't match now, we give up.
+ if (size != result.size())
+ return false;
+ }
+
+ *out = result;
+ return true;
+}
+
+bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale)
+{
+ return qt_u_strToCase(str, out, locale, ptr_u_strToUpper);
+}
+
+bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale)
+{
+ return qt_u_strToCase(str, out, locale, ptr_u_strToLower);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
new file mode 100644
index 0000000000..52005e0264
--- /dev/null
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -0,0 +1,463 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocale_p.h"
+
+#include "qstringlist.h"
+#include "qvariant.h"
+#include "qdatetime.h"
+
+#if !defined(QWS) && defined(Q_OS_MAC)
+# include "private/qcore_mac_p.h"
+# include <CoreFoundation/CoreFoundation.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/******************************************************************************
+** Wrappers for Mac locale system functions
+*/
+
+static QByteArray envVarLocale()
+{
+ static QByteArray lang = 0;
+#ifdef Q_OS_UNIX
+ lang = qgetenv("LC_ALL");
+ if (lang.isEmpty())
+ lang = qgetenv("LC_NUMERIC");
+ if (lang.isEmpty())
+#endif
+ lang = qgetenv("LANG");
+ return lang;
+}
+
+static QByteArray getMacLocaleName()
+{
+ QByteArray result = envVarLocale();
+
+ QString lang, script, cntry;
+ if (result.isEmpty() || result != "C"
+ && !qt_splitLocaleName(QString::fromLocal8Bit(result), lang, script, cntry)) {
+ QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
+ CFStringRef locale = CFLocaleGetIdentifier(l);
+ result = QCFString::toQString(locale).toUtf8();
+ }
+ return result;
+}
+
+static QString macMonthName(int month, bool short_format)
+{
+ month -= 1;
+ if (month < 0 || month > 11)
+ return QString();
+
+ QCFType<CFDateFormatterRef> formatter
+ = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
+ kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+ QCFType<CFArrayRef> values
+ = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
+ short_format ? kCFDateFormatterShortMonthSymbols
+ : kCFDateFormatterMonthSymbols));
+ if (values != 0) {
+ CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
+ return QCFString::toQString(cfstring);
+ }
+ return QString();
+}
+
+static QString macDayName(int day, bool short_format)
+{
+ if (day < 1 || day > 7)
+ return QString();
+
+ QCFType<CFDateFormatterRef> formatter
+ = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
+ kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+ QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
+ short_format ? kCFDateFormatterShortWeekdaySymbols
+ : kCFDateFormatterWeekdaySymbols));
+ if (values != 0) {
+ CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
+ return QCFString::toQString(cfstring);
+ }
+ return QString();
+}
+
+static QString macDateToString(const QDate &date, bool short_format)
+{
+ CFGregorianDate macGDate;
+ macGDate.year = date.year();
+ macGDate.month = date.month();
+ macGDate.day = date.day();
+ macGDate.hour = 0;
+ macGDate.minute = 0;
+ macGDate.second = 0.0;
+ QCFType<CFDateRef> myDate
+ = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
+ QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
+ QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
+ CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
+ QCFType<CFDateFormatterRef> myFormatter
+ = CFDateFormatterCreate(kCFAllocatorDefault,
+ mylocale, style,
+ kCFDateFormatterNoStyle);
+ return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+}
+
+static QString macTimeToString(const QTime &time, bool short_format)
+{
+ CFGregorianDate macGDate;
+ // Assume this is local time and the current date
+ QDate dt = QDate::currentDate();
+ macGDate.year = dt.year();
+ macGDate.month = dt.month();
+ macGDate.day = dt.day();
+ macGDate.hour = time.hour();
+ macGDate.minute = time.minute();
+ macGDate.second = time.second();
+ QCFType<CFDateRef> myDate
+ = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
+ QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
+
+ QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
+ CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
+ QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
+ mylocale,
+ kCFDateFormatterNoStyle,
+ style);
+ return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+}
+
+static QString macToQtFormat(const QString &sys_fmt)
+{
+ QString result;
+ int 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("''");
+ else
+ result += QLatin1Char('\'') + text + QLatin1Char('\'');
+ continue;
+ }
+
+ QChar c = sys_fmt.at(i);
+ int repeat = qt_repeatCount(sys_fmt, i);
+
+ switch (c.unicode()) {
+ case 'G': // Qt doesn't support these :(
+ case 'Y':
+ case 'D':
+ case 'F':
+ case 'w':
+ case 'W':
+ case 'g':
+ break;
+
+ case 'u': // extended year - use 'y'
+ if (repeat < 4)
+ result += QLatin1String("yy");
+ else
+ result += QLatin1String("yyyy");
+ break;
+ case 'S': // fractional second
+ if (repeat < 3)
+ result += QLatin1Char('z');
+ else
+ result += QLatin1String("zzz");
+ break;
+ case 'E':
+ if (repeat <= 3)
+ result += QLatin1String("ddd");
+ else
+ result += QLatin1String("dddd");
+ break;
+ case 'e':
+ if (repeat >= 2)
+ result += QLatin1String("dd");
+ else
+ result += QLatin1Char('d');
+ break;
+ case 'a':
+ result += QLatin1String("AP");
+ break;
+ case 'k':
+ result += QString(repeat, QLatin1Char('H'));
+ break;
+ case 'K':
+ result += QString(repeat, QLatin1Char('h'));
+ break;
+ case 'z':
+ case 'Z':
+ case 'v':
+ result += QLatin1Char('t');
+ break;
+ default:
+ result += QString(repeat, c);
+ break;
+ }
+
+ i += repeat;
+ }
+
+ return result;
+}
+
+QString getMacDateFormat(CFDateFormatterStyle style)
+{
+ QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
+ QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
+ l, style, kCFDateFormatterNoStyle);
+ return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
+}
+
+static QString getMacTimeFormat(CFDateFormatterStyle style)
+{
+ QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
+ QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
+ l, kCFDateFormatterNoStyle, style);
+ return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
+}
+
+static QString getCFLocaleValue(CFStringRef key)
+{
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ CFTypeRef value = CFLocaleGetValue(locale, key);
+ return QCFString::toQString(CFStringRef(static_cast<CFTypeRef>(value)));
+}
+
+static QLocale::MeasurementSystem macMeasurementSystem()
+{
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ CFStringRef system = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleMeasurementSystem));
+ if (QCFString::toQString(system) == QLatin1String("Metric")) {
+ return QLocale::MetricSystem;
+ } else {
+ return QLocale::ImperialSystem;
+ }
+}
+
+
+static quint8 macFirstDayOfWeek()
+{
+ QCFType<CFCalendarRef> calendar = CFCalendarCopyCurrent();
+ quint8 day = static_cast<quint8>(CFCalendarGetFirstWeekday(calendar))-1;
+ if (day == 0)
+ day = 7;
+ return day;
+}
+
+static QString macCurrencySymbol(QLocale::CurrencySymbolFormat format)
+{
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ switch (format) {
+ case QLocale::CurrencyIsoCode:
+ return QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencyCode)));
+ case QLocale::CurrencySymbol:
+ return QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencySymbol)));
+ case QLocale::CurrencyDisplayName: {
+ CFStringRef code = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencyCode));
+ QCFType<CFStringRef> value = CFLocaleCopyDisplayNameForPropertyValue(locale, kCFLocaleCurrencyCode, code);
+ return QCFString::toQString(value);
+ }
+ default:
+ break;
+ }
+ return QString();
+}
+
+#ifndef QT_NO_SYSTEMLOCALE
+static QString macFormatCurrency(const QSystemLocale::CurrencyToStringArgument &arg)
+{
+ QCFType<CFNumberRef> value;
+ switch (arg.value.type()) {
+ case QVariant::Int:
+ case QVariant::UInt: {
+ int v = arg.value.toInt();
+ value = CFNumberCreate(NULL, kCFNumberIntType, &v);
+ break;
+ }
+ case QVariant::Double: {
+ double v = arg.value.toDouble();
+ value = CFNumberCreate(NULL, kCFNumberDoubleType, &v);
+ break;
+ }
+ case QVariant::LongLong:
+ case QVariant::ULongLong: {
+ qint64 v = arg.value.toLongLong();
+ value = CFNumberCreate(NULL, kCFNumberLongLongType, &v);
+ break;
+ }
+ default:
+ return QString();
+ }
+
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ QCFType<CFNumberFormatterRef> currencyFormatter =
+ CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterCurrencyStyle);
+ if (!arg.symbol.isEmpty()) {
+ CFNumberFormatterSetProperty(currencyFormatter, kCFNumberFormatterCurrencySymbol,
+ QCFString::toCFStringRef(arg.symbol));
+ }
+ QCFType<CFStringRef> result = CFNumberFormatterCreateStringWithNumber(NULL, currencyFormatter, value);
+ return QCFString::toQString(result);
+}
+
+static QVariant macQuoteString(QSystemLocale::QueryType type, const QStringRef &str)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
+ return QVariant();
+
+ QString begin, end;
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ switch (type) {
+ case QSystemLocale::StringToStandardQuotation:
+ begin = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleQuotationBeginDelimiterKey)));
+ end = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleQuotationEndDelimiterKey)));
+ return QString(begin % str % end);
+ case QSystemLocale::StringToAlternateQuotation:
+ begin = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationBeginDelimiterKey)));
+ end = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationEndDelimiterKey)));
+ return QString(begin % str % end);
+ default:
+ break;
+ }
+#endif
+ return QVariant();
+}
+#endif //QT_NO_SYSTEMLOCALE
+
+#ifndef QT_NO_SYSTEMLOCALE
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+ return QLocale(QString::fromUtf8(getMacLocaleName().constData()));
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
+{
+ switch(type) {
+// case Name:
+// return getMacLocaleName();
+ case DecimalPoint: {
+ QString value = getCFLocaleValue(kCFLocaleDecimalSeparator);
+ return value.isEmpty() ? QVariant() : value;
+ }
+ case GroupSeparator: {
+ QString value = getCFLocaleValue(kCFLocaleGroupingSeparator);
+ return value.isEmpty() ? QVariant() : value;
+ }
+ case DateFormatLong:
+ case DateFormatShort:
+ return getMacDateFormat(type == DateFormatShort
+ ? kCFDateFormatterShortStyle
+ : kCFDateFormatterLongStyle);
+ case TimeFormatLong:
+ case TimeFormatShort:
+ return getMacTimeFormat(type == TimeFormatShort
+ ? kCFDateFormatterShortStyle
+ : kCFDateFormatterLongStyle);
+ case DayNameLong:
+ case DayNameShort:
+ return macDayName(in.toInt(), (type == DayNameShort));
+ case MonthNameLong:
+ case MonthNameShort:
+ return macMonthName(in.toInt(), (type == MonthNameShort));
+ case DateToStringShort:
+ case DateToStringLong:
+ return macDateToString(in.toDate(), (type == DateToStringShort));
+ case TimeToStringShort:
+ case TimeToStringLong:
+ return macTimeToString(in.toTime(), (type == TimeToStringShort));
+
+ case NegativeSign:
+ case PositiveSign:
+ case ZeroDigit:
+ break;
+
+ case MeasurementSystem:
+ return QVariant(static_cast<int>(macMeasurementSystem()));
+
+ case AMText:
+ case PMText: {
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterLongStyle, kCFDateFormatterLongStyle);
+ QCFType<CFStringRef> value = static_cast<CFStringRef>(CFDateFormatterCopyProperty(formatter,
+ (type == AMText ? kCFDateFormatterAMSymbol : kCFDateFormatterPMSymbol)));
+ return QCFString::toQString(value);
+ }
+ case FirstDayOfWeek:
+ return QVariant(macFirstDayOfWeek());
+ case CurrencySymbol:
+ return QVariant(macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt())));
+ case CurrencyToString:
+ return macFormatCurrency(in.value<QSystemLocale::CurrencyToStringArgument>());
+ case UILanguages: {
+ QCFType<CFArrayRef> languages = (CFArrayRef)CFPreferencesCopyValue(
+ CFSTR("AppleLanguages"),
+ kCFPreferencesAnyApplication,
+ kCFPreferencesCurrentUser,
+ kCFPreferencesAnyHost);
+ const int cnt = CFArrayGetCount(languages);
+ QStringList result;
+ result.reserve(cnt);
+ for (int i = 0; i < cnt; ++i) {
+ const QString lang = QCFString::toQString(
+ static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages, i)));
+ result.append(lang);
+ }
+ return QVariant(result);
+ }
+ case StringToStandardQuotation:
+ case StringToAlternateQuotation:
+ return macQuoteString(type, in.value<QStringRef>());
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+#endif // QT_NO_SYSTEMLOCALE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
new file mode 100644
index 0000000000..1b31929182
--- /dev/null
+++ b/src/corelib/tools/qlocale_p.h
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCALE_P_H
+#define QLOCALE_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/qstring.h"
+#include "QtCore/qvarlengtharray.h"
+#include "QtCore/qmetatype.h"
+
+#include "qlocale.h"
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+class CEnvironmentChangeNotifier;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+struct Q_CORE_EXPORT QLocalePrivate
+{
+public:
+ QChar decimal() const { return QChar(m_decimal); }
+ QChar group() const { return QChar(m_group); }
+ QChar list() const { return QChar(m_list); }
+ QChar percent() const { return QChar(m_percent); }
+ QChar zero() const { return QChar(m_zero); }
+ QChar plus() const { return QChar(m_plus); }
+ QChar minus() const { return QChar(m_minus); }
+ QChar exponential() const { return QChar(m_exponential); }
+
+ quint16 languageId() const { return m_language_id; }
+ quint16 countryId() const { return m_country_id; }
+
+ QString bcp47Name() const;
+
+ QString languageCode() const; // ### QByteArray::fromRawData would be more optimal
+ QString scriptCode() const;
+ QString countryCode() const;
+
+ static QLocale::Language codeToLanguage(const QString &code);
+ static QLocale::Script codeToScript(const QString &code);
+ static QLocale::Country codeToCountry(const QString &code);
+ static void getLangAndCountry(const QString &name, QLocale::Language &lang,
+ QLocale::Script &script, QLocale::Country &cntry);
+ static const QLocalePrivate *findLocale(QLocale::Language language,
+ QLocale::Script script,
+ QLocale::Country country);
+
+
+ QLocale::MeasurementSystem measurementSystem() const;
+
+ enum DoubleForm {
+ DFExponent = 0,
+ DFDecimal,
+ DFSignificantDigits,
+ _DFMax = DFSignificantDigits
+ };
+
+ enum Flags {
+ NoFlags = 0,
+ Alternate = 0x01,
+ ZeroPadded = 0x02,
+ LeftAdjusted = 0x04,
+ BlankBeforePositive = 0x08,
+ AlwaysShowSign = 0x10,
+ ThousandsGroup = 0x20,
+ CapitalEorX = 0x40,
+
+ ShowBase = 0x80,
+ UppercaseBase = 0x100,
+ ForcePoint = Alternate
+ };
+
+ enum GroupSeparatorMode {
+ FailOnGroupSeparators,
+ ParseGroupSeparators
+ };
+
+ static QString doubleToString(const QChar zero, const QChar plus,
+ const QChar minus, const QChar exponent,
+ const QChar group, const QChar decimal,
+ double d, int precision,
+ DoubleForm form,
+ int width, unsigned flags);
+ static QString longLongToString(const QChar zero, const QChar group,
+ const QChar plus, const QChar minus,
+ qint64 l, int precision, int base,
+ int width, unsigned flags);
+ static QString unsLongLongToString(const QChar zero, const QChar group,
+ const QChar 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;
+ double stringToDouble(const QString &num, bool *ok, GroupSeparatorMode group_sep_mode) const;
+ qint64 stringToLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
+ quint64 stringToUnsLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const;
+
+
+ static double bytearrayToDouble(const char *num, bool *ok, bool *overflow = 0);
+ static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow = 0);
+ static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok);
+
+ typedef QVarLengthArray<char, 256> CharBuff;
+ bool numberToCLocale(const QString &num,
+ GroupSeparatorMode group_sep_mode,
+ CharBuff *result) const;
+ inline char digitToCLocale(const QChar &c) const;
+
+ static void updateSystemPrivate();
+
+ enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };
+ bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const;
+
+ QString dateTimeToString(const QString &format, const QDate *date, const QTime *time,
+ const QLocale *q) const;
+
+ quint16 m_language_id, m_script_id, m_country_id;
+
+ quint16 m_decimal, m_group, m_list, m_percent,
+ m_zero, m_minus, m_plus, m_exponential;
+ quint16 m_quotation_start, m_quotation_end;
+ quint16 m_alternate_quotation_start, m_alternate_quotation_end;
+
+ quint16 m_list_pattern_part_start_idx, m_list_pattern_part_start_size;
+ quint16 m_list_pattern_part_mid_idx, m_list_pattern_part_mid_size;
+ quint16 m_list_pattern_part_end_idx, m_list_pattern_part_end_size;
+ quint16 m_list_pattern_part_two_idx, m_list_pattern_part_two_size;
+ quint16 m_short_date_format_idx, m_short_date_format_size;
+ quint16 m_long_date_format_idx, m_long_date_format_size;
+ quint16 m_short_time_format_idx, m_short_time_format_size;
+ quint16 m_long_time_format_idx, m_long_time_format_size;
+ quint16 m_standalone_short_month_names_idx, m_standalone_short_month_names_size;
+ quint16 m_standalone_long_month_names_idx, m_standalone_long_month_names_size;
+ quint16 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size;
+ quint16 m_short_month_names_idx, m_short_month_names_size;
+ quint16 m_long_month_names_idx, m_long_month_names_size;
+ quint16 m_narrow_month_names_idx, m_narrow_month_names_size;
+ quint16 m_standalone_short_day_names_idx, m_standalone_short_day_names_size;
+ quint16 m_standalone_long_day_names_idx, m_standalone_long_day_names_size;
+ quint16 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size;
+ quint16 m_short_day_names_idx, m_short_day_names_size;
+ quint16 m_long_day_names_idx, m_long_day_names_size;
+ quint16 m_narrow_day_names_idx, m_narrow_day_names_size;
+ quint16 m_am_idx, m_am_size;
+ quint16 m_pm_idx, m_pm_size;
+ char m_currency_iso_code[3];
+ quint16 m_currency_symbol_idx, m_currency_symbol_size;
+ quint16 m_currency_display_name_idx, m_currency_display_name_size;
+ quint8 m_currency_format_idx, m_currency_format_size;
+ quint8 m_currency_negative_format_idx, m_currency_negative_format_size;
+ quint16 m_language_endonym_idx, m_language_endonym_size;
+ quint16 m_country_endonym_idx, m_country_endonym_size;
+ quint16 m_currency_digits : 2;
+ quint16 m_currency_rounding : 3;
+ quint16 m_first_day_of_week : 3;
+ quint16 m_weekend_start : 3;
+ quint16 m_weekend_end : 3;
+
+};
+
+inline char QLocalePrivate::digitToCLocale(const QChar &in) const
+{
+ const QChar _zero = zero();
+ const QChar _group = group();
+ const ushort zeroUnicode = _zero.unicode();
+ const ushort tenUnicode = zeroUnicode + 10;
+
+ if (in.unicode() >= zeroUnicode && in.unicode() < tenUnicode)
+ return '0' + in.unicode() - zeroUnicode;
+
+ if (in.unicode() >= '0' && in.unicode() <= '9')
+ return in.toLatin1();
+
+ if (in == plus())
+ return '+';
+
+ if (in == minus())
+ return '-';
+
+ if (in == decimal())
+ return '.';
+
+ if (in == group())
+ return ',';
+
+ if (in == exponential() || in == exponential().toUpper())
+ return 'e';
+
+ // In several languages group() is the char 0xA0, which looks like a space.
+ // People use a regular space instead of it and complain it doesn't work.
+ if (_group.unicode() == 0xA0 && in.unicode() == ' ')
+ return ',';
+
+ return 0;
+}
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+class QEnvironmentChangeNotifier
+{
+public:
+ QEnvironmentChangeNotifier();
+ ~QEnvironmentChangeNotifier();
+
+ static TInt localeChanged(TAny *data);
+
+private:
+ CEnvironmentChangeNotifier *iChangeNotifier;
+};
+#endif
+
+QString qt_readEscapedFormatString(const QString &format, int *idx);
+bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry);
+int qt_repeatCount(const QString &s, int i);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QStringRef)
+Q_DECLARE_METATYPE(QList<Qt::DayOfWeek>)
+
+#endif // QLOCALE_P_H
diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp
new file mode 100644
index 0000000000..09d74d0136
--- /dev/null
+++ b/src/corelib/tools/qlocale_symbian.cpp
@@ -0,0 +1,929 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDate>
+#include <QLocale>
+#include <QTime>
+#include <QVariant>
+#include <QThread>
+
+#include <e32std.h>
+#include <e32const.h>
+#include <e32base.h>
+#include <e32property.h>
+#include <bacntf.h>
+#include "private/qcore_symbian_p.h"
+#include "private/qcoreapplication_p.h"
+#include "private/qlocale_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static TExtendedLocale _s60Locale;
+
+// Type definitions for runtime resolved function pointers
+typedef void (*FormatFunc)(TTime&, TDes&, const TDesC&, const TLocale&);
+typedef TPtrC (*FormatSpecFunc)(TExtendedLocale&);
+
+// Runtime resolved functions
+static FormatFunc ptrTimeFormatL = NULL;
+static FormatSpecFunc ptrGetTimeFormatSpec = NULL;
+static FormatSpecFunc ptrGetLongDateFormatSpec = NULL;
+static FormatSpecFunc ptrGetShortDateFormatSpec = NULL;
+
+// Default functions if functions cannot be resolved
+static void defaultTimeFormatL(TTime&, TDes& des, const TDesC&, const TLocale&)
+{
+ des.Zero();
+}
+
+static TPtrC defaultFormatSpec(TExtendedLocale&)
+{
+ return TPtrC(KNullDesC);
+}
+
+/*
+ Definition of struct for mapping Symbian to ISO locale
+*/
+struct symbianToISO {
+ int symbian_language;
+ char iso_name[8];
+};
+
+
+/*
+ Mapping from Symbian to ISO locale.
+ NOTE: This array should be sorted by the first column!
+*/
+static const symbianToISO symbian_to_iso_list[] = {
+ { ELangEnglish, "en_GB" }, // 1
+ { ELangFrench, "fr_FR" }, // 2
+ { ELangGerman, "de_DE" }, // 3
+ { ELangSpanish, "es_ES" }, // 4
+ { ELangItalian, "it_IT" }, // 5
+ { ELangSwedish, "sv_SE" }, // 6
+ { ELangDanish, "da_DK" }, // 7
+ { ELangNorwegian, "no_NO" }, // 8
+ { ELangFinnish, "fi_FI" }, // 9
+ { ELangAmerican, "en_US" }, // 10
+ { ELangPortuguese, "pt_PT" }, // 13
+ { ELangTurkish, "tr_TR" }, // 14
+ { ELangIcelandic, "is_IS" }, // 15
+ { ELangRussian, "ru_RU" }, // 16
+ { ELangHungarian, "hu_HU" }, // 17
+ { ELangDutch, "nl_NL" }, // 18
+ { ELangBelgianFlemish, "nl_BE" }, // 19
+ { ELangCzech, "cs_CZ" }, // 25
+ { ELangSlovak, "sk_SK" }, // 26
+ { ELangPolish, "pl_PL" }, // 27
+ { ELangSlovenian, "sl_SI" }, // 28
+ { ELangTaiwanChinese, "zh_TW" }, // 29
+ { ELangHongKongChinese, "zh_HK" }, // 30
+ { ELangPrcChinese, "zh_CN" }, // 31
+ { ELangJapanese, "ja_JP" }, // 32
+ { ELangThai, "th_TH" }, // 33
+ { ELangArabic, "ar_AE" }, // 37
+ { ELangTagalog, "tl_PH" }, // 39
+ { ELangBulgarian, "bg_BG" }, // 42
+ { ELangCatalan, "ca_ES" }, // 44
+ { ELangCroatian, "hr_HR" }, // 45
+ { ELangEstonian, "et_EE" }, // 49
+ { ELangFarsi, "fa_IR" }, // 50
+ { ELangCanadianFrench, "fr_CA" }, // 51
+ { ELangGreek, "el_GR" }, // 54
+ { ELangHebrew, "he_IL" }, // 57
+ { ELangHindi, "hi_IN" }, // 58
+ { ELangIndonesian, "id_ID" }, // 59
+ { ELangKorean, "ko_KO" }, // 65
+ { ELangLatvian, "lv_LV" }, // 67
+ { ELangLithuanian, "lt_LT" }, // 68
+ { ELangMalay, "ms_MY" }, // 70
+ { ELangNorwegianNynorsk, "nn_NO" }, // 75
+ { ELangBrazilianPortuguese, "pt_BR" }, // 76
+ { ELangRomanian, "ro_RO" }, // 78
+ { ELangSerbian, "sr_RS" }, // 79
+ { ELangLatinAmericanSpanish,"es_419" }, // 83
+ { ELangUkrainian, "uk_UA" }, // 93
+ { ELangUrdu, "ur_PK" }, // 94 - India/Pakistan
+ { ELangVietnamese, "vi_VN" }, // 96
+#ifdef __E32LANG_H__
+// 5.0
+ { ELangBasque, "eu_ES" }, // 102
+ { ELangGalician, "gl_ES" }, // 103
+#endif
+#if !defined(__SERIES60_31__)
+ { ELangEnglish_Apac, "en" }, // 129
+ { ELangEnglish_Taiwan, "en_TW" }, // 157 ### Not supported by CLDR
+ { ELangEnglish_HongKong, "en_HK" }, // 158
+ { ELangEnglish_Prc, "en_CN" }, // 159 ### Not supported by CLDR
+ { ELangEnglish_Japan, "en_JP"}, // 160 ### Not supported by CLDR
+ { ELangEnglish_Thailand, "en_TH" }, // 161 ### Not supported by CLDR
+ { ELangMalay_Apac, "ms" }, // 326
+#endif
+ { 327/*ELangIndonesian_Apac*/,"id_ID" } // 327 - appeared in Symbian^3
+};
+
+/*!
+ Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
+*/
+QByteArray qt_symbianLocaleName(int code)
+{
+ //Number of Symbian to ISO locale mappings
+ static const int symbian_to_iso_count
+ = sizeof(symbian_to_iso_list)/sizeof(symbianToISO);
+
+ int cmp = code - symbian_to_iso_list[0].symbian_language;
+ if (cmp < 0)
+ return 0;
+
+ if (cmp == 0)
+ return symbian_to_iso_list[0].iso_name;
+
+ int begin = 0;
+ int end = symbian_to_iso_count;
+
+ while (end - begin > 1) {
+ uint mid = (begin + end)/2;
+
+ const symbianToISO *elt = symbian_to_iso_list + mid;
+ int cmp = code - elt->symbian_language;
+ if (cmp < 0)
+ end = mid;
+ else if (cmp > 0)
+ begin = mid;
+ else
+ return elt->iso_name;
+ }
+
+ return 0;
+}
+
+
+// order is: normal, abbr, nmode, nmode+abbr
+static const char *us_locale_dep[] = {
+ "MM", "dd", "yyyy", "MM", "dd",
+ "M", "d", "yy", "M", "d",
+ "MMMM", "dd", "yyyy", "MMMM", "dd",
+ "MMM", "d", "yy", "MMM", "d" };
+
+static const char *eu_locale_dep[] = {
+ "dd", "MM", "yyyy", "dd", "MM",
+ "d", "M", "yy", "d", "M",
+ "dd", "MMMM", "yyyy", "dd", "MMMM",
+ "d", "MMM", "yy", "d", "MMM" };
+
+static const char *jp_locale_dep[] = {
+ "yyyy", "MM", "dd", "MM", "dd",
+ "yy", "M", "d", "M", "d",
+ "yyyy", "MMMM", "dd", "MMMM", "dd",
+ "yy", "MMM", "d", "MMM", "d" };
+
+/*!
+ Returns a Qt version of the given \a sys_fmt Symbian locale format string.
+*/
+static QString s60ToQtFormat(const QString &sys_fmt)
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ QString result;
+ QString other;
+ QString qtformatchars = QString::fromLatin1("adhmsyzAHM");
+
+ QChar c;
+ int i = 0;
+ bool open_escape = false;
+ bool abbrev_next = false;
+ bool locale_indep_ordering = false;
+ bool minus_mode = false;
+ bool plus_mode = false;
+ bool n_mode = false;
+ TTimeFormat tf = locale->TimeFormat();
+
+ while (i < sys_fmt.size()) {
+
+ c = sys_fmt.at(i);
+
+ // let formatting thru
+ if (c.unicode() == '%') {
+ // if we have gathered string, concat it
+ if (!other.isEmpty()) {
+ result += other;
+ other.clear();
+ }
+ // if we have open escape, end it
+ if (open_escape) {
+ result += QLatin1Char('\'');
+ open_escape = false;
+ }
+
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ // process specials
+ abbrev_next = c.unicode() == '*';
+ plus_mode = c.unicode() == '+';
+ minus_mode = c.unicode() == '-';
+
+ if (abbrev_next || plus_mode || minus_mode) {
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ if (plus_mode || minus_mode) {
+ // break on undefined plus/minus mode
+ if (c.unicode() != 'A' && c.unicode() != 'B')
+ break;
+ }
+ }
+
+ switch (c.unicode()) {
+ case 'F':
+ {
+ // locale indep mode on
+ locale_indep_ordering = true;
+ break;
+ }
+
+ case '/':
+ {
+ // date sep 0-3
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+ if (c.isDigit() && c.digitValue() <= 3) {
+ TChar s = locale->DateSeparator(c.digitValue());
+ TUint val = s;
+ // some indexes return zero for empty
+ if (val > 0)
+ result += QChar(val);
+ }
+ break;
+ }
+
+ case 'D':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("dd");
+ else
+ result += QLatin1Char('d');
+
+ break;
+ }
+
+ case 'M':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!n_mode) {
+ if (!abbrev_next)
+ result += QLatin1String("MM");
+ else
+ result += QLatin1String("M");
+ } else {
+ if (!abbrev_next)
+ result += QLatin1String("MMMM");
+ else
+ result += QLatin1String("MMM");
+ }
+
+ break;
+ }
+
+ case 'N':
+ {
+ n_mode = true;
+
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("MMMM");
+ else
+ result += QLatin1String("MMM");
+
+ break;
+ }
+
+ case 'Y':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("yyyy");
+ else
+ result += QLatin1String("yy");
+
+ break;
+ }
+
+ case 'E':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("dddd");
+ else
+ result += QLatin1String("ddd");
+
+ break;
+ }
+
+ case ':':
+ {
+ // timesep 0-3
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+ if (c.isDigit() && c.digitValue() <= 3) {
+ TChar s = locale->TimeSeparator(c.digitValue());
+ TUint val = s;
+ // some indexes return zero for empty
+ if (val > 0)
+ result += QChar(val);
+ }
+
+ break;
+ }
+
+ case 'J':
+ {
+ if (tf == ETime24 && !abbrev_next)
+ result += QLatin1String("hh");
+ else
+ result += QLatin1Char('h');
+
+ break;
+ }
+
+ case 'H':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("hh");
+ else
+ result += QLatin1Char('h');
+
+ break;
+ }
+
+ case 'I':
+ {
+ result += QLatin1Char('h');
+ break;
+ }
+
+ case 'T':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("mm");
+ else
+ result += QLatin1Char('m');
+
+ break;
+ }
+
+ case 'S':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("ss");
+ else
+ result += QLatin1Char('s');
+
+ break;
+ }
+
+ case 'B':
+ {
+ // only done for 12h clock
+ if (tf == ETime24)
+ break;
+ }
+
+ // fallthru to A
+ case 'A': {
+ // quickie to get capitalization, can't use s60 string as is because Qt 'hh' format's am/pm logic
+ TAmPmName ampm = TAmPmName();
+ TChar first(ampm[0]);
+ QString qtampm = QString::fromLatin1(first.IsUpper() ? "AP" : "ap");
+
+ int pos = locale->AmPmSymbolPosition();
+
+ if ((minus_mode && pos != ELocaleBefore) ||
+ (plus_mode && pos != ELocaleAfter))
+ break;
+
+ if (!abbrev_next && locale->AmPmSpaceBetween()) {
+ if (pos == ELocaleBefore)
+ qtampm.append(QLatin1Char(' '));
+ else
+ qtampm.prepend(QLatin1Char(' '));
+ }
+
+ result += qtampm;
+ }
+ break;
+
+ case '.': {
+ // decimal sep
+ TChar s = locale->DecimalSeparator();
+ TUint val = s;
+ if (val > 0)
+ result += QChar(val);
+ }
+ break;
+
+ case 'C':
+ {
+ // six digits in s60, three digits in qt
+ if (!abbrev_next) {
+ result += QLatin1String("zzz");
+ } else {
+ // next char is number from 0-6, how many digits to display
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ if (c.isDigit()) {
+ // try to match wanted digits
+ QChar val(c.digitValue());
+
+ if (val >= 3) {
+ result += QLatin1String("zzz");
+ } else if (val > 0) {
+ result += QLatin1Char('z');
+ }
+ }
+ }
+ break;
+ }
+
+ // these cases fallthru
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ {
+
+ // shouldn't parse these with %F
+ if (locale_indep_ordering)
+ break;
+
+ TDateFormat df = locale->DateFormat();
+
+ const char **locale_dep;
+ switch (df) {
+ default: // fallthru to american
+ case EDateAmerican:
+ locale_dep = us_locale_dep;
+ break;
+ case EDateEuropean:
+ locale_dep = eu_locale_dep;
+ break;
+ case EDateJapanese:
+ locale_dep = jp_locale_dep;
+ break;
+ }
+ int offset = 0;
+ if (abbrev_next)
+ offset += 5;
+ if (n_mode)
+ offset += 10;
+
+ result += QLatin1String(locale_dep[offset + (c.digitValue()-1)]);
+ break;
+ }
+
+ case '%': // fallthru percent
+ {
+ // any junk gets copied as is
+ }
+ default:
+ {
+ result += c;
+ break;
+ }
+
+ case 'Z': // Qt doesn't support these :(
+ case 'X':
+ case 'W':
+ {
+ break;
+ }
+ }
+ } else {
+ // double any single quotes, don't begin escape
+ if (c.unicode() == '\'') {
+ // end open escape
+ if (open_escape) {
+ result += other;
+ other.clear();
+ result += QLatin1Char('\'');
+ open_escape = false;
+ }
+
+ other += c;
+ }
+
+ // gather chars and escape them in one go if any format chars are found
+ if (!open_escape && qtformatchars.indexOf(c) != -1) {
+ result += QLatin1Char('\'');
+ open_escape = true;
+ }
+ other += c;
+ }
+
+ ++i;
+ }
+
+ if (!other.isEmpty())
+ result += other;
+ if (open_escape)
+ result += QLatin1Char('\'');
+
+ return result;
+}
+
+/*!
+ Retrieves Symbian locale decimal separator.
+*/
+static QString symbianDecimalPoint()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TChar decPoint = locale->DecimalSeparator();
+ int val = decPoint;
+ return QChar(val);
+}
+
+/*!
+ Retrieves Symbian locale group separator.
+*/
+static QString symbianGroupSeparator()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TChar grpSep = locale->ThousandsSeparator();
+ int val = grpSep;
+ return QChar(val);
+}
+
+/*!
+ Retrieves Symbian locale zero digit.
+*/
+static QString symbianZeroDigit()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ // TDigitType enumeration value returned by TLocale
+ // will always correspond to zero digit unicode value.
+ TDigitType digit = locale->DigitType();
+ return QChar(digit);
+}
+
+/*!
+ Retrieves a day name from Symbian locale. The \a day is an integer
+ from 1 to 7. When \a short_format is true the method returns
+ the day in short format. Otherwise it returns the day in a long format.
+*/
+static QString symbianDayName(int day, bool short_format)
+{
+ day -= 1;
+
+ if (day < 0 || day > 6)
+ return QString();
+
+ if (short_format) {
+ return qt_TDes2QString(TDayNameAbb(TDay(day)));
+ } else {
+ return qt_TDes2QString(TDayName(TDay(day)));
+ }
+}
+
+/*!
+ Retrieves a month name from Symbian locale. The \a month is an integer
+ from 1 to 12. When \a short_format is true the method returns
+ the month in short format. Otherwise it returns the month in a long format.
+*/
+static QString symbianMonthName(int month, bool short_format)
+{
+ month -= 1;
+ if (month < 0 || month > 11)
+ return QString();
+
+ if (short_format) {
+ return qt_TDes2QString(TMonthNameAbb(TMonth(month)));
+ } else {
+ return qt_TDes2QString(TMonthName(TMonth(month)));
+ }
+}
+
+/*!
+ Retrieves date format from Symbian locale and
+ transforms it to Qt format.
+
+ When \a short_format is true the method returns
+ short date format. Otherwise it returns the long format.
+*/
+static QString symbianDateFormat(bool short_format)
+{
+ TPtrC dateFormat;
+
+ if (short_format) {
+ dateFormat.Set(ptrGetShortDateFormatSpec(_s60Locale));
+ } else {
+ dateFormat.Set(ptrGetLongDateFormatSpec(_s60Locale));
+ }
+
+ return s60ToQtFormat(qt_TDesC2QString(dateFormat));
+}
+
+/*!
+ Retrieves time format from Symbian locale and
+ transforms it to Qt format.
+*/
+static QString symbianTimeFormat()
+{
+ return s60ToQtFormat(qt_TDesC2QString(ptrGetTimeFormatSpec(_s60Locale)));
+}
+
+/*!
+ Returns localized string representation of given \a date
+ formatted with Symbian locale date format.
+
+ If \a short_format is true the format will be a short version.
+ Otherwise it uses a longer version.
+*/
+static QString symbianDateToString(const QDate &date, bool short_format)
+{
+ int month = date.month() - 1;
+ int day = date.day() - 1;
+ int year = date.year();
+
+ TDateTime dateTime;
+ dateTime.Set(year, TMonth(month), day, 0, 0, 0, 0);
+
+ TTime timeStr(dateTime);
+ TBuf<KMaxLongDateFormatSpec*2> buffer;
+
+ TPtrC dateFormat;
+ if (short_format) {
+ dateFormat.Set(ptrGetShortDateFormatSpec(_s60Locale));
+ } else {
+ dateFormat.Set(ptrGetLongDateFormatSpec(_s60Locale));
+ }
+
+ TRAPD(err, ptrTimeFormatL(timeStr, buffer, dateFormat, *_s60Locale.GetLocale());)
+
+ if (err == KErrNone)
+ return qt_TDes2QString(buffer);
+ else
+ return QString();
+}
+
+/*!
+ Returns localized string representation of given \a time
+ formatted with Symbian locale time format.
+*/
+static QString symbianTimeToString(const QTime &time)
+{
+ int hour = time.hour();
+ int minute = time.minute();
+ int second = time.second();
+ int milliseconds = 0;
+
+ TDateTime dateTime;
+ dateTime.Set(0, TMonth(0), 0, hour, minute, second, milliseconds);
+
+ TTime timeStr(dateTime);
+ TBuf<KMaxTimeFormatSpec*2> buffer;
+
+ TRAPD(err, ptrTimeFormatL(
+ timeStr,
+ buffer,
+ ptrGetTimeFormatSpec(_s60Locale),
+ *_s60Locale.GetLocale());
+ )
+
+ if (err == KErrNone)
+ return qt_TDes2QString(buffer);
+ else
+ return QString();
+}
+
+/*!
+ Returns the measurement system stored in Symbian locale
+
+ \sa QLocale::MeasurementSystem
+*/
+static QLocale::MeasurementSystem symbianMeasurementSystem()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TUnitsFormat unitFormat = locale->UnitsGeneral();
+ if (unitFormat == EUnitsImperial)
+ return QLocale::ImperialSystem;
+ else
+ return QLocale::MetricSystem;
+}
+
+void qt_symbianUpdateSystemPrivate()
+{
+ // load system data before query calls
+ _s60Locale.LoadSystemSettings();
+}
+
+void qt_symbianInitSystemLocale()
+{
+ static QBasicAtomicInt initDone = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (initDone == 2)
+ return;
+ if (initDone.testAndSetRelaxed(0, 1)) {
+ // Initialize platform version dependent function pointers
+ ptrTimeFormatL = reinterpret_cast<FormatFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_TimeFormatL));
+ ptrGetTimeFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetTimeFormatSpec));
+ ptrGetLongDateFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetLongDateFormatSpec));
+ ptrGetShortDateFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetShortDateFormatSpec));
+ if (!ptrTimeFormatL)
+ ptrTimeFormatL = &defaultTimeFormatL;
+ if (!ptrGetTimeFormatSpec)
+ ptrGetTimeFormatSpec = &defaultFormatSpec;
+ if (!ptrGetLongDateFormatSpec)
+ ptrGetLongDateFormatSpec = &defaultFormatSpec;
+ if (!ptrGetShortDateFormatSpec)
+ ptrGetShortDateFormatSpec = &defaultFormatSpec;
+ bool ret = initDone.testAndSetRelease(1, 2);
+ Q_ASSERT(ret);
+ Q_UNUSED(ret);
+ }
+ while(initDone != 2)
+ QThread::yieldCurrentThread();
+}
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+ TLanguage lang = User::Language();
+ QString locale = QLatin1String(qt_symbianLocaleName(lang));
+ return QLocale(locale);
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
+{
+ switch(type) {
+ case DecimalPoint:
+ return symbianDecimalPoint();
+ case GroupSeparator:
+ return symbianGroupSeparator();
+
+ case ZeroDigit:
+ return symbianZeroDigit();
+
+ case DayNameLong:
+ case DayNameShort:
+ return symbianDayName(in.toInt(), (type == DayNameShort) );
+
+ case MonthNameLong:
+ case MonthNameShort:
+ return symbianMonthName(in.toInt(), (type == MonthNameShort) );
+
+ case DateFormatLong:
+ case DateFormatShort:
+ return symbianDateFormat( (type == DateFormatShort) );
+ case TimeFormatLong:
+ case TimeFormatShort:
+ return symbianTimeFormat();
+ case DateTimeFormatLong:
+ case DateTimeFormatShort:
+ return QString(symbianDateFormat( (type == DateTimeFormatShort) ) + QLatin1Char(' ') + symbianTimeFormat());
+ case DateToStringShort:
+ case DateToStringLong:
+ return symbianDateToString(in.toDate(), (type == DateToStringShort) );
+ case TimeToStringShort:
+ case TimeToStringLong:
+ return symbianTimeToString(in.toTime());
+ case DateTimeToStringShort:
+ case DateTimeToStringLong: {
+ const QDateTime dt = in.toDateTime();
+ return QString(symbianDateToString(dt.date(), (type == DateTimeToStringShort) )
+ + QLatin1Char(' ') + symbianTimeToString(dt.time()));
+ }
+ case MeasurementSystem:
+ return static_cast<int>(symbianMeasurementSystem());
+ case LanguageId:
+ case CountryId: {
+ TLanguage language = User::Language();
+ QString locale = QLatin1String(qt_symbianLocaleName(language));
+ QLocale::Language lang;
+ QLocale::Script script;
+ QLocale::Country cntry;
+ QLocalePrivate::getLangAndCountry(locale, lang, script, cntry);
+ if (type == LanguageId)
+ return lang;
+ // few iso codes have no country and will use this
+ if (cntry == QLocale::AnyCountry)
+ return fallbackLocale().country();
+
+ return cntry;
+ }
+ case ScriptId:
+ return QVariant(QLocale::AnyScript);
+ case NegativeSign:
+ case PositiveSign:
+ break;
+ case AMText:
+ return qt_TDes2QString(TAmPmName(TAmPm(EAm)));
+ case PMText:
+ return qt_TDes2QString(TAmPmName(TAmPm(EPm)));
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+#if !defined(QT_NO_SYSTEMLOCALE)
+QEnvironmentChangeNotifier::QEnvironmentChangeNotifier()
+{
+ // Create the change notifier and install the callback function
+ const TCallBack callback(&QEnvironmentChangeNotifier::localeChanged, this);
+ QT_TRAP_THROWING(iChangeNotifier = CEnvironmentChangeNotifier::NewL(CActive::EPriorityStandard, callback));
+ iChangeNotifier->Start();
+}
+
+TInt QEnvironmentChangeNotifier::localeChanged(TAny *data)
+{
+ QEnvironmentChangeNotifier *that = reinterpret_cast<QEnvironmentChangeNotifier *>(data);
+
+ TInt flag = that->iChangeNotifier->Change();
+ if (flag & EChangesLocale) {
+ static bool first = true;
+ if (!first) { // skip the first notification on app startup
+ QT_TRYCATCH_LEAVING(QLocalePrivate::updateSystemPrivate());
+ QT_TRYCATCH_LEAVING(QCoreApplication::postEvent(qApp, new QEvent(QEvent::LocaleChange)));
+ }
+ first = false;
+ }
+ return KErrNone;
+}
+
+QEnvironmentChangeNotifier::~QEnvironmentChangeNotifier()
+{
+ delete iChangeNotifier;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
new file mode 100644
index 0000000000..17d8b2a167
--- /dev/null
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -0,0 +1,2961 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocale_tools_p.h"
+#include "qlocale_p.h"
+#include "qstring.h"
+
+#include <ctype.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+
+#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
+# include <fenv.h>
+#endif
+
+// Sizes as defined by the ISO C99 standard - fallback
+#ifndef LLONG_MAX
+# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff)
+#endif
+#ifndef LLONG_MIN
+# define LLONG_MIN (-LLONG_MAX - Q_INT64_C(1))
+#endif
+#ifndef ULLONG_MAX
+# define ULLONG_MAX Q_UINT64_C(0xffffffffffffffff)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_QLOCALE_USES_FCVT
+static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
+ int *sign, char **rve, char **digits_str);
+#endif
+
+QString qulltoa(qulonglong l, int base, const QChar _zero)
+{
+ ushort buff[65]; // length of MAX_ULLONG in base 2
+ ushort *p = buff + 65;
+
+ if (base != 10 || _zero.unicode() == '0') {
+ while (l != 0) {
+ int c = l % base;
+
+ --p;
+
+ if (c < 10)
+ *p = '0' + c;
+ else
+ *p = c - 10 + 'a';
+
+ l /= base;
+ }
+ }
+ else {
+ while (l != 0) {
+ int c = l % base;
+
+ *(--p) = _zero.unicode() + c;
+
+ l /= base;
+ }
+ }
+
+ return QString(reinterpret_cast<QChar *>(p), 65 - (p - buff));
+}
+
+QString qlltoa(qlonglong l, int base, const QChar zero)
+{
+ return qulltoa(l < 0 ? -l : l, base, zero);
+}
+
+QString &decimalForm(QChar zero, QChar decimal, QChar group,
+ QString &digits, int decpt, uint precision,
+ PrecisionMode pm,
+ bool always_show_decpt,
+ bool thousands_group)
+{
+ if (decpt < 0) {
+ for (int i = 0; i < -decpt; ++i)
+ digits.prepend(zero);
+ decpt = 0;
+ }
+ else if (decpt > digits.length()) {
+ for (int i = digits.length(); i < decpt; ++i)
+ digits.append(zero);
+ }
+
+ if (pm == PMDecimalDigits) {
+ uint decimal_digits = digits.length() - decpt;
+ for (uint i = decimal_digits; i < precision; ++i)
+ digits.append(zero);
+ }
+ else if (pm == PMSignificantDigits) {
+ for (uint i = digits.length(); i < precision; ++i)
+ digits.append(zero);
+ }
+ else { // pm == PMChopTrailingZeros
+ }
+
+ if (always_show_decpt || decpt < digits.length())
+ digits.insert(decpt, decimal);
+
+ if (thousands_group) {
+ for (int i = decpt - 3; i > 0; i -= 3)
+ digits.insert(i, group);
+ }
+
+ if (decpt == 0)
+ digits.prepend(zero);
+
+ return digits;
+}
+
+QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
+ QChar group, QChar plus, QChar minus,
+ QString &digits, int decpt, uint precision,
+ PrecisionMode pm,
+ bool always_show_decpt)
+{
+ int exp = decpt - 1;
+
+ if (pm == PMDecimalDigits) {
+ for (uint i = digits.length(); i < precision + 1; ++i)
+ digits.append(zero);
+ }
+ else if (pm == PMSignificantDigits) {
+ for (uint i = digits.length(); i < precision; ++i)
+ digits.append(zero);
+ }
+ else { // pm == PMChopTrailingZeros
+ }
+
+ if (always_show_decpt || digits.length() > 1)
+ digits.insert(1, decimal);
+
+ digits.append(exponential);
+ digits.append(QLocalePrivate::longLongToString(zero, group, plus, minus,
+ exp, 2, 10, -1, QLocalePrivate::AlwaysShowSign));
+
+ return digits;
+}
+
+// Removes thousand-group separators in "C" locale.
+bool removeGroupSeparators(QLocalePrivate::CharBuff *num)
+{
+ int group_cnt = 0; // counts number of group chars
+ int decpt_idx = -1;
+
+ char *data = num->data();
+ int l = qstrlen(data);
+
+ // Find the decimal point and check if there are any group chars
+ int i = 0;
+ for (; i < l; ++i) {
+ char c = data[i];
+
+ if (c == ',') {
+ if (i == 0 || data[i - 1] < '0' || data[i - 1] > '9')
+ return false;
+ if (i == l - 1 || data[i + 1] < '0' || data[i + 1] > '9')
+ return false;
+ ++group_cnt;
+ }
+ else if (c == '.') {
+ // Fail if more than one decimal points
+ if (decpt_idx != -1)
+ return false;
+ decpt_idx = i;
+ } else if (c == 'e' || c == 'E') {
+ // an 'e' or 'E' - if we have not encountered a decimal
+ // point, this is where it "is".
+ if (decpt_idx == -1)
+ decpt_idx = i;
+ }
+ }
+
+ // If no group chars, we're done
+ if (group_cnt == 0)
+ return true;
+
+ // No decimal point means that it "is" at the end of the string
+ if (decpt_idx == -1)
+ decpt_idx = l;
+
+ i = 0;
+ while (i < l && group_cnt > 0) {
+ char c = data[i];
+
+ if (c == ',') {
+ // Don't allow group chars after the decimal point
+ if (i > decpt_idx)
+ return false;
+
+ // Check that it is placed correctly relative to the decpt
+ if ((decpt_idx - i) % 4 != 0)
+ return false;
+
+ // Remove it
+ memmove(data + i, data + i + 1, l - i - 1);
+ data[--l] = '\0';
+
+ --group_cnt;
+ --decpt_idx;
+ } else {
+ // Check that we are not missing a separator
+ if (i < decpt_idx
+ && (decpt_idx - i) % 4 == 0
+ && !(i == 0 && c == '-')) // check for negative sign at start of string
+ return false;
+ ++i;
+ }
+ }
+
+ return true;
+}
+
+#if defined(Q_CC_MWERKS) && defined(Q_OS_WIN32)
+inline bool isascii(int c)
+{
+ return (c >= 0 && c <=127);
+}
+#endif
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+// static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
+// "$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok)
+{
+ register const char *s = nptr;
+ register qulonglong acc;
+ register unsigned char c;
+ register qulonglong qbase, cutoff;
+ register int any, cutlim;
+
+ if (ok != 0)
+ *ok = true;
+
+ /*
+ * See strtoq for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ if (ok != 0)
+ *ok = false;
+ if (endptr != 0)
+ *endptr = s - 1;
+ return 0;
+ } else {
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ qbase = unsigned(base);
+ cutoff = qulonglong(ULLONG_MAX) / qbase;
+ cutlim = qulonglong(ULLONG_MAX) % qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any == 0) {
+ if (ok != 0)
+ *ok = false;
+ } else if (any < 0) {
+ acc = ULLONG_MAX;
+ if (ok != 0)
+ *ok = false;
+ }
+ if (endptr != 0)
+ *endptr = (any ? s - 1 : nptr);
+ return acc;
+}
+
+
+// "$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
+
+
+/*
+ * Convert a string to a long long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
+{
+ register const char *s;
+ register qulonglong acc;
+ register unsigned char c;
+ register qulonglong qbase, cutoff;
+ register int neg, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for quads is
+ * [-9223372036854775808..9223372036854775807] and the input base
+ * is 10, cutoff will be set to 922337203685477580 and cutlim to
+ * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+ * accumulated a value > 922337203685477580, or equal but the
+ * next digit is > 7 (or 8), the number is too big, and we will
+ * return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ qbase = unsigned(base);
+ cutoff = neg ? qulonglong(0-(LLONG_MIN + LLONG_MAX)) + LLONG_MAX : LLONG_MAX;
+ cutlim = cutoff % qbase;
+ cutoff /= qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LLONG_MIN : LLONG_MAX;
+ if (ok != 0)
+ *ok = false;
+ } else if (neg) {
+ acc = (~acc) + 1;
+ }
+ if (endptr != 0)
+ *endptr = (any >= 0 ? s - 1 : nptr);
+
+ if (ok != 0)
+ *ok = any > 0;
+
+ return acc;
+}
+
+#ifndef QT_QLOCALE_USES_FCVT
+
+/* From: NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp */
+/* $FreeBSD: src/lib/libc/stdlib/netbsd_strtod.c,v 1.2.2.2 2001/03/02 17:14:15 tegge Exp $ */
+
+/* Please send bug reports to
+ David M. Gay
+ AT&T Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-2070
+ U.S.A.
+ dmg@research.att.com or research!dmg
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define Sudden_Underflow for IEEE-format machines without gradual
+ * underflow (i.e., that flush to zero on underflow).
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic.
+ * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
+ * integer arithmetic. Whether this speeds things up or slows things
+ * down depends on the machine and the number being converted.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ * if memory is available and otherwise does something you deem
+ * appropriate. If MALLOC is undefined, malloc will be invoked
+ * directly -- and assumed always to succeed.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+/*
+#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
+ defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
+ defined(__powerpc__) || defined(Q_OS_WIN) || defined(Q_OS_DARWIN) || defined(Q_OS_MAC) || \
+ defined(mips) || defined(Q_OS_AIX) || defined(Q_OS_SOLARIS)
+# define IEEE_BIG_OR_LITTLE_ENDIAN 1
+#endif
+*/
+
+// *All* of our architectures have IEEE arithmetic, don't they?
+#define IEEE_BIG_OR_LITTLE_ENDIAN 1
+
+#ifdef __arm32__
+/*
+ * Although the CPU is little endian the FP has different
+ * byte and word endianness. The byte order is still little endian
+ * but the word order is big endian.
+ */
+#define IEEE_BIG_OR_LITTLE_ENDIAN
+#endif
+
+#ifdef vax
+#define VAX
+#endif
+
+#define Long qint32
+#define ULong quint32
+
+#define MALLOC malloc
+
+#ifdef BSD_QDTOA_DEBUG
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <stdio.h>
+QT_END_INCLUDE_NAMESPACE
+
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#ifdef Unsigned_Shifts
+#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
+#else
+#define Sign_Extend(a,b) /*no-op*/
+#endif
+
+#if (defined(IEEE_BIG_OR_LITTLE_ENDIAN) + defined(VAX) + defined(IBM)) != 1
+#error Exactly one of IEEE_BIG_OR_LITTLE_ENDIAN, VAX, or IBM should be defined.
+#endif
+
+static inline ULong _getWord0(const NEEDS_VOLATILE double x)
+{
+ const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x);
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3];
+ } else {
+ return (ptr[7]<<24) + (ptr[6]<<16) + (ptr[5]<<8) + ptr[4];
+ }
+}
+
+static inline void _setWord0(NEEDS_VOLATILE double *x, ULong l)
+{
+ NEEDS_VOLATILE uchar *ptr = reinterpret_cast<NEEDS_VOLATILE uchar *>(x);
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ ptr[0] = uchar(l>>24);
+ ptr[1] = uchar(l>>16);
+ ptr[2] = uchar(l>>8);
+ ptr[3] = uchar(l);
+ } else {
+ ptr[7] = uchar(l>>24);
+ ptr[6] = uchar(l>>16);
+ ptr[5] = uchar(l>>8);
+ ptr[4] = uchar(l);
+ }
+}
+
+static inline ULong _getWord1(const NEEDS_VOLATILE double x)
+{
+ const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x);
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (ptr[4]<<24) + (ptr[5]<<16) + (ptr[6]<<8) + ptr[7];
+ } else {
+ return (ptr[3]<<24) + (ptr[2]<<16) + (ptr[1]<<8) + ptr[0];
+ }
+}
+static inline void _setWord1(NEEDS_VOLATILE double *x, ULong l)
+{
+ NEEDS_VOLATILE uchar *ptr = reinterpret_cast<uchar NEEDS_VOLATILE *>(x);
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ ptr[4] = uchar(l>>24);
+ ptr[5] = uchar(l>>16);
+ ptr[6] = uchar(l>>8);
+ ptr[7] = uchar(l);
+ } else {
+ ptr[3] = uchar(l>>24);
+ ptr[2] = uchar(l>>16);
+ ptr[1] = uchar(l>>8);
+ ptr[0] = uchar(l);
+ }
+}
+
+static inline ULong getWord0(const NEEDS_VOLATILE double x)
+{
+#ifdef QT_ARMFPA
+ return _getWord1(x);
+#else
+ return _getWord0(x);
+#endif
+}
+
+static inline void setWord0(NEEDS_VOLATILE double *x, ULong l)
+{
+#ifdef QT_ARMFPA
+ _setWord1(x, l);
+#else
+ _setWord0(x, l);
+#endif
+}
+
+static inline ULong getWord1(const NEEDS_VOLATILE double x)
+{
+#ifdef QT_ARMFPA
+ return _getWord0(x);
+#else
+ return _getWord1(x);
+#endif
+}
+
+static inline void setWord1(NEEDS_VOLATILE double *x, ULong l)
+{
+#ifdef QT_ARMFPA
+ _setWord0(x, l);
+#else
+ _setWord1(x, l);
+#endif
+}
+
+static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c)
+{
+
+ *a = (ushort(b) << 16) | ushort(c);
+ ++a;
+}
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#if defined(IEEE_BIG_OR_LITTLE_ENDIAN)
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define IEEE_Arith
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#if defined(LSB) && defined(Q_OS_VXWORKS)
+#undef LSB
+#endif
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+#define Infinite(x) (getWord0(x) == 0x7ff00000) /* sufficient test for here */
+#else
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 0x1000000
+#define Exp_msk11 0x1000000
+#define Exp_mask 0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1 0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask 0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask 0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 0x800000
+#define Exp_mask 0x7f80
+#define P 56
+#define Bias 129
+#define Exp_1 0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask 0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask 0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif
+#endif
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#ifndef Just_16
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per Long.
+ */
+#ifndef Pack_32
+#define Pack_32
+#endif
+#endif
+
+#define Kmax 15
+
+struct
+Bigint {
+ struct Bigint *next;
+ int k, maxwds, sign, wds;
+ ULong x[1];
+};
+
+ typedef struct Bigint Bigint;
+
+static Bigint *Balloc(int k)
+{
+ int x;
+ Bigint *rv;
+
+ x = 1 << k;
+ rv = static_cast<Bigint *>(MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)));
+ Q_CHECK_PTR(rv);
+ rv->k = k;
+ rv->maxwds = x;
+ rv->sign = rv->wds = 0;
+ return rv;
+}
+
+static void Bfree(Bigint *v)
+{
+ free(v);
+}
+
+#define Bcopy(x,y) memcpy(reinterpret_cast<char *>(&x->sign), reinterpret_cast<char *>(&y->sign), \
+y->wds*sizeof(Long) + 2*sizeof(int))
+
+/* multiply by m and add a */
+static Bigint *multadd(Bigint *b, int m, int a)
+{
+ int i, wds;
+ ULong *x, y;
+#ifdef Pack_32
+ ULong xi, z;
+#endif
+ Bigint *b1;
+
+ wds = b->wds;
+ x = b->x;
+ i = 0;
+ do {
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + a;
+ z = (xi >> 16) * m + (y >> 16);
+ a = (z >> 16);
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + a;
+ a = (y >> 16);
+ *x++ = y & 0xffff;
+#endif
+ }
+ while(++i < wds);
+ if (a) {
+ if (wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = a;
+ b->wds = wds;
+ }
+ return b;
+}
+
+static Bigint *s2b(const char *s, int nd0, int nd, ULong y9)
+{
+ Bigint *b;
+ int i, k;
+ Long x, y;
+
+ x = (nd + 8) / 9;
+ for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+ b = Balloc(k);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ b = Balloc(k+1);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do b = multadd(b, 10, *s++ - '0');
+ while(++i < nd0);
+ s++;
+ }
+ else
+ s += 10;
+ for(; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+}
+
+static int hi0bits(ULong x)
+{
+ int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+}
+
+static int lo0bits(ULong *y)
+{
+ int k;
+ ULong x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x & 1)
+ return 32;
+ }
+ *y = x;
+ return k;
+}
+
+static Bigint *i2b(int i)
+{
+ Bigint *b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+}
+
+static Bigint *mult(Bigint *a, Bigint *b)
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong carry, y, z;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+#ifdef Pack_32
+ ULong z2;
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ for(x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef Pack_32
+ for(; xb < xbe; xb++, xc0++) {
+ if ((y = *xb & 0xffff) != 0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ if ((y = *xb >> 16) != 0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while(x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if (y = *xb++) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+ for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds = wc;
+ return c;
+}
+
+static Bigint *p5s;
+
+struct p5s_deleter
+{
+ ~p5s_deleter()
+ {
+ while (p5s) {
+ Bigint *next = p5s->next;
+ Bfree(p5s);
+ p5s = next;
+ }
+ }
+};
+
+static Bigint *pow5mult(Bigint *b, int k)
+{
+ Bigint *b1, *p5, *p51;
+ int i;
+ static const int p05[3] = { 5, 25, 125 };
+
+ if ((i = k & 3) != 0)
+#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
+ {
+ // work around a bug on 64 bit IRIX gcc
+ int *p = (int *) p05;
+ b = multadd(b, p[i-1], 0);
+ }
+#else
+ b = multadd(b, p05[i-1], 0);
+#endif
+
+ if (!(k >>= 2))
+ return b;
+ if (!(p5 = p5s)) {
+ /* first time */
+ static p5s_deleter deleter;
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+ }
+ for(;;) {
+ if (k & 1) {
+ b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if (!(p51 = p5->next)) {
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+ }
+ p5 = p51;
+ }
+ return b;
+}
+
+static Bigint *lshift(Bigint *b, int k)
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+#ifdef Pack_32
+ n = k >> 5;
+#else
+ n = k >> 4;
+#endif
+ k1 = b->k;
+ n1 = n + b->wds + 1;
+ for(i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc(k1);
+ x1 = b1->x;
+ for(i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ k1 = 32 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if ((*x1 = z) != 0)
+ ++n1;
+ }
+#else
+ if (k &= 0xf) {
+ k1 = 16 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#endif
+ else do
+ *x1++ = *x++;
+ while(x < xe);
+ b1->wds = n1 - 1;
+ Bfree(b);
+ return b1;
+}
+
+static int cmp(Bigint *a, Bigint *b)
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+#ifdef BSD_QDTOA_DEBUG
+ if (i > 1 && !a->x[i-1])
+ Bug("cmp called with a->x[a->wds-1] == 0");
+ if (j > 1 && !b->x[j-1])
+ Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for(;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+}
+
+static Bigint *diff(Bigint *a, Bigint *b)
+{
+ Bigint *c;
+ int i, wa, wb;
+ Long borrow, y; /* We need signed shifts here. */
+ ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef Pack_32
+ Long z;
+#endif
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+ borrow = 0;
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
+ borrow = z >> 16;
+ Sign_Extend(borrow, z);
+ Storeinc(xc, z, y);
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = (*xa & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ z = (*xa++ >> 16) + borrow;
+ borrow = z >> 16;
+ Sign_Extend(borrow, z);
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ - *xb++ + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ *xc++ = y & 0xffff;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ *xc++ = y & 0xffff;
+ }
+#endif
+ while(!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+}
+
+static double ulp(double x)
+{
+ Long L;
+ double a;
+
+ L = (getWord0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ setWord0(&a, L);
+ setWord1(&a, 0);
+#ifndef Sudden_Underflow
+ }
+ else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ setWord0(&a, 0x80000 >> L);
+ setWord1(&a, 0);
+ }
+ else {
+ setWord0(&a, 0);
+ L -= Exp_shift;
+ setWord1(&a, L >= 31 ? 1U : 1U << (31 - L));
+ }
+ }
+#endif
+ return a;
+}
+
+static double b2d(Bigint *a, int *e)
+{
+ ULong *xa, *xa0, w, y, z;
+ int k;
+ double d;
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+#ifdef BSD_QDTOA_DEBUG
+ if (!y) Bug("zero y in b2d");
+#endif
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ setWord0(&d, Exp_1 | y >> (Ebits - k));
+ w = xa > xa0 ? *--xa : 0;
+ setWord1(&d, y << ((32-Ebits) + k) | w >> (Ebits - k));
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ setWord0(&d, Exp_1 | y << k | z >> (32 - k));
+ y = xa > xa0 ? *--xa : 0;
+ setWord1(&d, z << k | y >> (32 - k));
+ }
+ else {
+ setWord0(&d, Exp_1 | y);
+ setWord1(&d, z);
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ setWord0(&d, Exp_1 | y << k - Ebits | z >> Ebits + 16 - k);
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ setWord1(&d, z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k);
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ setWord0(&d, Exp_1 | y << k + 16 | z << k | w >> 16 - k);
+ y = xa > xa0 ? *--xa : 0;
+ setWord1(&d, w << k + 16 | y << k);
+#endif
+ ret_d:
+ return d;
+}
+
+static Bigint *d2b(double d, int *e, int *bits)
+{
+ Bigint *b;
+ int de, i, k;
+ ULong *x, y, z;
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = getWord0(d) & Frac_mask;
+ setWord0(&d, getWord0(d) & 0x7fffffff); /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(getWord0(d) >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if ((de = int(getWord0(d) >> Exp_shift)) != 0)
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ((y = getWord1(d)) != 0) {
+ if ((k = lo0bits(&y)) != 0) {
+ x[0] = y | z << (32 - k);
+ z >>= k;
+ }
+ else
+ x[0] = y;
+ i = b->wds = (x[1] = z) ? 2 : 1;
+ }
+ else {
+#ifdef BSD_QDTOA_DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ x[0] = z;
+ i = b->wds = 1;
+ k += 32;
+ }
+#else
+ if (y = getWord1(d)) {
+ if (k = lo0bits(&y))
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k+16;
+ i = 3;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else {
+#ifdef BSD_QDTOA_DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ }
+ else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while(!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P-1) << 2) + k;
+ *bits = 4*P + 8 - k - hi0bits(getWord0(d) & Frac_mask);
+#else
+ *e = de - Bias - (P-1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else {
+ *e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32*i - hi0bits(x[i-1]);
+#else
+ *bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+}
+
+static double ratio(Bigint *a, Bigint *b)
+{
+ double da, db;
+ int k, ka, kb;
+
+ da = b2d(a, &ka);
+ db = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32*(a->wds - b->wds);
+#else
+ k = ka - kb + 16*(a->wds - b->wds);
+#endif
+#ifdef IBM
+ if (k > 0) {
+ setWord0(&da, getWord0(da) + (k >> 2)*Exp_msk1);
+ if (k &= 3)
+ da *= 1 << k;
+ }
+ else {
+ k = -k;
+ setWord0(&db, getWord0(db) + (k >> 2)*Exp_msk1);
+ if (k &= 3)
+ db *= 1 << k;
+ }
+#else
+ if (k > 0)
+ setWord0(&da, getWord0(da) + k*Exp_msk1);
+ else {
+ k = -k;
+ setWord0(&db, getWord0(db) + k*Exp_msk1);
+ }
+#endif
+ return da / db;
+}
+
+static const double tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+#ifdef VAX
+ , 1e23, 1e24
+#endif
+};
+
+#ifdef IEEE_Arith
+static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+#define n_bigtens 5
+#else
+#ifdef IBM
+static const double bigtens[] = { 1e16, 1e32, 1e64 };
+static const double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#define n_bigtens 3
+#else
+static const double bigtens[] = { 1e16, 1e32 };
+static const double tinytens[] = { 1e-16, 1e-32 };
+#define n_bigtens 2
+#endif
+#endif
+
+/*
+ The pre-release gcc3.3 shipped with SuSE 8.2 has a bug which causes
+ the comparison 1e-100 == 0.0 to return true. As a workaround, we
+ compare it to a global variable containing 0.0, which produces
+ correct assembler output.
+
+ ### consider detecting the broken compilers and using the static
+ ### double for these, and use a #define for all working compilers
+*/
+static double g_double_zero = 0.0;
+
+Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok)
+{
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ const char *s, *s0, *s1;
+ double aadj, aadj1, adj, rv, rv0;
+ Long L;
+ ULong y, z;
+ Bigint *bb1, *bd0;
+ Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */
+
+ /*
+ #ifndef KR_headers
+ const char decimal_point = localeconv()->decimal_point[0];
+ #else
+ const char decimal_point = '.';
+ #endif */
+ if (ok != 0)
+ *ok = true;
+
+ const char decimal_point = '.';
+
+ sign = nz0 = nz = 0;
+ rv = 0.;
+
+
+ for(s = s00; isspace(uchar(*s)); s++)
+ ;
+
+ if (*s == '-') {
+ sign = 1;
+ s++;
+ } else if (*s == '+') {
+ s++;
+ }
+
+ if (*s == '\0') {
+ s = s00;
+ goto ret;
+ }
+
+ if (*s == '0') {
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+ if (c == decimal_point) {
+ c = *++s;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ s = s00;
+ goto ret;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = int(L);
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0)
+ s = s00;
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ rv = y;
+ if (k > 9)
+#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
+ {
+ // work around a bug on 64 bit IRIX gcc
+ double *t = (double *) tens;
+ rv = t[k - 9] * rv + z;
+ }
+#else
+ rv = tens[k - 9] * rv + z;
+#endif
+
+ bd0 = 0;
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+ && FLT_ROUNDS == 1
+#endif
+ ) {
+ if (!e)
+ goto ret;
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+ /* rv = */ rounded_product(rv, tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+ e -= i;
+ rv *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ setWord0(&rv, getWord0(rv) - P*Exp_msk1);
+ /* rv = */ rounded_product(rv, tens[e]);
+ if ((getWord0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto ovfl;
+ setWord0(&rv, getWord0(rv) + P*Exp_msk1);
+#else
+ /* rv = */ rounded_product(rv, tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+ /* rv = */ rounded_quotient(rv, tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ((i = e1 & 15) != 0)
+ rv *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+ // errno = ERANGE;
+ if (ok != 0)
+ *ok = false;
+#ifdef __STDC__
+ rv = HUGE_VAL;
+#else
+ /* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+ setWord0(&rv, Exp_mask);
+ setWord1(&rv, 0);
+#else
+ setWord0(&rv, Big0);
+ setWord1(&rv, Big1);
+#endif
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ if (e1 >>= 4) {
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ rv *= bigtens[j];
+ /* The last multiplication could overflow. */
+ setWord0(&rv, getWord0(rv) - P*Exp_msk1);
+ rv *= bigtens[j];
+ if ((z = getWord0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+ goto ovfl;
+ if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ setWord0(&rv, Big0);
+ setWord1(&rv, Big1);
+ }
+ else
+ setWord0(&rv, getWord0(rv) + P*Exp_msk1);
+ }
+
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if ((i = e1 & 15) != 0)
+ rv /= tens[i];
+ if (e1 &= ~15) {
+ e1 >>= 4;
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ rv *= tinytens[j];
+ /* The last multiplication could underflow. */
+ rv0 = rv;
+ rv *= tinytens[j];
+ if (rv == g_double_zero)
+ {
+ rv = 2.*rv0;
+ rv *= tinytens[j];
+ if (rv == g_double_zero)
+ {
+ undfl:
+ rv = 0.;
+ // errno = ERANGE;
+ if (ok != 0)
+ *ok = false;
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ setWord0(&rv, Tiny0);
+ setWord1(&rv, Tiny1);
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y);
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ Bcopy(bd, bd0);
+ bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bs = i2b(1);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else
+ i = bbe + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j = bbe + (P-Emin);
+ else
+ j = P + 1 - bbbits;
+#endif
+ bb2 += j;
+ bd2 += j;
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(bb, bd);
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask)
+ break;
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((getWord0(rv) & Bndry_mask1) == Bndry_mask1
+ && getWord1(rv) == 0xffffffff) {
+ /*boundary case -- increment exponent*/
+ setWord0(&rv, (getWord0(rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ );
+ setWord1(&rv, 0);
+ break;
+ }
+ }
+ else if (!(getWord0(rv) & Bndry_mask) && !getWord1(rv)) {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow
+ L = getWord0(rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+ if (L <= Exp_msk1)
+#endif
+ goto undfl;
+ L -= Exp_msk1;
+#else
+ L = (getWord0(rv) & Exp_mask) - Exp_msk1;
+#endif
+ setWord0(&rv, L | Bndry_mask1);
+ setWord1(&rv, 0xffffffff);
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+ if (!(getWord1(rv) & LSB))
+ break;
+#endif
+ if (dsign)
+ rv += ulp(rv);
+#ifndef ROUND_BIASED
+ else {
+ rv -= ulp(rv);
+#ifndef Sudden_Underflow
+ if (rv == g_double_zero)
+ goto undfl;
+#endif
+ }
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = aadj1 = 1.;
+ else if (getWord1(rv) || getWord0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (getWord1(rv) == Tiny1 && !getWord0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ aadj1 = -1.;
+ }
+ else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2./FLT_RADIX)
+ aadj = 1./FLT_RADIX;
+ else
+ aadj *= 0.5;
+ aadj1 = -aadj;
+ }
+ }
+ else {
+ aadj *= 0.5;
+ aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch(FLT_ROUNDS) {
+ case 2: /* towards +infinity */
+ aadj1 -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ aadj1 += 0.5;
+ }
+#else
+ if (FLT_ROUNDS == 0)
+ aadj1 += 0.5;
+#endif
+ }
+ y = getWord0(rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+ rv0 = rv;
+ setWord0(&rv, getWord0(rv) - P*Exp_msk1);
+ adj = aadj1 * ulp(rv);
+ rv += adj;
+ if ((getWord0(rv) & Exp_mask) >=
+ Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+ if (getWord0(rv0) == Big0 && getWord1(rv0) == Big1)
+ goto ovfl;
+ setWord0(&rv, Big0);
+ setWord1(&rv, Big1);
+ goto cont;
+ }
+ else
+ setWord0(&rv, getWord0(rv) + P*Exp_msk1);
+ }
+ else {
+#ifdef Sudden_Underflow
+ if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1) {
+ rv0 = rv;
+ setWord0(&rv, getWord0(rv) + P*Exp_msk1);
+ adj = aadj1 * ulp(rv);
+ rv += adj;
+#ifdef IBM
+ if ((getWord0(rv) & Exp_mask) < P*Exp_msk1)
+#else
+ if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+ {
+ if (getWord0(rv0) == Tiny0
+ && getWord1(rv0) == Tiny1)
+ goto undfl;
+ setWord0(&rv, Tiny0);
+ setWord1(&rv, Tiny1);
+ goto cont;
+ }
+ else
+ setWord0(&rv, getWord0(rv) - P*Exp_msk1);
+ }
+ else {
+ adj = aadj1 * ulp(rv);
+ rv += adj;
+ }
+#else
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
+ aadj1 = int(aadj + 0.5);
+ if (!dsign)
+ aadj1 = -aadj1;
+ }
+ adj = aadj1 * ulp(rv);
+ rv += adj;
+#endif
+ }
+ z = getWord0(rv) & Exp_mask;
+ if (y == z) {
+ /* Can we stop now? */
+ L = Long(aadj);
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999/FLT_RADIX)
+ break;
+ }
+ cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+ retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ ret:
+ if (se)
+ *se = s;
+ return sign ? -rv : rv;
+}
+
+static int quorem(Bigint *b, Bigint *S)
+{
+ int n;
+ Long borrow, y;
+ ULong carry, q, ys;
+ ULong *bx, *bxe, *sx, *sxe;
+#ifdef Pack_32
+ Long z;
+ ULong si, zs;
+#endif
+
+ n = S->wds;
+#ifdef BSD_QDTOA_DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef BSD_QDTOA_DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ z = (*bx >> 16) - (zs & 0xffff) + borrow;
+ borrow = z >> 16;
+ Sign_Extend(borrow, z);
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ *bx++ = y & 0xffff;
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ z = (*bx >> 16) - (zs & 0xffff) + borrow;
+ borrow = z >> 16;
+ Sign_Extend(borrow, z);
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend(borrow, y);
+ *bx++ = y & 0xffff;
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+}
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+
+/* This actually sometimes returns a pointer to a string literal
+ cast to a char*. Do NOT try to modify the return value. */
+
+Q_CORE_EXPORT char *qdtoa ( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
+{
+ // Some values of the floating-point control word can cause _qdtoa to crash with an underflow.
+ // We set a safe value here.
+#ifdef Q_OS_WIN
+ _clear87();
+ unsigned int oldbits = _control87(0, 0);
+#ifndef MCW_EM
+# ifdef _MCW_EM
+# define MCW_EM _MCW_EM
+# else
+# define MCW_EM 0x0008001F
+# endif
+#endif
+ _control87(MCW_EM, MCW_EM);
+#endif
+
+#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
+ fenv_t envp;
+ feholdexcept(&envp);
+#endif
+
+ char *s = _qdtoa(d, mode, ndigits, decpt, sign, rve, resultp);
+
+#ifdef Q_OS_WIN
+ _clear87();
+#ifndef _M_X64
+ _control87(oldbits, 0xFFFFF);
+#else
+ _control87(oldbits, _MCW_EM|_MCW_DN|_MCW_RC);
+#endif //_M_X64
+#endif //Q_OS_WIN
+
+#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
+ fesetenv(&envp);
+#endif
+
+ return s;
+}
+
+static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
+{
+ /*
+ Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4-9 should give the same return values as 2-3, i.e.,
+ 4 <= mode <= 9 ==> same return as mode
+ 2 + (mode & 1). These modes are mainly for
+ debugging; often they run slower but sometimes
+ faster than modes 2-3.
+ 4,5,8,9 ==> left-to-right digit generation.
+ 6-9 ==> don't try fast floating-point estimate
+ (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim0,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ try_quick;
+ int ilim = 0, ilim1 = 0, spec_case = 0; /* pacify gcc */
+ Long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ ULong x;
+#endif
+ Bigint *b, *b1, *delta, *mhi, *S;
+ Bigint *mlo = NULL; /* pacify gcc */
+ double d2;
+ double ds, eps;
+ char *s, *s0;
+
+ if (getWord0(d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ setWord0(&d, getWord0(d) & ~Sign_bit); /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((getWord0(d) & Exp_mask) == Exp_mask)
+#else
+ if (getWord0(d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+ s =
+#ifdef IEEE_Arith
+ !getWord1(d) && !(getWord0(d) & 0xfffff) ? const_cast<char*>("Infinity") :
+#endif
+ const_cast<char*>("NaN");
+ if (rve)
+ *rve =
+#ifdef IEEE_Arith
+ s[3] ? s + 8 :
+#endif
+ s + 3;
+ return s;
+ }
+#endif
+#ifdef IBM
+ d += 0; /* normalize */
+#endif
+ if (d == g_double_zero)
+ {
+ *decpt = 1;
+ s = const_cast<char*>("0");
+ if (rve)
+ *rve = s + 1;
+ return s;
+ }
+
+ b = d2b(d, &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+ if ((i = int(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
+#endif
+ d2 = d;
+ setWord0(&d2, getWord0(d2) & Frac_mask1);
+ setWord0(&d2, getWord0(d2) | Exp_11);
+#ifdef IBM
+ if (j = 11 - hi0bits(getWord0(d2) & Frac_mask))
+ d2 /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P-1) - 1);
+ x = i > 32 ? getWord0(d) << (64 - i) | getWord1(d) >> (i - 32)
+ : getWord1(d) << (32 - i);
+ d2 = x;
+ setWord0(&d2, getWord0(d2) - 31*Exp_msk1); /* adjust exponent */
+ i -= (Bias + (P-1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k = int(ds);
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (d < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+ try_quick = 1;
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ switch(mode) {
+ case 0:
+ case 1:
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ QT_TRY {
+ *resultp = static_cast<char *>(malloc(i + 1));
+ Q_CHECK_PTR(*resultp);
+ } QT_CATCH(...) {
+ Bfree(b);
+ QT_RETHROW;
+ }
+ s = s0 = *resultp;
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ d2 = d;
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ d /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ d /= ds;
+ }
+ else if ((j1 = -k) != 0) {
+ d *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ d *= bigtens[i];
+ }
+ }
+ if (k_check && d < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ d *= 10.;
+ ieps++;
+ }
+ eps = ieps*d + 7.;
+ setWord0(&eps, getWord0(eps) - (P-1)*Exp_msk1);
+ if (ilim == 0) {
+ S = mhi = 0;
+ d -= 5.;
+ if (d > eps)
+ goto one_digit;
+ if (d < -eps)
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ eps = 0.5/tens[ilim-1] - eps;
+ for(i = 0;;) {
+ L = Long(d);
+ d -= L;
+ *s++ = '0' + int(L);
+ if (d < eps)
+ goto ret1;
+ if (1. - d < eps)
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ eps *= 10.;
+ d *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
+ // work around a bug on 64 bit IRIX gcc
+ double *t = (double *) tens;
+ eps *= t[ilim-1];
+#else
+ eps *= tens[ilim-1];
+#endif
+ for(i = 1;; i++, d *= 10.) {
+ L = Long(d);
+ d -= L;
+ *s++ = '0' + int(L);
+ if (i == ilim) {
+ if (d > 0.5 + eps)
+ goto bump_up;
+ else if (d < 0.5 - eps) {
+ while(*--s == '0') {}
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ d = d2;
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || d <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++) {
+ L = Long(d / ds);
+ d -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (d < 0) {
+ L--;
+ d += ds;
+ }
+#endif
+ *s++ = '0' + int(L);
+ if (i == ilim) {
+ d += d;
+ if (d > ds || (d == ds && L & 1)) {
+ bump_up:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ if ((d *= 10.) == g_double_zero)
+ break;
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ if (mode < 2) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ }
+ else {
+ j = ilim - 1;
+ if (m5 >= j)
+ m5 -= j;
+ else {
+ s5 += j -= m5;
+ b5 += j;
+ m5 = 0;
+ }
+ if ((i = ilim) < 0) {
+ m2 -= i;
+ i = 0;
+ }
+ }
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if ((j = b5 - m5) != 0)
+ b = pow5mult(b, j);
+ }
+ else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = pow5mult(S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ if (mode < 2) {
+ if (!getWord1(d) && !(getWord0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && getWord0(d) & Exp_mask
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ else
+ spec_case = 0;
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
+ i = 32 - i;
+#else
+ if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && mode > 2) {
+ if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ k = -1 - ndigits;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && !mode && !(getWord1(d) & 1)) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && !mode
+#ifndef ROUND_BIASED
+ && !(getWord1(d) & 1)
+#endif
+ )) {
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd(mhi, 10, 0);
+ else {
+ mlo = multadd(mlo, 10, 0);
+ mhi = multadd(mhi, 10, 0);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || (j == 0 && dig & 1)) {
+ roundoff:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+ while(*--s == '0') {}
+ s++;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+ Bfree(b);
+ if (s == s0) { /* don't return empty string */
+ *s++ = '0';
+ k = 0;
+ }
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+}
+#else
+// NOT thread safe!
+
+#include <errno.h>
+
+Q_CORE_EXPORT char *qdtoa( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
+{
+ if(rve)
+ *rve = 0;
+
+ char *res;
+ if (mode == 0)
+ ndigits = 80;
+
+ if (mode == 3)
+ res = fcvt(d, ndigits, decpt, sign);
+ else
+ res = ecvt(d, ndigits, decpt, sign);
+
+ int n = qstrlen(res);
+ if (mode == 0) { // remove trailing 0's
+ const int stop = qMax(1, *decpt);
+ int i;
+ for (i = n-1; i >= stop; --i) {
+ if (res[i] != '0')
+ break;
+ }
+ n = i + 1;
+ }
+ *resultp = static_cast<char*>(malloc(n + 1));
+ Q_CHECK_PTR(resultp);
+ qstrncpy(*resultp, res, n + 1);
+ return *resultp;
+}
+
+Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok)
+{
+ double ret = strtod((char*)s00, (char**)se);
+ if (ok) {
+ if((ret == 0.0l && errno == ERANGE)
+ || ret == HUGE_VAL || ret == -HUGE_VAL)
+ *ok = false;
+ else
+ *ok = true; // the result will be that we don't report underflow in this case
+ }
+ return ret;
+}
+
+#endif // QT_QLOCALE_USES_FCVT
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h
new file mode 100644
index 0000000000..07631d5de5
--- /dev/null
+++ b/src/corelib/tools/qlocale_tools_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCALE_TOOLS_P_H
+#define QLOCALE_TOOLS_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 "qlocale_p.h"
+#include "qstring.h"
+
+#if !defined(QT_QLOCALE_NEEDS_VOLATILE)
+# if defined(Q_CC_GNU)
+# if __GNUC__ == 4
+# define QT_QLOCALE_NEEDS_VOLATILE
+# elif defined(Q_OS_WIN)
+# define QT_QLOCALE_NEEDS_VOLATILE
+# endif
+# endif
+#endif
+
+#if defined(QT_QLOCALE_NEEDS_VOLATILE)
+# define NEEDS_VOLATILE volatile
+#else
+# define NEEDS_VOLATILE
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QString qulltoa(qulonglong l, int base, const QChar _zero);
+QString qlltoa(qlonglong l, int base, const QChar zero);
+
+enum PrecisionMode {
+ PMDecimalDigits = 0x01,
+ PMSignificantDigits = 0x02,
+ PMChopTrailingZeros = 0x03
+};
+
+QString &decimalForm(QChar zero, QChar decimal, QChar group,
+ QString &digits, int decpt, uint precision,
+ PrecisionMode pm,
+ bool always_show_decpt,
+ bool thousands_group);
+QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
+ QChar group, QChar plus, QChar minus,
+ QString &digits, int decpt, uint precision,
+ PrecisionMode pm,
+ bool always_show_decpt);
+
+inline bool isZero(double d)
+{
+ uchar *ch = (uchar *)&d;
+#ifdef QT_ARMFPA
+ return !(ch[3] & 0x7F || ch[2] || ch[1] || ch[0] || ch[7] || ch[6] || ch[5] || ch[4]);
+#else
+ 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]);
+ }
+#endif
+}
+
+// Removes thousand-group separators in "C" locale.
+bool removeGroupSeparators(QLocalePrivate::CharBuff *num);
+
+Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt,
+ int *sign, char **rve, char **digits_str);
+Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
+qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
+qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp
new file mode 100644
index 0000000000..40a52ba967
--- /dev/null
+++ b/src/corelib/tools/qlocale_unix.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocale_p.h"
+
+#include "qstringbuilder.h"
+#include "qdatetime.h"
+#include "qstringlist.h"
+#include "qvariant.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMLOCALE
+struct QSystemLocaleData
+{
+ QSystemLocaleData()
+ : lc_numeric(QLocale::C)
+ ,lc_time(QLocale::C)
+ ,lc_monetary(QLocale::C)
+ ,lc_messages(QLocale::C)
+ {
+ QByteArray all = qgetenv("LC_ALL");
+ QByteArray numeric = all.isEmpty() ? qgetenv("LC_NUMERIC") : all;
+ QByteArray time = all.isEmpty() ? qgetenv("LC_TIME") : all;
+ QByteArray monetary = all.isEmpty() ? qgetenv("LC_MONETARY") : all;
+ lc_messages_var = all.isEmpty() ? qgetenv("LC_MESSAGES") : all;
+ lc_measurement_var = all.isEmpty() ? qgetenv("LC_MEASUREMENT") : all;
+ QByteArray lang = qgetenv("LANG");
+ if (lang.isEmpty())
+ lang = QByteArray("C");
+ if (numeric.isEmpty())
+ numeric = lang;
+ if (monetary.isEmpty())
+ monetary = lang;
+ if (lc_messages_var.isEmpty())
+ lc_messages_var = lang;
+ if (lc_measurement_var.isEmpty())
+ lc_measurement_var = lang;
+ lc_numeric = QLocale(QString::fromLatin1(numeric));
+ lc_time = QLocale(QString::fromLatin1(time));
+ lc_monetary = QLocale(QString::fromLatin1(monetary));
+ lc_messages = QLocale(QString::fromLatin1(lc_messages_var));
+ }
+
+ QLocale lc_numeric;
+ QLocale lc_time;
+ QLocale lc_monetary;
+ QLocale lc_messages;
+ QByteArray lc_messages_var;
+ QByteArray lc_measurement_var;
+};
+Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData)
+#endif
+
+#ifndef QT_NO_SYSTEMLOCALE
+QLocale QSystemLocale::fallbackLocale() const
+{
+ QByteArray lang = qgetenv("LC_ALL");
+ if (lang.isEmpty())
+ lang = qgetenv("LC_NUMERIC");
+ if (lang.isEmpty())
+ lang = qgetenv("LANG");
+ return QLocale(QLatin1String(lang));
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant in) const
+{
+ QSystemLocaleData *d = qSystemLocaleData();
+ const QLocale &lc_numeric = d->lc_numeric;
+ const QLocale &lc_time = d->lc_time;
+ const QLocale &lc_monetary = d->lc_monetary;
+ const QLocale &lc_messages = d->lc_messages;
+
+ switch (type) {
+ case DecimalPoint:
+ return lc_numeric.decimalPoint();
+ case GroupSeparator:
+ return lc_numeric.groupSeparator();
+ case ZeroDigit:
+ return lc_numeric.zeroDigit();
+ case NegativeSign:
+ return lc_numeric.negativeSign();
+ case DateFormatLong:
+ return lc_time.dateFormat(QLocale::LongFormat);
+ case DateFormatShort:
+ return lc_time.dateFormat(QLocale::ShortFormat);
+ case TimeFormatLong:
+ return lc_time.timeFormat(QLocale::LongFormat);
+ case TimeFormatShort:
+ return lc_time.timeFormat(QLocale::ShortFormat);
+ case DayNameLong:
+ return lc_time.dayName(in.toInt(), QLocale::LongFormat);
+ case DayNameShort:
+ return lc_time.dayName(in.toInt(), QLocale::ShortFormat);
+ case MonthNameLong:
+ return lc_time.monthName(in.toInt(), QLocale::LongFormat);
+ case MonthNameShort:
+ return lc_time.monthName(in.toInt(), QLocale::ShortFormat);
+ case DateToStringLong:
+ return lc_time.toString(in.toDate(), QLocale::LongFormat);
+ case DateToStringShort:
+ return lc_time.toString(in.toDate(), QLocale::ShortFormat);
+ case TimeToStringLong:
+ return lc_time.toString(in.toTime(), QLocale::LongFormat);
+ case TimeToStringShort:
+ return lc_time.toString(in.toTime(), QLocale::ShortFormat);
+ case DateTimeFormatLong:
+ return lc_time.dateTimeFormat(QLocale::LongFormat);
+ case DateTimeFormatShort:
+ return lc_time.dateTimeFormat(QLocale::ShortFormat);
+ case DateTimeToStringLong:
+ return lc_time.toString(in.toDateTime(), QLocale::LongFormat);
+ case DateTimeToStringShort:
+ return lc_time.toString(in.toDateTime(), QLocale::ShortFormat);
+ case PositiveSign:
+ return lc_numeric.positiveSign();
+ case AMText:
+ return lc_time.amText();
+ case PMText:
+ return lc_time.pmText();
+ case FirstDayOfWeek:
+ return lc_time.firstDayOfWeek();
+ case CurrencySymbol:
+ return lc_monetary.currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
+ case CurrencyToString: {
+ switch (in.type()) {
+ case QVariant::Int:
+ return lc_monetary.toCurrencyString(in.toInt());
+ case QVariant::UInt:
+ return lc_monetary.toCurrencyString(in.toUInt());
+ case QVariant::Double:
+ return lc_monetary.toCurrencyString(in.toDouble());
+ case QVariant::LongLong:
+ return lc_monetary.toCurrencyString(in.toLongLong());
+ case QVariant::ULongLong:
+ return lc_monetary.toCurrencyString(in.toULongLong());
+ default:
+ break;
+ }
+ return QString();
+ }
+ case MeasurementSystem: {
+ const QString meas_locale = QString::fromLatin1(d->lc_measurement_var.constData(), d->lc_measurement_var.size());
+ if (meas_locale.compare(QLatin1String("Metric"), Qt::CaseInsensitive) == 0)
+ return QLocale::MetricSystem;
+ if (meas_locale.compare(QLatin1String("Other"), Qt::CaseInsensitive) == 0)
+ return QLocale::MetricSystem;
+ return QVariant((int)QLocale(meas_locale).measurementSystem());
+ }
+ case UILanguages: {
+ static QString languages = QString::fromLatin1(qgetenv("LANGUAGE"));
+ if (!languages.isEmpty()) {
+ QStringList lst = languages.split(QLatin1Char(':'));
+ for (int i = 0; i < lst.size();) {
+ const QString &name = lst.at(i);
+ QString lang, script, cntry;
+ if (name.isEmpty() || !qt_splitLocaleName(name, lang, script, cntry))
+ lst.removeAt(i);
+ else
+ ++i;
+ }
+ return lst;
+ }
+ if (!d->lc_messages_var.isEmpty()) {
+ QString lang, script, cntry;
+ if (qt_splitLocaleName(QString::fromLatin1(d->lc_messages_var.constData(), d->lc_messages_var.size()),
+ lang, script, cntry)) {
+ if (!cntry.length() && lang.length())
+ return QStringList(lang);
+ return QStringList(lang % QLatin1Char('-') % cntry);
+ }
+ }
+ return QVariant();
+ }
+ case StringToStandardQuotation:
+ return lc_messages.quoteString(in.value<QStringRef>());
+ case StringToAlternateQuotation:
+ return lc_messages.quoteString(in.value<QStringRef>(), QLocale::AlternateQuotation);
+ case ListToSeparatedString:
+ return lc_messages.createSeparatedList(in.value<QStringList>());
+ default:
+ break;
+ }
+ return QVariant();
+}
+#endif // QT_NO_SYSTEMLOCALE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
new file mode 100644
index 0000000000..4a215614d2
--- /dev/null
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -0,0 +1,988 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocale_p.h"
+#include "qlocale_tools_p.h"
+
+#include "qstringlist.h"
+#include "qvariant.h"
+#include "qdatetime.h"
+
+#include "private/qsystemlibrary_p.h"
+
+#include "qdebug.h"
+
+#if defined(Q_OS_WIN)
+# include "qt_windows.h"
+# include <time.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT);
+static const char *winLangCodeToIsoName(int code);
+static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT);
+static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT);
+
+#ifndef QT_NO_SYSTEMLOCALE
+
+#ifndef MUI_LANGUAGE_NAME
+#define MUI_LANGUAGE_NAME 0x8
+#endif
+#ifndef LOCALE_SSHORTESTDAYNAME1
+# define LOCALE_SSHORTESTDAYNAME1 0x0060
+# define LOCALE_SSHORTESTDAYNAME2 0x0061
+# define LOCALE_SSHORTESTDAYNAME3 0x0062
+# define LOCALE_SSHORTESTDAYNAME4 0x0063
+# define LOCALE_SSHORTESTDAYNAME5 0x0064
+# define LOCALE_SSHORTESTDAYNAME6 0x0065
+# define LOCALE_SSHORTESTDAYNAME7 0x0066
+#endif
+#ifndef LOCALE_SNATIVELANGUAGENAME
+# define LOCALE_SNATIVELANGUAGENAME 0x00000004
+#endif
+#ifndef LOCALE_SNATIVECOUNTRYNAME
+# define LOCALE_SNATIVECOUNTRYNAME 0x00000008
+#endif
+
+struct QSystemLocalePrivate
+{
+ QSystemLocalePrivate();
+
+ QChar zeroDigit();
+ QChar decimalPoint();
+ QChar groupSeparator();
+ QChar negativeSign();
+ QChar positiveSign();
+ QVariant dateFormat(QLocale::FormatType);
+ QVariant timeFormat(QLocale::FormatType);
+ QVariant dateTimeFormat(QLocale::FormatType);
+ QVariant dayName(int, QLocale::FormatType);
+ QVariant monthName(int, QLocale::FormatType);
+ QVariant toString(const QDate &, QLocale::FormatType);
+ QVariant toString(const QTime &, QLocale::FormatType);
+ QVariant toString(const QDateTime &, QLocale::FormatType);
+ QVariant measurementSystem();
+ QVariant amText();
+ QVariant pmText();
+ QVariant firstDayOfWeek();
+ QVariant currencySymbol(QLocale::CurrencySymbolFormat);
+ QVariant toCurrencyString(const QSystemLocale::CurrencyToStringArgument &);
+ QVariant uiLanguages();
+ QVariant nativeLanguageName();
+ QVariant nativeCountryName();
+
+ void update();
+
+private:
+ QByteArray langEnvVar;
+
+ enum SubstitutionType {
+ SUnknown,
+ SContext,
+ SAlways,
+ SNever
+ };
+
+ // cached values:
+ LCID lcid;
+ SubstitutionType substitutionType;
+ QChar zero;
+
+ QString getLocaleInfo(LCTYPE type, int maxlen = 0);
+ int getLocaleInfo_int(LCTYPE type, int maxlen = 0);
+ QChar getLocaleInfo_qchar(LCTYPE type);
+
+ SubstitutionType substitution();
+ QString &substituteDigits(QString &string);
+
+ static QString winToQtFormat(const QString &sys_fmt);
+
+};
+Q_GLOBAL_STATIC(QSystemLocalePrivate, systemLocalePrivate)
+
+QSystemLocalePrivate::QSystemLocalePrivate()
+ : substitutionType(SUnknown)
+{
+ langEnvVar = qgetenv("LANG");
+ lcid = GetUserDefaultLCID();
+}
+
+QString QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen)
+{
+ QVarLengthArray<wchar_t, 64> buf(maxlen ? maxlen : 64);
+ if (!GetLocaleInfo(lcid, type, buf.data(), buf.size()))
+ return QString();
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ int cnt = GetLocaleInfo(lcid, type, 0, 0);
+ if (cnt == 0)
+ return QString();
+ buf.resize(cnt);
+ if (!GetLocaleInfo(lcid, type, buf.data(), buf.size()))
+ return QString();
+ }
+ return QString::fromWCharArray(buf.data());
+}
+
+int QSystemLocalePrivate::getLocaleInfo_int(LCTYPE type, int maxlen)
+{
+ QString str = getLocaleInfo(type, maxlen);
+ bool ok = false;
+ int v = str.toInt(&ok);
+ return ok ? v : 0;
+}
+
+QChar QSystemLocalePrivate::getLocaleInfo_qchar(LCTYPE type)
+{
+ QString str = getLocaleInfo(type);
+ return str.isEmpty() ? QChar() : str.at(0);
+}
+
+QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution()
+{
+ if (substitutionType == SUnknown) {
+ wchar_t buf[8];
+ if (!GetLocaleInfo(lcid, LOCALE_IDIGITSUBSTITUTION, buf, 8)) {
+ substitutionType = QSystemLocalePrivate::SNever;
+ return substitutionType;
+ }
+ if (buf[0] == '1')
+ substitutionType = QSystemLocalePrivate::SNever;
+ else if (buf[0] == '0')
+ substitutionType = QSystemLocalePrivate::SContext;
+ else if (buf[0] == '2')
+ substitutionType = QSystemLocalePrivate::SAlways;
+ else {
+ wchar_t digits[11];
+ if (!GetLocaleInfo(lcid, LOCALE_SNATIVEDIGITS, digits, 11)) {
+ substitutionType = QSystemLocalePrivate::SNever;
+ return substitutionType;
+ }
+ const wchar_t zero = digits[0];
+ if (buf[0] == zero + 2)
+ substitutionType = QSystemLocalePrivate::SAlways;
+ else
+ substitutionType = QSystemLocalePrivate::SNever;
+ }
+ }
+ return substitutionType;
+}
+
+QString &QSystemLocalePrivate::substituteDigits(QString &string)
+{
+ ushort zero = zeroDigit().unicode();
+ ushort *qch = (ushort *)string.data();
+ for (ushort *end = qch + string.size(); qch != end; ++qch) {
+ if (*qch >= '0' && *qch <= '9')
+ *qch = zero + (*qch - '0');
+ }
+ return string;
+}
+
+QChar QSystemLocalePrivate::zeroDigit()
+{
+ if (zero.isNull())
+ zero = getLocaleInfo_qchar(LOCALE_SNATIVEDIGITS);
+ return zero;
+}
+
+QChar QSystemLocalePrivate::decimalPoint()
+{
+ return getLocaleInfo_qchar(LOCALE_SDECIMAL);
+}
+
+QChar QSystemLocalePrivate::groupSeparator()
+{
+ return getLocaleInfo_qchar(LOCALE_STHOUSAND);
+}
+
+QChar QSystemLocalePrivate::negativeSign()
+{
+ return getLocaleInfo_qchar(LOCALE_SNEGATIVESIGN);
+}
+
+QChar QSystemLocalePrivate::positiveSign()
+{
+ return getLocaleInfo_qchar(LOCALE_SPOSITIVESIGN);
+}
+
+QVariant QSystemLocalePrivate::dateFormat(QLocale::FormatType type)
+{
+ switch (type) {
+ case QLocale::ShortFormat:
+ return winToQtFormat(getLocaleInfo(LOCALE_SSHORTDATE));
+ case QLocale::LongFormat:
+ return winToQtFormat(getLocaleInfo(LOCALE_SLONGDATE));
+ case QLocale::NarrowFormat:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QSystemLocalePrivate::timeFormat(QLocale::FormatType type)
+{
+ switch (type) {
+ case QLocale::ShortFormat:
+ return winToQtFormat(getLocaleInfo(LOCALE_STIMEFORMAT)); //###
+ case QLocale::LongFormat:
+ return winToQtFormat(getLocaleInfo(LOCALE_STIMEFORMAT));
+ case QLocale::NarrowFormat:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QSystemLocalePrivate::dateTimeFormat(QLocale::FormatType type)
+{
+ return QString(dateFormat(type).toString() + QLatin1Char(' ') + timeFormat(type).toString());
+}
+
+QVariant QSystemLocalePrivate::dayName(int day, QLocale::FormatType type)
+{
+ static const LCTYPE short_day_map[]
+ = { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
+ LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
+ LOCALE_SABBREVDAYNAME6, LOCALE_SABBREVDAYNAME7 };
+
+ static const LCTYPE long_day_map[]
+ = { LOCALE_SDAYNAME1, LOCALE_SDAYNAME2,
+ LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5,
+ LOCALE_SDAYNAME6, LOCALE_SDAYNAME7 };
+
+ static const 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(long_day_map[day]);
+ else if (type == QLocale::NarrowFormat && QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
+ return getLocaleInfo(narrow_day_map[day]);
+ return getLocaleInfo(short_day_map[day]);
+}
+
+QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
+{
+ static const 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[]
+ = { 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();
+
+ LCTYPE lctype = (type == QLocale::ShortFormat || type == QLocale::NarrowFormat)
+ ? short_month_map[month] : long_month_map[month];
+ return getLocaleInfo(lctype);
+}
+
+QVariant QSystemLocalePrivate::toString(const QDate &date, QLocale::FormatType type)
+{
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ st.wYear = date.year();
+ st.wMonth = date.month();
+ st.wDay = date.day();
+
+ DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE);
+ wchar_t buf[255];
+ if (GetDateFormat(lcid, flags, &st, NULL, buf, 255)) {
+ QString format = QString::fromWCharArray(buf);
+ if (substitution() == SAlways)
+ substituteDigits(format);
+ return format;
+ }
+ return QString();
+}
+
+QVariant QSystemLocalePrivate::toString(const QTime &time, QLocale::FormatType)
+{
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ st.wHour = time.hour();
+ st.wMinute = time.minute();
+ st.wSecond = time.second();
+ st.wMilliseconds = 0;
+
+ DWORD flags = 0;
+
+ wchar_t buf[255];
+ if (GetTimeFormat(lcid, flags, &st, NULL, buf, 255)) {
+ QString format = QString::fromWCharArray(buf);
+ if (substitution() == SAlways)
+ substituteDigits(format);
+ return format;
+ }
+ return QString();
+}
+
+QVariant QSystemLocalePrivate::toString(const QDateTime &dt, QLocale::FormatType type)
+{
+ return QString(toString(dt.date(), type).toString() + QLatin1Char(' ') + toString(dt.time(), type).toString());
+}
+
+QVariant QSystemLocalePrivate::measurementSystem()
+{
+ wchar_t output[2];
+
+ if (GetLocaleInfo(lcid, LOCALE_IMEASURE, output, 2)) {
+ QString iMeasure = QString::fromWCharArray(output);
+ if (iMeasure == QLatin1String("1")) {
+ return QLocale::ImperialSystem;
+ }
+ }
+
+ return QLocale::MetricSystem;
+}
+
+QVariant QSystemLocalePrivate::amText()
+{
+ wchar_t output[15]; // maximum length including terminating zero character for Win2003+
+
+ if (GetLocaleInfo(lcid, LOCALE_S1159, output, 15)) {
+ return QString::fromWCharArray(output);
+ }
+
+ return QVariant();
+}
+
+QVariant QSystemLocalePrivate::pmText()
+{
+ wchar_t output[15]; // maximum length including terminating zero character for Win2003+
+
+ if (GetLocaleInfo(lcid, LOCALE_S2359, output, 15)) {
+ return QString::fromWCharArray(output);
+ }
+
+ return QVariant();
+}
+
+QVariant QSystemLocalePrivate::firstDayOfWeek()
+{
+ wchar_t output[4]; // maximum length including terminating zero character for Win2003+
+
+ if (GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, output, 4))
+ return QString::fromWCharArray(output).toUInt()+1;
+
+ return 1;
+}
+
+QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat format)
+{
+ wchar_t buf[13];
+ switch (format) {
+ case QLocale::CurrencySymbol:
+ if (GetLocaleInfo(lcid, LOCALE_SCURRENCY, buf, 13))
+ return QString::fromWCharArray(buf);
+ break;
+ case QLocale::CurrencyIsoCode:
+ if (GetLocaleInfo(lcid, LOCALE_SINTLSYMBOL, buf, 9))
+ return QString::fromWCharArray(buf);
+ break;
+ case QLocale::CurrencyDisplayName: {
+ QVarLengthArray<wchar_t, 64> buf(64);
+ if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ break;
+ buf.resize(255); // should be large enough, right?
+ if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size()))
+ break;
+ }
+ return QString::fromWCharArray(buf.data());
+ }
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToStringArgument &arg)
+{
+ QString value;
+ switch (arg.value.type()) {
+ case QVariant::Int:
+ value = QLocalePrivate::longLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), QLatin1Char('-'),
+ arg.value.toInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
+ break;
+ case QVariant::UInt:
+ value = QLocalePrivate::unsLongLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'),
+ arg.value.toUInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
+ break;
+ case QVariant::Double:
+ value = QLocalePrivate::doubleToString(QLatin1Char('0'), QLatin1Char('+'), QLatin1Char('-'),
+ QLatin1Char(' '), QLatin1Char(','), QLatin1Char('.'),
+ arg.value.toDouble(), -1, QLocalePrivate::DFDecimal, -1, QLocale::OmitGroupSeparator);
+ break;
+ case QVariant::LongLong:
+ value = QLocalePrivate::longLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'), QLatin1Char('-'),
+ arg.value.toLongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
+ break;
+ case QVariant::ULongLong:
+ value = QLocalePrivate::unsLongLongToString(QLatin1Char('0'), QLatin1Char(','), QLatin1Char('+'),
+ arg.value.toULongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
+ break;
+ default:
+ return QVariant();
+ }
+
+ QVarLengthArray<wchar_t, 64> out(64);
+
+ QString decimalSep;
+ QString thousandSep;
+ CURRENCYFMT format;
+ CURRENCYFMT *pformat = NULL;
+ if (!arg.symbol.isEmpty()) {
+ format.NumDigits = getLocaleInfo_int(lcid, LOCALE_ICURRDIGITS);
+ format.LeadingZero = getLocaleInfo_int(lcid, LOCALE_ILZERO);
+ decimalSep = getLocaleInfo(lcid, LOCALE_SMONDECIMALSEP);
+ format.lpDecimalSep = (wchar_t *)decimalSep.utf16();
+ thousandSep = getLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP);
+ format.lpThousandSep = (wchar_t *)thousandSep.utf16();
+ format.NegativeOrder = getLocaleInfo_int(lcid, LOCALE_INEGCURR);
+ format.PositiveOrder = getLocaleInfo_int(lcid, LOCALE_ICURRENCY);
+ format.lpCurrencySymbol = (wchar_t *)arg.symbol.utf16();
+
+ // grouping is complicated and ugly:
+ // int(0) == "123456789.00" == string("0")
+ // int(3) == "123,456,789.00" == string("3;0")
+ // 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(lcid, LOCALE_SMONGROUPING);
+ format.Grouping = groupingStr.remove(QLatin1Char(';')).toInt();
+ if (format.Grouping % 10 == 0) // magic
+ format.Grouping /= 10;
+ else
+ format.Grouping *= 10;
+ pformat = &format;
+ }
+
+ int ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()),
+ pformat, out.data(), out.size());
+ if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()),
+ pformat, out.data(), 0);
+ out.resize(ret);
+ ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()),
+ pformat, out.data(), out.size());
+ }
+
+ value = QString::fromWCharArray(out.data());
+ if (substitution() == SAlways)
+ substituteDigits( value);
+ return value;
+}
+
+QVariant QSystemLocalePrivate::uiLanguages()
+{
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) {
+ typedef BOOL (*GetUserPreferredUILanguagesFunc) (
+ DWORD dwFlags,
+ PULONG pulNumLanguages,
+ PWSTR pwszLanguagesBuffer,
+ PULONG pcchLanguagesBuffer);
+ static GetUserPreferredUILanguagesFunc GetUserPreferredUILanguages_ptr = 0;
+ if (!GetUserPreferredUILanguages_ptr) {
+ QSystemLibrary lib(QLatin1String("kernel32"));
+ if (lib.load())
+ GetUserPreferredUILanguages_ptr = (GetUserPreferredUILanguagesFunc)lib.resolve("GetUserPreferredUILanguages");
+ }
+ if (GetUserPreferredUILanguages_ptr) {
+ unsigned long cnt = 0;
+ QVarLengthArray<wchar_t, 64> buf(64);
+ unsigned long size = buf.size();
+ if (!GetUserPreferredUILanguages_ptr(MUI_LANGUAGE_NAME, &cnt, buf.data(), &size)) {
+ size = 0;
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
+ GetUserPreferredUILanguages_ptr(MUI_LANGUAGE_NAME, &cnt, NULL, &size)) {
+ buf.resize(size);
+ if (!GetUserPreferredUILanguages_ptr(MUI_LANGUAGE_NAME, &cnt, buf.data(), &size))
+ return QStringList();
+ }
+ }
+ QStringList result;
+ result.reserve(cnt);
+ const wchar_t *str = buf.constData();
+ for (; cnt > 0; --cnt) {
+ QString s = QString::fromWCharArray(str);
+ if (s.isEmpty())
+ break; // something is wrong
+ result.append(s);
+ str += s.size()+1;
+ }
+ return result;
+ }
+ }
+
+ // old Windows before Vista
+ return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage())));
+}
+
+QVariant QSystemLocalePrivate::nativeLanguageName()
+{
+ if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
+ return getLocaleInfo(LOCALE_SNATIVELANGNAME);
+ return getLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
+}
+
+QVariant QSystemLocalePrivate::nativeCountryName()
+{
+ if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
+ return getLocaleInfo(LOCALE_SNATIVECTRYNAME);
+ return getLocaleInfo(LOCALE_SNATIVECOUNTRYNAME);
+}
+
+
+void QSystemLocalePrivate::update()
+{
+ lcid = GetUserDefaultLCID();
+ substitutionType = SUnknown;
+ zero = QChar();
+}
+
+QString QSystemLocalePrivate::winToQtFormat(const QString &sys_fmt)
+{
+ QString result;
+ int i = 0;
+
+ while (i < sys_fmt.size()) {
+ if (sys_fmt.at(i).unicode() == QLatin1Char('\'')) {
+ QString text = qt_readEscapedFormatString(sys_fmt, &i);
+ if (text == QLatin1String("'"))
+ result += QLatin1String("''");
+ else
+ result += QString(QLatin1Char('\'') + text + QLatin1Char('\''));
+ continue;
+ }
+
+ QChar c = sys_fmt.at(i);
+ int repeat = qt_repeatCount(sys_fmt, i);
+
+ switch (c.unicode()) {
+ // Date
+ case 'y':
+ if (repeat > 5)
+ repeat = 5;
+ else if (repeat == 3)
+ repeat = 2;
+ switch (repeat) {
+ case 1:
+ result += QLatin1String("yy"); // "y" unsupported by Qt, use "yy"
+ break;
+ case 5:
+ result += QLatin1String("yyyy"); // "yyyyy" same as "yyyy" on Windows
+ break;
+ default:
+ result += QString(repeat, QLatin1Char('y'));
+ break;
+ }
+ break;
+ case 'g':
+ if (repeat > 2)
+ repeat = 2;
+ switch (repeat) {
+ case 2:
+ break; // no equivalent of "gg" in Qt
+ default:
+ result += QLatin1Char('g');
+ break;
+ }
+ break;
+ case 't':
+ if (repeat > 2)
+ repeat = 2;
+ result += QLatin1String("AP"); // "t" unsupported, use "AP"
+ break;
+ default:
+ result += QString(repeat, c);
+ break;
+ }
+
+ i += repeat;
+ }
+
+ return result;
+}
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+ return QLocale(QString::fromLatin1(getWinLocaleName()));
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
+{
+ QSystemLocalePrivate *d = systemLocalePrivate();
+ switch(type) {
+ case DecimalPoint:
+ return d->decimalPoint();
+ case GroupSeparator:
+ return d->groupSeparator();
+ case NegativeSign:
+ return d->negativeSign();
+ case PositiveSign:
+ return d->positiveSign();
+ case DateFormatLong:
+ return d->dateFormat(QLocale::LongFormat);
+ case DateFormatShort:
+ return d->dateFormat(QLocale::ShortFormat);
+ case TimeFormatLong:
+ return d->timeFormat(QLocale::LongFormat);
+ case TimeFormatShort:
+ return d->timeFormat(QLocale::ShortFormat);
+ case DateTimeFormatLong:
+ return d->dateTimeFormat(QLocale::LongFormat);
+ case DateTimeFormatShort:
+ return d->dateTimeFormat(QLocale::ShortFormat);
+ case DayNameLong:
+ return d->dayName(in.toInt(), QLocale::LongFormat);
+ case DayNameShort:
+ return d->dayName(in.toInt(), QLocale::ShortFormat);
+ case MonthNameLong:
+ return d->monthName(in.toInt(), QLocale::LongFormat);
+ case MonthNameShort:
+ return d->monthName(in.toInt(), QLocale::ShortFormat);
+ case DateToStringShort:
+ return d->toString(in.toDate(), QLocale::ShortFormat);
+ case DateToStringLong:
+ return d->toString(in.toDate(), QLocale::LongFormat);
+ case TimeToStringShort:
+ return d->toString(in.toTime(), QLocale::ShortFormat);
+ case TimeToStringLong:
+ return d->toString(in.toTime(), QLocale::LongFormat);
+ case DateTimeToStringShort:
+ return d->toString(in.toDateTime(), QLocale::ShortFormat);
+ case DateTimeToStringLong:
+ return d->toString(in.toDateTime(), QLocale::LongFormat);
+ case ZeroDigit:
+ return d->zeroDigit();
+ case LanguageId:
+ case CountryId: {
+ QString locale = QString::fromLatin1(getWinLocaleName());
+ QLocale::Language lang;
+ QLocale::Script script;
+ QLocale::Country cntry;
+ QLocalePrivate::getLangAndCountry(locale, lang, script, cntry);
+ if (type == LanguageId)
+ return lang;
+ if (cntry == QLocale::AnyCountry)
+ return fallbackLocale().country();
+ return cntry;
+ }
+ case ScriptId:
+ return QVariant(QLocale::AnyScript);
+ case MeasurementSystem:
+ return d->measurementSystem();
+ case AMText:
+ return d->amText();
+ case PMText:
+ return d->pmText();
+ case FirstDayOfWeek:
+ return d->firstDayOfWeek();
+ case CurrencySymbol:
+ return d->currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
+ case CurrencyToString:
+ return d->toCurrencyString(in.value<QSystemLocale::CurrencyToStringArgument>());
+ case UILanguages:
+ return d->uiLanguages();
+ case LocaleChanged:
+ d->update();
+ break;
+ case NativeLanguageName:
+ return d->nativeLanguageName();
+ case NativeCountryName:
+ return d->nativeCountryName();
+ default:
+ break;
+ }
+ return QVariant();
+}
+#endif // QT_NO_SYSTEMLOCALE
+
+struct WindowsToISOListElt {
+ ushort windows_code;
+ char iso_name[6];
+};
+
+/* NOTE: This array should be sorted by the first column! */
+static const WindowsToISOListElt windows_to_iso_list[] = {
+ { 0x0401, "ar_SA" },
+ { 0x0402, "bg\0 " },
+ { 0x0403, "ca\0 " },
+ { 0x0404, "zh_TW" },
+ { 0x0405, "cs\0 " },
+ { 0x0406, "da\0 " },
+ { 0x0407, "de\0 " },
+ { 0x0408, "el\0 " },
+ { 0x0409, "en_US" },
+ { 0x040a, "es\0 " },
+ { 0x040b, "fi\0 " },
+ { 0x040c, "fr\0 " },
+ { 0x040d, "he\0 " },
+ { 0x040e, "hu\0 " },
+ { 0x040f, "is\0 " },
+ { 0x0410, "it\0 " },
+ { 0x0411, "ja\0 " },
+ { 0x0412, "ko\0 " },
+ { 0x0413, "nl\0 " },
+ { 0x0414, "no\0 " },
+ { 0x0415, "pl\0 " },
+ { 0x0416, "pt_BR" },
+ { 0x0418, "ro\0 " },
+ { 0x0419, "ru\0 " },
+ { 0x041a, "hr\0 " },
+ { 0x041c, "sq\0 " },
+ { 0x041d, "sv\0 " },
+ { 0x041e, "th\0 " },
+ { 0x041f, "tr\0 " },
+ { 0x0420, "ur\0 " },
+ { 0x0421, "in\0 " },
+ { 0x0422, "uk\0 " },
+ { 0x0423, "be\0 " },
+ { 0x0425, "et\0 " },
+ { 0x0426, "lv\0 " },
+ { 0x0427, "lt\0 " },
+ { 0x0429, "fa\0 " },
+ { 0x042a, "vi\0 " },
+ { 0x042d, "eu\0 " },
+ { 0x042f, "mk\0 " },
+ { 0x0436, "af\0 " },
+ { 0x0438, "fo\0 " },
+ { 0x0439, "hi\0 " },
+ { 0x043e, "ms\0 " },
+ { 0x0458, "mt\0 " },
+ { 0x0801, "ar_IQ" },
+ { 0x0804, "zh_CN" },
+ { 0x0807, "de_CH" },
+ { 0x0809, "en_GB" },
+ { 0x080a, "es_MX" },
+ { 0x080c, "fr_BE" },
+ { 0x0810, "it_CH" },
+ { 0x0812, "ko\0 " },
+ { 0x0813, "nl_BE" },
+ { 0x0814, "no\0 " },
+ { 0x0816, "pt\0 " },
+ { 0x081a, "sr\0 " },
+ { 0x081d, "sv_FI" },
+ { 0x0c01, "ar_EG" },
+ { 0x0c04, "zh_HK" },
+ { 0x0c07, "de_AT" },
+ { 0x0c09, "en_AU" },
+ { 0x0c0a, "es\0 " },
+ { 0x0c0c, "fr_CA" },
+ { 0x0c1a, "sr\0 " },
+ { 0x1001, "ar_LY" },
+ { 0x1004, "zh_SG" },
+ { 0x1007, "de_LU" },
+ { 0x1009, "en_CA" },
+ { 0x100a, "es_GT" },
+ { 0x100c, "fr_CH" },
+ { 0x1401, "ar_DZ" },
+ { 0x1407, "de_LI" },
+ { 0x1409, "en_NZ" },
+ { 0x140a, "es_CR" },
+ { 0x140c, "fr_LU" },
+ { 0x1801, "ar_MA" },
+ { 0x1809, "en_IE" },
+ { 0x180a, "es_PA" },
+ { 0x1c01, "ar_TN" },
+ { 0x1c09, "en_ZA" },
+ { 0x1c0a, "es_DO" },
+ { 0x2001, "ar_OM" },
+ { 0x2009, "en_JM" },
+ { 0x200a, "es_VE" },
+ { 0x2401, "ar_YE" },
+ { 0x2409, "en\0 " },
+ { 0x240a, "es_CO" },
+ { 0x2801, "ar_SY" },
+ { 0x2809, "en_BZ" },
+ { 0x280a, "es_PE" },
+ { 0x2c01, "ar_JO" },
+ { 0x2c09, "en_TT" },
+ { 0x2c0a, "es_AR" },
+ { 0x3001, "ar_LB" },
+ { 0x300a, "es_EC" },
+ { 0x3401, "ar_KW" },
+ { 0x340a, "es_CL" },
+ { 0x3801, "ar_AE" },
+ { 0x380a, "es_UY" },
+ { 0x3c01, "ar_BH" },
+ { 0x3c0a, "es_PY" },
+ { 0x4001, "ar_QA" },
+ { 0x400a, "es_BO" },
+ { 0x440a, "es_SV" },
+ { 0x480a, "es_HN" },
+ { 0x4c0a, "es_NI" },
+ { 0x500a, "es_PR" }
+};
+
+static const int windows_to_iso_count
+ = sizeof(windows_to_iso_list)/sizeof(WindowsToISOListElt);
+
+static const char *winLangCodeToIsoName(int code)
+{
+ int cmp = code - windows_to_iso_list[0].windows_code;
+ if (cmp < 0)
+ return 0;
+
+ if (cmp == 0)
+ return windows_to_iso_list[0].iso_name;
+
+ int begin = 0;
+ int end = windows_to_iso_count;
+
+ 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;
+
+}
+
+static QString winIso639LangName(LCID id)
+{
+ QString result;
+
+ // Windows returns the wrong ISO639 for some languages, we need to detect them here using
+ // the language code
+ QString lang_code;
+ wchar_t out[256];
+ if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) // ### shouldn't use them according to msdn
+ lang_code = QString::fromWCharArray(out);
+
+ if (!lang_code.isEmpty()) {
+ const char *endptr;
+ bool ok;
+ QByteArray latin1_lang_code = lang_code.toLatin1();
+ int i = qstrtoull(latin1_lang_code, &endptr, 16, &ok);
+ if (ok && *endptr == '\0') {
+ switch (i) {
+ case 0x814:
+ result = QLatin1String("nn"); // Nynorsk
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!result.isEmpty())
+ return result;
+
+ // not one of the problematic languages - do the usual lookup
+ if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255))
+ result = QString::fromWCharArray(out);
+
+ return result;
+}
+
+static QString winIso3116CtryName(LCID id)
+{
+ QString result;
+
+ wchar_t out[256];
+ if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255))
+ result = QString::fromWCharArray(out);
+
+ return result;
+}
+
+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;
+ else
+ return winLangCodeToIsoName( (int)id );
+ }
+ }
+
+#if defined(Q_OS_WINCE)
+ result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID());
+#else
+ if (id == LOCALE_USER_DEFAULT)
+ id = GetUserDefaultLCID();
+ QString resultuage = winIso639LangName(id);
+ QString country = winIso3116CtryName(id);
+ result = resultuage.toLatin1();
+ if (!country.isEmpty()) {
+ result += '_';
+ result += country.toLatin1();
+ }
+#endif
+
+ return result;
+}
+
+Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id)
+{
+ return QLocale(QString::fromLatin1(getWinLocaleName(id)));
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
new file mode 100644
index 0000000000..9e13fcc05e
--- /dev/null
+++ b/src/corelib/tools/qmap.cpp
@@ -0,0 +1,1646 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmap.h"
+
+#include <stdlib.h>
+
+#ifdef QT_QMAP_DEBUG
+# include <qstring.h>
+# include <qvector.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QMapData QMapData::shared_null = {
+ &shared_null,
+ { &shared_null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, false, true, false, 0
+};
+
+QMapData *QMapData::createData()
+{
+ return createData(0);
+}
+
+QMapData *QMapData::createData(int alignment)
+{
+ QMapData *d = new QMapData;
+ Q_CHECK_PTR(d);
+ Node *e = reinterpret_cast<Node *>(d);
+ e->backward = e;
+ e->forward[0] = e;
+ d->ref = 1;
+ d->topLevel = 0;
+ d->size = 0;
+ d->randomBits = 0;
+ d->insertInOrder = false;
+ d->sharable = true;
+ d->strictAlignment = alignment > 8;
+ d->reserved = 0;
+ return d;
+}
+
+void QMapData::continueFreeData(int offset)
+{
+ Node *e = reinterpret_cast<Node *>(this);
+ Node *cur = e->forward[0];
+ Node *prev;
+ while (cur != e) {
+ prev = cur;
+ cur = cur->forward[0];
+ if (strictAlignment)
+ qFreeAligned(reinterpret_cast<char *>(prev) - offset);
+ else
+ qFree(reinterpret_cast<char *>(prev) - offset);
+ }
+ delete this;
+}
+
+QMapData::Node *QMapData::node_create(Node *update[], int offset)
+{
+ return node_create(update, offset, 0);
+}
+
+/*!
+ Creates a new node inside the data structure.
+
+ \a update is an array with pointers to the node after which the new node
+ should be inserted. Because of the strange skip list data structure there
+ could be several pointers to this node on different levels.
+ \a offset is an amount of bytes that needs to reserved just before the
+ QMapData::Node structure.
+
+ \a alignment dictates the alignment for the data.
+
+ \internal
+ \since 4.6
+*/
+QMapData::Node *QMapData::node_create(Node *update[], int offset, int alignment)
+{
+ int level = 0;
+ uint mask = (1 << Sparseness) - 1;
+
+ while ((randomBits & mask) == mask && level < LastLevel) {
+ ++level;
+ mask <<= Sparseness;
+ }
+
+ if (level > topLevel) {
+ Node *e = reinterpret_cast<Node *>(this);
+ level = ++topLevel;
+ e->forward[level] = e;
+ update[level] = e;
+ }
+
+ ++randomBits;
+ if (level == 3 && !insertInOrder)
+ randomBits = qrand();
+
+ void *concreteNode = strictAlignment ?
+ qMallocAligned(offset + sizeof(Node) + level * sizeof(Node *), alignment) :
+ qMalloc(offset + sizeof(Node) + level * sizeof(Node *));
+ Q_CHECK_PTR(concreteNode);
+
+ Node *abstractNode = reinterpret_cast<Node *>(reinterpret_cast<char *>(concreteNode) + offset);
+
+ abstractNode->backward = update[0];
+ update[0]->forward[0]->backward = abstractNode;
+
+ for (int i = level; i >= 0; i--) {
+ abstractNode->forward[i] = update[i]->forward[i];
+ update[i]->forward[i] = abstractNode;
+ update[i] = abstractNode;
+ }
+ ++size;
+ return abstractNode;
+}
+
+void QMapData::node_delete(Node *update[], int offset, Node *node)
+{
+ node->forward[0]->backward = node->backward;
+
+ for (int i = 0; i <= topLevel; ++i) {
+ if (update[i]->forward[i] != node)
+ break;
+ update[i]->forward[i] = node->forward[i];
+ }
+ --size;
+ if (strictAlignment)
+ qFreeAligned(reinterpret_cast<char *>(node) - offset);
+ else
+ qFree(reinterpret_cast<char *>(node) - offset);
+}
+
+#ifdef QT_QMAP_DEBUG
+
+uint QMapData::adjust_ptr(Node *node)
+{
+ if (node == reinterpret_cast<Node *>(this)) {
+ return (uint)0xDEADBEEF;
+ } else {
+ return (uint)node;
+ }
+}
+
+void QMapData::dump()
+{
+ qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", int(ref), size, randomBits);
+
+ QString preOutput;
+ QVector<QString> output(topLevel + 1);
+ Node *e = reinterpret_cast<Node *>(this);
+
+ QString str;
+ str.sprintf(" %.8x", adjust_ptr(reinterpret_cast<Node *>(this)));
+ preOutput += str;
+
+ Node *update[LastLevel + 1];
+ for (int i = 0; i <= topLevel; ++i) {
+ str.sprintf("%d: [%.8x] -", i, adjust_ptr(reinterpret_cast<Node *>(forward[i])));
+ output[i] += str;
+ update[i] = reinterpret_cast<Node *>(forward[i]);
+ }
+
+ Node *node = reinterpret_cast<Node *>(forward[0]);
+ while (node != e) {
+ int level = 0;
+ while (level < topLevel && update[level + 1] == node)
+ ++level;
+
+ str.sprintf(" %.8x", adjust_ptr(node));
+ preOutput += str;
+
+ for (int i = 0; i <= level; ++i) {
+ str.sprintf("-> [%.8x] -", adjust_ptr(node->forward[i]));
+ output[i] += str;
+ update[i] = node->forward[i];
+ }
+ for (int j = level + 1; j <= topLevel; ++j)
+ output[j] += QLatin1String("---------------");
+ node = node->forward[0];
+ }
+
+ qDebug("%s", preOutput.ascii());
+ for (int i = 0; i <= topLevel; ++i)
+ qDebug("%s", output[i].ascii());
+}
+#endif
+
+/*!
+ \class QMap
+ \brief The QMap class is a template class that provides a skip-list-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
+ \i QHash provides faster lookups than QMap. (See \l{Algorithmic
+ Complexity} for details.)
+ \i When iterating over a QHash, the items are arbitrarily ordered.
+ With QMap, the items are always sorted by key.
+ \i 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.
+ \endlist
+
+ Here's an example QMap with QString keys and \c int values:
+ \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 0
+
+ To insert a (key, value) pair into the map, you can use operator[]():
+
+ \snippet doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 2
+
+ To look up a value, use operator[]() or value():
+
+ \snippet doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 7
+
+ Here's the same code, but using an STL-style iterator this time:
+
+ \snippet doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 9
+
+ However, you can store multiple values per key by using
+ insertMulti() instead of insert() (or using the convenience
+ 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 QMap::QMap()
+
+ Constructs an empty map.
+
+ \sa clear()
+*/
+
+/*! \fn QMap::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 QMap::QMap(const std::map<Key, T> & other)
+
+ Constructs a copy of \a other.
+
+ This function is only available if Qt is configured with STL
+ compatibility enabled.
+
+ \sa toStdMap()
+*/
+
+/*! \fn std::map<Key, T> QMap::toStdMap() const
+
+ Returns an STL map equivalent to this QMap.
+
+ This function is only available if Qt is configured with STL
+ compatibility enabled.
+*/
+
+/*! \fn QMap::~QMap()
+
+ Destroys the map. References to the values in the map, and all
+ iterators over this map, become invalid.
+*/
+
+/*! \fn QMap<Key, T> &QMap::operator=(const QMap<Key, T> &other)
+
+ Assigns \a other to this map and returns a reference to this map.
+*/
+
+/*! \fn void QMap::swap(QMap<Key, T> &other)
+ \since 4.8
+
+ Swaps map \a other with this map. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn void QMultiMap::swap(QMultiMap<Key, T> &other)
+ \since 4.8
+
+ Swaps map \a other with this map. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QMap::operator==(const QMap<Key, T> &other) const
+
+ Returns 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 bool QMap::operator!=(const QMap<Key, T> &other) const
+
+ Returns true if \a other is not 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 int QMap::size() const
+
+ Returns the number of (key, value) pairs in the map.
+
+ \sa isEmpty(), count()
+*/
+
+/*!
+ \fn bool QMap::isEmpty() const
+
+ Returns true if the map contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn void QMap::detach()
+
+ \internal
+
+ Detaches this map from any other maps with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn bool QMap::isDetached() const
+
+ \internal
+
+ Returns true if the map's internal data isn't shared with any
+ other map object; otherwise returns false.
+
+ \sa detach()
+*/
+
+/*! \fn void QMap::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn bool QMap::isSharedWith(const QMap<Key, T> &other) const
+
+ \internal
+*/
+
+/*! \fn void QMap::setInsertInOrder(bool sharable)
+
+ \internal
+*/
+
+/*! \fn void QMap::clear()
+
+ Removes all items from the map.
+
+ \sa remove()
+*/
+
+/*! \fn int QMap::remove(const Key &key)
+
+ Removes all the items that have the key \a key from the map.
+ Returns the number of items removed which is usually 1 but will be
+ 0 if the key isn't in the map, or \> 1 if insertMulti() has been
+ used with the \a key.
+
+ \sa clear(), take(), QMultiMap::remove()
+*/
+
+/*! \fn T QMap::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 bool QMap::contains(const Key &key) const
+
+ Returns true if the map contains an item with key \a key;
+ otherwise returns false.
+
+ \sa count(), QMultiMap::contains()
+*/
+
+/*! \fn const T QMap::value(const Key &key) const
+
+ Returns the value associated with the key \a key.
+
+ If the map contains no item with key \a key, 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 const T QMap::value(const Key &key, const T &defaultValue) const
+
+ \overload
+
+ If the map contains no item with key \a key, the function returns
+ \a defaultValue.
+*/
+
+/*! \fn T &QMap::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 const T QMap::operator[](const Key &key) const
+
+ \overload
+
+ Same as value().
+*/
+
+/*! \fn QList<Key> QMap::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 (because items
+ were inserted with insertMulti(), or unite() was used) occur only
+ once in the returned list.
+
+ \sa keys(), values()
+*/
+
+/*! \fn QList<Key> QMap::keys() const
+
+ 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) also
+ occur multiple times in the list.
+
+ To obtain a list of unique keys, where each key from the map only
+ occurs once, use uniqueKeys().
+
+ The order is guaranteed to be the same as that used by values().
+
+ \sa uniqueKeys(), values(), key()
+*/
+
+/*! \fn QList<Key> QMap::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 Key QMap::key(const T &value) const
+
+ Returns the first key with value \a value.
+
+ If the map contains no item with value \a value, the function
+ returns a \link {default-constructed value} default-constructed
+ key \endlink.
+
+ 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 Key QMap::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.
+
+ 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 QList<T> QMap::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 QList<T> QMap::values(const Key &key) const
+
+ \overload
+
+ Returns a list containing all the values associated with key
+ \a key, from the most recently inserted to the least recently
+ inserted one.
+
+ \sa count(), insertMulti()
+*/
+
+/*! \fn int QMap::count(const Key &key) const
+
+ Returns the number of items associated with key \a key.
+
+ \sa contains(), insertMulti(), QMultiMap::count()
+*/
+
+/*! \fn int QMap::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn QMap::iterator QMap::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QMap::const_iterator QMap::begin() const
+
+ \overload
+*/
+
+/*! \fn QMap::const_iterator QMap::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QMap::iterator QMap::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QMap::const_iterator QMap::end() const
+
+ \overload
+*/
+
+/*! \fn QMap::const_iterator QMap::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QMap::iterator QMap::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 QMap::iterator QMap::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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 14
+
+ \sa constFind(), value(), values(), lowerBound(), upperBound(), QMultiMap::find()
+*/
+
+/*! \fn QMap::const_iterator QMap::find(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn QMap::iterator QMap::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 QMap::iterator QMap::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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 16
+
+ \sa qLowerBound(), upperBound(), find()
+*/
+
+/*! \fn QMap::const_iterator QMap::lowerBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn QMap::iterator QMap::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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 17
+
+ \sa qUpperBound(), lowerBound(), find()
+*/
+
+/*! \fn QMap::const_iterator QMap::upperBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn QMap::iterator QMap::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 insertMulti()
+*/
+
+/*! \fn QMap::iterator QMap::insertMulti(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 insert(), which overwrites the value of an
+ existing item.)
+
+ \sa insert(), values()
+*/
+
+/*! \fn QMap<Key, T> &QMap::unite(const QMap<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.
+
+ \sa insertMulti()
+*/
+
+/*! \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 bool QMap::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty(), returning true if the map is empty; otherwise
+ returning false.
+*/
+
+/*! \class QMap::iterator
+ \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 doc/src/snippets/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 they were inserted using QMap::insertMulti(), or due to a
+ unite()) 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 21
+
+ It might be tempting to write code like this:
+
+ \snippet doc/src/snippets/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.
+
+ \sa QMap::const_iterator, QMutableMapIterator
+*/
+
+/*! \fn QMap::iterator::operator QMapData::Node *() const
+
+ \internal
+*/
+
+/*! \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 QMap::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 QMap::iterator::iterator(QMapData::Node *node)
+
+ \internal
+*/
+
+/*! \fn const Key &QMap::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 T &QMap::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 doc/src/snippets/code/src_corelib_tools_qmap.cpp 23
+
+ \sa key(), operator*()
+*/
+
+/*! \fn T &QMap::iterator::operator*() const
+
+ Returns a modifiable reference to the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn T *QMap::iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*!
+ \fn bool QMap::iterator::operator==(const iterator &other) const
+ \fn bool QMap::iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QMap::iterator::operator!=(const iterator &other) const
+ \fn bool QMap::iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QMap::iterator QMap::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 QMap::iterator QMap::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 QMap::iterator QMap::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 QMap::iterator QMap::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 QMap::iterator QMap::iterator::operator+(int 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 QMap::iterator QMap::iterator::operator-(int 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 QMap::iterator &QMap::iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QMap::iterator &QMap::iterator::operator-=(int 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
+ \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 doc/src/snippets/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 they were inserted using QMap::insertMulti()) 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.
+
+ \sa QMap::iterator, QMapIterator
+*/
+
+/*! \fn QMap::const_iterator::operator QMapData::Node *() const
+
+ \internal
+*/
+
+/*! \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 QMap::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 QMap::const_iterator::const_iterator(QMapData::Node *node)
+
+ \internal
+*/
+
+/*! \fn QMap::const_iterator::const_iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn const Key &QMap::const_iterator::key() const
+
+ Returns the current item's key.
+
+ \sa value()
+*/
+
+/*! \fn const T &QMap::const_iterator::value() const
+
+ Returns the current item's value.
+
+ \sa key(), operator*()
+*/
+
+/*! \fn const T &QMap::const_iterator::operator*() const
+
+ Returns the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn const T *QMap::const_iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*! \fn bool QMap::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QMap::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn QMap::const_iterator QMap::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 QMap::const_iterator QMap::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 QMap::const_iterator &QMap::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 QMap::const_iterator QMap::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 QMap::const_iterator QMap::const_iterator::operator+(int 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 QMap::const_iterator QMap::const_iterator::operator-(int 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 QMap::const_iterator &QMap::const_iterator::operator+=(int 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 QMap::const_iterator &QMap::const_iterator::operator-=(int 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-()
+*/
+
+/*! \fn 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 \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*! \fn 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 \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*! \class QMultiMap
+ \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 convenience functions
+ that make it more suitable than QMap for storing multi-valued
+ maps. A multi-valued map is a map that allows multiple values
+ with the same key; QMap normally doesn't allow that, unless you
+ call QMap::insertMulti().
+
+ 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 corresponds to
+ QMap::insertMulti(), and a replace() function that corresponds to
+ QMap::insert(). It also provides convenient operator+() and
+ operator+=().
+
+ Example:
+ \snippet doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 QMultiMap::QMultiMap()
+
+ Constructs an empty map.
+*/
+
+/*! \fn QMultiMap::QMultiMap(const QMap<Key, T> &other)
+
+ Constructs a copy of \a other (which can be a QMap or a
+ QMultiMap).
+
+ \sa operator=()
+*/
+
+/*! \fn QMultiMap::iterator QMultiMap::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 QMultiMap::iterator QMultiMap::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 &QMultiMap::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 QMultiMap QMultiMap::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 bool QMultiMap::contains(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns true if the map contains an item with key \a key and
+ value \a value; otherwise returns false.
+
+ \sa QMap::contains()
+*/
+
+/*!
+ \fn bool QMultiMap::contains(const Key &key) const
+ \overload
+ \sa QMap::contains()
+*/
+
+/*!
+ \fn int QMultiMap::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 int QMultiMap::remove(const Key &key)
+ \overload
+ \sa QMap::remove()
+*/
+
+/*!
+ \fn int QMultiMap::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 int QMultiMap::count(const Key &key) const
+ \overload
+ \sa QMap::count()
+*/
+
+/*!
+ \fn int QMultiMap::count() const
+ \overload
+ \sa QMap::count()
+*/
+
+/*!
+ \fn typename QMap<Key, T>::iterator QMultiMap::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 typename QMap<Key, T>::iterator QMultiMap::find(const Key &key)
+ \overload
+ \sa QMap::find()
+*/
+
+/*!
+ \fn typename QMap<Key, T>::const_iterator QMultiMap::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 typename QMap<Key, T>::const_iterator QMultiMap::find(const Key &key) const
+ \since 4.3
+ \overload
+ \sa QMap::find()
+*/
+
+/*!
+ \fn typename QMap<Key, T>::const_iterator QMultiMap::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 typename QMap<Key, T>::const_iterator QMultiMap::constFind(const Key &key) const
+ \overload
+ \sa QMap::constFind()
+*/
+
+/*!
+ \fn T &QMap::iterator::data() const
+
+ Use value() instead.
+*/
+
+/*!
+ \fn const T &QMap::const_iterator::data() const
+
+ Use value() instead.
+*/
+
+/*!
+ \fn iterator QMap::remove(iterator it)
+
+ Use erase(\a it) instead.
+*/
+
+/*!
+ \fn void QMap::erase(const Key &key)
+
+ Use remove(\a key) instead.
+*/
+
+/*!
+ \fn iterator QMap::insert(const Key &key, const T &value, bool overwrite);
+
+ Use the two-argument insert() overload instead. If you don't want
+ to overwrite, call contains() beforehand.
+
+ \oldcode
+ QMap<QString, int> map;
+ ...
+ map.insert("delay", 30000, false);
+ \newcode
+ QMap<QString, int> map;
+ ...
+ if (!map.contains("delay"))
+ map.insert("delay", 30000);
+ \endcode
+*/
+
+/*!
+ \fn iterator QMap::replace(const Key &key, const T &value)
+
+ Use remove() then insert().
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
new file mode 100644
index 0000000000..6ac30dd5a7
--- /dev/null
+++ b/src/corelib/tools/qmap.h
@@ -0,0 +1,1090 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMAP_H
+#define QMAP_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qiterator.h>
+#include <QtCore/qlist.h>
+
+#ifndef QT_NO_STL
+#include <map>
+#endif
+
+#include <new>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QMapData
+{
+ struct Node {
+ Node *backward;
+ Node *forward[1];
+ };
+ enum { LastLevel = 11, Sparseness = 3 };
+
+ QMapData *backward;
+ QMapData *forward[QMapData::LastLevel + 1];
+ QBasicAtomicInt ref;
+ int topLevel;
+ int size;
+ uint randomBits;
+ uint insertInOrder : 1;
+ uint sharable : 1;
+ uint strictAlignment : 1;
+ uint reserved : 29;
+
+ static QMapData *createData(); // ### Qt5 remove me
+ static QMapData *createData(int alignment);
+ void continueFreeData(int offset);
+ Node *node_create(Node *update[], int offset); // ### Qt5 remove me
+ Node *node_create(Node *update[], int offset, int alignment);
+ void node_delete(Node *update[], int offset, Node *node);
+#ifdef QT_QMAP_DEBUG
+ uint adjust_ptr(Node *node);
+ void dump();
+#endif
+
+ static QMapData shared_null;
+};
+
+
+/*
+ QMap uses qMapLessThanKey() to compare keys. The default
+ implementation uses operator<(). For pointer types,
+ qMapLessThanKey() casts the pointers to integers before it
+ compares them, because operator<() is undefined on pointers
+ that come from different memory blocks. (In practice, this
+ is only a problem when running a program such as
+ BoundsChecker.)
+*/
+
+template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
+{
+ return key1 < key2;
+}
+
+template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2)
+{
+ Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *));
+ return quintptr(key1) < quintptr(key2);
+}
+
+template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
+{
+ Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
+ return quintptr(key1) < quintptr(key2);
+}
+
+template <class Key, class T>
+struct QMapNode {
+ Key key;
+ T value;
+
+private:
+ // never access these members through this structure.
+ // see below
+ QMapData::Node *backward;
+ QMapData::Node *forward[1];
+};
+
+template <class Key, class T>
+struct QMapPayloadNode
+{
+ Key key;
+ T value;
+
+private:
+ // QMap::e is a pointer to QMapData::Node, which matches the member
+ // below. However, the memory allocation node in QMapData::node_create
+ // allocates sizeof(QMapPayloNode) and incorrectly calculates the offset
+ // of 'backward' below. If the alignment of QMapPayloadNode is larger
+ // than the alignment of a pointer, the 'backward' member is aligned to
+ // the end of this structure, not to 'value' above, and will occupy the
+ // tail-padding area.
+ //
+ // e.g., on a 32-bit archictecture with Key = int and
+ // sizeof(T) = alignof(T) = 8
+ // 0 4 8 12 16 20 24 byte
+ // | key | PAD | value |backward| PAD | correct layout
+ // | key | PAD | value | |backward| how it's actually used
+ // |<----- value of QMap::payload() = 20 ----->|
+ QMapData::Node *backward;
+};
+
+template <class Key, class T>
+class QMap
+{
+ typedef QMapNode<Key, T> Node;
+ typedef QMapPayloadNode<Key, T> PayloadNode;
+
+ union {
+ QMapData *d;
+ QMapData::Node *e;
+ };
+
+ static inline int payload() { return sizeof(PayloadNode) - sizeof(QMapData::Node *); }
+ static inline int alignment() {
+#ifdef Q_ALIGNOF
+ return int(qMax(sizeof(void*), Q_ALIGNOF(Node)));
+#else
+ return 0;
+#endif
+ }
+ static inline Node *concrete(QMapData::Node *node) {
+ return reinterpret_cast<Node *>(reinterpret_cast<char *>(node) - payload());
+ }
+
+public:
+ inline QMap() : d(&QMapData::shared_null) { d->ref.ref(); }
+ inline QMap(const QMap<Key, T> &other) : d(other.d)
+ { d->ref.ref(); if (!d->sharable) detach(); }
+ inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); }
+
+ QMap<Key, T> &operator=(const QMap<Key, T> &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QMap<Key, T> &operator=(QMap<Key, T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QMap<Key, T> &other) { qSwap(d, other.d); }
+#ifndef QT_NO_STL
+ explicit QMap(const typename std::map<Key, T> &other);
+ std::map<Key, T> toStdMap() const;
+#endif
+
+ bool operator==(const QMap<Key, T> &other) const;
+ inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); }
+
+ inline int size() const { return d->size; }
+
+ inline bool isEmpty() const { return d->size == 0; }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+ inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
+ inline void setInsertInOrder(bool ordered) { d->insertInOrder = ordered; }
+
+ void clear();
+
+ int remove(const Key &key);
+ T take(const Key &key);
+
+ bool contains(const Key &key) const;
+ const Key key(const T &value) const;
+ const Key key(const T &value, const Key &defaultKey) const;
+ const T value(const Key &key) const;
+ const T value(const Key &key, const T &defaultValue) const;
+ T &operator[](const Key &key);
+ const T operator[](const Key &key) const;
+
+ QList<Key> uniqueKeys() const;
+ QList<Key> keys() const;
+ QList<Key> keys(const T &value) const;
+ QList<T> values() const;
+ QList<T> values(const Key &key) const;
+ int count(const Key &key) const;
+
+ class const_iterator;
+
+ class iterator
+ {
+ friend class const_iterator;
+ QMapData::Node *i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ // ### Qt 5: get rid of 'operator Node *'
+ inline operator QMapData::Node *() const { return i; }
+ inline iterator() : i(0) { }
+ inline iterator(QMapData::Node *node) : i(node) { }
+
+ inline const Key &key() const { return concrete(i)->key; }
+ inline T &value() const { return concrete(i)->value; }
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT T &data() const { return concrete(i)->value; }
+#endif
+ inline T &operator*() const { return concrete(i)->value; }
+ inline T *operator->() const { return &concrete(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->forward[0];
+ return *this;
+ }
+ inline iterator operator++(int) {
+ iterator r = *this;
+ i = i->forward[0];
+ return r;
+ }
+ inline iterator &operator--() {
+ i = i->backward;
+ return *this;
+ }
+ inline iterator operator--(int) {
+ iterator r = *this;
+ i = i->backward;
+ return r;
+ }
+ inline iterator operator+(int j) const
+ { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
+ inline iterator operator-(int j) const { return operator+(-j); }
+ inline iterator &operator+=(int j) { return *this = *this + j; }
+ inline iterator &operator-=(int j) { return *this = *this - j; }
+
+ // ### Qt 5: not sure this is necessary anymore
+#ifdef QT_STRICT_ITERATORS
+ private:
+#else
+ public:
+#endif
+ inline bool operator==(const const_iterator &o) const
+ { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const
+ { return i != o.i; }
+
+ private:
+ // ### Qt 5: remove
+ inline operator bool() const { return false; }
+ };
+ friend class iterator;
+
+ class const_iterator
+ {
+ friend class iterator;
+ QMapData::Node *i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ // ### Qt 5: get rid of 'operator Node *'
+ inline operator QMapData::Node *() const { return i; }
+ inline const_iterator() : i(0) { }
+ inline const_iterator(QMapData::Node *node) : i(node) { }
+#ifdef QT_STRICT_ITERATORS
+ explicit inline const_iterator(const iterator &o)
+#else
+ inline const_iterator(const iterator &o)
+#endif
+ { i = o.i; }
+
+ inline const Key &key() const { return concrete(i)->key; }
+ inline const T &value() const { return concrete(i)->value; }
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT const T &data() const { return concrete(i)->value; }
+#endif
+ inline const T &operator*() const { return concrete(i)->value; }
+ inline const T *operator->() const { return &concrete(i)->value; }
+ 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 const_iterator &operator++() {
+ i = i->forward[0];
+ return *this;
+ }
+ inline const_iterator operator++(int) {
+ const_iterator r = *this;
+ i = i->forward[0];
+ return r;
+ }
+ inline const_iterator &operator--() {
+ i = i->backward;
+ return *this;
+ }
+ inline const_iterator operator--(int) {
+ const_iterator r = *this;
+ i = i->backward;
+ return r;
+ }
+ inline const_iterator operator+(int j) const
+ { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
+ inline const_iterator operator-(int j) const { return operator+(-j); }
+ inline const_iterator &operator+=(int j) { return *this = *this + j; }
+ inline const_iterator &operator-=(int j) { return *this = *this - j; }
+
+ // ### Qt 5: not sure this is necessary anymore
+#ifdef QT_STRICT_ITERATORS
+ private:
+ inline bool operator==(const iterator &o) { return operator==(const_iterator(o)); }
+ inline bool operator!=(const iterator &o) { return operator!=(const_iterator(o)); }
+#endif
+
+ private:
+ // ### Qt 5: remove
+ inline operator bool() const { return false; }
+ };
+ friend class const_iterator;
+
+ // STL style
+ inline iterator begin() { detach(); return iterator(e->forward[0]); }
+ inline const_iterator begin() const { return const_iterator(e->forward[0]); }
+ inline const_iterator constBegin() const { return const_iterator(e->forward[0]); }
+ inline iterator end() {
+ detach();
+ return iterator(e);
+ }
+ inline const_iterator end() const { return const_iterator(e); }
+ inline const_iterator constEnd() const { return const_iterator(e); }
+ iterator erase(iterator it);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT iterator remove(iterator it) { return erase(it); }
+ inline QT3_SUPPORT void erase(const Key &aKey) { remove(aKey); }
+#endif
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline int 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);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT iterator insert(const Key &key, const T &value, bool overwrite);
+#endif
+ iterator insertMulti(const Key &key, const T &value);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT iterator replace(const Key &aKey, const T &aValue) { return insert(aKey, aValue); }
+#endif
+ QMap<Key, T> &unite(const QMap<Key, T> &other);
+
+ // STL compatibility
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef qptrdiff difference_type;
+ typedef int size_type;
+ inline bool empty() const { return isEmpty(); }
+
+#ifdef QT_QMAP_DEBUG
+ inline void dump() const { d->dump(); }
+#endif
+
+private:
+ void detach_helper();
+ void freeData(QMapData *d);
+ QMapData::Node *findNode(const Key &key) const;
+ QMapData::Node *mutableFindNode(QMapData::Node *update[], const Key &key) const;
+ QMapData::Node *node_create(QMapData *d, QMapData::Node *update[], const Key &key,
+ const T &value);
+};
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
+{
+ if (d != other.d) {
+ QMapData* o = other.d;
+ o->ref.ref();
+ if (!d->ref.deref())
+ freeData(d);
+ d = o;
+ if (!d->sharable)
+ detach_helper();
+ }
+ return *this;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QMap<Key, T>::clear()
+{
+ *this = QMap<Key, T>();
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMapData::Node *
+QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue)
+{
+ QMapData::Node *abstractNode = adt->node_create(aupdate, payload(), alignment());
+ QT_TRY {
+ Node *concreteNode = concrete(abstractNode);
+ new (&concreteNode->key) Key(akey);
+ QT_TRY {
+ new (&concreteNode->value) T(avalue);
+ } QT_CATCH(...) {
+ concreteNode->key.~Key();
+ QT_RETHROW;
+ }
+ } QT_CATCH(...) {
+ adt->node_delete(aupdate, payload(), abstractNode);
+ QT_RETHROW;
+ }
+
+ // clean up the update array for further insertions
+ /*
+ for (int i = 0; i <= d->topLevel; ++i) {
+ if ( aupdate[i]==reinterpret_cast<QMapData::Node *>(adt) || aupdate[i]->forward[i] != abstractNode)
+ break;
+ aupdate[i] = abstractNode;
+ }
+*/
+
+ return abstractNode;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QMapData::Node *QMap<Key, T>::findNode(const Key &akey) const
+{
+ QMapData::Node *cur = e;
+ QMapData::Node *next = e;
+
+ for (int i = d->topLevel; i >= 0; i--) {
+ while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
+ cur = next;
+ }
+
+ if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
+ return next;
+ } else {
+ return e;
+ }
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey) const
+{
+ QMapData::Node *node;
+ if (d->size == 0 || (node = findNode(akey)) == e) {
+ return T();
+ } else {
+ return concrete(node)->value;
+ }
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey, const T &adefaultValue) const
+{
+ QMapData::Node *node;
+ if (d->size == 0 || (node = findNode(akey)) == e) {
+ return adefaultValue;
+ } else {
+ return concrete(node)->value;
+ }
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE const T QMap<Key, T>::operator[](const Key &akey) const
+{
+ return value(akey);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *node = mutableFindNode(update, akey);
+ if (node == e)
+ node = node_create(d, update, akey, T());
+ return concrete(node)->value;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
+{
+ int cnt = 0;
+ QMapData::Node *node = findNode(akey);
+ if (node != e) {
+ do {
+ ++cnt;
+ node = node->forward[0];
+ } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key));
+ }
+ return cnt;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
+{
+ return findNode(akey) != e;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey,
+ const T &avalue)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *node = mutableFindNode(update, akey);
+ if (node == e) {
+ node = node_create(d, update, akey, avalue);
+ } else {
+ concrete(node)->value = avalue;
+ }
+ return iterator(node);
+}
+
+#ifdef QT3_SUPPORT
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey,
+ const T &avalue,
+ bool aoverwrite)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *node = mutableFindNode(update, akey);
+ if (node == e) {
+ node = node_create(d, update, akey, avalue);
+ } else {
+ if (aoverwrite)
+ concrete(node)->value = avalue;
+ }
+ return iterator(node);
+}
+#endif
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey,
+ const T &avalue)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ mutableFindNode(update, akey);
+ return iterator(node_create(d, update, akey, avalue));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &akey) const
+{
+ return const_iterator(findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &akey) const
+{
+ return const_iterator(findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::find(const Key &akey)
+{
+ detach();
+ return iterator(findNode(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other)
+{
+ QMap<Key, T> copy(other);
+ const_iterator it = copy.constEnd();
+ const const_iterator b = copy.constBegin();
+ while (it != b) {
+ --it;
+ insertMulti(it.key(), it.value());
+ }
+ return *this;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x)
+{
+ if (QTypeInfo<Key>::isComplex || QTypeInfo<T>::isComplex) {
+ QMapData *cur = x;
+ QMapData *next = cur->forward[0];
+ while (next != x) {
+ cur = next;
+ next = cur->forward[0];
+#if defined(_MSC_VER)
+#pragma warning(disable:4189)
+#endif
+ Node *concreteNode = concrete(reinterpret_cast<QMapData::Node *>(cur));
+ concreteNode->key.~Key();
+ concreteNode->value.~T();
+#if defined(_MSC_VER)
+#pragma warning(default:4189)
+#endif
+ }
+ }
+ x->continueFreeData(payload());
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QMap<Key, T>::remove(const Key &akey)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *cur = e;
+ QMapData::Node *next = e;
+ int oldSize = d->size;
+
+ for (int i = d->topLevel; i >= 0; i--) {
+ while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
+ cur = next;
+ update[i] = cur;
+ }
+
+ if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
+ bool deleteNext = true;
+ do {
+ cur = next;
+ next = cur->forward[0];
+ deleteNext = (next != e && !qMapLessThanKey<Key>(concrete(cur)->key, concrete(next)->key));
+ concrete(cur)->key.~Key();
+ concrete(cur)->value.~T();
+ d->node_delete(update, payload(), cur);
+ } while (deleteNext);
+ }
+ return oldSize - d->size;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey)
+{
+ detach();
+
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *cur = e;
+ QMapData::Node *next = e;
+
+ for (int i = d->topLevel; i >= 0; i--) {
+ while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
+ cur = next;
+ update[i] = cur;
+ }
+
+ if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
+ T t = concrete(next)->value;
+ concrete(next)->key.~Key();
+ concrete(next)->value.~T();
+ d->node_delete(update, payload(), next);
+ return t;
+ }
+ return T();
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterator it)
+{
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *cur = e;
+ QMapData::Node *next = e;
+
+ if (it == iterator(e))
+ return it;
+
+ for (int i = d->topLevel; i >= 0; i--) {
+ while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, it.key()))
+ cur = next;
+ update[i] = cur;
+ }
+
+ while (next != e) {
+ cur = next;
+ next = cur->forward[0];
+ if (cur == it) {
+ concrete(cur)->key.~Key();
+ concrete(cur)->value.~T();
+ d->node_delete(update, payload(), cur);
+ return iterator(next);
+ }
+
+ for (int i = 0; i <= d->topLevel; ++i) {
+ if (update[i]->forward[i] != cur)
+ break;
+ update[i] = cur;
+ }
+ }
+ return end();
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
+{
+ union { QMapData *d; QMapData::Node *e; } x;
+ x.d = QMapData::createData(alignment());
+ if (d->size) {
+ x.d->insertInOrder = true;
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ QMapData::Node *cur = e->forward[0];
+ update[0] = x.e;
+ while (cur != e) {
+ QT_TRY {
+ Node *concreteNode = concrete(cur);
+ node_create(x.d, update, concreteNode->key, concreteNode->value);
+ } QT_CATCH(...) {
+ freeData(x.d);
+ QT_RETHROW;
+ }
+ cur = cur->forward[0];
+ }
+ x.d->insertInOrder = false;
+ }
+ if (!d->ref.deref())
+ freeData(d);
+ d = x.d;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QMapData::Node *QMap<Key, T>::mutableFindNode(QMapData::Node *aupdate[],
+ const Key &akey) const
+{
+ QMapData::Node *cur = e;
+ QMapData::Node *next = e;
+
+ for (int i = d->topLevel; i >= 0; i--) {
+ while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
+ cur = next;
+ aupdate[i] = cur;
+ }
+ if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
+ return next;
+ } else {
+ return e;
+ }
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::uniqueKeys() const
+{
+ QList<Key> res;
+ res.reserve(size()); // May be too much, but assume short lifetime
+ const_iterator i = begin();
+ if (i != end()) {
+ for (;;) {
+ const Key &aKey = i.key();
+ res.append(aKey);
+ do {
+ if (++i == end())
+ goto break_out_of_outer_loop;
+ } while (!(aKey < i.key())); // loop while (key == i.key())
+ }
+ }
+break_out_of_outer_loop:
+ return res;
+}
+
+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;
+}
+
+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;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue) const
+{
+ return key(avalue, Key());
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE const 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;
+ }
+
+ return defaultKey;
+}
+
+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;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values(const Key &akey) const
+{
+ QList<T> res;
+ QMapData::Node *node = findNode(akey);
+ if (node != e) {
+ do {
+ res.append(concrete(node)->value);
+ node = node->forward[0];
+ } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key));
+ }
+ return res;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
+QMap<Key, T>::lowerBound(const Key &akey) const
+{
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ mutableFindNode(update, akey);
+ return const_iterator(update[0]->forward[0]);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey)
+{
+ detach();
+ return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->lowerBound(akey));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
+QMap<Key, T>::upperBound(const Key &akey) const
+{
+ QMapData::Node *update[QMapData::LastLevel + 1];
+ mutableFindNode(update, akey);
+ QMapData::Node *node = update[0]->forward[0];
+ while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key))
+ node = node->forward[0];
+ return const_iterator(node);
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey)
+{
+ detach();
+ return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->upperBound(akey));
+}
+
+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;
+
+ const_iterator it1 = begin();
+ const_iterator it2 = other.begin();
+
+ while (it1 != end()) {
+ if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
+ return false;
+ ++it2;
+ ++it1;
+ }
+ return true;
+}
+
+#ifndef QT_NO_STL
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
+{
+ d = QMapData::createData(alignment());
+ d->insertInOrder = true;
+ typename std::map<Key,T>::const_iterator it = other.end();
+ while (it != other.begin()) {
+ --it;
+ insert((*it).first, (*it).second);
+ }
+ d->insertInOrder = false;
+}
+
+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(std::pair<Key, T>(it.key(), it.value()));
+ }
+ return map;
+}
+
+#endif // QT_NO_STL
+
+template <class Key, class T>
+class QMultiMap : public QMap<Key, T>
+{
+public:
+ QMultiMap() {}
+ QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
+ inline void swap(QMultiMap<Key, T> &other) { QMap<Key, T>::swap(other); }
+
+ inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
+ { return QMap<Key, T>::insert(key, value); }
+ inline typename QMap<Key, T>::iterator insert(const Key &key, const T &value)
+ { return QMap<Key, T>::insertMulti(key, value); }
+
+ inline QMultiMap &operator+=(const QMultiMap &other)
+ { this->unite(other); return *this; }
+ inline QMultiMap operator+(const QMultiMap &other) const
+ { QMultiMap result = *this; result += other; return result; }
+
+#if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
+ // RVCT compiler doesn't handle using-keyword right when used functions are overloaded in child class
+ 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;
+#else
+ inline bool contains(const Key &key) const
+ { return QMap<Key, T>::contains(key); }
+ inline int remove(const Key &key)
+ { return QMap<Key, T>::remove(key); }
+ inline int count(const Key &key) const
+ { return QMap<Key, T>::count(key); }
+ inline int count() const
+ { return QMap<Key, T>::count(); }
+ inline typename QMap<Key, T>::iterator find(const Key &key)
+ { return QMap<Key, T>::find(key); }
+ inline typename QMap<Key, T>::const_iterator find(const Key &key) const
+ { return QMap<Key, T>::find(key); }
+ inline typename QMap<Key, T>::const_iterator constFind(const Key &key) const
+ { return QMap<Key, T>::constFind(key); }
+#endif
+
+ bool contains(const Key &key, const T &value) const;
+
+ int remove(const Key &key, const T &value);
+
+ int 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;
+ ++i;
+ }
+ 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;
+ ++i;
+ }
+ 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_INLINE_TEMPLATE bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
+{
+ return constFind(key, value) != QMap<Key, T>::constEnd();
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
+{
+ int 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 = this->erase(i);
+ ++n;
+ } else {
+ ++i;
+ }
+ }
+ return n;
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
+{
+ int 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;
+}
+
+Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMAP_H
diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp
new file mode 100644
index 0000000000..18ebe656f9
--- /dev/null
+++ b/src/corelib/tools/qmargins.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmargins.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMargins
+ \ingroup painting
+ \since 4.6
+
+ \brief The QMargins class defines the four margins of a rectangle.
+
+ 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 true only if all margins are set to zero.
+
+ QMargin objects can be streamed as well as compared.
+*/
+
+
+/*****************************************************************************
+ QMargins member functions
+ *****************************************************************************/
+
+/*!
+ \fn QMargins::QMargins()
+
+ Constructs a margins object with all margins set to 0.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QMargins::QMargins(int left, int top, int right, int bottom)
+
+ Constructs margins with the given \a left, \a top, \a right, \a bottom
+
+ \sa setLeft(), setRight(), setTop(), setBottom()
+*/
+
+/*!
+ \fn bool QMargins::isNull() const
+
+ Returns true if all margins are is 0; otherwise returns
+ false.
+*/
+
+
+/*!
+ \fn int QMargins::left() const
+
+ Returns the left margin.
+
+ \sa setLeft()
+*/
+
+/*!
+ \fn int QMargins::top() const
+
+ Returns the top margin.
+
+ \sa setTop()
+*/
+
+/*!
+ \fn int QMargins::right() const
+
+ Returns the right margin.
+*/
+
+/*!
+ \fn int QMargins::bottom() const
+
+ Returns the bottom margin.
+*/
+
+
+/*!
+ \fn void QMargins::setLeft(int left)
+
+ Sets the left margin to \a left.
+*/
+
+/*!
+ \fn void QMargins::setTop(int Top)
+
+ Sets the Top margin to \a Top.
+*/
+
+/*!
+ \fn void QMargins::setRight(int right)
+
+ Sets the right margin to \a right.
+*/
+
+/*!
+ \fn void QMargins::setBottom(int bottom)
+
+ Sets the bottom margin to \a bottom.
+*/
+
+/*!
+ \fn bool operator==(const QMargins &m1, const QMargins &m2)
+ \relates QMargins
+
+ Returns true if \a m1 and \a m2 are equal; otherwise returns false.
+*/
+
+/*!
+ \fn bool operator!=(const QMargins &m1, const QMargins &m2)
+ \relates QMargins
+
+ Returns true if \a m1 and \a m2 are different; otherwise returns false.
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QMargins &m) {
+ dbg.nospace() << "QMargins(" << m.left() << ", "
+ << m.top() << ", " << m.right() << ", " << m.bottom() << ')';
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h
new file mode 100644
index 0000000000..4b69c5b8a0
--- /dev/null
+++ b/src/corelib/tools/qmargins.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMARGINS_H
+#define QMARGINS_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QMargins
+{
+public:
+ QMargins();
+ QMargins(int left, int top, int right, int bottom);
+
+ bool isNull() const;
+
+ int left() const;
+ int top() const;
+ int right() const;
+ int bottom() const;
+
+ void setLeft(int left);
+ void setTop(int top);
+ void setRight(int right);
+ void setBottom(int bottom);
+
+private:
+ int m_left;
+ int m_top;
+ int m_right;
+ int m_bottom;
+
+ friend inline bool operator==(const QMargins &, const QMargins &);
+ friend inline bool operator!=(const QMargins &, const QMargins &);
+};
+
+Q_DECLARE_TYPEINFO(QMargins, Q_MOVABLE_TYPE);
+
+/*****************************************************************************
+ QMargins inline functions
+ *****************************************************************************/
+
+inline QMargins::QMargins()
+{ m_top = m_bottom = m_left = m_right = 0; }
+
+inline QMargins::QMargins(int aleft, int atop, int aright, int abottom)
+ : m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {}
+
+inline bool QMargins::isNull() const
+{ return m_left==0 && m_top==0 && m_right==0 && m_bottom==0; }
+
+inline int QMargins::left() const
+{ return m_left; }
+
+inline int QMargins::top() const
+{ return m_top; }
+
+inline int QMargins::right() const
+{ return m_right; }
+
+inline int QMargins::bottom() const
+{ return m_bottom; }
+
+
+inline void QMargins::setLeft(int aleft)
+{ m_left = aleft; }
+
+inline void QMargins::setTop(int atop)
+{ m_top = atop; }
+
+inline void QMargins::setRight(int aright)
+{ m_right = aright; }
+
+inline void QMargins::setBottom(int abottom)
+{ m_bottom = abottom; }
+
+inline bool operator==(const QMargins &m1, const QMargins &m2)
+{
+ 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;
+}
+
+inline bool operator!=(const QMargins &m1, const QMargins &m2)
+{
+ 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;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QMargins &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMARGINS_H
diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h
new file mode 100644
index 0000000000..ed27971595
--- /dev/null
+++ b/src/corelib/tools/qpair.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAIR_H
+#define QPAIR_H
+
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T1, class T2>
+struct QPair
+{
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ QPair() : first(T1()), second(T2()) {}
+ QPair(const T1 &t1, const T2 &t2) : first(t1), second(t2) {}
+
+ QPair<T1, T2> &operator=(const QPair<T1, T2> &other)
+ { first = other.first; second = other.second; return *this; }
+
+ T1 first;
+ T2 second;
+};
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{ return p1.first == p2.first && p1.second == p2.second; }
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{ return !(p1 == p2); }
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{
+ return p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second);
+}
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{
+ return p2 < p1;
+}
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{
+ return !(p2 < p1);
+}
+
+template <class T1, class T2>
+Q_INLINE_TEMPLATE bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+{
+ return !(p1 < p2);
+}
+
+template <class T1, class T2>
+Q_OUTOFLINE_TEMPLATE QPair<T1, T2> qMakePair(const T1 &x, const T2 &y)
+{
+ return QPair<T1, T2>(x, y);
+}
+
+#ifndef QT_NO_DATASTREAM
+template <class T1, class T2>
+inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)
+{
+ s >> p.first >> p.second;
+ return s;
+}
+
+template <class T1, class T2>
+inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p)
+{
+ s << p.first << p.second;
+ return s;
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPAIR_H
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
new file mode 100644
index 0000000000..925100d4e5
--- /dev/null
+++ b/src/corelib/tools/qpair.qdoc
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPair
+ \brief The QPair class is a template class that stores a pair of items.
+
+ \ingroup tools
+
+ QPair\<T1, T2\> can be used in your application if the STL \c
+ pair type is not available. It stores one value of type T1 and
+ one value of type T2. It can be used as a return value for a
+ function that needs to return two values, or as the value type of
+ a \l{Container classes}{generic container}.
+
+ Here's an example of a QPair that stores one QString and one \c
+ double value:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.cpp 0
+
+ The components are accessible as public data members called \l
+ first and \l second. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.cpp 1
+
+ QPair's template data types (T1 and T2) must be \l{assignable
+ data types}. You cannot, for example, store a QWidget as a value;
+ instead, store a QWidget *. A few functions have additional
+ requirements; these requirements are documented on a per-function
+ basis.
+
+ \sa {Container Classes}
+*/
+
+/*! \typedef QPair::first_type
+
+ The type of the first element in the pair (T1).
+
+ \sa first
+*/
+
+/*! \typedef QPair::second_type
+
+ The type of the second element in the pair (T2).
+
+ \sa second
+*/
+
+/*! \variable QPair::first
+
+ The first element in the pair.
+*/
+
+/*! \variable QPair::second
+
+ The second element in the pair.
+*/
+
+/*! \fn QPair::QPair()
+
+ Constructs an empty pair. The \c first and \c second elements are
+ initialized with \l{default-constructed values}.
+*/
+
+/*!
+ \fn QPair::QPair(const T1 &value1, const T2 &value2)
+
+ Constructs a pair and initializes the \c first element with \a
+ value1 and the \c second element with \a value2.
+
+ \sa qMakePair()
+*/
+
+/*!
+ \fn QPair<T1, T2> &QPair::operator=(const QPair<T1, T2> &other)
+
+ Assigns \a other to this pair.
+*/
+
+/*! \fn bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is equal to \a p2; otherwise returns false.
+ Two pairs compare equal if their \c first data members compare
+ equal and if their \c second data members compare equal.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator==().
+*/
+
+/*! \fn bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is not equal to \a p2; otherwise returns
+ false. Two pairs compare as not equal if their \c first data
+ members are not equal or if their \c second data members are not
+ equal.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator==().
+*/
+
+/*! \fn bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is less than \a p2; otherwise returns
+ false. The comparison is done on the \c first members of \a p1
+ and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is greater than \a p2; otherwise returns
+ false. The comparison is done on the \c first members of \a p1
+ and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is less than or equal to \a p2; otherwise
+ returns false. The comparison is done on the \c first members of
+ \a p1 and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is greater than or equal to \a p2;
+ otherwise returns false. The comparison is done on the \c first
+ members of \a p1 and \a p2; if they compare equal, the \c second
+ members are compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*!
+ \fn QPair<T1, T2> qMakePair(const T1 &value1, const T2 &value2)
+
+ \relates QPair
+
+ Returns a QPair\<T1, T2\> that contains \a value1 and \a value2.
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.cpp 2
+
+ This is equivalent to QPair<T1, T2>(\a value1, \a value2), but
+ usually requires less typing.
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QPair<T1, T2> &pair)
+
+ \relates QPair
+
+ Reads a pair from stream \a in into \a pair.
+
+ This function requires the T1 and T2 types to implement \c operator>>().
+
+ \sa {Serializing Qt Data Types}
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QPair<T1, T2> &pair)
+
+ \relates QPair
+
+ Writes the pair \a pair to stream \a out.
+
+ This function requires the T1 and T2 types to implement \c operator<<().
+
+ \sa {Serializing Qt Data Types}
+*/
diff --git a/src/corelib/tools/qpodlist_p.h b/src/corelib/tools/qpodlist_p.h
new file mode 100644
index 0000000000..e871eccba0
--- /dev/null
+++ b/src/corelib/tools/qpodlist_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPODLIST_P_H
+#define QPODLIST_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/qvarlengtharray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T, int Prealloc>
+class QPodList : public QVarLengthArray<T, Prealloc>
+{
+ using QVarLengthArray<T, Prealloc>::s;
+ using QVarLengthArray<T, Prealloc>::a;
+ using QVarLengthArray<T, Prealloc>::ptr;
+ using QVarLengthArray<T, Prealloc>::realloc;
+public:
+ inline explicit QPodList(int size = 0)
+ : QVarLengthArray<T, Prealloc>(size)
+ {}
+
+ inline void insert(int idx, const T &t)
+ {
+ const int sz = s++;
+ if (s == a)
+ realloc(s, s << 1);
+ ::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T));
+ ptr[idx] = t;
+ }
+
+ inline void removeAll(const T &t)
+ {
+ int i = 0;
+ for (int j = 0; j < s; ++j) {
+ if (ptr[j] != t)
+ ptr[i++] = ptr[j];
+ }
+ s = i;
+ }
+
+ inline void removeAt(int idx)
+ {
+ Q_ASSERT(idx >= 0 && idx < s);
+ ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
+ --s;
+ }
+
+ inline T takeFirst()
+ {
+ Q_ASSERT(s > 0);
+ T tmp = ptr[0];
+ removeAt(0);
+ return tmp;
+ }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPODLIST_P_H
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
new file mode 100644
index 0000000000..2a13fc401e
--- /dev/null
+++ b/src/corelib/tools/qpoint.cpp
@@ -0,0 +1,741 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpoint.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPoint
+ \ingroup painting
+
+ \brief The QPoint class defines a point in the plane using integer
+ precision.
+
+ A point is specified by a x coordinate and an y coordinate which
+ can be accessed using the x() and y() functions. The isNull()
+ function returns true if both x and y are set to 0. The
+ coordinates can be set (or altered) using the setX() and setY()
+ functions, or alternatively the rx() and ry() functions which
+ return references to the coordinates (allowing direct
+ manipulation).
+
+ Given a point \e p, the following statements are all equivalent:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 0
+
+ A QPoint object can also be used as a vector: Addition and
+ subtraction are defined as for vectors (each component is added
+ separately). A QPoint object can also be divided or multiplied by
+ an \c int or a \c qreal.
+
+ In addition, the QPoint class provides the manhattanLength()
+ function which gives an inexpensive approximation of the length of
+ the QPoint object interpreted as a vector. Finally, QPoint objects
+ can be streamed as well as compared.
+
+ \sa QPointF, QPolygon
+*/
+
+
+/*****************************************************************************
+ QPoint member functions
+ *****************************************************************************/
+
+/*!
+ \fn QPoint::QPoint()
+
+ Constructs a null point, i.e. with coordinates (0, 0)
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPoint::QPoint(int x, int y)
+
+ Constructs a point with the given coordinates (\a x, \a y).
+
+ \sa setX(), setY()
+*/
+
+/*!
+ \fn bool QPoint::isNull() const
+
+ Returns true if both the x and y coordinates are set to 0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn int QPoint::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), rx()
+*/
+
+/*!
+ \fn int QPoint::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), ry()
+*/
+
+/*!
+ \fn void QPoint::setX(int x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x() setY()
+*/
+
+/*!
+ \fn void QPoint::setY(int y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y() setX()
+*/
+
+
+/*!
+ \fn int &QPoint::rx()
+
+ Returns a reference to the x coordinate of this point.
+
+ Using a reference makes it possible to directly manipulate x. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 1
+
+ \sa x() setX()
+*/
+
+/*!
+ \fn int &QPoint::ry()
+
+ Returns a reference to the y coordinate of this point.
+
+ Using a reference makes it possible to directly manipulate y. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 2
+
+ \sa y(), setY()
+*/
+
+
+/*!
+ \fn QPoint &QPoint::operator+=(const QPoint &point)
+
+ Adds the given \a point to this point and returns a reference to
+ this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 3
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QPoint &QPoint::operator-=(const QPoint &point)
+
+ Subtracts the given \a point from this point and returns a
+ reference to this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 4
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QPoint &QPoint::operator*=(float factor)
+
+ Multiplies this point's coordinates by the given \a factor, and
+ returns a reference to this point.
+
+ Note that the result is rounded to the nearest integer as points are held as
+ integers. Use QPointF for floating point accuracy.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QPoint &QPoint::operator*=(double factor)
+
+ Multiplies this point's coordinates by the given \a factor, and
+ returns a reference to this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 5
+
+ Note that the result is rounded to the nearest integer as points are held as
+ integers. Use QPointF for floating point accuracy.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QPoint &QPoint::operator*=(int factor)
+
+ Multiplies this point's coordinates by the given \a factor, and
+ returns a reference to this point.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn bool operator==(const QPoint &p1, const QPoint &p2)
+ \relates QPoint
+
+ Returns true if \a p1 and \a p2 are equal; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool operator!=(const QPoint &p1, const QPoint &p2)
+ \relates QPoint
+
+ Returns true if \a p1 and \a p2 are not equal; otherwise returns false.
+*/
+
+/*!
+ \fn const QPoint operator+(const QPoint &p1, const QPoint &p2)
+ \relates QPoint
+
+ Returns a QPoint object that is the sum of the given points, \a p1
+ and \a p2; each component is added separately.
+
+ \sa QPoint::operator+=()
+*/
+
+/*!
+ \fn const QPoint operator-(const QPoint &p1, const QPoint &p2)
+ \relates QPoint
+
+ Returns a QPoint object that is formed by subtracting \a p2 from
+ \a p1; each component is subtracted separately.
+
+ \sa QPoint::operator-=()
+*/
+
+/*!
+ \fn const QPoint operator*(const QPoint &point, float factor)
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+
+ Note that the result is rounded to the nearest integer as points
+ are held as integers. Use QPointF for floating point accuracy.
+
+ \sa QPoint::operator*=()
+*/
+
+/*!
+ \fn const QPoint operator*(const QPoint &point, double factor)
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+
+ Note that the result is rounded to the nearest integer as points
+ are held as integers. Use QPointF for floating point accuracy.
+
+ \sa QPoint::operator*=()
+*/
+
+/*!
+ \fn const QPoint operator*(const QPoint &point, int factor)
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+
+ \sa QPoint::operator*=()
+*/
+
+/*!
+ \fn const QPoint operator*(float factor, const QPoint &point)
+ \overload
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+*/
+
+/*!
+ \fn const QPoint operator*(double factor, const QPoint &point)
+ \overload
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+*/
+
+/*!
+ \fn const QPoint operator*(int factor, const QPoint &point)
+ \overload
+ \relates QPoint
+
+ Returns a copy of the given \a point multiplied by the given \a factor.
+*/
+
+/*!
+ \fn const 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.
+
+ Equivalent to \c{QPoint(0,0) - point}.
+*/
+
+/*!
+ \fn QPoint &QPoint::operator/=(qreal divisor)
+ \overload
+
+ Divides both x and y by the given \a divisor, and returns a reference to this
+ point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 6
+
+ Note that the result is rounded to the nearest integer as points are held as
+ integers. Use QPointF for floating point accuracy.
+
+ \sa operator*=()
+*/
+
+/*!
+ \fn const QPoint operator/(const QPoint &point, qreal divisor)
+ \relates QPoint
+
+ Returns the QPoint formed by dividing both components of the given \a point
+ by the given \a divisor.
+
+ Note that the result is rounded to the nearest integer as points are held as
+ integers. Use QPointF for floating point accuracy.
+
+ \sa QPoint::operator/=()
+*/
+
+/*****************************************************************************
+ QPoint stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QPoint &point)
+ \relates QPoint
+
+ Writes the given \a point to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QPoint &p)
+{
+ if (s.version() == 1)
+ s << (qint16)p.x() << (qint16)p.y();
+ else
+ s << (qint32)p.x() << (qint32)p.y();
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QPoint &point)
+ \relates QPoint
+
+ Reads a point from the given \a stream into the given \a point
+ and returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QPoint &p)
+{
+ if (s.version() == 1) {
+ qint16 x, y;
+ s >> x; p.rx() = x;
+ s >> y; p.ry() = y;
+ }
+ else {
+ qint32 x, y;
+ s >> x; p.rx() = x;
+ s >> y; p.ry() = y;
+ }
+ return s;
+}
+
+#endif // QT_NO_DATASTREAM
+/*!
+ Returns the sum of the absolute values of x() and y(),
+ traditionally known as the "Manhattan length" of the vector from
+ the origin to the point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 7
+
+ This is a useful, and quick to calculate, approximation to the
+ true length:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 8
+
+ The tradition of "Manhattan length" arises because such distances
+ apply to travelers who can only travel on a rectangular grid, like
+ the streets of Manhattan.
+*/
+int QPoint::manhattanLength() const
+{
+ return qAbs(x())+qAbs(y());
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QPoint &p) {
+ dbg.nospace() << "QPoint(" << p.x() << ',' << p.y() << ')';
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug d, const QPointF &p)
+{
+ d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
+ return d.space();
+}
+#endif
+
+/*!
+ \class QPointF
+ \ingroup painting
+
+ \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
+ accuracy. The isNull() function returns 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
+ return references to the coordinates (allowing direct
+ manipulation).
+
+ Given a point \e p, the following statements are all equivalent:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 9
+
+ A QPointF object can also be used as a vector: Addition and
+ subtraction are defined as for vectors (each component is added
+ separately). A QPointF object can also be divided or multiplied by
+ an \c int or a \c qreal.
+
+ In addition, the QPointF class provides a constructor converting a
+ QPoint object into a QPointF object, and a corresponding toPoint()
+ function which returns a QPoint copy of \e this point. Finally,
+ QPointF objects can be streamed as well as compared.
+
+ \sa QPoint, QPolygonF
+*/
+
+/*!
+ \fn QPointF::QPointF()
+
+ Constructs a null point, i.e. with coordinates (0.0, 0.0)
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPointF::QPointF(const QPoint &point)
+
+ Constructs a copy of the given \a point.
+
+ \sa toPoint()
+*/
+
+/*!
+ \fn QPointF::QPointF(qreal x, qreal y)
+
+ Constructs a point with the given coordinates (\a x, \a y).
+
+ \sa setX(), setY()
+*/
+
+/*!
+ \fn bool QPointF::isNull() const
+
+ Returns true if both the x and y coordinates are set to +0.0;
+ otherwise returns false.
+
+ \note Since this function treats +0.0 and -0.0 differently, points
+ with zero-valued coordinates where either or both values have a
+ negative sign are not defined to be null points.
+*/
+
+
+/*!
+ \since 4.6
+
+ Returns the sum of the absolute values of x() and y(),
+ traditionally known as the "Manhattan length" of the vector from
+ the origin to the point.
+
+ \sa QPoint::manhattanLength()
+*/
+qreal QPointF::manhattanLength() const
+{
+ return qAbs(x())+qAbs(y());
+}
+
+/*!
+ \fn qreal QPointF::x() const
+
+ Returns the x-coordinate of this point.
+
+ \sa setX(), rx()
+*/
+
+/*!
+ \fn qreal QPointF::y() const
+
+ Returns the y-coordinate of this point.
+
+ \sa setY(), ry()
+*/
+
+/*!
+ \fn void QPointF::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x() setY()
+*/
+
+/*!
+ \fn void QPointF::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX()
+*/
+
+/*!
+ \fn qreal& QPointF::rx()
+
+ Returns a reference to the x coordinate of this point.
+
+ Using a reference makes it possible to directly manipulate x. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 10
+
+ \sa x(), setX()
+*/
+
+/*!
+ \fn qreal& QPointF::ry()
+
+ Returns a reference to the y coordinate of this point.
+
+ Using a reference makes it possible to directly manipulate y. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 11
+
+ \sa y() setY()
+*/
+
+/*!
+ \fn QPointF& QPointF::operator+=(const QPointF &point)
+
+ Adds the given \a point to this point and returns a reference to
+ this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 12
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QPointF& QPointF::operator-=(const QPointF &point)
+
+ Subtracts the given \a point from this point and returns a reference
+ to this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 13
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QPointF& QPointF::operator*=(qreal factor)
+
+ Multiplies this point's coordinates by the given \a factor, and
+ returns a reference to this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 14
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QPointF& QPointF::operator/=(qreal divisor)
+
+ Divides both x and y by the given \a divisor, and returns a reference
+ to this point. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 15
+
+ \sa operator*=()
+*/
+
+/*!
+ \fn const QPointF operator+(const QPointF &p1, const QPointF &p2)
+ \relates QPointF
+
+ Returns a QPointF object that is the sum of the given points, \a p1
+ and \a p2; each component is added separately.
+
+ \sa QPointF::operator+=()
+*/
+
+/*!
+ \fn const QPointF operator-(const QPointF &p1, const QPointF &p2)
+ \relates QPointF
+
+ Returns a QPointF object that is formed by subtracting \a p2 from \a p1;
+ each component is subtracted separately.
+
+ \sa QPointF::operator-=()
+*/
+
+/*!
+ \fn const QPointF operator*(const QPointF &point, qreal factor)
+ \relates QPointF
+
+ Returns a copy of the given \a point, multiplied by the given \a factor.
+
+ \sa QPointF::operator*=()
+*/
+
+/*!
+ \fn const QPointF operator*(qreal factor, const QPointF &point)
+ \relates QPointF
+
+ \overload
+
+ Returns a copy of the given \a point, multiplied by the given \a factor.
+*/
+
+/*!
+ \fn const QPointF operator-(const QPointF &point)
+ \relates QPointF
+ \overload
+
+ Returns a QPointF object that is formed by changing the sign of
+ both components of the given \a point.
+
+ Equivalent to \c {QPointF(0,0) - point}.
+*/
+
+/*!
+ \fn const QPointF operator/(const QPointF &point, qreal divisor)
+ \relates QPointF
+
+ Returns the QPointF object formed by dividing both components of
+ the given \a point by the given \a divisor.
+
+ \sa QPointF::operator/=()
+*/
+
+/*!
+ \fn QPoint QPointF::toPoint() const
+
+ Rounds the coordinates of this point to the nearest integer, and
+ returns a QPoint object with the rounded coordinates.
+
+ \sa QPointF()
+*/
+
+/*!
+ \fn bool operator==(const QPointF &p1, const QPointF &p2)
+ \relates QPointF
+
+ Returns true if \a p1 is equal to \a p2; otherwise returns false.
+*/
+
+/*!
+ \fn bool operator!=(const QPointF &p1, const QPointF &p2);
+ \relates QPointF
+
+ Returns true if \a p1 is not equal to \a p2; otherwise returns false.
+*/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QPointF &point)
+ \relates QPointF
+
+ Writes the given \a point to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QPointF &p)
+{
+ s << double(p.x()) << double(p.y());
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QPointF &point)
+ \relates QPointF
+
+ Reads a point from the given \a stream into the given \a point
+ and returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QPointF &p)
+{
+ double x, y;
+ s >> x;
+ s >> y;
+ p.setX(qreal(x));
+ p.setY(qreal(y));
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
new file mode 100644
index 0000000000..449612767d
--- /dev/null
+++ b/src/corelib/tools/qpoint.h
@@ -0,0 +1,389 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPOINT_H
+#define QPOINT_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QPoint
+{
+public:
+ QPoint();
+ QPoint(int xpos, int ypos);
+
+ bool isNull() const;
+
+ int x() const;
+ int y() const;
+ void setX(int x);
+ void setY(int y);
+
+ int manhattanLength() const;
+
+ int &rx();
+ int &ry();
+
+ QPoint &operator+=(const QPoint &p);
+ QPoint &operator-=(const QPoint &p);
+
+ QPoint &operator*=(float c);
+ QPoint &operator*=(double c);
+ QPoint &operator*=(int c);
+
+ QPoint &operator/=(qreal c);
+
+ friend inline bool operator==(const QPoint &, const QPoint &);
+ friend inline bool operator!=(const QPoint &, const QPoint &);
+ friend inline const QPoint operator+(const QPoint &, const QPoint &);
+ friend inline const QPoint operator-(const QPoint &, const QPoint &);
+ friend inline const QPoint operator*(const QPoint &, float);
+ friend inline const QPoint operator*(float, const QPoint &);
+ friend inline const QPoint operator*(const QPoint &, double);
+ friend inline const QPoint operator*(double, const QPoint &);
+ friend inline const QPoint operator*(const QPoint &, int);
+ friend inline const QPoint operator*(int, const QPoint &);
+ friend inline const QPoint operator-(const QPoint &);
+ friend inline const QPoint operator/(const QPoint &, qreal);
+
+private:
+ friend class QTransform;
+ // ### Qt 5; remove the ifdef and just have the same order on all platforms.
+#if defined(Q_OS_MAC)
+ int yp;
+ int xp;
+#else
+ int xp;
+ int yp;
+#endif
+};
+
+Q_DECLARE_TYPEINFO(QPoint, Q_MOVABLE_TYPE);
+
+/*****************************************************************************
+ QPoint stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPoint &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPoint &);
+#endif
+
+/*****************************************************************************
+ QPoint inline functions
+ *****************************************************************************/
+
+inline QPoint::QPoint()
+{ xp=0; yp=0; }
+
+inline QPoint::QPoint(int xpos, int ypos)
+{ xp = xpos; yp = ypos; }
+
+inline bool QPoint::isNull() const
+{ return xp == 0 && yp == 0; }
+
+inline int QPoint::x() const
+{ return xp; }
+
+inline int QPoint::y() const
+{ return yp; }
+
+inline void QPoint::setX(int xpos)
+{ xp = xpos; }
+
+inline void QPoint::setY(int ypos)
+{ yp = ypos; }
+
+inline int &QPoint::rx()
+{ return xp; }
+
+inline int &QPoint::ry()
+{ return yp; }
+
+inline QPoint &QPoint::operator+=(const QPoint &p)
+{ xp+=p.xp; yp+=p.yp; return *this; }
+
+inline QPoint &QPoint::operator-=(const QPoint &p)
+{ xp-=p.xp; yp-=p.yp; return *this; }
+
+inline QPoint &QPoint::operator*=(float c)
+{ xp = qRound(xp*c); yp = qRound(yp*c); return *this; }
+
+inline QPoint &QPoint::operator*=(double c)
+{ xp = qRound(xp*c); yp = qRound(yp*c); return *this; }
+
+inline QPoint &QPoint::operator*=(int c)
+{ xp = xp*c; yp = yp*c; return *this; }
+
+inline bool operator==(const QPoint &p1, const QPoint &p2)
+{ return p1.xp == p2.xp && p1.yp == p2.yp; }
+
+inline bool operator!=(const QPoint &p1, const QPoint &p2)
+{ return p1.xp != p2.xp || p1.yp != p2.yp; }
+
+inline const QPoint operator+(const QPoint &p1, const QPoint &p2)
+{ return QPoint(p1.xp+p2.xp, p1.yp+p2.yp); }
+
+inline const QPoint operator-(const QPoint &p1, const QPoint &p2)
+{ return QPoint(p1.xp-p2.xp, p1.yp-p2.yp); }
+
+inline const QPoint operator*(const QPoint &p, float c)
+{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); }
+
+inline const QPoint operator*(const QPoint &p, double c)
+{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); }
+
+inline const QPoint operator*(const QPoint &p, int c)
+{ return QPoint(p.xp*c, p.yp*c); }
+
+inline const QPoint operator*(float c, const QPoint &p)
+{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); }
+
+inline const QPoint operator*(double c, const QPoint &p)
+{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); }
+
+inline const QPoint operator*(int c, const QPoint &p)
+{ return QPoint(p.xp*c, p.yp*c); }
+
+inline const QPoint operator-(const QPoint &p)
+{ return QPoint(-p.xp, -p.yp); }
+
+inline QPoint &QPoint::operator/=(qreal c)
+{
+ xp = qRound(xp/c);
+ yp = qRound(yp/c);
+ return *this;
+}
+
+inline const QPoint operator/(const QPoint &p, qreal c)
+{
+ return QPoint(qRound(p.xp/c), qRound(p.yp/c));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QPoint &);
+#endif
+
+
+
+
+
+class Q_CORE_EXPORT QPointF
+{
+public:
+ QPointF();
+ QPointF(const QPoint &p);
+ QPointF(qreal xpos, qreal ypos);
+
+ qreal manhattanLength() const;
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ void setX(qreal x);
+ void setY(qreal y);
+
+ qreal &rx();
+ qreal &ry();
+
+ QPointF &operator+=(const QPointF &p);
+ QPointF &operator-=(const QPointF &p);
+ QPointF &operator*=(qreal c);
+ QPointF &operator/=(qreal c);
+
+ friend inline bool operator==(const QPointF &, const QPointF &);
+ friend inline bool operator!=(const QPointF &, const QPointF &);
+ friend inline const QPointF operator+(const QPointF &, const QPointF &);
+ friend inline const QPointF operator-(const QPointF &, const QPointF &);
+ friend inline const QPointF operator*(qreal, const QPointF &);
+ friend inline const QPointF operator*(const QPointF &, qreal);
+ friend inline const QPointF operator-(const QPointF &);
+ friend inline const QPointF operator/(const QPointF &, qreal);
+
+ QPoint toPoint() const;
+
+private:
+ friend class QMatrix;
+ friend class QTransform;
+
+ qreal xp;
+ qreal yp;
+};
+
+Q_DECLARE_TYPEINFO(QPointF, Q_MOVABLE_TYPE);
+
+/*****************************************************************************
+ QPointF stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPointF &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPointF &);
+#endif
+
+/*****************************************************************************
+ QPointF inline functions
+ *****************************************************************************/
+
+inline QPointF::QPointF() : xp(0), yp(0) { }
+
+inline QPointF::QPointF(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) { }
+
+inline QPointF::QPointF(const QPoint &p) : xp(p.x()), yp(p.y()) { }
+
+inline bool QPointF::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp);
+}
+
+inline qreal QPointF::x() const
+{
+ return xp;
+}
+
+inline qreal QPointF::y() const
+{
+ return yp;
+}
+
+inline void QPointF::setX(qreal xpos)
+{
+ xp = xpos;
+}
+
+inline void QPointF::setY(qreal ypos)
+{
+ yp = ypos;
+}
+
+inline qreal &QPointF::rx()
+{
+ return xp;
+}
+
+inline qreal &QPointF::ry()
+{
+ return yp;
+}
+
+inline QPointF &QPointF::operator+=(const QPointF &p)
+{
+ xp+=p.xp;
+ yp+=p.yp;
+ return *this;
+}
+
+inline QPointF &QPointF::operator-=(const QPointF &p)
+{
+ xp-=p.xp; yp-=p.yp; return *this;
+}
+
+inline QPointF &QPointF::operator*=(qreal c)
+{
+ xp*=c; yp*=c; return *this;
+}
+
+inline bool operator==(const QPointF &p1, const QPointF &p2)
+{
+ return qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp);
+}
+
+inline bool operator!=(const QPointF &p1, const QPointF &p2)
+{
+ return !qFuzzyIsNull(p1.xp - p2.xp) || !qFuzzyIsNull(p1.yp - p2.yp);
+}
+
+inline const QPointF operator+(const QPointF &p1, const QPointF &p2)
+{
+ return QPointF(p1.xp+p2.xp, p1.yp+p2.yp);
+}
+
+inline const QPointF operator-(const QPointF &p1, const QPointF &p2)
+{
+ return QPointF(p1.xp-p2.xp, p1.yp-p2.yp);
+}
+
+inline const QPointF operator*(const QPointF &p, qreal c)
+{
+ return QPointF(p.xp*c, p.yp*c);
+}
+
+inline const QPointF operator*(qreal c, const QPointF &p)
+{
+ return QPointF(p.xp*c, p.yp*c);
+}
+
+inline const QPointF operator-(const QPointF &p)
+{
+ return QPointF(-p.xp, -p.yp);
+}
+
+inline QPointF &QPointF::operator/=(qreal c)
+{
+ xp/=c;
+ yp/=c;
+ return *this;
+}
+
+inline const QPointF operator/(const QPointF &p, qreal c)
+{
+ return QPointF(p.xp/c, p.yp/c);
+}
+
+inline QPoint QPointF::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPOINT_H
diff --git a/src/corelib/tools/qqueue.cpp b/src/corelib/tools/qqueue.cpp
new file mode 100644
index 0000000000..a256b03b59
--- /dev/null
+++ b/src/corelib/tools/qqueue.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QQueue
+ \brief The QQueue class is a generic container that provides a queue.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QQueue\<T\> is one of Qt's generic \l{container classes}. It
+ implements a queue data structure for items of a same type.
+
+ A queue is a first in, first out (FIFO) structure. Items are
+ added to the tail of the queue using enqueue() and retrieved from
+ the head using dequeue(). The head() function provides access to
+ the head item without removing it.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qqueue.cpp 0
+
+ The example will output 1, 2, 3 in that order.
+
+ QQueue inherits from QList. All of QList's functionality also
+ applies to QQueue. For example, you can use isEmpty() to test
+ whether the queue is empty, and you can traverse a QQueue using
+ QList's iterator classes (for example, QListIterator). But in
+ addition, QQueue provides three convenience functions that make
+ it easy to implement FIFO semantics: enqueue(), dequeue(), and
+ head().
+
+ QQueue's value type must be an \l{assignable data type}. This
+ covers most data types that are commonly used, but the compiler
+ won't let you, for example, store a QWidget as a value. Use
+ QWidget* instead.
+
+ \sa QList, QStack
+*/
+
+/*!
+ \fn QQueue::QQueue()
+
+ Constructs an empty queue.
+*/
+
+/*!
+ \fn QQueue::~QQueue()
+
+ Destroys the queue. References to the values in the queue, and all
+ iterators over this queue, become invalid.
+*/
+
+/*!
+ \fn void QQueue::swap(QQueue<T> &other)
+ \since 4.8
+
+ Swaps queue \a other with this queue. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ \fn void QQueue::enqueue(const T& t)
+
+ Adds value \a t to the tail of the queue.
+
+ This is the same as QList::append().
+
+ \sa dequeue(), head()
+*/
+
+/*!
+ \fn T &QQueue::head()
+
+ Returns a reference to the queue's head item. This function
+ assumes that the queue isn't empty.
+
+ This is the same as QList::first().
+
+ \sa dequeue(), enqueue(), isEmpty()
+*/
+
+/*!
+ \fn const T &QQueue::head() const
+
+ \overload
+*/
+
+/*!
+ \fn T QQueue::dequeue()
+
+ Removes the head item in the queue and returns it. This function
+ assumes that the queue isn't empty.
+
+ This is the same as QList::takeFirst().
+
+ \sa head(), enqueue(), isEmpty()
+*/
diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h
new file mode 100644
index 0000000000..c0d5ce8f09
--- /dev/null
+++ b/src/corelib/tools/qqueue.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUEUE_H
+#define QQUEUE_H
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T>
+class QQueue : public QList<T>
+{
+public:
+ inline QQueue() {}
+ inline ~QQueue() {}
+ inline void swap(QQueue<T> &other) { QList<T>::swap(other); } // prevent QList<->QQueue swaps
+ inline void enqueue(const T &t) { QList<T>::append(t); }
+ inline T dequeue() { return QList<T>::takeFirst(); }
+ inline T &head() { return QList<T>::first(); }
+ inline const T &head() const { return QList<T>::first(); }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUEUE_H
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
new file mode 100644
index 0000000000..36627264ce
--- /dev/null
+++ b/src/corelib/tools/qrect.cpp
@@ -0,0 +1,2465 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrect.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qmath.h"
+
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRect
+ \ingroup painting
+
+ \brief The QRect class defines a rectangle in the plane using
+ integer precision.
+
+ A rectangle is normally expressed as an upper-left corner and a
+ size. The size (width and height) of a QRect is always equivalent
+ to the mathematical rectangle that forms the basis for its
+ rendering.
+
+ A QRect can be constructed with a set of left, top, width and
+ height integers, or from a QPoint and a QSize. The following code
+ creates two identical rectangles.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qrect.cpp 0
+
+ There is a third constructor that creates a QRect using the
+ top-left and bottom-right coordinates, but we recommend that you
+ avoid using it. The rationale is that for historical reasons the
+ values returned by the bottom() and right() functions deviate from
+ the true bottom-right corner of the rectangle.
+
+ The QRect class provides a collection of functions that return the
+ various rectangle coordinates, and enable manipulation of
+ these. QRect also provide functions to move the rectangle relative
+ to the various coordinates. In addition there is a moveTo()
+ function that moves the rectangle, leaving its top left corner at
+ the given coordinates. Alternatively, the translate() function
+ moves the rectangle the given offset relative to the current
+ position, and the translated() function returns a translated copy
+ of this rectangle.
+
+ The size() function returns the rectange'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,
+ the size can be changed by applying either of the functions
+ setting the rectangle coordinates, for example, setBottom() or
+ setRight().
+
+ The contains() function tells whether a given point is inside the
+ rectangle or not, and the intersects() function returns true if
+ this rectangle intersects with a given rectangle. The QRect class
+ also provides the intersected() function which returns the
+ intersection rectangle, and the united() function which returns the
+ rectangle that encloses the given rectangle and this:
+
+ \table
+ \row
+ \o \inlineimage qrect-intersect.png
+ \o \inlineimage qrect-unite.png
+ \row
+ \o intersected()
+ \o united()
+ \endtable
+
+ The isEmpty() function returns true if left() > right() or top() >
+ bottom(). Note that an empty rectangle is not valid: The isValid()
+ function returns true if left() <= right() \e and top() <=
+ bottom(). A null rectangle (isNull() == true) on the other hand,
+ has both width and height set to 0.
+
+ Note that due to the way QRect and QRectF are defined, an
+ empty QRect is defined in essentially the same way as QRectF.
+
+ Finally, QRect objects can be streamed as well as compared.
+
+ \tableofcontents
+
+ \section1 Rendering
+
+ When using an \l {QPainter::Antialiasing}{anti-aliased} painter,
+ the boundary line of a QRect will be rendered symmetrically on
+ both sides of the mathematical rectangle's boundary line. But when
+ using an aliased painter (the default) other rules apply.
+
+ Then, when rendering with a one pixel wide pen the QRect's boundary
+ line will be rendered to the right and below the mathematical
+ rectangle's boundary line.
+
+ When rendering with a two pixels wide pen the boundary line will
+ be split in the middle by the mathematical rectangle. This will be
+ the case whenever the pen is set to an even number of pixels,
+ while rendering with a pen with an odd number of pixels, the spare
+ pixel will be rendered to the right and below the mathematical
+ rectangle as in the one pixel case.
+
+ \table
+ \row
+ \o \inlineimage qrect-diagram-zero.png
+ \o \inlineimage qrect-diagram-one.png
+ \row
+ \o Logical representation
+ \o One pixel wide pen
+ \row
+ \o \inlineimage qrect-diagram-two.png
+ \o \inlineimage qrect-diagram-three.png
+ \row
+ \o Two pixel wide pen
+ \o Three pixel wide pen
+ \endtable
+
+ \section1 Coordinates
+
+ The QRect class provides a collection of functions that return the
+ various rectangle coordinates, and enable manipulation of
+ these. QRect also provide functions to move the rectangle relative
+ to the various coordinates.
+
+ For example the left(), setLeft() and moveLeft() functions as an
+ example: left() returns the x-coordinate of the rectangle's left
+ edge, setLeft() sets the left edge of the rectangle to the given x
+ coordinate (it may change the width, but will never change the
+ rectangle's right edge) and moveLeft() moves the entire rectangle
+ horizontally, leaving the rectangle's left edge at the given x
+ coordinate and its size unchanged.
+
+ \image qrect-coordinates.png
+
+ Note that for historical reasons the values returned by the
+ bottom() and right() functions deviate from the true bottom-right
+ corner of the rectangle: The right() function returns \e { left()
+ + width() - 1} and the bottom() function returns \e {top() +
+ height() - 1}. The same is the case for the point returned by the
+ bottomRight() convenience function. In addition, the x and y
+ coordinate of the topRight() and bottomLeft() functions,
+ respectively, contain the same deviation from the true right and
+ bottom edges.
+
+ We recommend that you use x() + width() and y() + height() to find
+ the true bottom-right corner, and avoid right() and
+ bottom(). Another solution is to use QRectF: The QRectF class
+ defines a rectangle in the plane using floating point accuracy for
+ coordinates, and the QRectF::right() and QRectF::bottom()
+ functions \e do return the right and bottom coordinates.
+
+ It is also possible to add offsets to this rectangle's coordinates
+ using the adjust() function, as well as retrieve a new rectangle
+ based on adjustments of the original one using the adjusted()
+ function. If either of the width and height is negative, use the
+ normalized() function to retrieve a rectangle where the corners
+ are swapped.
+
+ In addition, QRect provides the getCoords() function which extracts
+ the position of the rectangle's top-left and bottom-right corner,
+ and the getRect() function which extracts the rectangle's top-left
+ corner, width and height. Use the setCoords() and setRect()
+ function to manipulate the rectangle's coordinates and dimensions
+ in one go.
+
+ \sa QRectF, QRegion
+*/
+
+/*****************************************************************************
+ QRect member functions
+ *****************************************************************************/
+
+/*!
+ \fn QRect::QRect()
+
+ Constructs a null rectangle.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight)
+
+ Constructs a rectangle with the given \a topLeft and \a bottomRight corners.
+
+ \sa setTopLeft(), setBottomRight()
+*/
+
+
+/*!
+ \fn QRect::QRect(const QPoint &topLeft, const QSize &size)
+
+ Constructs a rectangle with the given \a topLeft corner and the
+ given \a size.
+
+ \sa setTopLeft(), setSize()
+*/
+
+
+/*!
+ \fn QRect::QRect(int x, int y, int width, int height)
+
+ Constructs a rectangle with (\a x, \a y) as its top-left corner
+ and the given \a width and \a height.
+
+ \sa setRect()
+*/
+
+
+/*!
+ \fn bool QRect::isNull() const
+
+ Returns true if the rectangle is a null rectangle, otherwise
+ returns false.
+
+ A null rectangle has both the width and the height set to 0 (i.e.,
+ right() == left() - 1 and bottom() == top() - 1). A null rectangle
+ is also empty, and hence is not valid.
+
+ \sa isEmpty(), isValid()
+*/
+
+/*!
+ \fn bool QRect::isEmpty() const
+
+ Returns true if the rectangle is empty, otherwise returns false.
+
+ An empty rectangle has a left() > right() or top() > bottom(). An
+ empty rectangle is not valid (i.e., isEmpty() == !isValid()).
+
+ Use the normalized() function to retrieve a rectangle where the
+ corners are swapped.
+
+ \sa isNull(), isValid(), normalized()
+*/
+
+/*!
+ \fn bool QRect::isValid() const
+
+ Returns true if the rectangle is valid, otherwise returns false.
+
+ A valid rectangle has a left() < right() and top() <
+ bottom(). Note that non-trivial operations like intersections are
+ not defined for invalid rectangles. A valid rectangle is not empty
+ (i.e., isValid() == !isEmpty()).
+
+ \sa isNull(), isEmpty(), normalized()
+*/
+
+
+/*!
+ Returns a normalized rectangle; i.e., a rectangle that has a
+ 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.
+
+ \sa isValid(), isEmpty()
+*/
+
+QRect QRect::normalized() const
+{
+ QRect r;
+ if (x2 < x1 - 1) { // swap bad x values
+ r.x1 = x2;
+ r.x2 = x1;
+ } else {
+ r.x1 = x1;
+ r.x2 = x2;
+ }
+ if (y2 < y1 - 1) { // swap bad y values
+ r.y1 = y2;
+ r.y2 = y1;
+ } else {
+ r.y1 = y1;
+ r.y2 = y2;
+ }
+ return r;
+}
+
+
+/*!
+ \fn QRect QRect::normalize() const
+ \compat
+
+ Returns a normalized rectangle; i.e., a rectangle that has a
+ non-negative width and height.
+
+ Use the normalized() function instead
+*/
+
+/*!
+ \fn int QRect::left() const
+
+ Returns the x-coordinate of the rectangle's left edge. Equivalent
+ to x().
+
+ \sa setLeft(), topLeft(), bottomLeft()
+*/
+
+/*!
+ \fn int QRect::top() const
+
+ Returns the y-coordinate of the rectangle's top edge.
+ Equivalent to y().
+
+ \sa setTop(), topLeft(), topRight()
+*/
+
+/*!
+ \fn int QRect::right() const
+
+ Returns the x-coordinate of the rectangle's right edge.
+
+ Note that for historical reasons this function returns left() +
+ width() - 1; use x() + width() to retrieve the true x-coordinate.
+
+ \sa setRight(), topRight(), bottomRight()
+*/
+
+/*!
+ \fn int QRect::bottom() const
+
+ Returns the y-coordinate of the rectangle's bottom edge.
+
+ Note that for historical reasons this function returns top() +
+ height() - 1; use y() + height() to retrieve the true y-coordinate.
+
+ \sa setBottom(), bottomLeft(), bottomRight()
+*/
+
+/*!
+ \fn int &QRect::rLeft()
+ \compat
+
+ Returns a reference to the left coordinate of the rectangle.
+
+ Use the left() function instead.
+*/
+
+/*!
+ \fn int &QRect::rTop()
+ \compat
+
+ Returns a reference to the top coordinate of the rectangle.
+
+ Use the top() function instead.
+*/
+
+/*!
+ \fn int &QRect::rRight()
+ \compat
+
+ Returns a reference to the right coordinate of the rectangle.
+
+ Use the right() function instead.
+*/
+
+/*!
+ \fn int &QRect::rBottom()
+ \compat
+
+ Returns a reference to the bottom coordinate of the rectangle.
+
+ Use the bottom() function instead.
+*/
+
+/*!
+ \fn int QRect::x() const
+
+ Returns the x-coordinate of the rectangle's left edge. Equivalent to left().
+
+ \sa setX(), y(), topLeft()
+*/
+
+/*!
+ \fn int QRect::y() const
+
+ Returns the y-coordinate of the rectangle's top edge. Equivalent to top().
+
+ \sa setY(), x(), topLeft()
+*/
+
+/*!
+ \fn void QRect::setLeft(int x)
+
+ Sets the left edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the right
+ edge of the rectangle.
+
+ Equivalent to setX().
+
+ \sa left(), moveLeft()
+*/
+
+/*!
+ \fn void QRect::setTop(int y)
+
+ Sets the top edge of the rectangle to the given \a y
+ coordinate. May change the height, but will never change the
+ bottom edge of the rectangle.
+
+ Equivalent to setY().
+
+ \sa top(), moveTop()
+*/
+
+/*!
+ \fn void QRect::setRight(int x)
+
+ Sets the right edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the left
+ edge of the rectangle.
+
+ \sa right(), moveRight()
+*/
+
+/*!
+ \fn void QRect::setBottom(int y)
+
+ Sets the bottom edge of the rectangle to the given \a y
+ coordinate. May change the height, but will never change the top
+ edge of the rectangle.
+
+ \sa bottom(), moveBottom(),
+*/
+
+/*!
+ \fn void QRect::setX(int x)
+
+ Sets the left edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the right
+ edge of the rectangle.
+
+ Equivalent to setLeft().
+
+ \sa x(), setY(), setTopLeft()
+*/
+
+/*!
+ \fn void QRect::setY(int y)
+
+ Sets the top edge of the rectangle to the given \a y
+ coordinate. May change the height, but will never change the
+ bottom edge of the rectangle.
+
+ Equivalent to setTop().
+
+ \sa y(), setX(), setTopLeft()
+*/
+
+/*!
+ \fn void QRect::setTopLeft(const QPoint &position)
+
+ Set the top-left corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ bottom-right corner of the rectangle.
+
+ \sa topLeft(), moveTopLeft()
+*/
+
+/*!
+ \fn void QRect::setBottomRight(const QPoint &position)
+
+ Set the bottom-right corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ top-left corner of the rectangle.
+
+ \sa bottomRight(), moveBottomRight()
+*/
+
+/*!
+ \fn void QRect::setTopRight(const QPoint &position)
+
+ Set the top-right corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ bottom-left corner of the rectangle.
+
+ \sa topRight(), moveTopRight()
+*/
+
+/*!
+ \fn void QRect::setBottomLeft(const QPoint &position)
+
+ Set the bottom-left corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ top-right corner of the rectangle.
+
+ \sa bottomLeft(), moveBottomLeft()
+*/
+
+/*!
+ \fn QPoint QRect::topLeft() const
+
+ Returns the position of the rectangle's top-left corner.
+
+ \sa setTopLeft(), top(), left()
+*/
+
+/*!
+ \fn QPoint QRect::bottomRight() const
+
+ Returns the position of the rectangle's bottom-right corner.
+
+ Note that for historical reasons this function returns
+ QPoint(left() + width() -1, top() + height() - 1).
+
+ \sa setBottomRight(), bottom(), right()
+*/
+
+/*!
+ \fn QPoint QRect::topRight() const
+
+ Returns the position of the rectangle's top-right corner.
+
+ Note that for historical reasons this function returns
+ QPoint(left() + width() -1, top()).
+
+ \sa setTopRight(), top(), right()
+*/
+
+/*!
+ \fn QPoint QRect::bottomLeft() const
+
+ Returns the position of the rectangle's bottom-left corner. Note
+ that for historical reasons this function returns QPoint(left(),
+ top() + height() - 1).
+
+ \sa setBottomLeft(), bottom(), left()
+*/
+
+/*!
+ \fn QPoint QRect::center() const
+
+ Returns the center point of the rectangle.
+
+ \sa moveCenter()
+*/
+
+
+/*!
+ \fn void QRect::getRect(int *x, int *y, int *width, int *height) const
+
+ Extracts the position of the rectangle's top-left corner to *\a x
+ and *\a y, and its dimensions to *\a width and *\a height.
+
+ \sa setRect(), getCoords()
+*/
+
+
+/*!
+ \fn void QRect::getCoords(int *x1, int *y1, int *x2, int *y2) const
+
+ Extracts the position of the rectangle's top-left corner to *\a x1
+ and *\a y1, and the position of the bottom-right corner to *\a x2
+ and *\a y2.
+
+ \sa setCoords(), getRect()
+*/
+
+/*!
+ \fn void QRect::rect(int *x, int *y, int *width, int *height) const
+ \compat
+
+ Extracts the position of the rectangle's top-left corner to *\a x and
+ *\a y, and its dimensions to *\a width and * \a height.
+
+ Use the getRect() function instead.
+*/
+
+
+/*!
+ \fn void QRect::coords(int *x1, int *y1, int *x2, int *y2) const
+ \compat
+
+ Extracts the position of the rectangle's top-left corner to *\a x1
+ and *\a y1, and the position of the bottom-right corner to *\a x2
+ and *\a y2.
+
+ Use the getCoords() function instead.
+*/
+
+/*!
+ \fn void QRect::moveLeft(int x)
+
+ Moves the rectangle horizontally, leaving the rectangle's left
+ edge at the given \a x coordinate. The rectangle's size is
+ unchanged.
+
+ \sa left(), setLeft(), moveRight()
+*/
+
+/*!
+ \fn void QRect::moveTop(int y)
+
+ Moves the rectangle vertically, leaving the rectangle's top edge
+ at the given \a y coordinate. The rectangle's size is unchanged.
+
+ \sa top(), setTop(), moveBottom()
+*/
+
+
+/*!
+ \fn void QRect::moveRight(int x)
+
+ Moves the rectangle horizontally, leaving the rectangle's right
+ edge at the given \a x coordinate. The rectangle's size is
+ unchanged.
+
+ \sa right(), setRight(), moveLeft()
+*/
+
+
+/*!
+ \fn void QRect::moveBottom(int y)
+
+ Moves the rectangle vertically, leaving the rectangle's bottom
+ edge at the given \a y coordinate. The rectangle's size is
+ unchanged.
+
+ \sa bottom(), setBottom(), moveTop()
+*/
+
+
+/*!
+ \fn void QRect::moveTopLeft(const QPoint &position)
+
+ Moves the rectangle, leaving the top-left corner at the given \a
+ position. The rectangle's size is unchanged.
+
+ \sa setTopLeft(), moveTop(), moveLeft()
+*/
+
+
+/*!
+ \fn void QRect::moveBottomRight(const QPoint &position)
+
+ Moves the rectangle, leaving the bottom-right corner at the given
+ \a position. The rectangle's size is unchanged.
+
+ \sa setBottomRight(), moveRight(), moveBottom()
+*/
+
+
+/*!
+ \fn void QRect::moveTopRight(const QPoint &position)
+
+ Moves the rectangle, leaving the top-right corner at the given \a
+ position. The rectangle's size is unchanged.
+
+ \sa setTopRight(), moveTop(), moveRight()
+*/
+
+
+/*!
+ \fn void QRect::moveBottomLeft(const QPoint &position)
+
+ Moves the rectangle, leaving the bottom-left corner at the given
+ \a position. The rectangle's size is unchanged.
+
+ \sa setBottomLeft(), moveBottom(), moveLeft()
+*/
+
+
+/*!
+ \fn void QRect::moveCenter(const QPoint &position)
+
+ Moves the rectangle, leaving the center point at the given \a
+ position. The rectangle's size is unchanged.
+
+ \sa center()
+*/
+
+void QRect::moveCenter(const QPoint &p)
+{
+ int w = x2 - x1;
+ int h = y2 - y1;
+ x1 = p.x() - w/2;
+ y1 = p.y() - h/2;
+ x2 = x1 + w;
+ y2 = y1 + h;
+}
+
+/*!
+ \fn void QRect::moveBy(int dx, int dy)
+ \compat
+
+ Moves the rectangle \a dx along the x axis and \a dy along the y
+ axis, relative to the current position.
+
+ Use the translate() function instead.
+*/
+
+/*!
+ \fn void QRect::moveBy(const QPoint &)
+ \compat
+
+ Use the translate() function instead.
+*/
+
+/*!
+ \fn void QRect::moveTo(int x, int y)
+
+ Moves the rectangle, leaving the top-left corner at the given
+ position (\a x, \a y). The rectangle's size is unchanged.
+
+ \sa translate(), moveTopLeft()
+*/
+
+/*!
+ \fn void QRect::moveTo(const QPoint &position)
+
+ Moves the rectangle, leaving the top-left corner at the given \a
+ position.
+*/
+
+/*!
+ \fn void QRect::translate(int dx, int dy)
+
+ 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 down.
+
+ \sa moveTopLeft(), moveTo(), translated()
+*/
+
+
+/*!
+ \fn void QRect::translate(const QPoint &offset)
+ \overload
+
+ Moves the rectangle \a{offset}.\l{QPoint::x()}{x()} along the x
+ axis and \a{offset}.\l{QPoint::y()}{y()} along the y axis,
+ relative to the current position.
+*/
+
+
+/*!
+ \fn QRect QRect::translated(int dx, int dy) const
+
+ 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.
+
+ \sa translate()
+
+*/
+
+
+/*!
+ \fn QRect QRect::translated(const QPoint &offset) const
+
+ \overload
+
+ Returns a copy of the rectangle that is translated
+ \a{offset}.\l{QPoint::x()}{x()} along the x axis and
+ \a{offset}.\l{QPoint::y()}{y()} along the y axis, relative to the
+ current position.
+*/
+
+
+/*!
+ \fn void QRect::setRect(int x, int y, int width, int 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.
+
+ \sa getRect(), setCoords()
+*/
+
+
+/*!
+ \fn void QRect::setCoords(int x1, int y1, int x2, int y2)
+
+ 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).
+
+ \sa getCoords(), setRect()
+*/
+
+
+/*!
+ \fn void QRect::addCoords(int dx1, int dy1, int dx2, int dy2)
+ \compat
+
+ Adds \a dx1, \a dy1, \a dx2 and \a dy2 to the existing coordinates
+ of the rectangle respectively.
+
+ Use the adjust() function instead.
+*/
+
+/*! \fn QRect QRect::adjusted(int dx1, int dy1, int dx2, int dy2) const
+
+ Returns a new rectangle with \a dx1, \a dy1, \a dx2 and \a dy2
+ added respectively to the existing coordinates of this rectangle.
+
+ \sa adjust()
+*/
+
+/*! \fn void QRect::adjust(int dx1, int dy1, int dx2, int dy2)
+
+ Adds \a dx1, \a dy1, \a dx2 and \a dy2 respectively to the
+ existing coordinates of the rectangle.
+
+ \sa adjusted(), setRect()
+*/
+
+/*!
+ \fn QSize QRect::size() const
+
+ Returns the size of the rectangle.
+
+ \sa setSize(), width(), height()
+*/
+
+/*!
+ \fn int QRect::width() const
+
+ Returns the width of the rectangle.
+
+ \sa setWidth(), height(), size()
+*/
+
+/*!
+ \fn int QRect::height() const
+
+ Returns the height of the rectangle.
+
+ \sa setHeight(), width(), size()
+*/
+
+/*!
+ \fn void QRect::setWidth(int width)
+
+ Sets the width of the rectangle to the given \a width. The right
+ edge is changed, but not the left one.
+
+ \sa width(), setSize()
+*/
+
+
+/*!
+ \fn void QRect::setHeight(int height)
+
+ Sets the height of the rectangle to the given \a height. The bottom
+ edge is changed, but not the top one.
+
+ \sa height(), setSize()
+*/
+
+
+/*!
+ \fn void QRect::setSize(const QSize &size)
+
+ Sets the size of the rectangle to the given \a size. The top-left
+ corner is not moved.
+
+ \sa size(), setWidth(), setHeight()
+*/
+
+
+/*!
+ \fn bool QRect::contains(const QPoint &point, bool proper) const
+
+ Returns true if the given \a point is inside or on the edge of
+ the rectangle, otherwise returns false. If \a proper is true, this
+ function only returns true if the given \a point is \e inside the
+ rectangle (i.e., not on the edge).
+
+ \sa intersects()
+*/
+
+bool QRect::contains(const QPoint &p, bool proper) const
+{
+ int l, r;
+ if (x2 < x1 - 1) {
+ l = x2;
+ r = x1;
+ } else {
+ l = x1;
+ r = x2;
+ }
+ if (proper) {
+ if (p.x() <= l || p.x() >= r)
+ return false;
+ } else {
+ if (p.x() < l || p.x() > r)
+ return false;
+ }
+ int t, b;
+ if (y2 < y1 - 1) {
+ t = y2;
+ b = y1;
+ } else {
+ t = y1;
+ b = y2;
+ }
+ if (proper) {
+ if (p.y() <= t || p.y() >= b)
+ return false;
+ } else {
+ if (p.y() < t || p.y() > b)
+ return false;
+ }
+ return true;
+}
+
+
+/*!
+ \fn bool QRect::contains(int x, int y, bool proper) const
+ \overload
+
+ Returns true if the point (\a x, \a y) is inside or on the edge of
+ the rectangle, otherwise returns false. If \a proper is true, this
+ function only returns true if the point is entirely inside the
+ rectangle(not on the edge).
+*/
+
+/*!
+ \fn bool QRect::contains(int x, int y) const
+ \overload
+
+ Returns true if the point (\a x, \a y) is inside this rectangle,
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QRect::contains(const QRect &rectangle, bool proper) const
+ \overload
+
+ Returns true if the given \a rectangle is inside this rectangle.
+ otherwise returns false. If \a proper is true, this function only
+ returns true if the \a rectangle is entirely inside this
+ rectangle (not on the edge).
+*/
+
+bool QRect::contains(const QRect &r, bool proper) const
+{
+ if (isNull() || r.isNull())
+ return false;
+
+ int l1 = x1;
+ int r1 = x1;
+ if (x2 - x1 + 1 < 0)
+ l1 = x2;
+ else
+ r1 = x2;
+
+ int l2 = r.x1;
+ int r2 = r.x1;
+ if (r.x2 - r.x1 + 1 < 0)
+ l2 = r.x2;
+ else
+ r2 = r.x2;
+
+ if (proper) {
+ if (l2 <= l1 || r2 >= r1)
+ return false;
+ } else {
+ if (l2 < l1 || r2 > r1)
+ return false;
+ }
+
+ int t1 = y1;
+ int b1 = y1;
+ if (y2 - y1 + 1 < 0)
+ t1 = y2;
+ else
+ b1 = y2;
+
+ int t2 = r.y1;
+ int b2 = r.y1;
+ if (r.y2 - r.y1 + 1 < 0)
+ t2 = r.y2;
+ else
+ b2 = r.y2;
+
+ if (proper) {
+ if (t2 <= t1 || b2 >= b1)
+ return false;
+ } else {
+ if (t2 < t1 || b2 > b1)
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \fn QRect& QRect::operator|=(const QRect &rectangle)
+
+ Unites this rectangle with the given \a rectangle.
+
+ \sa united(), operator|()
+*/
+
+/*!
+ \fn QRect& QRect::operator&=(const QRect &rectangle)
+
+ Intersects this rectangle with the given \a rectangle.
+
+ \sa intersected(), operator&()
+*/
+
+
+/*!
+ \fn QRect QRect::operator|(const QRect &rectangle) const
+
+ Returns the bounding rectangle of this rectangle and the given \a
+ rectangle.
+
+ \sa operator|=(), united()
+*/
+
+QRect QRect::operator|(const QRect &r) const
+{
+ if (isNull())
+ return r;
+ if (r.isNull())
+ return *this;
+
+ int l1 = x1;
+ int r1 = x1;
+ if (x2 - x1 + 1 < 0)
+ l1 = x2;
+ else
+ r1 = x2;
+
+ int l2 = r.x1;
+ int r2 = r.x1;
+ if (r.x2 - r.x1 + 1 < 0)
+ l2 = r.x2;
+ else
+ r2 = r.x2;
+
+ int t1 = y1;
+ int b1 = y1;
+ if (y2 - y1 + 1 < 0)
+ t1 = y2;
+ else
+ b1 = y2;
+
+ int t2 = r.y1;
+ int b2 = r.y1;
+ if (r.y2 - r.y1 + 1 < 0)
+ t2 = r.y2;
+ else
+ b2 = r.y2;
+
+ QRect tmp;
+ tmp.x1 = qMin(l1, l2);
+ tmp.x2 = qMax(r1, r2);
+ tmp.y1 = qMin(t1, t2);
+ tmp.y2 = qMax(b1, b2);
+ return tmp;
+}
+
+/*!
+ \fn QRect QRect::unite(const QRect &rectangle) const
+ \obsolete
+
+ Use united(\a rectangle) instead.
+*/
+
+/*!
+ \fn QRect QRect::united(const QRect &rectangle) const
+ \since 4.2
+
+ Returns the bounding rectangle of this rectangle and the given \a rectangle.
+
+ \image qrect-unite.png
+
+ \sa intersected()
+*/
+
+
+/*!
+ \fn QRect QRect::operator&(const QRect &rectangle) const
+
+ Returns the intersection of this rectangle and the given \a
+ rectangle. Returns an empty rectangle if there is no intersection.
+
+ \sa operator&=(), intersected()
+*/
+
+QRect QRect::operator&(const QRect &r) const
+{
+ if (isNull() || r.isNull())
+ return QRect();
+
+ int l1 = x1;
+ int r1 = x1;
+ if (x2 - x1 + 1 < 0)
+ l1 = x2;
+ else
+ r1 = x2;
+
+ int l2 = r.x1;
+ int r2 = r.x1;
+ if (r.x2 - r.x1 + 1 < 0)
+ l2 = r.x2;
+ else
+ r2 = r.x2;
+
+ if (l1 > r2 || l2 > r1)
+ return QRect();
+
+ int t1 = y1;
+ int b1 = y1;
+ if (y2 - y1 + 1 < 0)
+ t1 = y2;
+ else
+ b1 = y2;
+
+ int t2 = r.y1;
+ int b2 = r.y1;
+ if (r.y2 - r.y1 + 1 < 0)
+ t2 = r.y2;
+ else
+ b2 = r.y2;
+
+ if (t1 > b2 || t2 > b1)
+ return QRect();
+
+ QRect tmp;
+ tmp.x1 = qMax(l1, l2);
+ tmp.x2 = qMin(r1, r2);
+ tmp.y1 = qMax(t1, t2);
+ tmp.y2 = qMin(b1, b2);
+ return tmp;
+}
+
+/*!
+ \fn QRect QRect::intersect(const QRect &rectangle) const
+ \obsolete
+
+ Use intersected(\a rectangle) instead.
+*/
+
+/*!
+ \fn QRect QRect::intersected(const QRect &rectangle) const
+ \since 4.2
+
+ Returns the intersection of this rectangle and the given \a
+ rectangle. Note that \c{r.intersected(s)} is equivalent to \c{r & s}.
+
+ \image qrect-intersect.png
+
+ \sa intersects(), united(), operator&=()
+*/
+
+/*!
+ \fn bool QRect::intersects(const QRect &rectangle) const
+
+ Returns true if this rectangle intersects with the given \a
+ rectangle (i.e., there is at least one pixel that is within both
+ rectangles), otherwise returns false.
+
+ The intersection rectangle can be retrieved using the intersected()
+ function.
+
+ \sa contains()
+*/
+
+bool QRect::intersects(const QRect &r) const
+{
+ if (isNull() || r.isNull())
+ return false;
+
+ int l1 = x1;
+ int r1 = x1;
+ if (x2 - x1 + 1 < 0)
+ l1 = x2;
+ else
+ r1 = x2;
+
+ int l2 = r.x1;
+ int r2 = r.x1;
+ if (r.x2 - r.x1 + 1 < 0)
+ l2 = r.x2;
+ else
+ r2 = r.x2;
+
+ if (l1 > r2 || l2 > r1)
+ return false;
+
+ int t1 = y1;
+ int b1 = y1;
+ if (y2 - y1 + 1 < 0)
+ t1 = y2;
+ else
+ b1 = y2;
+
+ int t2 = r.y1;
+ int b2 = r.y1;
+ if (r.y2 - r.y1 + 1 < 0)
+ t2 = r.y2;
+ else
+ b2 = r.y2;
+
+ if (t1 > b2 || t2 > b1)
+ return false;
+
+ return true;
+}
+
+/*!
+ \fn bool operator==(const QRect &r1, const QRect &r2)
+ \relates QRect
+
+ Returns true if the rectangles \a r1 and \a r2 are equal,
+ otherwise returns false.
+*/
+
+
+/*!
+ \fn bool operator!=(const QRect &r1, const QRect &r2)
+ \relates QRect
+
+ Returns true if the rectangles \a r1 and \a r2 are different, otherwise
+ returns false.
+*/
+
+
+/*****************************************************************************
+ QRect stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QRect &rectangle)
+ \relates QRect
+
+ Writes the given \a rectangle to the given \a stream, and returns
+ a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QRect &r)
+{
+ if (s.version() == 1)
+ s << (qint16)r.left() << (qint16)r.top()
+ << (qint16)r.right() << (qint16)r.bottom();
+ else
+ s << (qint32)r.left() << (qint32)r.top()
+ << (qint32)r.right() << (qint32)r.bottom();
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QRect &rectangle)
+ \relates QRect
+
+ Reads a rectangle from the given \a stream into the given \a
+ rectangle, and returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QRect &r)
+{
+ if (s.version() == 1) {
+ qint16 x1, y1, x2, y2;
+ s >> x1; s >> y1; s >> x2; s >> y2;
+ r.setCoords(x1, y1, x2, y2);
+ }
+ else {
+ qint32 x1, y1, x2, y2;
+ s >> x1; s >> y1; s >> x2; s >> y2;
+ r.setCoords(x1, y1, x2, y2);
+ }
+ return s;
+}
+
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRect &r) {
+ dbg.nospace() << "QRect(" << r.x() << ',' << r.y() << ' '
+ << r.width() << 'x' << r.height() << ')';
+ return dbg.space();
+}
+#endif
+
+/*!
+ \class QRectF
+ \ingroup painting
+
+ \brief The QRectF class defines a rectangle in the plane using floating
+ point precision.
+
+ A rectangle is normally expressed as an upper-left corner and a
+ size. The size (width and height) of a QRectF is always equivalent
+ to the mathematical rectangle that forms the basis for its
+ rendering.
+
+ A QRectF can be constructed with a set of left, top, width and
+ height integers, or from a QPoint and a QSize. The following code
+ creates two identical rectangles.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qrect.cpp 1
+
+ There is also a third constructor creating a QRectF from a QRect,
+ and a corresponding toRect() function that returns a QRect object
+ based on the values of this rectangle (note that the coordinates
+ in the returned rectangle are rounded to the nearest integer).
+
+ The QRectF class provides a collection of functions that return
+ the various rectangle coordinates, and enable manipulation of
+ these. QRectF also provide functions to move the rectangle
+ relative to the various coordinates. In addition there is a
+ moveTo() function that moves the rectangle, leaving its top left
+ corner at the given coordinates. Alternatively, the translate()
+ function moves the rectangle the given offset relative to the
+ current position, and the translated() function returns a
+ translated copy of this rectangle.
+
+ The size() function returns the rectange'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,
+ the size can be changed by applying either of the functions
+ setting the rectangle coordinates, for example, setBottom() or
+ setRight().
+
+ The contains() function tells whether a given point is inside the
+ rectangle or not, and the intersects() function returns true if
+ this rectangle intersects with a given rectangle (otherwise
+ false). The QRectF class also provides the intersected() function
+ which returns the intersection rectangle, and the united() function
+ which returns the rectangle that encloses the given rectangle and
+ this:
+
+ \table
+ \row
+ \o \inlineimage qrect-intersect.png
+ \o \inlineimage qrect-unite.png
+ \row
+ \o intersected()
+ \o united()
+ \endtable
+
+ The isEmpty() function returns true if the rectangle's width or
+ height is less than, or equal to, 0. Note that an empty rectangle
+ is not valid: The isValid() function returns true if both width
+ and height is larger than 0. A null rectangle (isNull() == true)
+ on the other hand, has both width and height set to 0.
+
+ Note that due to the way QRect and QRectF are defined, an
+ empty QRectF is defined in essentially the same way as QRect.
+
+ Finally, QRectF objects can be streamed as well as compared.
+
+ \tableofcontents
+
+ \section1 Rendering
+
+ When using an \l {QPainter::Antialiasing}{anti-aliased} painter,
+ the boundary line of a QRectF will be rendered symmetrically on both
+ sides of the mathematical rectangle's boundary line. But when
+ using an aliased painter (the default) other rules apply.
+
+ Then, when rendering with a one pixel wide pen the QRectF's boundary
+ line will be rendered to the right and below the mathematical
+ rectangle's boundary line.
+
+ When rendering with a two pixels wide pen the boundary line will
+ be split in the middle by the mathematical rectangle. This will be
+ the case whenever the pen is set to an even number of pixels,
+ while rendering with a pen with an odd number of pixels, the spare
+ pixel will be rendered to the right and below the mathematical
+ rectangle as in the one pixel case.
+
+ \table
+ \row
+ \o \inlineimage qrect-diagram-zero.png
+ \o \inlineimage qrectf-diagram-one.png
+ \row
+ \o Logical representation
+ \o One pixel wide pen
+ \row
+ \o \inlineimage qrectf-diagram-two.png
+ \o \inlineimage qrectf-diagram-three.png
+ \row
+ \o Two pixel wide pen
+ \o Three pixel wide pen
+ \endtable
+
+ \section1 Coordinates
+
+ The QRectF class provides a collection of functions that return
+ the various rectangle coordinates, and enable manipulation of
+ these. QRectF also provide functions to move the rectangle
+ relative to the various coordinates.
+
+ For example: the bottom(), setBottom() and moveBottom() functions:
+ bottom() returns the y-coordinate of the rectangle's bottom edge,
+ setBottom() sets the bottom edge of the rectangle to the given y
+ coordinate (it may change the height, but will never change the
+ rectangle's top edge) and moveBottom() moves the entire rectangle
+ vertically, leaving the rectangle's bottom edge at the given y
+ coordinate and its size unchanged.
+
+ \image qrectf-coordinates.png
+
+ It is also possible to add offsets to this rectangle's coordinates
+ using the adjust() function, as well as retrieve a new rectangle
+ based on adjustments of the original one using the adjusted()
+ function. If either of the width and height is negative, use the
+ normalized() function to retrieve a rectangle where the corners
+ are swapped.
+
+ In addition, QRectF provides the getCoords() function which extracts
+ the position of the rectangle's top-left and bottom-right corner,
+ and the getRect() function which extracts the rectangle's top-left
+ corner, width and height. Use the setCoords() and setRect()
+ function to manipulate the rectangle's coordinates and dimensions
+ in one go.
+
+ \sa QRect, QRegion
+*/
+
+/*****************************************************************************
+ QRectF member functions
+ *****************************************************************************/
+
+/*!
+ \fn QRectF::QRectF()
+
+ Constructs a null rectangle.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QRectF::QRectF(const QPointF &topLeft, const QSizeF &size)
+
+ Constructs a rectangle with the given \a topLeft corner and the given \a size.
+
+ \sa setTopLeft(), setSize()
+*/
+
+/*!
+ \fn QRectF::QRectF(const QPointF &topLeft, const QPointF &bottomRight)
+ \since 4.3
+
+ Constructs a rectangle with the given \a topLeft and \a bottomRight corners.
+
+ \sa setTopLeft(), setBottomRight()
+*/
+
+/*!
+ \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.
+
+ \sa setRect()
+*/
+
+/*!
+ \fn QRectF::QRectF(const QRect &rectangle)
+
+ Constructs a QRectF rectangle from the given QRect \a rectangle.
+
+ \sa toRect()
+*/
+
+/*!
+ \fn bool QRectF::isNull() const
+
+ Returns true if the rectangle is a null rectangle, otherwise returns false.
+
+ A null rectangle has both the width and the height set to 0. A
+ null rectangle is also empty, and hence not valid.
+
+ \sa isEmpty(), isValid()
+*/
+
+/*!
+ \fn bool QRectF::isEmpty() const
+
+ Returns true if the rectangle is empty, otherwise returns false.
+
+ An empty rectangle has width() <= 0 or height() <= 0. An empty
+ rectangle is not valid (i.e., isEmpty() == !isValid()).
+
+ Use the normalized() function to retrieve a rectangle where the
+ corners are swapped.
+
+ \sa isNull(), isValid(), normalized()
+*/
+
+/*!
+ \fn bool QRectF::isValid() const
+
+ Returns true if the rectangle is valid, otherwise returns false.
+
+ A valid rectangle has a width() > 0 and height() > 0. Note that
+ non-trivial operations like intersections are not defined for
+ invalid rectangles. A valid rectangle is not empty (i.e., isValid()
+ == !isEmpty()).
+
+ \sa isNull(), isEmpty(), normalized()
+*/
+
+
+/*!
+ Returns a normalized rectangle; i.e., a rectangle that has a
+ 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.
+
+ \sa isValid(), isEmpty()
+*/
+
+QRectF QRectF::normalized() const
+{
+ QRectF r = *this;
+ if (r.w < 0) {
+ r.xp += r.w;
+ r.w = -r.w;
+ }
+ if (r.h < 0) {
+ r.yp += r.h;
+ r.h = -r.h;
+ }
+ return r;
+}
+
+/*!
+ \fn qreal QRectF::x() const
+
+ Returns the x-coordinate of the rectangle's left edge. Equivalent
+ to left().
+
+
+ \sa setX(), y(), topLeft()
+*/
+
+/*!
+ \fn qreal QRectF::y() const
+
+ Returns the y-coordinate of the rectangle's top edge. Equivalent
+ to top().
+
+ \sa setY(), x(), topLeft()
+*/
+
+
+/*!
+ \fn void QRectF::setLeft(qreal x)
+
+ Sets the left edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the right
+ edge of the rectangle.
+
+ Equivalent to setX().
+
+ \sa left(), moveLeft()
+*/
+
+/*!
+ \fn void QRectF::setTop(qreal y)
+
+ Sets the top edge of the rectangle to the given \a y coordinate. May
+ change the height, but will never change the bottom edge of the
+ rectangle.
+
+ Equivalent to setY().
+
+ \sa top(), moveTop()
+*/
+
+/*!
+ \fn void QRectF::setRight(qreal x)
+
+ Sets the right edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the left
+ edge of the rectangle.
+
+ \sa right(), moveRight()
+*/
+
+/*!
+ \fn void QRectF::setBottom(qreal y)
+
+ Sets the bottom edge of the rectangle to the given \a y
+ coordinate. May change the height, but will never change the top
+ edge of the rectangle.
+
+ \sa bottom(), moveBottom()
+*/
+
+/*!
+ \fn void QRectF::setX(qreal x)
+
+ Sets the left edge of the rectangle to the given \a x
+ coordinate. May change the width, but will never change the right
+ edge of the rectangle.
+
+ Equivalent to setLeft().
+
+ \sa x(), setY(), setTopLeft()
+*/
+
+/*!
+ \fn void QRectF::setY(qreal y)
+
+ Sets the top edge of the rectangle to the given \a y
+ coordinate. May change the height, but will never change the
+ bottom edge of the rectangle.
+
+ Equivalent to setTop().
+
+ \sa y(), setX(), setTopLeft()
+*/
+
+/*!
+ \fn void QRectF::setTopLeft(const QPointF &position)
+
+ Set the top-left corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ bottom-right corner of the rectangle.
+
+ \sa topLeft(), moveTopLeft()
+*/
+
+/*!
+ \fn void QRectF::setBottomRight(const QPointF &position)
+
+ Set the bottom-right corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ top-left corner of the rectangle.
+
+ \sa bottomRight(), moveBottomRight()
+*/
+
+/*!
+ \fn void QRectF::setTopRight(const QPointF &position)
+
+ Set the top-right corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ bottom-left corner of the rectangle.
+
+ \sa topRight(), moveTopRight()
+*/
+
+/*!
+ \fn void QRectF::setBottomLeft(const QPointF &position)
+
+ Set the bottom-left corner of the rectangle to the given \a
+ position. May change the size, but will never change the
+ top-right corner of the rectangle.
+
+ \sa bottomLeft(), moveBottomLeft()
+*/
+
+/*!
+ \fn QPointF QRectF::center() const
+
+ Returns the center point of the rectangle.
+
+ \sa moveCenter()
+*/
+
+
+/*!
+ \fn void QRectF::getRect(qreal *x, qreal *y, qreal *width, qreal *height) const
+
+ Extracts the position of the rectangle's top-left corner to *\a x and
+ *\a y, and its dimensions to *\a width and *\a height.
+
+ \sa setRect(), getCoords()
+*/
+
+
+/*!
+ \fn void QRectF::getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const
+
+ Extracts the position of the rectangle's top-left corner to *\a x1
+ and *\a y1, and the position of the bottom-right corner to *\a x2 and
+ *\a y2.
+
+ \sa setCoords(), getRect()
+*/
+
+/*!
+ \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
+ unchanged.
+
+ \sa left(), setLeft(), moveRight()
+*/
+
+/*!
+ \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.
+
+ \sa top(), setTop(), moveBottom()
+*/
+
+
+/*!
+ \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
+ unchanged.
+
+ \sa right(), setRight(), moveLeft()
+*/
+
+
+/*!
+ \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
+ unchanged.
+
+ \sa bottom(), setBottom(), moveTop()
+*/
+
+
+/*!
+ \fn void QRectF::moveTopLeft(const QPointF &position)
+
+ Moves the rectangle, leaving the top-left corner at the given \a
+ position. The rectangle's size is unchanged.
+
+ \sa setTopLeft(), moveTop(), moveLeft()
+*/
+
+
+/*!
+ \fn void QRectF::moveBottomRight(const QPointF &position)
+
+ Moves the rectangle, leaving the bottom-right corner at the given
+ \a position. The rectangle's size is unchanged.
+
+ \sa setBottomRight(), moveBottom(), moveRight()
+*/
+
+
+/*!
+ \fn void QRectF::moveTopRight(const QPointF &position)
+
+ Moves the rectangle, leaving the top-right corner at the given
+ \a position. The rectangle's size is unchanged.
+
+ \sa setTopRight(), moveTop(), moveRight()
+*/
+
+
+/*!
+ \fn void QRectF::moveBottomLeft(const QPointF &position)
+
+ Moves the rectangle, leaving the bottom-left corner at the given
+ \a position. The rectangle's size is unchanged.
+
+ \sa setBottomLeft(), moveBottom(), moveLeft()
+*/
+
+
+/*!
+ \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.
+
+ \sa translate(), moveTopLeft()
+*/
+
+/*!
+ \fn void QRectF::moveTo(const QPointF &position)
+ \overload
+
+ Moves the rectangle, leaving the top-left corner at the given \a
+ position.
+*/
+
+/*!
+ \fn void QRectF::translate(qreal dx, qreal dy)
+
+ 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.
+
+ \sa moveTopLeft(), moveTo(), translated()
+*/
+
+
+/*!
+ \fn void QRectF::translate(const QPointF &offset)
+ \overload
+
+ Moves the rectangle \a{offset}.\l{QPointF::x()}{x()} along the x
+ axis and \a{offset}.\l{QPointF::y()}{y()} along the y axis,
+ relative to the current position.
+*/
+
+
+/*!
+ \fn QRectF QRectF::translated(qreal dx, qreal dy) const
+
+ 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.
+
+ \sa translate()
+*/
+
+
+/*!
+ \fn QRectF QRectF::translated(const QPointF &offset) const
+ \overload
+
+ Returns a copy of the rectangle that is translated
+ \a{offset}.\l{QPointF::x()}{x()} along the x axis and
+ \a{offset}.\l{QPointF::y()}{y()} along the y axis, relative to the
+ current position.
+*/
+
+
+/*!
+ \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.
+
+ \sa getRect(), setCoords()
+*/
+
+
+/*!
+ \fn void QRectF::setCoords(qreal x1, qreal y1, qreal x2, qreal y2)
+
+ 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).
+
+ \sa getCoords() setRect()
+*/
+
+/*!
+ \fn QRectF QRectF::adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const
+
+ Returns a new rectangle with \a dx1, \a dy1, \a dx2 and \a dy2
+ added respectively to the existing coordinates of this rectangle.
+
+ \sa adjust()
+*/
+
+/*! \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.
+
+ \sa adjusted(), setRect()
+*/
+/*!
+ \fn QSizeF QRectF::size() const
+
+ Returns the size of the rectangle.
+
+ \sa setSize(), width(), height()
+*/
+
+/*!
+ \fn qreal QRectF::width() const
+
+ Returns the width of the rectangle.
+
+ \sa setWidth(), height(), size()
+*/
+
+/*!
+ \fn qreal QRectF::height() const
+
+ Returns the height of the rectangle.
+
+ \sa setHeight(), width(), size()
+*/
+
+/*!
+ \fn void QRectF::setWidth(qreal width)
+
+ Sets the width of the rectangle to the given \a width. The right
+ edge is changed, but not the left one.
+
+ \sa width(), setSize()
+*/
+
+
+/*!
+ \fn void QRectF::setHeight(qreal height)
+
+ Sets the height of the rectangle to the given \a height. The bottom
+ edge is changed, but not the top one.
+
+ \sa height(), setSize()
+*/
+
+
+/*!
+ \fn void QRectF::setSize(const QSizeF &size)
+
+ Sets the size of the rectangle to the given \a size. The top-left
+ corner is not moved.
+
+ \sa size(), setWidth(), setHeight()
+*/
+
+
+/*!
+ \fn bool QRectF::contains(const QPointF &point) const
+
+ Returns true if the given \a point is inside or on the edge of the
+ rectangle; otherwise returns false.
+
+ \sa intersects()
+*/
+
+bool QRectF::contains(const QPointF &p) const
+{
+ qreal l = xp;
+ qreal r = xp;
+ if (w < 0)
+ l += w;
+ else
+ r += w;
+ if (l == r) // null rect
+ return false;
+
+ if (p.x() < l || p.x() > r)
+ return false;
+
+ qreal t = yp;
+ qreal b = yp;
+ if (h < 0)
+ t += h;
+ else
+ b += h;
+ if (t == b) // null rect
+ return false;
+
+ if (p.y() < t || p.y() > b)
+ return false;
+
+ return true;
+}
+
+
+/*!
+ \fn bool QRectF::contains(qreal x, qreal y) const
+ \overload
+
+ Returns true if the point (\a x, \a y) is inside or on the edge of
+ the rectangle; otherwise returns false.
+*/
+
+/*!
+ \fn bool QRectF::contains(const QRectF &rectangle) const
+ \overload
+
+ Returns true if the given \a rectangle is inside this rectangle;
+ otherwise returns false.
+*/
+
+bool QRectF::contains(const QRectF &r) const
+{
+ qreal l1 = xp;
+ qreal r1 = xp;
+ if (w < 0)
+ l1 += w;
+ else
+ r1 += w;
+ if (l1 == r1) // null rect
+ return false;
+
+ qreal l2 = r.xp;
+ qreal r2 = r.xp;
+ if (r.w < 0)
+ l2 += r.w;
+ else
+ r2 += r.w;
+ if (l2 == r2) // null rect
+ return false;
+
+ if (l2 < l1 || r2 > r1)
+ return false;
+
+ qreal t1 = yp;
+ qreal b1 = yp;
+ if (h < 0)
+ t1 += h;
+ else
+ b1 += h;
+ if (t1 == b1) // null rect
+ return false;
+
+ qreal t2 = r.yp;
+ qreal b2 = r.yp;
+ if (r.h < 0)
+ t2 += r.h;
+ else
+ b2 += r.h;
+ if (t2 == b2) // null rect
+ return false;
+
+ if (t2 < t1 || b2 > b1)
+ return false;
+
+ return true;
+}
+
+/*!
+ \fn qreal QRectF::left() const
+
+ Returns the x-coordinate of the rectangle's left edge. Equivalent
+ to x().
+
+ \sa setLeft(), topLeft(), bottomLeft()
+*/
+
+/*!
+ \fn qreal QRectF::top() const
+
+ Returns the y-coordinate of the rectangle's top edge. Equivalent
+ to y().
+
+ \sa setTop(), topLeft(), topRight()
+*/
+
+/*!
+ \fn qreal QRectF::right() const
+
+ Returns the x-coordinate of the rectangle's right edge.
+
+ \sa setRight(), topRight(), bottomRight()
+*/
+
+/*!
+ \fn qreal QRectF::bottom() const
+
+ Returns the y-coordinate of the rectangle's bottom edge.
+
+ \sa setBottom(), bottomLeft(), bottomRight()
+*/
+
+/*!
+ \fn QPointF QRectF::topLeft() const
+
+ Returns the position of the rectangle's top-left corner.
+
+ \sa setTopLeft(), top(), left()
+*/
+
+/*!
+ \fn QPointF QRectF::bottomRight() const
+
+ Returns the position of the rectangle's bottom-right corner.
+
+ \sa setBottomRight(), bottom(), right()
+*/
+
+/*!
+ \fn QPointF QRectF::topRight() const
+
+ Returns the position of the rectangle's top-right corner.
+
+ \sa setTopRight(), top(), right()
+*/
+
+/*!
+ \fn QPointF QRectF::bottomLeft() const
+
+ Returns the position of the rectangle's bottom-left corner.
+
+ \sa setBottomLeft(), bottom(), left()
+*/
+
+/*!
+ \fn QRectF& QRectF::operator|=(const QRectF &rectangle)
+
+ Unites this rectangle with the given \a rectangle.
+
+ \sa united(), operator|()
+*/
+
+/*!
+ \fn QRectF& QRectF::operator&=(const QRectF &rectangle)
+
+ Intersects this rectangle with the given \a rectangle.
+
+ \sa intersected(), operator|=()
+*/
+
+
+/*!
+ \fn QRectF QRectF::operator|(const QRectF &rectangle) const
+
+ Returns the bounding rectangle of this rectangle and the given \a rectangle.
+
+ \sa united(), operator|=()
+*/
+
+QRectF QRectF::operator|(const QRectF &r) const
+{
+ if (isNull())
+ return r;
+ if (r.isNull())
+ return *this;
+
+ qreal left = xp;
+ qreal right = xp;
+ if (w < 0)
+ left += w;
+ else
+ right += w;
+
+ if (r.w < 0) {
+ left = qMin(left, r.xp + r.w);
+ right = qMax(right, r.xp);
+ } else {
+ left = qMin(left, r.xp);
+ right = qMax(right, r.xp + r.w);
+ }
+
+ qreal top = yp;
+ qreal bottom = yp;
+ if (h < 0)
+ top += h;
+ else
+ bottom += h;
+
+ if (r.h < 0) {
+ top = qMin(top, r.yp + r.h);
+ bottom = qMax(bottom, r.yp);
+ } else {
+ top = qMin(top, r.yp);
+ bottom = qMax(bottom, r.yp + r.h);
+ }
+
+ return QRectF(left, top, right - left, bottom - top);
+}
+
+/*!
+ \fn QRectF QRectF::unite(const QRectF &rectangle) const
+ \obsolete
+
+ Use united(\a rectangle) instead.
+*/
+
+/*!
+ \fn QRectF QRectF::united(const QRectF &rectangle) const
+ \since 4.2
+
+ Returns the bounding rectangle of this rectangle and the given \a
+ rectangle.
+
+ \image qrect-unite.png
+
+ \sa intersected()
+*/
+
+
+/*!
+ \fn QRectF QRectF::operator &(const QRectF &rectangle) const
+
+ Returns the intersection of this rectangle and the given \a
+ rectangle. Returns an empty rectangle if there is no intersection.
+
+ \sa operator&=(), intersected()
+*/
+
+QRectF QRectF::operator&(const QRectF &r) const
+{
+ qreal l1 = xp;
+ qreal r1 = xp;
+ if (w < 0)
+ l1 += w;
+ else
+ r1 += w;
+ if (l1 == r1) // null rect
+ return QRectF();
+
+ qreal l2 = r.xp;
+ qreal r2 = r.xp;
+ if (r.w < 0)
+ l2 += r.w;
+ else
+ r2 += r.w;
+ if (l2 == r2) // null rect
+ return QRectF();
+
+ if (l1 >= r2 || l2 >= r1)
+ return QRectF();
+
+ qreal t1 = yp;
+ qreal b1 = yp;
+ if (h < 0)
+ t1 += h;
+ else
+ b1 += h;
+ if (t1 == b1) // null rect
+ return QRectF();
+
+ qreal t2 = r.yp;
+ qreal b2 = r.yp;
+ if (r.h < 0)
+ t2 += r.h;
+ else
+ b2 += r.h;
+ if (t2 == b2) // null rect
+ return QRectF();
+
+ if (t1 >= b2 || t2 >= b1)
+ return QRectF();
+
+ QRectF tmp;
+ tmp.xp = qMax(l1, l2);
+ tmp.yp = qMax(t1, t2);
+ tmp.w = qMin(r1, r2) - tmp.xp;
+ tmp.h = qMin(b1, b2) - tmp.yp;
+ return tmp;
+}
+
+/*!
+ \fn QRectF QRectF::intersect(const QRectF &rectangle) const
+ \obsolete
+
+ Use intersected(\a rectangle) instead.
+*/
+
+/*!
+ \fn QRectF QRectF::intersected(const QRectF &rectangle) const
+ \since 4.2
+
+ Returns the intersection of this rectangle and the given \a
+ rectangle. Note that \c {r.intersected(s)} is equivalent to \c
+ {r & s}.
+
+ \image qrect-intersect.png
+
+ \sa intersects(), united(), operator&=()
+*/
+
+/*!
+ \fn bool QRectF::intersects(const QRectF &rectangle) const
+
+ Returns true if this rectangle intersects with the given \a
+ rectangle (i.e. there is a non-empty area of overlap between
+ them), otherwise returns false.
+
+ The intersection rectangle can be retrieved using the intersected()
+ function.
+
+ \sa contains()
+*/
+
+bool QRectF::intersects(const QRectF &r) const
+{
+ qreal l1 = xp;
+ qreal r1 = xp;
+ if (w < 0)
+ l1 += w;
+ else
+ r1 += w;
+ if (l1 == r1) // null rect
+ return false;
+
+ qreal l2 = r.xp;
+ qreal r2 = r.xp;
+ if (r.w < 0)
+ l2 += r.w;
+ else
+ r2 += r.w;
+ if (l2 == r2) // null rect
+ return false;
+
+ if (l1 >= r2 || l2 >= r1)
+ return false;
+
+ qreal t1 = yp;
+ qreal b1 = yp;
+ if (h < 0)
+ t1 += h;
+ else
+ b1 += h;
+ if (t1 == b1) // null rect
+ return false;
+
+ qreal t2 = r.yp;
+ qreal b2 = r.yp;
+ if (r.h < 0)
+ t2 += r.h;
+ else
+ b2 += r.h;
+ if (t2 == b2) // null rect
+ return false;
+
+ if (t1 >= b2 || t2 >= b1)
+ return false;
+
+ return true;
+}
+
+/*!
+ \fn QRect QRectF::toRect() const
+
+ 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()
+*/
+
+/*!
+ \fn QRect QRectF::toAlignedRect() const
+ \since 4.3
+
+ Returns a QRect based on the values of this rectangle that is the
+ smallest possible integer rectangle that completely contains this
+ rectangle.
+
+ \sa toRect()
+*/
+
+QRect QRectF::toAlignedRect() const
+{
+ int xmin = int(qFloor(xp));
+ int xmax = int(qCeil(xp + w));
+ int ymin = int(qFloor(yp));
+ int ymax = int(qCeil(yp + h));
+ return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
+}
+
+/*!
+ \fn void QRectF::moveCenter(const QPointF &position)
+
+ Moves the rectangle, leaving the center point at the given \a
+ position. The rectangle's size is unchanged.
+
+ \sa center()
+*/
+
+/*!
+ \fn bool operator==(const QRectF &r1, const QRectF &r2)
+ \relates QRectF
+
+ Returns true if the rectangles \a r1 and \a r2 are equal,
+ otherwise returns false.
+*/
+
+
+/*!
+ \fn bool operator!=(const QRectF &r1, const QRectF &r2)
+ \relates QRectF
+
+ Returns true if the rectangles \a r1 and \a r2 are different, otherwise
+ returns false.
+*/
+
+/*****************************************************************************
+ QRectF stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QRectF &rectangle)
+
+ \relates QRectF
+
+ Writes the \a rectangle to the \a stream, and returns a reference to the
+ stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QRectF &r)
+{
+ s << double(r.x()) << double(r.y()) << double(r.width()) << double(r.height());
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QRectF &rectangle)
+
+ \relates QRectF
+
+ Reads a \a rectangle from the \a stream, and returns a reference to the
+ stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QRectF &r)
+{
+ double x, y, w, h;
+ s >> x;
+ s >> y;
+ s >> w;
+ s >> h;
+ r.setRect(qreal(x), qreal(y), qreal(w), qreal(h));
+ return s;
+}
+
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRectF &r) {
+ dbg.nospace() << "QRectF(" << r.x() << ',' << r.y() << ' '
+ << r.width() << 'x' << r.height() << ')';
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
new file mode 100644
index 0000000000..8ab511c388
--- /dev/null
+++ b/src/corelib/tools/qrect.h
@@ -0,0 +1,858 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRECT_H
+#define QRECT_H
+
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+
+#ifdef topLeft
+#error qrect.h must be included before any header file that defines topLeft
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QRect
+{
+public:
+ QRect() { x1 = y1 = 0; x2 = y2 = -1; }
+ QRect(const QPoint &topleft, const QPoint &bottomright);
+ QRect(const QPoint &topleft, const QSize &size);
+ QRect(int left, int top, int width, int height);
+
+ bool isNull() const;
+ bool isEmpty() const;
+ bool isValid() const;
+
+ int left() const;
+ int top() const;
+ int right() const;
+ int bottom() const;
+ QRect normalized() const;
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT int &rLeft() { return x1; }
+ QT3_SUPPORT int &rTop() { return y1; }
+ QT3_SUPPORT int &rRight() { return x2; }
+ QT3_SUPPORT int &rBottom() { return y2; }
+
+ QT3_SUPPORT QRect normalize() const { return normalized(); }
+#endif
+
+ int x() const;
+ int y() const;
+ void setLeft(int pos);
+ void setTop(int pos);
+ void setRight(int pos);
+ void setBottom(int pos);
+ void setX(int x);
+ void setY(int y);
+
+ void setTopLeft(const QPoint &p);
+ void setBottomRight(const QPoint &p);
+ void setTopRight(const QPoint &p);
+ void setBottomLeft(const QPoint &p);
+
+ QPoint topLeft() const;
+ QPoint bottomRight() const;
+ QPoint topRight() const;
+ QPoint bottomLeft() const;
+ QPoint center() const;
+
+ void moveLeft(int pos);
+ void moveTop(int pos);
+ void moveRight(int pos);
+ void moveBottom(int pos);
+ void moveTopLeft(const QPoint &p);
+ void moveBottomRight(const QPoint &p);
+ void moveTopRight(const QPoint &p);
+ void moveBottomLeft(const QPoint &p);
+ void moveCenter(const QPoint &p);
+
+ inline void translate(int dx, int dy);
+ inline void translate(const QPoint &p);
+ inline QRect translated(int dx, int dy) const;
+ inline QRect translated(const QPoint &p) const;
+
+ void moveTo(int x, int t);
+ void moveTo(const QPoint &p);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void moveBy(int dx, int dy) { translate(dx, dy); }
+ QT3_SUPPORT void moveBy(const QPoint &p) { translate(p); }
+#endif
+
+ void setRect(int x, int y, int w, int h);
+ inline void getRect(int *x, int *y, int *w, int *h) const;
+
+ void setCoords(int x1, int y1, int x2, int y2);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void addCoords(int x1, int y1, int x2, int y2);
+#endif
+ inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
+
+ inline void adjust(int x1, int y1, int x2, int y2);
+ inline QRect adjusted(int x1, int y1, int x2, int y2) const;
+
+ QSize size() const;
+ int width() const;
+ int height() const;
+ void setWidth(int w);
+ void setHeight(int h);
+ void setSize(const QSize &s);
+
+ QRect operator|(const QRect &r) const;
+ QRect operator&(const QRect &r) const;
+ QRect& operator|=(const QRect &r);
+ QRect& operator&=(const QRect &r);
+
+ bool contains(const QPoint &p, bool proper=false) const;
+ bool contains(int x, int y) const; // inline methods, _don't_ merge these
+ bool contains(int x, int y, bool proper) const;
+ bool contains(const QRect &r, bool proper = false) const;
+ QRect unite(const QRect &r) const; // ### Qt 5: make QT4_SUPPORT
+ QRect united(const QRect &other) const;
+ QRect intersect(const QRect &r) const; // ### Qt 5: make QT4_SUPPORT
+ QRect intersected(const QRect &other) const;
+ bool intersects(const QRect &r) const;
+
+ friend Q_CORE_EXPORT_INLINE bool operator==(const QRect &, const QRect &);
+ friend Q_CORE_EXPORT_INLINE bool operator!=(const QRect &, const QRect &);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void rect(int *x, int *y, int *w, int *h) const { getRect(x, y, w, h); }
+ inline QT3_SUPPORT void coords(int *ax1, int *ay1, int *ax2, int *ay2) const
+ { getCoords(ax1, ay1, ax2, ay2); }
+#endif
+
+private:
+#if defined(Q_WS_X11)
+ friend void qt_setCoords(QRect *r, int xp1, int yp1, int xp2, int yp2);
+#endif
+ // ### Qt 5; remove the ifdef and just have the same order on all platforms.
+#if defined(Q_OS_MAC)
+ int y1;
+ int x1;
+ int y2;
+ int x2;
+#else
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+#endif
+
+};
+Q_DECLARE_TYPEINFO(QRect, Q_MOVABLE_TYPE);
+
+Q_CORE_EXPORT_INLINE bool operator==(const QRect &, const QRect &);
+Q_CORE_EXPORT_INLINE bool operator!=(const QRect &, const QRect &);
+
+
+/*****************************************************************************
+ QRect stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QRect &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRect &);
+#endif
+
+/*****************************************************************************
+ QRect inline member functions
+ *****************************************************************************/
+
+inline QRect::QRect(int aleft, int atop, int awidth, int aheight)
+{
+ x1 = aleft;
+ y1 = atop;
+ x2 = (aleft + awidth - 1);
+ y2 = (atop + aheight - 1);
+}
+
+inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight)
+{
+ x1 = atopLeft.x();
+ y1 = atopLeft.y();
+ x2 = abottomRight.x();
+ y2 = abottomRight.y();
+}
+
+inline QRect::QRect(const QPoint &atopLeft, const QSize &asize)
+{
+ x1 = atopLeft.x();
+ y1 = atopLeft.y();
+ x2 = (x1+asize.width() - 1);
+ y2 = (y1+asize.height() - 1);
+}
+
+inline bool QRect::isNull() const
+{ return x2 == x1 - 1 && y2 == y1 - 1; }
+
+inline bool QRect::isEmpty() const
+{ return x1 > x2 || y1 > y2; }
+
+inline bool QRect::isValid() const
+{ return x1 <= x2 && y1 <= y2; }
+
+inline int QRect::left() const
+{ return x1; }
+
+inline int QRect::top() const
+{ return y1; }
+
+inline int QRect::right() const
+{ return x2; }
+
+inline int QRect::bottom() const
+{ return y2; }
+
+inline int QRect::x() const
+{ return x1; }
+
+inline int QRect::y() const
+{ return y1; }
+
+inline void QRect::setLeft(int pos)
+{ x1 = pos; }
+
+inline void QRect::setTop(int pos)
+{ y1 = pos; }
+
+inline void QRect::setRight(int pos)
+{ x2 = pos; }
+
+inline void QRect::setBottom(int pos)
+{ y2 = pos; }
+
+inline void QRect::setTopLeft(const QPoint &p)
+{ x1 = p.x(); y1 = p.y(); }
+
+inline void QRect::setBottomRight(const QPoint &p)
+{ x2 = p.x(); y2 = p.y(); }
+
+inline void QRect::setTopRight(const QPoint &p)
+{ x2 = p.x(); y1 = p.y(); }
+
+inline void QRect::setBottomLeft(const QPoint &p)
+{ x1 = p.x(); y2 = p.y(); }
+
+inline void QRect::setX(int ax)
+{ x1 = ax; }
+
+inline void QRect::setY(int ay)
+{ y1 = ay; }
+
+inline QPoint QRect::topLeft() const
+{ return QPoint(x1, y1); }
+
+inline QPoint QRect::bottomRight() const
+{ return QPoint(x2, y2); }
+
+inline QPoint QRect::topRight() const
+{ return QPoint(x2, y1); }
+
+inline QPoint QRect::bottomLeft() const
+{ return QPoint(x1, y2); }
+
+inline QPoint QRect::center() const
+{ return QPoint((x1+x2)/2, (y1+y2)/2); }
+
+inline int QRect::width() const
+{ return x2 - x1 + 1; }
+
+inline int QRect::height() const
+{ return y2 - y1 + 1; }
+
+inline QSize QRect::size() const
+{ return QSize(width(), height()); }
+
+inline void QRect::translate(int dx, int dy)
+{
+ x1 += dx;
+ y1 += dy;
+ x2 += dx;
+ y2 += dy;
+}
+
+inline void QRect::translate(const QPoint &p)
+{
+ x1 += p.x();
+ y1 += p.y();
+ x2 += p.x();
+ y2 += p.y();
+}
+
+inline QRect QRect::translated(int dx, int dy) const
+{ return QRect(QPoint(x1 + dx, y1 + dy), QPoint(x2 + dx, y2 + dy)); }
+
+inline QRect QRect::translated(const QPoint &p) const
+{ return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y())); }
+
+inline void QRect::moveTo(int ax, int ay)
+{
+ x2 += ax - x1;
+ y2 += ay - y1;
+ x1 = ax;
+ y1 = ay;
+}
+
+inline void QRect::moveTo(const QPoint &p)
+{
+ x2 += p.x() - x1;
+ y2 += p.y() - y1;
+ x1 = p.x();
+ y1 = p.y();
+}
+
+inline void QRect::moveLeft(int pos)
+{ x2 += (pos - x1); x1 = pos; }
+
+inline void QRect::moveTop(int pos)
+{ y2 += (pos - y1); y1 = pos; }
+
+inline void QRect::moveRight(int pos)
+{
+ x1 += (pos - x2);
+ x2 = pos;
+}
+
+inline void QRect::moveBottom(int pos)
+{
+ y1 += (pos - y2);
+ y2 = pos;
+}
+
+inline void QRect::moveTopLeft(const QPoint &p)
+{
+ moveLeft(p.x());
+ moveTop(p.y());
+}
+
+inline void QRect::moveBottomRight(const QPoint &p)
+{
+ moveRight(p.x());
+ moveBottom(p.y());
+}
+
+inline void QRect::moveTopRight(const QPoint &p)
+{
+ moveRight(p.x());
+ moveTop(p.y());
+}
+
+inline void QRect::moveBottomLeft(const QPoint &p)
+{
+ moveLeft(p.x());
+ moveBottom(p.y());
+}
+
+inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const
+{
+ *ax = x1;
+ *ay = y1;
+ *aw = x2 - x1 + 1;
+ *ah = y2 - y1 + 1;
+}
+
+inline void QRect::setRect(int ax, int ay, int aw, int ah)
+{
+ x1 = ax;
+ y1 = ay;
+ x2 = (ax + aw - 1);
+ y2 = (ay + ah - 1);
+}
+
+inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const
+{
+ *xp1 = x1;
+ *yp1 = y1;
+ *xp2 = x2;
+ *yp2 = y2;
+}
+
+inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2)
+{
+ x1 = xp1;
+ y1 = yp1;
+ x2 = xp2;
+ y2 = yp2;
+}
+
+#ifdef QT3_SUPPORT
+inline void QRect::addCoords(int dx1, int dy1, int dx2, int dy2)
+{
+ adjust(dx1, dy1, dx2, dy2);
+}
+#endif
+
+inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const
+{ return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2)); }
+
+inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2)
+{
+ x1 += dx1;
+ y1 += dy1;
+ x2 += dx2;
+ y2 += dy2;
+}
+
+inline void QRect::setWidth(int w)
+{ x2 = (x1 + w - 1); }
+
+inline void QRect::setHeight(int h)
+{ y2 = (y1 + h - 1); }
+
+inline void QRect::setSize(const QSize &s)
+{
+ x2 = (s.width() + x1 - 1);
+ y2 = (s.height() + y1 - 1);
+}
+
+inline bool QRect::contains(int ax, int ay, bool aproper) const
+{
+ return contains(QPoint(ax, ay), aproper);
+}
+
+inline bool QRect::contains(int ax, int ay) const
+{
+ return contains(QPoint(ax, ay), false);
+}
+
+inline QRect& QRect::operator|=(const QRect &r)
+{
+ *this = *this | r;
+ return *this;
+}
+
+inline QRect& QRect::operator&=(const QRect &r)
+{
+ *this = *this & r;
+ return *this;
+}
+
+inline QRect QRect::intersect(const QRect &r) const
+{
+ return *this & r;
+}
+
+inline QRect QRect::intersected(const QRect &other) const
+{
+ return intersect(other);
+}
+
+inline QRect QRect::unite(const QRect &r) const
+{
+ return *this | r;
+}
+
+inline QRect QRect::united(const QRect &r) const
+{
+ return unite(r);
+}
+
+inline bool operator==(const QRect &r1, const QRect &r2)
+{
+ return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
+}
+
+inline bool operator!=(const QRect &r1, const QRect &r2)
+{
+ return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &);
+#endif
+
+
+class Q_CORE_EXPORT QRectF
+{
+public:
+ QRectF() { xp = yp = 0.; w = h = 0.; }
+ QRectF(const QPointF &topleft, const QSizeF &size);
+ QRectF(const QPointF &topleft, const QPointF &bottomRight);
+ QRectF(qreal left, qreal top, qreal width, qreal height);
+ QRectF(const QRect &rect);
+
+ bool isNull() const;
+ bool isEmpty() const;
+ bool isValid() const;
+ QRectF normalized() const;
+
+ inline qreal left() const { return xp; }
+ inline qreal top() const { return yp; }
+ inline qreal right() const { return xp + w; }
+ inline qreal bottom() const { return yp + h; }
+
+ inline qreal x() const;
+ inline qreal y() const;
+ inline void setLeft(qreal pos);
+ inline void setTop(qreal pos);
+ inline void setRight(qreal pos);
+ inline void setBottom(qreal pos);
+ inline void setX(qreal pos) { setLeft(pos); }
+ inline void setY(qreal pos) { setTop(pos); }
+
+ inline QPointF topLeft() const { return QPointF(xp, yp); }
+ inline QPointF bottomRight() const { return QPointF(xp+w, yp+h); }
+ inline QPointF topRight() const { return QPointF(xp+w, yp); }
+ inline QPointF bottomLeft() const { return QPointF(xp, yp+h); }
+ inline QPointF center() const;
+
+ void setTopLeft(const QPointF &p);
+ void setBottomRight(const QPointF &p);
+ void setTopRight(const QPointF &p);
+ void setBottomLeft(const QPointF &p);
+
+ void moveLeft(qreal pos);
+ void moveTop(qreal pos);
+ void moveRight(qreal pos);
+ void moveBottom(qreal pos);
+ void moveTopLeft(const QPointF &p);
+ void moveBottomRight(const QPointF &p);
+ void moveTopRight(const QPointF &p);
+ void moveBottomLeft(const QPointF &p);
+ void moveCenter(const QPointF &p);
+
+ void translate(qreal dx, qreal dy);
+ void translate(const QPointF &p);
+
+ QRectF translated(qreal dx, qreal dy) const;
+ QRectF translated(const QPointF &p) const;
+
+ void moveTo(qreal x, qreal t);
+ void moveTo(const QPointF &p);
+
+ void setRect(qreal x, qreal y, qreal w, qreal h);
+ void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const;
+
+ void setCoords(qreal x1, qreal y1, qreal x2, qreal y2);
+ void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
+
+ inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2);
+ inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const;
+
+ QSizeF size() const;
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal w);
+ void setHeight(qreal h);
+ void setSize(const QSizeF &s);
+
+ QRectF operator|(const QRectF &r) const;
+ QRectF operator&(const QRectF &r) const;
+ QRectF& operator|=(const QRectF &r);
+ QRectF& operator&=(const QRectF &r);
+
+ bool contains(const QPointF &p) const;
+ bool contains(qreal x, qreal y) const;
+ bool contains(const QRectF &r) const;
+ QRectF unite(const QRectF &r) const; // ### Qt 5: make QT4_SUPPORT
+ QRectF united(const QRectF &other) const;
+ QRectF intersect(const QRectF &r) const; // ### Qt 5: make QT4_SUPPORT
+ QRectF intersected(const QRectF &other) const;
+ bool intersects(const QRectF &r) const;
+
+ friend Q_CORE_EXPORT_INLINE bool operator==(const QRectF &, const QRectF &);
+ friend Q_CORE_EXPORT_INLINE bool operator!=(const QRectF &, const QRectF &);
+
+ QRect toRect() const;
+ QRect toAlignedRect() const;
+
+private:
+ qreal xp;
+ qreal yp;
+ qreal w;
+ qreal h;
+};
+Q_DECLARE_TYPEINFO(QRectF, Q_MOVABLE_TYPE);
+
+Q_CORE_EXPORT_INLINE bool operator==(const QRectF &, const QRectF &);
+Q_CORE_EXPORT_INLINE bool operator!=(const QRectF &, const QRectF &);
+
+
+/*****************************************************************************
+ QRectF stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QRectF &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRectF &);
+#endif
+
+/*****************************************************************************
+ QRectF inline member functions
+ *****************************************************************************/
+
+inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight)
+ : xp(aleft), yp(atop), w(awidth), h(aheight)
+{
+}
+
+inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize)
+{
+ xp = atopLeft.x();
+ yp = atopLeft.y();
+ w = asize.width();
+ h = asize.height();
+}
+
+inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight)
+{
+ xp = atopLeft.x();
+ yp = atopLeft.y();
+ w = abottomRight.x() - xp;
+ h = abottomRight.y() - yp;
+}
+
+inline QRectF::QRectF(const QRect &r)
+ : xp(r.x()), yp(r.y()), w(r.width()), h(r.height())
+{
+}
+
+inline bool QRectF::isNull() const
+{ return w == 0. && h == 0.; }
+
+inline bool QRectF::isEmpty() const
+{ return w <= 0. || h <= 0.; }
+
+inline bool QRectF::isValid() const
+{ return w > 0. && h > 0.; }
+
+inline qreal QRectF::x() const
+{ return xp; }
+
+inline qreal QRectF::y() const
+{ return yp; }
+
+inline void QRectF::setLeft(qreal pos) { qreal diff = pos - xp; xp += diff; w -= diff; }
+
+inline void QRectF::setRight(qreal pos) { w = pos - xp; }
+
+inline void QRectF::setTop(qreal pos) { qreal diff = pos - yp; yp += diff; h -= diff; }
+
+inline void QRectF::setBottom(qreal pos) { h = pos - yp; }
+
+inline void QRectF::setTopLeft(const QPointF &p) { setLeft(p.x()); setTop(p.y()); }
+
+inline void QRectF::setTopRight(const QPointF &p) { setRight(p.x()); setTop(p.y()); }
+
+inline void QRectF::setBottomLeft(const QPointF &p) { setLeft(p.x()); setBottom(p.y()); }
+
+inline void QRectF::setBottomRight(const QPointF &p) { setRight(p.x()); setBottom(p.y()); }
+
+inline QPointF QRectF::center() const
+{ return QPointF(xp + w/2, yp + h/2); }
+
+inline void QRectF::moveLeft(qreal pos) { xp = pos; }
+
+inline void QRectF::moveTop(qreal pos) { yp = pos; }
+
+inline void QRectF::moveRight(qreal pos) { xp = pos - w; }
+
+inline void QRectF::moveBottom(qreal pos) { yp = pos - h; }
+
+inline void QRectF::moveTopLeft(const QPointF &p) { moveLeft(p.x()); moveTop(p.y()); }
+
+inline void QRectF::moveTopRight(const QPointF &p) { moveRight(p.x()); moveTop(p.y()); }
+
+inline void QRectF::moveBottomLeft(const QPointF &p) { moveLeft(p.x()); moveBottom(p.y()); }
+
+inline void QRectF::moveBottomRight(const QPointF &p) { moveRight(p.x()); moveBottom(p.y()); }
+
+inline void QRectF::moveCenter(const QPointF &p) { xp = p.x() - w/2; yp = p.y() - h/2; }
+
+inline qreal QRectF::width() const
+{ return w; }
+
+inline qreal QRectF::height() const
+{ return h; }
+
+inline QSizeF QRectF::size() const
+{ return QSizeF(w, h); }
+
+inline void QRectF::translate(qreal dx, qreal dy)
+{
+ xp += dx;
+ yp += dy;
+}
+
+inline void QRectF::translate(const QPointF &p)
+{
+ xp += p.x();
+ yp += p.y();
+}
+
+inline void QRectF::moveTo(qreal ax, qreal ay)
+{
+ xp = ax;
+ yp = ay;
+}
+
+inline void QRectF::moveTo(const QPointF &p)
+{
+ xp = p.x();
+ yp = p.y();
+}
+
+inline QRectF QRectF::translated(qreal dx, qreal dy) const
+{ return QRectF(xp + dx, yp + dy, w, h); }
+
+inline QRectF QRectF::translated(const QPointF &p) const
+{ return QRectF(xp + p.x(), yp + p.y(), w, h); }
+
+inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const
+{
+ *ax = this->xp;
+ *ay = this->yp;
+ *aaw = this->w;
+ *aah = this->h;
+}
+
+inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah)
+{
+ this->xp = ax;
+ this->yp = ay;
+ this->w = aaw;
+ this->h = aah;
+}
+
+inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const
+{
+ *xp1 = xp;
+ *yp1 = yp;
+ *xp2 = xp + w;
+ *yp2 = yp + h;
+}
+
+inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2)
+{
+ xp = xp1;
+ yp = yp1;
+ w = xp2 - xp1;
+ h = yp2 - yp1;
+}
+
+inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2)
+{ xp += xp1; yp += yp1; w += xp2 - xp1; h += yp2 - yp1; }
+
+inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const
+{ return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1); }
+
+inline void QRectF::setWidth(qreal aw)
+{ this->w = aw; }
+
+inline void QRectF::setHeight(qreal ah)
+{ this->h = ah; }
+
+inline void QRectF::setSize(const QSizeF &s)
+{
+ w = s.width();
+ h = s.height();
+}
+
+inline bool QRectF::contains(qreal ax, qreal ay) const
+{
+ return contains(QPointF(ax, ay));
+}
+
+inline QRectF& QRectF::operator|=(const QRectF &r)
+{
+ *this = *this | r;
+ return *this;
+}
+
+inline QRectF& QRectF::operator&=(const QRectF &r)
+{
+ *this = *this & r;
+ return *this;
+}
+
+inline QRectF QRectF::intersect(const QRectF &r) const
+{
+ return *this & r;
+}
+
+inline QRectF QRectF::intersected(const QRectF &r) const
+{
+ return intersect(r);
+}
+
+inline QRectF QRectF::unite(const QRectF &r) const
+{
+ return *this | r;
+}
+
+inline QRectF QRectF::united(const QRectF &r) const
+{
+ return unite(r);
+}
+
+inline bool operator==(const QRectF &r1, const QRectF &r2)
+{
+ return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp)
+ && qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h);
+}
+
+inline bool operator!=(const QRectF &r1, const QRectF &r2)
+{
+ return !qFuzzyCompare(r1.xp, r2.xp) || !qFuzzyCompare(r1.yp, r2.yp)
+ || !qFuzzyCompare(r1.w, r2.w) || !qFuzzyCompare(r1.h, r2.h);
+}
+
+inline QRect QRectF::toRect() const
+{
+ return QRect(qRound(xp), qRound(yp), qRound(w), qRound(h));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QRectF &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QRECT_H
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
new file mode 100644
index 0000000000..486a5dfeca
--- /dev/null
+++ b/src/corelib/tools/qregexp.cpp
@@ -0,0 +1,4503 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qregexp.h"
+
+#include "qalgorithms.h"
+#include "qbitarray.h"
+#include "qcache.h"
+#include "qdatastream.h"
+#include "qlist.h"
+#include "qmap.h"
+#include "qmutex.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qstringmatcher.h"
+#include "qvector.h"
+#include "private/qfunctions_p.h"
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+int qFindString(const QChar *haystack, int haystackLen, int from,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+
+// 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_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
+ \reentrant
+ \brief The QRegExp class provides pattern matching using regular expressions.
+
+ \ingroup tools
+ \ingroup shared
+
+ \keyword regular expression
+
+ A regular expression, or "regexp", is a pattern for matching
+ substrings in a text. This is useful in many contexts, e.g.,
+
+ \table
+ \row \i Validation
+ \i A regexp can test whether a substring meets some criteria,
+ e.g. is an integer or contains no whitespace.
+ \row \i Searching
+ \i 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 \i Search and Replace
+ \i 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 \i String Splitting
+ \i 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.
+
+ \tableofcontents
+
+ \section1 Introduction
+
+ Regexps are built up from expressions, quantifiers, and
+ assertions. The simplest expression is a character, e.g. \bold{x}
+ or \bold{5}. An expression can also be a set of characters
+ enclosed in square brackets. \bold{[ABCD]} will match an \bold{A}
+ or a \bold{B} or a \bold{C} or a \bold{D}. We can write this same
+ expression as \bold{[A-D]}, and an experession to match any
+ captital letter in the English alphabet is written as
+ \bold{[A-Z]}.
+
+ A quantifier specifies the number of occurrences of an expression
+ that must be matched. \bold{x{1,1}} means match one and only one
+ \bold{x}. \bold{x{1,5}} means match a sequence of \bold{x}
+ characters that contains at least one \bold{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
+ \bold{[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 \bold{[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, \bold{^} (caret) and \bold{$} (dollar). When
+ \bold{^} is the first character in a regexp, it means the regexp
+ must match from the beginning of the string. When \bold{$} is the
+ last character of the regexp, it means the regexp must match to
+ the end of the string. The regexp becomes \bold{^[0-9]{1,2}$}.
+ Note that assertions, e.g. \bold{^} and \bold{$}, 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. \bold{[0-9]} can be
+ replaced with the symbol \bold{\\d}. The quantifier to match
+ exactly one occurrence, \bold{{1,1}}, can be replaced with the
+ expression itself, i.e. \bold{x{1,1}} is the same as \bold{x}. So
+ our 0 to 99 matcher could be written as \bold{^\\d{1,2}$}. It can
+ also be written \bold{^\\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 \bold{^\\d\\d?$}. The \bold{?}
+ is shorthand for the quantifier \bold{{0,1}}, i.e. 0 or 1
+ occurrences. \bold{?} makes an expression optional. The regexp
+ \bold{^\\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 \bold{m{1,1}a{1,1}i{1,1}l{1,1}}, but because
+ a character expression is automatically quantified by
+ \bold{{1,1}}, we can simplify the regexp to \bold{mail}, i.e., an
+ 'm' followed by an 'a' followed by an 'i' followed by an 'l'. Now
+ we can use the vertical bar \bold{|}, which means \bold{or}, to
+ include the other two words, so our regexp for matching any of the
+ three words becomes \bold{mail|letter|correspondence}. Match
+ 'mail' \bold{or} 'letter' \bold{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, \bold{(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
+ \bold{\\b} \e{word boundary} assertions:
+ \bold{\\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 \bold{\\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
+ \bold{\&amp;}, the regexp to match is simply \bold{\&}. 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 \bold{amp;}. For this, we need the negative
+ lookahead assertion, \bold{(?!}__\bold{)}. The regexp can then be
+ written as \bold{\&(?!amp;)}, i.e. \e{Match an ampersand that is}
+ \bold{not} \e{followed by} \bold{amp;}.
+
+ If we want to count all the occurrences of 'Eric' and 'Eirik' in a
+ string, two valid solutions are \bold{\\b(Eric|Eirik)\\b} and
+ \bold{\\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
+ \link #code-examples code examples \endlink section.
+
+ \target characters-and-abbreviations-for-sets-of-characters
+ \section1 Characters and Abbreviations for Sets of Characters
+
+ \table
+ \header \i Element \i Meaning
+ \row \i \bold{c}
+ \i A character represents itself unless it has a special
+ regexp meaning. e.g. \bold{c} matches the character \e c.
+ \row \i \bold{\\c}
+ \i 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 \bold{\\^}.
+ \row \i \bold{\\a}
+ \i Matches the ASCII bell (BEL, 0x07).
+ \row \i \bold{\\f}
+ \i Matches the ASCII form feed (FF, 0x0C).
+ \row \i \bold{\\n}
+ \i Matches the ASCII line feed (LF, 0x0A, Unix newline).
+ \row \i \bold{\\r}
+ \i Matches the ASCII carriage return (CR, 0x0D).
+ \row \i \bold{\\t}
+ \i Matches the ASCII horizontal tab (HT, 0x09).
+ \row \i \bold{\\v}
+ \i Matches the ASCII vertical tab (VT, 0x0B).
+ \row \i \bold{\\x\e{hhhh}}
+ \i Matches the Unicode character corresponding to the
+ hexadecimal number \e{hhhh} (between 0x0000 and 0xFFFF).
+ \row \i \bold{\\0\e{ooo}} (i.e., \\zero \e{ooo})
+ \i matches the ASCII/Latin1 character for the octal number
+ \e{ooo} (between 0 and 0377).
+ \row \i \bold{. (dot)}
+ \i Matches any character (including newline).
+ \row \i \bold{\\d}
+ \i Matches a digit (QChar::isDigit()).
+ \row \i \bold{\\D}
+ \i Matches a non-digit.
+ \row \i \bold{\\s}
+ \i Matches a whitespace character (QChar::isSpace()).
+ \row \i \bold{\\S}
+ \i Matches a non-whitespace character.
+ \row \i \bold{\\w}
+ \i Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_').
+ \row \i \bold{\\W}
+ \i Matches a non-word character.
+ \row \i \bold{\\\e{n}}
+ \i The \e{n}-th \l backreference, e.g. \\1, \\2, etc.
+ \endtable
+
+ \bold{Note:} The C++ compiler transforms backslashes in strings.
+ To include a \bold{\\} 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 \i \bold{^}
+
+ \i The caret negates the character set if it occurs as the
+ first character (i.e. immediately after the opening square
+ bracket). \bold{[abc]} matches 'a' or 'b' or 'c', but
+ \bold{[^abc]} matches anything \e but 'a' or 'b' or 'c'.
+
+ \row \i \bold{-}
+
+ \i The dash indicates a range of characters. \bold{[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, \bold{[0-9]} matches a digit in Western alphabets but
+ \bold{\\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
+ \bold{{1,1}}, i.e. it should occur exactly once. In the following
+ list, \bold{\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 \i \bold{\e {E}?}
+
+ \i 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. \bold{\e
+ {E}?} is the same as \bold{\e {E}{0,1}}. e.g., \bold{dents?}
+ matches 'dent' or 'dents'.
+
+ \row \i \bold{\e {E}+}
+
+ \i Matches one or more occurrences of \e E. \bold{\e {E}+} is
+ the same as \bold{\e {E}{1,}}. e.g., \bold{0+} matches '0',
+ '00', '000', etc.
+
+ \row \i \bold{\e {E}*}
+
+ \i Matches zero or more occurrences of \e E. It is the same
+ as \bold{\e {E}{0,}}. The \bold{*} quantifier is often used
+ in error where \bold{+} should be used. For example, if
+ \bold{\\s*$} is used in an expression to match strings that
+ end in whitespace, it will match every string because
+ \bold{\\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
+ \bold{\\s+$}.
+
+ \row \i \bold{\e {E}{n}}
+
+ \i Matches exactly \e n occurrences of \e E. \bold{\e {E}{n}}
+ is the same as repeating \e E \e n times. For example,
+ \bold{x{5}} is the same as \bold{xxxxx}. It is also the same
+ as \bold{\e {E}{n,n}}, e.g. \bold{x{5,5}}.
+
+ \row \i \bold{\e {E}{n,}}
+ \i Matches at least \e n occurrences of \e E.
+
+ \row \i \bold{\e {E}{,m}}
+ \i Matches at most \e m occurrences of \e E. \bold{\e {E}{,m}}
+ is the same as \bold{\e {E}{0,m}}.
+
+ \row \i \bold{\e {E}{n,m}}
+ \i 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, \bold{tag+} matches a 't' followed by an 'a' followed by
+ at least one 'g', whereas \bold{(tag)+} matches at least one
+ occurrence of 'tag'.
+
+ Note: Quantifiers are normally "greedy". They always match as much
+ text as they can. For example, \bold{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
+ \bold{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 \bold{(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 \bold{\\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.
+ \bold{(?: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. \bold{*}) that apply to
+ capturing parentheses are more "greedy" than other quantifiers.
+ For example, \bold{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 doc/src/snippets/code/src_corelib_tools_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 \bold{\e {E}} stands for any expression.
+
+ \table
+ \row \i \bold{^}
+ \i 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, \bold{^#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 \link #sets-of-characters Sets of
+ Characters \endlink.)
+
+ \row \i \bold{$}
+ \i The dollar signifies the end of the string. For example
+ \bold{\\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 \i \bold{\\b}
+ \i A word boundary. For example the regexp
+ \bold{\\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 \bold{(\\bOK\\b)} and we have a match it will only
+ contain 'OK' even if the string is "It's \underline{OK} now".
+
+ \row \i \bold{\\B}
+ \i A non-word boundary. This assertion is true wherever
+ \bold{\\b} is false. For example if we searched for
+ \bold{\\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 \i \bold{(?=\e E)}
+ \i Positive lookahead. This assertion is true if the
+ expression matches at this point in the regexp. For example,
+ \bold{const(?=\\s+char)} matches 'const' whenever it is
+ followed by 'char', as in 'static \underline{const} char *'.
+ (Compare with \bold{const\\s+char}, which matches 'static
+ \underline{const char} *'.)
+
+ \row \i \bold{(?!\e E)}
+ \i Negative lookahead. This assertion is true if the
+ expression does not match at this point in the regexp. For
+ example, \bold{const(?!\\s+char)} matches 'const' \e except
+ when it is followed by 'char'.
+ \endtable
+
+ \keyword 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 \i \bold{c}
+ \i Any character represents itself apart from those mentioned
+ below. Thus \bold{c} matches the character \e c.
+ \row \i \bold{?}
+ \i Matches any single character. It is the same as
+ \bold{.} in full regexps.
+ \row \i \bold{*}
+ \i Matches zero or more of any characters. It is the
+ same as \bold{.*} in full regexps.
+ \row \i \bold{[...]}
+ \i 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 \bold{*.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 doc/src/snippets/code/src_corelib_tools_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 \link
+ #characters-and-abbreviations-for-sets-of-characters characters
+ and abbreviations for sets of characters \endlink.
+
+ 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 \bold{ro+?m} requires:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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 \bold{.} 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 doc/src/snippets/code/src_corelib_tools_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. \bold{\\b} must be written \bold{\\\\b}.
+
+ \target code-examples
+ \section1 Code Examples
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 4
+
+ The third string matches '\underline{6}'. This is a simple validation
+ regexp for integers in the range 0 to 99.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_qregexp.cpp 8
+
+ Here we've passed the QRegExp to QString's replace() function to
+ replace the matched text with new text.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_qregexp.cpp 12
+
+ Wildcard matching can be convenient because of its simplicity, but
+ any wildcard regexp can be defined using full regexps, e.g.
+ \bold{.*\.html$}. Notice that we can't match both \c .html and \c
+ .htm files with a wildcard unless we use \bold{*.htm*} which will
+ also match 'test.html.bak'. A full regexp gives us the precision
+ we need, \bold{.*\\.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
+ setWildcard(). Searching can be 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, QRegExpValidator, QSortFilterProxyModel,
+ {tools/regexp}{Regular Expression Example}
+*/
+
+#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(QVector<int> *a, const QVector<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;
+ QVector<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+1 == 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 (rx[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;
+ }
+};
+
+Q_STATIC_GLOBAL_OPERATOR bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2)
+{
+ return key1.pattern == key2.pattern && key1.patternSyntax == key2.patternSyntax
+ && key1.cs == key2.cs;
+}
+
+class QRegExpEngine;
+
+//Q_DECLARE_TYPEINFO(QVector<int>, Q_MOVABLE_TYPE);
+
+/*
+ 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<QVector<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(0), captured(0) {}
+ inline ~QRegExpMatchState() { free(bigArray); }
+
+ void drain() { free(bigArray); bigArray = 0; captured = 0; } // 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)
+ QVector<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
+/*
+ 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();
+ inline QRegExpCharClass(const QRegExpCharClass &cc) { operator=(cc); }
+
+ QRegExpCharClass &operator=(const QRegExpCharClass &cc);
+
+ void clear();
+ bool negative() const { return n; }
+ void setNegative(bool negative);
+ void addCategories(int 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 QVector<int> &firstOccurrence() const { return occ1; }
+#endif
+
+#if defined(QT_DEBUG)
+ void dump() const;
+#endif
+
+private:
+ int c; // character classes
+ QVector<QRegExpCharClassRange> r; // character ranges
+ bool n; // negative?
+#ifndef QT_NO_REGEXP_OPTIM
+ QVector<int> occ1; // first-occurrence array
+#endif
+};
+#else
+struct QRegExpCharClass
+{
+ int dummy;
+
+#ifndef QT_NO_REGEXP_OPTIM
+ QRegExpCharClass() { occ1.fill(0, NumBadChars); }
+
+ const QVector<int> &firstOccurrence() const { return occ1; }
+ QVector<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 QVector<int> &from, const QVector<int> &to);
+#ifndef QT_NO_REGEXP_CAPTURE
+ void addPlusTransitions(const QVector<int> &from, const QVector<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
+
+ QVector<QRegExpAutomatonState> s; // array of states
+#ifndef QT_NO_REGEXP_CAPTURE
+ QVector<QRegExpAtom> f; // atom hierarchy
+ int nf; // number of atoms
+ int cf; // current atom
+ QVector<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
+ QVector<QRegExpCharClass> cl; // array of character classes
+#endif
+#ifndef QT_NO_REGEXP_LOOKAHEAD
+ QVector<QRegExpLookahead *> ahead; // array of lookaheads
+#endif
+#ifndef QT_NO_REGEXP_ANCHOR_ALT
+ QVector<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
+ QVector<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
+ QVector<int> ls; // the left states (firstpos)
+ QVector<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
+ QVector<int> occ1; // first-occurrence array
+#endif
+ };
+
+ friend class Box;
+
+ void setupCategoriesRangeMap();
+
+ /*
+ 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
+ QHash<QByteArray, QPair<int, int> > categoriesRangeMap; // fast lookup hash for xml schema extensions
+
+ 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);
+ break;
+ case QRegExp::WildcardUnix:
+ return wc2rx(pattern, true);
+ break;
+#endif
+ case QRegExp::FixedString:
+ return QRegExp::escape(pattern);
+ break;
+ 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 QVector<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) {
+ pos = qFindString(str0, len0, pos0, eng->goodStr.unicode(), eng->goodStr.length(), eng->cs);
+ matchLen = eng->goodStr.length();
+ matched = (pos != -1);
+ } else
+#endif
+ {
+ in = str0;
+ if (in == 0)
+ 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 QVector<int> &from, const QVector<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 QVector<int> &from, const QVector<int> &to, int atom)
+{
+ for (int i = 0; i < from.size(); i++) {
+ QRegExpAutomatonState &st = s[from.at(i)];
+ const QVector<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)) &&
+ qBinaryFind(oldOuts.constBegin(), oldOuts.constEnd(), to.at(j)) == oldOuts.end())
+ 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 = 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 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 QVector<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, matchState.caretPos - matchState.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 QVector<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(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) {
+ QVector<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 QVector<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
+}
+
+QRegExpCharClass &QRegExpCharClass::operator=(const QRegExpCharClass &cc)
+{
+ c = cc.c;
+ r = cc.r;
+ n = cc.n;
+#ifndef QT_NO_REGEXP_OPTIM
+ occ1 = cc.occ1;
+#endif
+ return *this;
+}
+
+void QRegExpCharClass::clear()
+{
+ c = 0;
+ r.resize(0);
+ n = false;
+}
+
+void QRegExpCharClass::setNegative(bool negative)
+{
+ n = negative;
+#ifndef QT_NO_REGEXP_OPTIM
+ occ1.fill(0, NumBadChars);
+#endif
+}
+
+void QRegExpCharClass::addCategories(int cats)
+{
+ c |= 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 & (1 << (int)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.unite(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.unite(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.unite(b.lanchors);
+ mergeInto(&rs, b.rs);
+ ranchors.unite(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);
+ }
+ }
+}
+
+void QRegExpEngine::setupCategoriesRangeMap()
+{
+ categoriesRangeMap.insert("IsBasicLatin", qMakePair(0x0000, 0x007F));
+ categoriesRangeMap.insert("IsLatin-1Supplement", qMakePair(0x0080, 0x00FF));
+ categoriesRangeMap.insert("IsLatinExtended-A", qMakePair(0x0100, 0x017F));
+ categoriesRangeMap.insert("IsLatinExtended-B", qMakePair(0x0180, 0x024F));
+ categoriesRangeMap.insert("IsIPAExtensions", qMakePair(0x0250, 0x02AF));
+ categoriesRangeMap.insert("IsSpacingModifierLetters", qMakePair(0x02B0, 0x02FF));
+ categoriesRangeMap.insert("IsCombiningDiacriticalMarks", qMakePair(0x0300, 0x036F));
+ categoriesRangeMap.insert("IsGreek", qMakePair(0x0370, 0x03FF));
+ categoriesRangeMap.insert("IsCyrillic", qMakePair(0x0400, 0x04FF));
+ categoriesRangeMap.insert("IsCyrillicSupplement", qMakePair(0x0500, 0x052F));
+ categoriesRangeMap.insert("IsArmenian", qMakePair(0x0530, 0x058F));
+ categoriesRangeMap.insert("IsHebrew", qMakePair(0x0590, 0x05FF));
+ categoriesRangeMap.insert("IsArabic", qMakePair(0x0600, 0x06FF));
+ categoriesRangeMap.insert("IsSyriac", qMakePair(0x0700, 0x074F));
+ categoriesRangeMap.insert("IsArabicSupplement", qMakePair(0x0750, 0x077F));
+ categoriesRangeMap.insert("IsThaana", qMakePair(0x0780, 0x07BF));
+ categoriesRangeMap.insert("IsDevanagari", qMakePair(0x0900, 0x097F));
+ categoriesRangeMap.insert("IsBengali", qMakePair(0x0980, 0x09FF));
+ categoriesRangeMap.insert("IsGurmukhi", qMakePair(0x0A00, 0x0A7F));
+ categoriesRangeMap.insert("IsGujarati", qMakePair(0x0A80, 0x0AFF));
+ categoriesRangeMap.insert("IsOriya", qMakePair(0x0B00, 0x0B7F));
+ categoriesRangeMap.insert("IsTamil", qMakePair(0x0B80, 0x0BFF));
+ categoriesRangeMap.insert("IsTelugu", qMakePair(0x0C00, 0x0C7F));
+ categoriesRangeMap.insert("IsKannada", qMakePair(0x0C80, 0x0CFF));
+ categoriesRangeMap.insert("IsMalayalam", qMakePair(0x0D00, 0x0D7F));
+ categoriesRangeMap.insert("IsSinhala", qMakePair(0x0D80, 0x0DFF));
+ categoriesRangeMap.insert("IsThai", qMakePair(0x0E00, 0x0E7F));
+ categoriesRangeMap.insert("IsLao", qMakePair(0x0E80, 0x0EFF));
+ categoriesRangeMap.insert("IsTibetan", qMakePair(0x0F00, 0x0FFF));
+ categoriesRangeMap.insert("IsMyanmar", qMakePair(0x1000, 0x109F));
+ categoriesRangeMap.insert("IsGeorgian", qMakePair(0x10A0, 0x10FF));
+ categoriesRangeMap.insert("IsHangulJamo", qMakePair(0x1100, 0x11FF));
+ categoriesRangeMap.insert("IsEthiopic", qMakePair(0x1200, 0x137F));
+ categoriesRangeMap.insert("IsEthiopicSupplement", qMakePair(0x1380, 0x139F));
+ categoriesRangeMap.insert("IsCherokee", qMakePair(0x13A0, 0x13FF));
+ categoriesRangeMap.insert("IsUnifiedCanadianAboriginalSyllabics", qMakePair(0x1400, 0x167F));
+ categoriesRangeMap.insert("IsOgham", qMakePair(0x1680, 0x169F));
+ categoriesRangeMap.insert("IsRunic", qMakePair(0x16A0, 0x16FF));
+ categoriesRangeMap.insert("IsTagalog", qMakePair(0x1700, 0x171F));
+ categoriesRangeMap.insert("IsHanunoo", qMakePair(0x1720, 0x173F));
+ categoriesRangeMap.insert("IsBuhid", qMakePair(0x1740, 0x175F));
+ categoriesRangeMap.insert("IsTagbanwa", qMakePair(0x1760, 0x177F));
+ categoriesRangeMap.insert("IsKhmer", qMakePair(0x1780, 0x17FF));
+ categoriesRangeMap.insert("IsMongolian", qMakePair(0x1800, 0x18AF));
+ categoriesRangeMap.insert("IsLimbu", qMakePair(0x1900, 0x194F));
+ categoriesRangeMap.insert("IsTaiLe", qMakePair(0x1950, 0x197F));
+ categoriesRangeMap.insert("IsNewTaiLue", qMakePair(0x1980, 0x19DF));
+ categoriesRangeMap.insert("IsKhmerSymbols", qMakePair(0x19E0, 0x19FF));
+ categoriesRangeMap.insert("IsBuginese", qMakePair(0x1A00, 0x1A1F));
+ categoriesRangeMap.insert("IsPhoneticExtensions", qMakePair(0x1D00, 0x1D7F));
+ categoriesRangeMap.insert("IsPhoneticExtensionsSupplement", qMakePair(0x1D80, 0x1DBF));
+ categoriesRangeMap.insert("IsCombiningDiacriticalMarksSupplement", qMakePair(0x1DC0, 0x1DFF));
+ categoriesRangeMap.insert("IsLatinExtendedAdditional", qMakePair(0x1E00, 0x1EFF));
+ categoriesRangeMap.insert("IsGreekExtended", qMakePair(0x1F00, 0x1FFF));
+ categoriesRangeMap.insert("IsGeneralPunctuation", qMakePair(0x2000, 0x206F));
+ categoriesRangeMap.insert("IsSuperscriptsandSubscripts", qMakePair(0x2070, 0x209F));
+ categoriesRangeMap.insert("IsCurrencySymbols", qMakePair(0x20A0, 0x20CF));
+ categoriesRangeMap.insert("IsCombiningMarksforSymbols", qMakePair(0x20D0, 0x20FF));
+ categoriesRangeMap.insert("IsLetterlikeSymbols", qMakePair(0x2100, 0x214F));
+ categoriesRangeMap.insert("IsNumberForms", qMakePair(0x2150, 0x218F));
+ categoriesRangeMap.insert("IsArrows", qMakePair(0x2190, 0x21FF));
+ categoriesRangeMap.insert("IsMathematicalOperators", qMakePair(0x2200, 0x22FF));
+ categoriesRangeMap.insert("IsMiscellaneousTechnical", qMakePair(0x2300, 0x23FF));
+ categoriesRangeMap.insert("IsControlPictures", qMakePair(0x2400, 0x243F));
+ categoriesRangeMap.insert("IsOpticalCharacterRecognition", qMakePair(0x2440, 0x245F));
+ categoriesRangeMap.insert("IsEnclosedAlphanumerics", qMakePair(0x2460, 0x24FF));
+ categoriesRangeMap.insert("IsBoxDrawing", qMakePair(0x2500, 0x257F));
+ categoriesRangeMap.insert("IsBlockElements", qMakePair(0x2580, 0x259F));
+ categoriesRangeMap.insert("IsGeometricShapes", qMakePair(0x25A0, 0x25FF));
+ categoriesRangeMap.insert("IsMiscellaneousSymbols", qMakePair(0x2600, 0x26FF));
+ categoriesRangeMap.insert("IsDingbats", qMakePair(0x2700, 0x27BF));
+ categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-A", qMakePair(0x27C0, 0x27EF));
+ categoriesRangeMap.insert("IsSupplementalArrows-A", qMakePair(0x27F0, 0x27FF));
+ categoriesRangeMap.insert("IsBraillePatterns", qMakePair(0x2800, 0x28FF));
+ categoriesRangeMap.insert("IsSupplementalArrows-B", qMakePair(0x2900, 0x297F));
+ categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-B", qMakePair(0x2980, 0x29FF));
+ categoriesRangeMap.insert("IsSupplementalMathematicalOperators", qMakePair(0x2A00, 0x2AFF));
+ categoriesRangeMap.insert("IsMiscellaneousSymbolsandArrows", qMakePair(0x2B00, 0x2BFF));
+ categoriesRangeMap.insert("IsGlagolitic", qMakePair(0x2C00, 0x2C5F));
+ categoriesRangeMap.insert("IsCoptic", qMakePair(0x2C80, 0x2CFF));
+ categoriesRangeMap.insert("IsGeorgianSupplement", qMakePair(0x2D00, 0x2D2F));
+ categoriesRangeMap.insert("IsTifinagh", qMakePair(0x2D30, 0x2D7F));
+ categoriesRangeMap.insert("IsEthiopicExtended", qMakePair(0x2D80, 0x2DDF));
+ categoriesRangeMap.insert("IsSupplementalPunctuation", qMakePair(0x2E00, 0x2E7F));
+ categoriesRangeMap.insert("IsCJKRadicalsSupplement", qMakePair(0x2E80, 0x2EFF));
+ categoriesRangeMap.insert("IsKangxiRadicals", qMakePair(0x2F00, 0x2FDF));
+ categoriesRangeMap.insert("IsIdeographicDescriptionCharacters", qMakePair(0x2FF0, 0x2FFF));
+ categoriesRangeMap.insert("IsCJKSymbolsandPunctuation", qMakePair(0x3000, 0x303F));
+ categoriesRangeMap.insert("IsHiragana", qMakePair(0x3040, 0x309F));
+ categoriesRangeMap.insert("IsKatakana", qMakePair(0x30A0, 0x30FF));
+ categoriesRangeMap.insert("IsBopomofo", qMakePair(0x3100, 0x312F));
+ categoriesRangeMap.insert("IsHangulCompatibilityJamo", qMakePair(0x3130, 0x318F));
+ categoriesRangeMap.insert("IsKanbun", qMakePair(0x3190, 0x319F));
+ categoriesRangeMap.insert("IsBopomofoExtended", qMakePair(0x31A0, 0x31BF));
+ categoriesRangeMap.insert("IsCJKStrokes", qMakePair(0x31C0, 0x31EF));
+ categoriesRangeMap.insert("IsKatakanaPhoneticExtensions", qMakePair(0x31F0, 0x31FF));
+ categoriesRangeMap.insert("IsEnclosedCJKLettersandMonths", qMakePair(0x3200, 0x32FF));
+ categoriesRangeMap.insert("IsCJKCompatibility", qMakePair(0x3300, 0x33FF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionA", qMakePair(0x3400, 0x4DB5));
+ categoriesRangeMap.insert("IsYijingHexagramSymbols", qMakePair(0x4DC0, 0x4DFF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographs", qMakePair(0x4E00, 0x9FFF));
+ categoriesRangeMap.insert("IsYiSyllables", qMakePair(0xA000, 0xA48F));
+ categoriesRangeMap.insert("IsYiRadicals", qMakePair(0xA490, 0xA4CF));
+ categoriesRangeMap.insert("IsModifierToneLetters", qMakePair(0xA700, 0xA71F));
+ categoriesRangeMap.insert("IsSylotiNagri", qMakePair(0xA800, 0xA82F));
+ categoriesRangeMap.insert("IsHangulSyllables", qMakePair(0xAC00, 0xD7A3));
+ categoriesRangeMap.insert("IsPrivateUse", qMakePair(0xE000, 0xF8FF));
+ categoriesRangeMap.insert("IsCJKCompatibilityIdeographs", qMakePair(0xF900, 0xFAFF));
+ categoriesRangeMap.insert("IsAlphabeticPresentationForms", qMakePair(0xFB00, 0xFB4F));
+ categoriesRangeMap.insert("IsArabicPresentationForms-A", qMakePair(0xFB50, 0xFDFF));
+ categoriesRangeMap.insert("IsVariationSelectors", qMakePair(0xFE00, 0xFE0F));
+ categoriesRangeMap.insert("IsVerticalForms", qMakePair(0xFE10, 0xFE1F));
+ categoriesRangeMap.insert("IsCombiningHalfMarks", qMakePair(0xFE20, 0xFE2F));
+ categoriesRangeMap.insert("IsCJKCompatibilityForms", qMakePair(0xFE30, 0xFE4F));
+ categoriesRangeMap.insert("IsSmallFormVariants", qMakePair(0xFE50, 0xFE6F));
+ categoriesRangeMap.insert("IsArabicPresentationForms-B", qMakePair(0xFE70, 0xFEFF));
+ categoriesRangeMap.insert("IsHalfwidthandFullwidthForms", qMakePair(0xFF00, 0xFFEF));
+ categoriesRangeMap.insert("IsSpecials", qMakePair(0xFFF0, 0xFFFF));
+ categoriesRangeMap.insert("IsLinearBSyllabary", qMakePair(0x10000, 0x1007F));
+ categoriesRangeMap.insert("IsLinearBIdeograms", qMakePair(0x10080, 0x100FF));
+ categoriesRangeMap.insert("IsAegeanNumbers", qMakePair(0x10100, 0x1013F));
+ categoriesRangeMap.insert("IsAncientGreekNumbers", qMakePair(0x10140, 0x1018F));
+ categoriesRangeMap.insert("IsOldItalic", qMakePair(0x10300, 0x1032F));
+ categoriesRangeMap.insert("IsGothic", qMakePair(0x10330, 0x1034F));
+ categoriesRangeMap.insert("IsUgaritic", qMakePair(0x10380, 0x1039F));
+ categoriesRangeMap.insert("IsOldPersian", qMakePair(0x103A0, 0x103DF));
+ categoriesRangeMap.insert("IsDeseret", qMakePair(0x10400, 0x1044F));
+ categoriesRangeMap.insert("IsShavian", qMakePair(0x10450, 0x1047F));
+ categoriesRangeMap.insert("IsOsmanya", qMakePair(0x10480, 0x104AF));
+ categoriesRangeMap.insert("IsCypriotSyllabary", qMakePair(0x10800, 0x1083F));
+ categoriesRangeMap.insert("IsKharoshthi", qMakePair(0x10A00, 0x10A5F));
+ categoriesRangeMap.insert("IsByzantineMusicalSymbols", qMakePair(0x1D000, 0x1D0FF));
+ categoriesRangeMap.insert("IsMusicalSymbols", qMakePair(0x1D100, 0x1D1FF));
+ categoriesRangeMap.insert("IsAncientGreekMusicalNotation", qMakePair(0x1D200, 0x1D24F));
+ categoriesRangeMap.insert("IsTaiXuanJingSymbols", qMakePair(0x1D300, 0x1D35F));
+ categoriesRangeMap.insert("IsMathematicalAlphanumericSymbols", qMakePair(0x1D400, 0x1D7FF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionB", qMakePair(0x20000, 0x2A6DF));
+ categoriesRangeMap.insert("IsCJKCompatibilityIdeographsSupplement", qMakePair(0x2F800, 0x2FA1F));
+ categoriesRangeMap.insert("IsTags", qMakePair(0xE0000, 0xE007F));
+ categoriesRangeMap.insert("IsVariationSelectorsSupplement", qMakePair(0xE0100, 0xE01EF));
+ categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-A", qMakePair(0xF0000, 0xFFFFF));
+ categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-B", qMakePair(0x100000, 0x10FFFF));
+}
+
+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 != 0)
+ 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(0x7fffffef);
+ return Tok_CharClass;
+ case 'S':
+ // see QChar::isSpace()
+ yyCharClass->addCategories(0x7ffff87f);
+ yyCharClass->addRange(0x0000, 0x0008);
+ yyCharClass->addRange(0x000e, 0x001f);
+ yyCharClass->addRange(0x007f, 0x009f);
+ return Tok_CharClass;
+ case 'W':
+ // see QChar::isLetterOrNumber() and QChar::isMark()
+ yyCharClass->addCategories(0x7fe07f81);
+ 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(0x00000010);
+ return Tok_CharClass;
+ case 's':
+ // see QChar::isSpace()
+ yyCharClass->addCategories(0x00000380);
+ yyCharClass->addRange(0x0009, 0x000d);
+ return Tok_CharClass;
+ case 'w':
+ // see QChar::isLetterOrNumber() and QChar::isMark()
+ yyCharClass->addCategories(0x000f807e);
+ yyCharClass->addSingleton(0x005f); // '_'
+ return Tok_CharClass;
+ case 'I':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ case 'i':
+ if (xmlSchemaExtensions) {
+ yyCharClass->addCategories(0x000f807e);
+ 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;
+ case 'C':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ case 'c':
+ if (xmlSchemaExtensions) {
+ yyCharClass->addCategories(0x000f807e);
+ 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;
+ case 'P':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ 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 '}'
+
+ if (category == "M") {
+ yyCharClass->addCategories(0x0000000e);
+ } else if (category == "Mn") {
+ yyCharClass->addCategories(0x00000002);
+ } else if (category == "Mc") {
+ yyCharClass->addCategories(0x00000004);
+ } else if (category == "Me") {
+ yyCharClass->addCategories(0x00000008);
+ } else if (category == "N") {
+ yyCharClass->addCategories(0x00000070);
+ } else if (category == "Nd") {
+ yyCharClass->addCategories(0x00000010);
+ } else if (category == "Nl") {
+ yyCharClass->addCategories(0x00000020);
+ } else if (category == "No") {
+ yyCharClass->addCategories(0x00000040);
+ } else if (category == "Z") {
+ yyCharClass->addCategories(0x00000380);
+ } else if (category == "Zs") {
+ yyCharClass->addCategories(0x00000080);
+ } else if (category == "Zl") {
+ yyCharClass->addCategories(0x00000100);
+ } else if (category == "Zp") {
+ yyCharClass->addCategories(0x00000200);
+ } else if (category == "C") {
+ yyCharClass->addCategories(0x00006c00);
+ } else if (category == "Cc") {
+ yyCharClass->addCategories(0x00000400);
+ } else if (category == "Cf") {
+ yyCharClass->addCategories(0x00000800);
+ } else if (category == "Cs") {
+ yyCharClass->addCategories(0x00001000);
+ } else if (category == "Co") {
+ yyCharClass->addCategories(0x00002000);
+ } else if (category == "Cn") {
+ yyCharClass->addCategories(0x00004000);
+ } else if (category == "L") {
+ yyCharClass->addCategories(0x000f8000);
+ } else if (category == "Lu") {
+ yyCharClass->addCategories(0x00008000);
+ } else if (category == "Ll") {
+ yyCharClass->addCategories(0x00010000);
+ } else if (category == "Lt") {
+ yyCharClass->addCategories(0x00020000);
+ } else if (category == "Lm") {
+ yyCharClass->addCategories(0x00040000);
+ } else if (category == "Lo") {
+ yyCharClass->addCategories(0x00080000);
+ } else if (category == "P") {
+ yyCharClass->addCategories(0x4f580780);
+ } else if (category == "Pc") {
+ yyCharClass->addCategories(0x00100000);
+ } else if (category == "Pd") {
+ yyCharClass->addCategories(0x00200000);
+ } else if (category == "Ps") {
+ yyCharClass->addCategories(0x00400000);
+ } else if (category == "Pe") {
+ yyCharClass->addCategories(0x00800000);
+ } else if (category == "Pi") {
+ yyCharClass->addCategories(0x01000000);
+ } else if (category == "Pf") {
+ yyCharClass->addCategories(0x02000000);
+ } else if (category == "Po") {
+ yyCharClass->addCategories(0x04000000);
+ } else if (category == "S") {
+ yyCharClass->addCategories(0x78000000);
+ } else if (category == "Sm") {
+ yyCharClass->addCategories(0x08000000);
+ } else if (category == "Sc") {
+ yyCharClass->addCategories(0x10000000);
+ } else if (category == "Sk") {
+ yyCharClass->addCategories(0x20000000);
+ } else if (category == "So") {
+ yyCharClass->addCategories(0x40000000);
+ } else if (category.startsWith("Is")) {
+ if (categoriesRangeMap.isEmpty())
+ setupCategoriesRangeMap();
+
+ if (categoriesRangeMap.contains(category)) {
+ const QPair<int, int> range = categoriesRangeMap.value(category);
+ yyCharClass->addRange(range.first, range.second);
+ } else {
+ error(RXERR_CATEGORY);
+ }
+ } else {
+ error(RXERR_CATEGORY);
+ }
+ }
+ return Tok_CharClass;
+#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:
+ 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;
+ 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(0);
+
+#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 = 0;
+ 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(0), engineKey(QString(), QRegExp::RegExp, Qt::CaseSensitive), minimal(false) { }
+ inline QRegExpPrivate(const QRegExpEngineKey &key)
+ : eng(0), engineKey(key), minimal(false) {}
+};
+
+#if !defined(QT_NO_REGEXP_OPTIM)
+uint qHash(const QRegExpEngineKey &key)
+{
+ return qHash(key.pattern);
+}
+
+typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache;
+Q_GLOBAL_STATIC(EngineCache, globalEngineCache)
+Q_GLOBAL_STATIC(QMutex, mutex)
+#endif // QT_NO_REGEXP_OPTIM
+
+static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key)
+{
+ if (!eng->ref.deref()) {
+#if !defined(QT_NO_REGEXP_OPTIM)
+ if (globalEngineCache()) {
+ QMutexLocker locker(mutex());
+ QT_TRY {
+ globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
+ } QT_CATCH(const std::bad_alloc &) {
+ // in case of an exception (e.g. oom), just delete the engine
+ delete eng;
+ }
+ } else {
+ delete eng;
+ }
+#else
+ Q_UNUSED(key);
+ delete eng;
+#endif
+ }
+}
+
+static void prepareEngine_helper(QRegExpPrivate *priv)
+{
+ bool initMatchState = !priv->eng;
+#if !defined(QT_NO_REGEXP_OPTIM)
+ if (!priv->eng && globalEngineCache()) {
+ QMutexLocker locker(mutex());
+ priv->eng = globalEngineCache()->take(priv->engineKey);
+ if (priv->eng != 0)
+ priv->eng->ref.ref();
+ }
+#endif // QT_NO_REGEXP_OPTIM
+
+ if (!priv->eng)
+ priv->eng = new QRegExpEngine(priv->engineKey);
+
+ if (initMatchState)
+ priv->matchState.prepareForMatch(priv->eng);
+}
+
+inline static void prepareEngine(QRegExpPrivate *priv)
+{
+ if (priv->eng)
+ return;
+ prepareEngine_helper(priv);
+}
+
+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 != 0) {
+ derefEngine(priv->eng, priv->engineKey);
+ priv->eng = 0;
+ priv->matchState.drain();
+ }
+}
+
+/*!
+ \enum QRegExp::CaretMode
+
+ The CaretMode enum defines the different meanings of the caret
+ (\bold{^}) 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}. This
+ will be the default in Qt 5. (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{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;
+}
+
+/*!
+ 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));
+}
+
+/*!
+ 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 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 true if this regular expression is equal to \a rx;
+ otherwise returns 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;
+}
+
+/*!
+ \fn bool QRegExp::operator!=(const QRegExp &rx) const
+
+ Returns true if this regular expression is not equal to \a rx;
+ otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns 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 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 true if the regular expression is valid; otherwise returns
+ false. An invalid regular expression never matches.
+
+ The pattern \bold{[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 \bold{*.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, \bold{\\.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{wildcard matching}. For example, \bold{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 true if minimal (non-greedy) matching is enabled;
+ otherwise returns 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
+ \bold{<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
+ \bold{<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 true if \a str is matched exactly by this regular
+ expression; otherwise returns 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 \bold{blue}, then
+ exactMatch() returns true only for input \c blue. For inputs \c
+ bluebell, \c blutak and \c lightblue, exactMatch() returns 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;
+ }
+}
+
+// ### 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 \bold{^}
+ 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 doc/src/snippets/code/src_corelib_tools_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 \bold{^}
+ 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];
+}
+
+#ifndef QT_NO_REGEXP_CAPTURE
+
+#ifndef QT_NO_DEPRECATED
+/*!
+ \obsolete
+ Returns the number of captures contained in the regular expression.
+
+ \sa captureCount()
+ */
+int QRegExp::numCaptures() const
+{
+ return captureCount();
+}
+#endif
+
+/*!
+ \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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_qregexp.cpp 15
+
+ Note that if you want to iterate over the list, you should iterate
+ over a copy, e.g.
+ \snippet doc/src/snippets/code/src_corelib_tools_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 \bold{(\\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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_qregexp.cpp 19
+
+ This function is useful to construct regexp patterns dynamically:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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;
+}
+
+/*!
+ \fn bool QRegExp::caseSensitive() const
+
+ Use \l caseSensitivity() instead.
+*/
+
+/*!
+ \fn void QRegExp::setCaseSensitive(bool sensitive)
+
+ Use \l setCaseSensitivity() instead.
+*/
+
+/*!
+ \fn bool QRegExp::wildcard() const
+
+ Use \l patternSyntax() instead.
+
+ \oldcode
+ bool wc = rx.wildcard();
+ \newcode
+ bool wc = (rx.patternSyntax() == QRegExp::Wildcard);
+ \endcode
+*/
+
+/*!
+ \fn void QRegExp::setWildcard(bool wildcard)
+
+ Use \l setPatternSyntax() instead.
+
+ \oldcode
+ rx.setWildcard(wc);
+ \newcode
+ rx.setPatternSyntax(wc ? QRegExp::Wildcard : QRegExp::RegExp);
+ \endcode
+*/
+
+/*!
+ \fn bool QRegExp::minimal() const
+
+ Use \l isMinimal() instead.
+*/
+
+/*!
+ \fn int QRegExp::search(const QString &str, int from = 0,
+ CaretMode caretMode = CaretAtZero) const
+
+ Use \l indexIn() instead.
+*/
+
+/*!
+ \fn int QRegExp::searchRev(const QString &str, int from = -1, \
+ CaretMode caretMode = CaretAtZero) const
+
+ Use \l lastIndexIn() instead.
+*/
+
+/*!
+ \fn QRegExp::QRegExp(const QString &pattern, bool cs, bool wildcard = false)
+
+ Use another constructor instead.
+
+ \oldcode
+ QRegExp rx("*.txt", false, true);
+ \newcode
+ QRegExp rx("*.txt", Qt::CaseInsensitive, QRegExp::Wildcard);
+ \endcode
+*/
+
+#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
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h
new file mode 100644
index 0000000000..98d82f99a8
--- /dev/null
+++ b/src/corelib/tools/qregexp.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREGEXP_H
+#define QREGEXP_H
+
+#ifndef QT_NO_REGEXP
+
+#include <QtCore/qstring.h>
+#ifdef QT3_SUPPORT
+#include <new>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct QRegExpPrivate;
+class QStringList;
+
+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);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QRegExp &operator=(QRegExp &&other)
+ { qSwap(priv,other.priv); return *this; }
+#endif
+ inline void swap(QRegExp &other) { 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);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool caseSensitive() const { return caseSensitivity() == Qt::CaseSensitive; }
+ inline QT3_SUPPORT void setCaseSensitive(bool sensitive)
+ { setCaseSensitivity(sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); }
+#endif
+ PatternSyntax patternSyntax() const;
+ void setPatternSyntax(PatternSyntax syntax);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool wildcard() const { return patternSyntax() == Wildcard; }
+ inline QT3_SUPPORT void setWildcard(bool aWildcard)
+ { setPatternSyntax(aWildcard ? Wildcard : RegExp); }
+#endif
+
+ bool isMinimal() const;
+ void setMinimal(bool minimal);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool minimal() const { return isMinimal(); }
+#endif
+
+ bool exactMatch(const QString &str) 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;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT int search(const QString &str, int from = 0,
+ CaretMode caretMode = CaretAtZero) const
+ { return indexIn(str, from, caretMode); }
+ inline QT3_SUPPORT int searchRev(const QString &str, int from = -1,
+ CaretMode caretMode = CaretAtZero) const
+ { return lastIndexIn(str, from, caretMode); }
+#endif
+ int matchedLength() const;
+#ifndef QT_NO_REGEXP_CAPTURE
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED int numCaptures() const;
+#endif
+ 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
+
+ static QString escape(const QString &str);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QRegExp(const QString &aPattern, bool cs, bool aWildcard = false)
+ {
+ new (this)
+ QRegExp(aPattern, cs ? Qt::CaseSensitive : Qt::CaseInsensitive,
+ aWildcard ? Wildcard : RegExp);
+ }
+#endif
+
+private:
+ QRegExpPrivate *priv;
+};
+
+Q_DECLARE_TYPEINFO(QRegExp, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegExp &regExp);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegExp &regExp);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_REGEXP
+
+#endif // QREGEXP_H
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
new file mode 100644
index 0000000000..53bbd58883
--- /dev/null
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRINGBUFFER_P_H
+#define QRINGBUFFER_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/qbytearray.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRingBuffer
+{
+public:
+ inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
+ buffers << QByteArray();
+ clear();
+ }
+
+ inline int nextDataBlockSize() const {
+ return (tailBuffer == 0 ? tail : buffers.first().size()) - head;
+ }
+
+ inline const char *readPointer() const {
+ return buffers.isEmpty() ? 0 : (buffers.first().constData() + head);
+ }
+
+ // access the bytes at a specified position
+ // the out-variable length will contain the amount of bytes readable
+ // from there, e.g. the amount still the same QByteArray
+ inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
+ if (buffers.isEmpty()) {
+ length = 0;
+ return 0;
+ }
+
+ if (pos >= bufferSize) {
+ length = 0;
+ return 0;
+ }
+
+ // special case: it is in the first buffer
+ int nextDataBlockSizeValue = nextDataBlockSize();
+ if (pos - head < nextDataBlockSizeValue) {
+ length = nextDataBlockSizeValue - pos;
+ return buffers.at(0).constData() + head + pos;
+ }
+
+ // special case: we only had one buffer and tried to read over it
+ if (buffers.length() == 1) {
+ length = 0;
+ return 0;
+ }
+
+ // skip the first
+ pos -= nextDataBlockSizeValue;
+
+ // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
+ for (int i = 1; i < tailBuffer; i++) {
+ if (pos >= buffers[i].size()) {
+ pos -= buffers[i].size();
+ continue;
+ }
+
+ length = buffers[i].length() - pos;
+ return buffers[i].constData() + pos;
+ }
+
+ // it is in the tail buffer
+ length = tail - pos;
+ return buffers[tailBuffer].constData() + pos;
+ }
+
+ inline void free(int bytes) {
+ bufferSize -= bytes;
+ if (bufferSize < 0)
+ bufferSize = 0;
+
+ for (;;) {
+ int nextBlockSize = nextDataBlockSize();
+ if (bytes < nextBlockSize) {
+ head += bytes;
+ if (head == tail && tailBuffer == 0)
+ head = tail = 0;
+ break;
+ }
+
+ bytes -= nextBlockSize;
+ if (buffers.count() == 1) {
+ if (buffers.at(0).size() != basicBlockSize)
+ buffers[0].resize(basicBlockSize);
+ head = tail = 0;
+ tailBuffer = 0;
+ break;
+ }
+
+ buffers.removeAt(0);
+ --tailBuffer;
+ head = 0;
+ }
+
+ if (isEmpty())
+ clear(); // try to minify/squeeze us
+ }
+
+ inline char *reserve(int bytes) {
+ // if this is a fresh empty QRingBuffer
+ if (bufferSize == 0) {
+ buffers[0].resize(qMax(basicBlockSize, bytes));
+ bufferSize += bytes;
+ tail = bytes;
+ return buffers[tailBuffer].data();
+ }
+
+ bufferSize += bytes;
+
+ // if there is already enough space, simply return.
+ if (tail + bytes <= buffers.at(tailBuffer).size()) {
+ char *writePtr = buffers[tailBuffer].data() + tail;
+ tail += bytes;
+ return writePtr;
+ }
+
+ // if our buffer isn't half full yet, simply resize it.
+ if (tail < buffers.at(tailBuffer).size() / 2) {
+ buffers[tailBuffer].resize(tail + bytes);
+ char *writePtr = buffers[tailBuffer].data() + tail;
+ tail += bytes;
+ return writePtr;
+ }
+
+ // shrink this buffer to its current size
+ buffers[tailBuffer].resize(tail);
+
+ // create a new QByteArray with the right size
+ buffers << QByteArray();
+ ++tailBuffer;
+ buffers[tailBuffer].resize(qMax(basicBlockSize, bytes));
+ tail = bytes;
+ return buffers[tailBuffer].data();
+ }
+
+ inline void truncate(int pos) {
+ if (pos < size())
+ chop(size() - pos);
+ }
+
+ inline void chop(int bytes) {
+ bufferSize -= bytes;
+ if (bufferSize < 0)
+ bufferSize = 0;
+
+ for (;;) {
+ // special case: head and tail are in the same buffer
+ if (tailBuffer == 0) {
+ tail -= bytes;
+ if (tail <= head)
+ tail = head = 0;
+ return;
+ }
+
+ if (bytes <= tail) {
+ tail -= bytes;
+ return;
+ }
+
+ bytes -= tail;
+ buffers.removeAt(tailBuffer);
+
+ --tailBuffer;
+ tail = buffers.at(tailBuffer).size();
+ }
+
+ if (isEmpty())
+ clear(); // try to minify/squeeze us
+ }
+
+ inline bool isEmpty() const {
+ return tailBuffer == 0 && tail == 0;
+ }
+
+ inline int getChar() {
+ if (isEmpty())
+ return -1;
+ char c = *readPointer();
+ free(1);
+ return int(uchar(c));
+ }
+
+ inline void putChar(char c) {
+ char *ptr = reserve(1);
+ *ptr = c;
+ }
+
+ inline void ungetChar(char c) {
+ --head;
+ if (head < 0) {
+ buffers.prepend(QByteArray());
+ buffers[0].resize(basicBlockSize);
+ head = basicBlockSize - 1;
+ ++tailBuffer;
+ }
+ buffers[0][head] = c;
+ ++bufferSize;
+ }
+
+ inline int size() const {
+ return bufferSize;
+ }
+
+ inline void clear() {
+ buffers.erase(buffers.begin() + 1, buffers.end());
+ buffers[0].resize(0);
+ buffers[0].squeeze();
+
+ head = tail = 0;
+ tailBuffer = 0;
+ bufferSize = 0;
+ }
+
+ inline int indexOf(char c) const {
+ int index = 0;
+ for (int i = 0; i < buffers.size(); ++i) {
+ int start = 0;
+ int end = buffers.at(i).size();
+
+ if (i == 0)
+ start = head;
+ if (i == tailBuffer)
+ end = tail;
+ const char *ptr = buffers.at(i).data() + start;
+ for (int j = start; j < end; ++j) {
+ if (*ptr++ == c)
+ return index;
+ ++index;
+ }
+ }
+ return -1;
+ }
+
+ inline int indexOf(char c, int maxLength) const {
+ int index = 0;
+ int remain = qMin(size(), maxLength);
+ for (int i = 0; remain && i < buffers.size(); ++i) {
+ int start = 0;
+ int end = buffers.at(i).size();
+
+ if (i == 0)
+ start = head;
+ if (i == tailBuffer)
+ end = tail;
+ if (remain < end - start) {
+ end = start + remain;
+ remain = 0;
+ } else {
+ remain -= end - start;
+ }
+ const char *ptr = buffers.at(i).data() + start;
+ for (int j = start; j < end; ++j) {
+ if (*ptr++ == c)
+ return index;
+ ++index;
+ }
+ }
+ return -1;
+ }
+
+ inline int read(char *data, int maxLength) {
+ int bytesToRead = qMin(size(), maxLength);
+ int readSoFar = 0;
+ while (readSoFar < bytesToRead) {
+ const char *ptr = readPointer();
+ int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize());
+ if (data)
+ memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ readSoFar += bytesToReadFromThisBlock;
+ free(bytesToReadFromThisBlock);
+ }
+ return readSoFar;
+ }
+
+ inline QByteArray read(int maxLength) {
+ QByteArray tmp;
+ tmp.resize(qMin(maxLength, size()));
+ read(tmp.data(), tmp.size());
+ return tmp;
+ }
+
+ inline QByteArray readAll() {
+ return read(size());
+ }
+
+ // read an unspecified amount (will read the first buffer)
+ inline QByteArray read() {
+ if (bufferSize == 0)
+ return QByteArray();
+
+ // multiple buffers, just take the first one
+ if (head == 0 && tailBuffer != 0) {
+ QByteArray qba = buffers.takeFirst();
+ --tailBuffer;
+ bufferSize -= qba.length();
+ return qba;
+ }
+
+ // one buffer with good value for head. Just take it.
+ if (head == 0 && tailBuffer == 0) {
+ QByteArray qba = buffers.takeFirst();
+ qba.resize(tail);
+ buffers << QByteArray();
+ bufferSize = 0;
+ tail = 0;
+ return qba;
+ }
+
+ // Bad case: We have to memcpy.
+ // We can avoid by initializing the QRingBuffer with basicBlockSize of 0
+ // and only using this read() function.
+ QByteArray qba(readPointer(), nextDataBlockSize());
+ buffers.removeFirst();
+ head = 0;
+ if (tailBuffer == 0) {
+ buffers << QByteArray();
+ tail = 0;
+ } else {
+ --tailBuffer;
+ }
+ bufferSize -= qba.length();
+ return qba;
+ }
+
+ // append a new buffer to the end
+ inline void append(const QByteArray &qba) {
+ buffers[tailBuffer].resize(tail);
+ buffers << qba;
+ ++tailBuffer;
+ tail = qba.length();
+ bufferSize += qba.length();
+ }
+
+ inline QByteArray peek(int maxLength) const {
+ int bytesToRead = qMin(size(), maxLength);
+ if(maxLength <= 0)
+ return QByteArray();
+ QByteArray ret;
+ ret.resize(bytesToRead);
+ int readSoFar = 0;
+ for (int i = 0; readSoFar < bytesToRead && i < buffers.size(); ++i) {
+ int start = 0;
+ int end = buffers.at(i).size();
+ if (i == 0)
+ start = head;
+ if (i == tailBuffer)
+ end = tail;
+ const int len = qMin(ret.size()-readSoFar, end-start);
+ memcpy(ret.data()+readSoFar, buffers.at(i).constData()+start, len);
+ readSoFar += len;
+ }
+ Q_ASSERT(readSoFar == ret.size());
+ return ret;
+ }
+
+ inline int skip(int length) {
+ return read(0, length);
+ }
+
+ inline int readLine(char *data, int maxLength) {
+ int index = indexOf('\n');
+ if (index == -1)
+ return read(data, maxLength);
+ if (maxLength <= 0)
+ return -1;
+
+ int readSoFar = 0;
+ while (readSoFar < index + 1 && readSoFar < maxLength - 1) {
+ int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize());
+ bytesToRead = qMin(bytesToRead, (maxLength - 1) - readSoFar);
+ memcpy(data + readSoFar, readPointer(), bytesToRead);
+ readSoFar += bytesToRead;
+ free(bytesToRead);
+ }
+
+ // Terminate it.
+ data[readSoFar] = '\0';
+ return readSoFar;
+ }
+
+ inline bool canReadLine() const {
+ return indexOf('\n') != -1;
+ }
+
+private:
+ QList<QByteArray> buffers;
+ int head, tail;
+ int tailBuffer; // always buffers.size() - 1
+ int basicBlockSize;
+ int bufferSize;
+};
+
+QT_END_NAMESPACE
+
+#endif // QRINGBUFFER_P_H
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
new file mode 100644
index 0000000000..60a5d70632
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscopedpointer.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QScopedPointer
+ \brief The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction.
+ \since 4.6
+ \reentrant
+ \ingroup misc
+
+ Managing heap allocated objects manually is hard and error prone, with the
+ common result that code leaks memory and is hard to maintain.
+ QScopedPointer is a small utility class that heavily simplifies this by
+ assigning stack-based memory ownership to heap allocations, more generally
+ called resource acquisition is initialization(RAII).
+
+ QScopedPointer guarantees that the object pointed to will get deleted when
+ the current scope disappears.
+
+ Consider this function which does heap allocations, and have various exit points:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 0
+
+ It's encumbered by the manual delete calls. With QScopedPointer, the code
+ can be simplified to:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 1
+
+ The code the compiler generates for QScopedPointer is the same as when
+ writing it manually. Code that makes use of \a delete are candidates for
+ QScopedPointer usage (and if not, possibly another type of smart pointer
+ such as QSharedPointer). QScopedPointer intentionally has no copy
+ constructor or assignment operator, such that ownership and lifetime is
+ clearly communicated.
+
+ The const qualification on a regular C++ pointer can also be expressed with
+ a QScopedPointer:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 2
+
+ \section1 Custom cleanup handlers
+
+ Arrays as well as pointers that have been allocated with \c malloc must
+ not be deleted using \c delete. QScopedPointer's second template parameter
+ can be used for custom cleanup handlers.
+
+ The following custom cleanup handlers exist:
+
+ \list
+ \i QScopedPointerDeleter - the default, deletes the pointer using \c delete
+ \i QScopedPointerArrayDeleter - deletes the pointer using \c{delete []}. Use
+ this handler for pointers that were allocated with \c{new []}.
+ \i QScopedPointerPodDeleter - deletes the pointer using \c{free()}. Use this
+ handler for pointers that were allocated with \c{malloc()}.
+ \endlist
+
+ You can pass your own classes as handlers, provided that they have a public
+ static function \c{void cleanup(T *pointer)}.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 5
+
+ \section1 Forward Declared Pointers
+
+ Classes that are forward declared can be used within QScopedPointer, as
+ long as the destructor of the forward declared class is available whenever
+ a QScopedPointer needs to clean up.
+
+ Concretely, this means that all classes containing a QScopedPointer that
+ points to a forward declared class must have non-inline constructors,
+ destructors and assignment operators:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 4
+
+ Otherwise, the compiler output a warning about not being able to destruct
+ \c MyPrivateClass.
+
+ \sa QSharedPointer
+*/
+
+/*! \typedef QScopedPointer::pointer
+ \internal
+ */
+
+/*!
+ \fn QScopedPointer::QScopedPointer(T *p = 0)
+
+ Constructs this QScopedPointer instance and sets its pointer to \a p.
+*/
+
+/*!
+ \fn QScopedPointer::~QScopedPointer()
+
+ Destroys this QScopedPointer object. Delete the object its pointer points
+ to.
+*/
+
+/*!
+ \fn T *QScopedPointer::data() const
+
+ Returns the value of the pointer referenced by this object. QScopedPointer
+ still owns the object pointed to.
+*/
+
+/*!
+ \fn T &QScopedPointer::operator*() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QScopedPointer::operator->() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QScopedPointer::operator bool() const
+
+ Returns \c true if this object is not \c null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 3
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+
+ Equality operator. Returns true if the scoped pointers
+ \a lhs and \a rhs are pointing to the same object.
+ Otherwise returns false.
+*/
+
+
+/*!
+ \fn bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+
+ Inequality operator. Returns true if the scoped pointers
+ \a lhs and \a rhs are \e not pointing to the same object.
+ Otherwise returns false.
+*/
+
+/*!
+ \fn bool QScopedPointer::isNull() const
+
+ Returns \c true if this object is holding a pointer that is \c null.
+*/
+
+/*!
+ \fn void QScopedPointer::reset(T *other = 0)
+
+ 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.
+*/
+
+/*!
+ \fn T *QScopedPointer::take()
+
+ Returns the value of the pointer referenced by this object. The pointer of this
+ QScopedPointer object will be reset to \c null.
+
+ Callers of this function take ownership of the pointer.
+*/
+
+/*! \fn bool QScopedPointer::operator!() const
+
+ Returns \c true if the pointer referenced by this object is \c null, otherwise
+ returns \c false.
+
+ \sa isNull()
+*/
+
+/*! \fn void QScopedPointer::swap(QScopedPointer<T, Cleanup> &other)
+ Swap this pointer with \a other.
+ */
+
+/*!
+ \class QScopedArrayPointer
+
+ \brief The QScopedArrayPointer class stores a pointer to a
+ dynamically allocated array of objects, and deletes it upon
+ destruction.
+
+ \since 4.6
+ \reentrant
+ \ingroup misc
+
+ A QScopedArrayPointer is a QScopedPointer that defaults to
+ deleting the object it is pointing to with the delete[] operator. It
+ also features operator[] for convenience, so we can write:
+
+ \code
+ void foo()
+ {
+ QScopedArrayPointer<int> i(new int[10]);
+ i[2] = 42;
+ ...
+ return; // our integer array is now deleted using delete[]
+ }
+ \endcode
+*/
+
+/*!
+ \fn QScopedArrayPointer::QScopedArrayPointer(T *p = 0)
+
+ Constructs this QScopedArrayPointer instance and sets its pointer
+ to \a p.
+*/
+
+/*!
+ \fn T *QScopedArrayPointer::operator[](int i)
+
+ Provides access to entry \a i of the scoped pointer's array of
+ objects.
+
+ If the contained pointer is \c null, behavior is undefined.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QScopedArrayPointer::operator[](int i) const
+
+ Provides access to entry \a i of the scoped pointer's array of
+ objects.
+
+ If the contained pointer is \c null, behavior is undefined.
+
+ \sa isNull()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
new file mode 100644
index 0000000000..92bccf5961
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCOPEDPOINTER_H
+#define QSCOPEDPOINTER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+
+template <typename T>
+struct QScopedPointerDeleter
+{
+ static inline void cleanup(T *pointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the section on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ delete pointer;
+ }
+};
+
+template <typename T>
+struct QScopedPointerArrayDeleter
+{
+ static inline void cleanup(T *pointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the section on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ delete [] pointer;
+ }
+};
+
+struct QScopedPointerPodDeleter
+{
+ static inline void cleanup(void *pointer) { if (pointer) qFree(pointer); }
+};
+
+template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
+class QScopedPointer
+{
+#ifndef Q_CC_NOKIAX86
+ typedef T *QScopedPointer:: *RestrictedBool;
+#endif
+public:
+ explicit inline QScopedPointer(T *p = 0) : d(p)
+ {
+ }
+
+ inline ~QScopedPointer()
+ {
+ T *oldD = this->d;
+ Cleanup::cleanup(oldD);
+ this->d = 0;
+ }
+
+ inline T &operator*() const
+ {
+ Q_ASSERT(d);
+ return *d;
+ }
+
+ inline T *operator->() const
+ {
+ Q_ASSERT(d);
+ return d;
+ }
+
+ inline bool operator!() const
+ {
+ return !d;
+ }
+
+#if defined(Q_CC_NOKIAX86) || defined(Q_QDOC)
+ inline operator bool() const
+ {
+ return isNull() ? 0 : &QScopedPointer::d;
+ }
+#else
+ inline operator RestrictedBool() const
+ {
+ return isNull() ? 0 : &QScopedPointer::d;
+ }
+#endif
+
+ inline T *data() const
+ {
+ return d;
+ }
+
+ inline bool isNull() const
+ {
+ return !d;
+ }
+
+ inline void reset(T *other = 0)
+ {
+ if (d == other)
+ return;
+ T *oldD = d;
+ d = other;
+ Cleanup::cleanup(oldD);
+ }
+
+ inline T *take()
+ {
+ T *oldD = d;
+ d = 0;
+ return oldD;
+ }
+
+ inline void swap(QScopedPointer<T, Cleanup> &other)
+ {
+ qSwap(d, other.d);
+ }
+
+ typedef T *pointer;
+
+protected:
+ T *d;
+
+private:
+ Q_DISABLE_COPY(QScopedPointer)
+};
+
+template <class T, class Cleanup>
+inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+{
+ return lhs.data() == rhs.data();
+}
+
+template <class T, class Cleanup>
+inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+{
+ return lhs.data() != rhs.data();
+}
+
+template <class T, class Cleanup>
+Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2)
+{ p1.swap(p2); }
+
+#ifndef QT_NO_STL
+QT_END_NAMESPACE
+namespace std {
+ template <class T, class Cleanup>
+ Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QScopedPointer)<T, Cleanup> &p1, QT_PREPEND_NAMESPACE(QScopedPointer)<T, Cleanup> &p2)
+ { p1.swap(p2); }
+}
+QT_BEGIN_NAMESPACE
+#endif
+
+
+
+namespace QtPrivate {
+ template <typename X, typename Y> struct QScopedArrayEnsureSameType;
+ template <typename X> struct QScopedArrayEnsureSameType<X,X> { typedef X* Type; };
+ template <typename X> struct QScopedArrayEnsureSameType<const X, X> { typedef X* Type; };
+}
+
+template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
+class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
+{
+public:
+ template <typename D>
+ explicit inline QScopedArrayPointer(D *p = 0, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = 0)
+ : QScopedPointer<T, Cleanup>(p)
+ {
+ }
+
+ inline T &operator[](int i)
+ {
+ return this->d[i];
+ }
+
+ inline const T &operator[](int i) const
+ {
+ return this->d[i];
+ }
+
+private:
+ explicit inline QScopedArrayPointer(void *) {
+ // Enforce the same type.
+
+ // If you get a compile error here, make sure you declare
+ // QScopedArrayPointer with the same template type as you pass to the
+ // constructor. See also the QScopedPointer documentation.
+
+ // Storing a scalar array as a pointer to a different type is not
+ // allowed and results in undefined behavior.
+ }
+
+ Q_DISABLE_COPY(QScopedArrayPointer)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSCOPEDPOINTER_H
diff --git a/src/corelib/tools/qscopedpointer_p.h b/src/corelib/tools/qscopedpointer_p.h
new file mode 100644
index 0000000000..9b2ad6cbf6
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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.
+//
+
+#ifndef QSCOPEDPOINTER_P_H
+#define QSCOPEDPOINTER_P_H
+
+#include "QtCore/qscopedpointer.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+
+
+/* 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
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp
new file mode 100644
index 0000000000..8933efc180
--- /dev/null
+++ b/src/corelib/tools/qscopedvaluerollback.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscopedvaluerollback.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QScopedValueRollback
+ \brief The QScopedValueRollback resets a variable to its previous value on destruction
+ \since 4.8
+ \ingroup misc
+
+ The QScopedAssignment class can be used to revert state when an
+ exception is thrown without needing 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 template can only be instantiated with a type that supports assignment.
+
+ \sa QScopedPointer
+*/
+
+/*!
+ \fn QScopedValueRollback::QScopedValueRollback(T &var)
+
+ Stores the previous value of var internally, for revert on destruction.
+*/
+
+/*!
+ \fn QScopedValueRollback::~QScopedValueRollback()
+
+ Assigns the previous value to the managed variable.
+ This is the value at construction time, or at the last call to commit()
+*/
+
+/*!
+ \fn void QScopedValueRollback::commit()
+
+ Updates the previous value of the managed variable to its current value.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
new file mode 100644
index 0000000000..e874428b3c
--- /dev/null
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCOPEDVALUEROLLBACK_H
+#define QSCOPEDVALUEROLLBACK_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+
+template <typename T>
+class QScopedValueRollback
+{
+public:
+ QScopedValueRollback(T &var) :
+ varRef(var)
+ {
+ oldValue = varRef;
+ }
+
+ ~QScopedValueRollback()
+ {
+ varRef = oldValue;
+ }
+
+ void commit()
+ {
+ oldValue = varRef;
+ }
+
+private:
+ T& varRef;
+ T oldValue;
+
+ Q_DISABLE_COPY(QScopedValueRollback)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSCOPEDVALUEROLLBACK_H
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
new file mode 100644
index 0000000000..a2a805250f
--- /dev/null
+++ b/src/corelib/tools/qset.h
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSET_H
+#define QSET_H
+
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T>
+class QSet
+{
+ typedef QHash<T, QHashDummyValue> Hash;
+
+public:
+ inline QSet() {}
+ inline QSet(const QSet<T> &other) : q_hash(other.q_hash) {}
+
+ inline QSet<T> &operator=(const QSet<T> &other)
+ { q_hash = other.q_hash; return *this; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QSet<T> &operator=(QSet<T> &&other)
+ { qSwap(q_hash, other.q_hash); return *this; }
+#endif
+ inline void swap(QSet<T> &other) { 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; }
+
+ inline int 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 void squeeze() { q_hash.squeeze(); }
+
+ inline void detach() { q_hash.detach(); }
+ inline bool isDetached() const { return q_hash.isDetached(); }
+ inline void setSharable(bool sharable) { q_hash.setSharable(sharable); }
+
+ inline void clear() { q_hash.clear(); }
+
+ inline bool remove(const T &value) { return q_hash.remove(value) != 0; }
+
+ inline bool contains(const T &value) const { return q_hash.contains(value); }
+
+ bool contains(const QSet<T> &set) const;
+
+ class const_iterator;
+
+ class iterator
+ {
+ typedef QHash<T, QHashDummyValue> Hash;
+ typename Hash::iterator i;
+ friend class const_iterator;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline iterator() {}
+ inline iterator(typename Hash::iterator o) : i(o) {}
+ inline iterator(const iterator &o) : i(o.i) {}
+ inline iterator &operator=(const iterator &o) { i = o.i; return *this; }
+ inline const T &operator*() const { return i.key(); }
+ inline const T *operator->() const { return &i.key(); }
+ 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 const_iterator &o) const
+ { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const
+ { return i != o.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 { return i + j; }
+ inline iterator operator-(int j) const { return i - j; }
+ inline iterator &operator+=(int j) { i += j; return *this; }
+ inline iterator &operator-=(int j) { i -= j; return *this; }
+ };
+
+ class const_iterator
+ {
+ typedef QHash<T, QHashDummyValue> Hash;
+ typename Hash::const_iterator i;
+ friend class iterator;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline const_iterator() {}
+ inline const_iterator(typename Hash::const_iterator o) : i(o) {}
+ inline const_iterator(const const_iterator &o) : i(o.i) {}
+ inline const_iterator(const iterator &o)
+ : i(o.i) {}
+ inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; }
+ inline const T &operator*() const { return i.key(); }
+ inline const T *operator->() const { return &i.key(); }
+ 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 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 { return i + j; }
+ inline const_iterator operator-(int j) const { return i - j; }
+ inline const_iterator &operator+=(int j) { i += j; return *this; }
+ inline const_iterator &operator-=(int j) { i -= j; return *this; }
+ };
+
+ // STL style
+ inline iterator begin() { return q_hash.begin(); }
+ inline const_iterator begin() const { return q_hash.begin(); }
+ inline const_iterator constBegin() const { return q_hash.constBegin(); }
+ inline iterator end() { return q_hash.end(); }
+ inline const_iterator end() const { return q_hash.end(); }
+ inline const_iterator constEnd() const { return q_hash.constEnd(); }
+ iterator erase(iterator i)
+ { return q_hash.erase(reinterpret_cast<typename Hash::iterator &>(i)); }
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline int count() const { return q_hash.count(); }
+ inline const_iterator insert(const T &value) // ### Qt 5: should return an 'iterator'
+ { return static_cast<typename Hash::const_iterator>(q_hash.insert(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); }
+ QSet<T> &unite(const QSet<T> &other);
+ QSet<T> &intersect(const QSet<T> &other);
+ QSet<T> &subtract(const QSet<T> &other);
+
+ // STL compatibility
+ typedef T key_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 int size_type;
+
+ inline bool empty() const { return isEmpty(); }
+ // comfort
+ inline QSet<T> &operator<<(const T &value) { insert(value); return *this; }
+ inline QSet<T> &operator|=(const QSet<T> &other) { unite(other); return *this; }
+ inline QSet<T> &operator|=(const T &value) { insert(value); return *this; }
+ inline QSet<T> &operator&=(const QSet<T> &other) { intersect(other); return *this; }
+ inline QSet<T> &operator&=(const T &value)
+ { QSet<T> result; if (contains(value)) result.insert(value); return (*this = result); }
+ inline QSet<T> &operator+=(const QSet<T> &other) { unite(other); return *this; }
+ 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; }
+#if QT_VERSION < 0x050000
+ // ### Qt 5: remove
+ inline QSet<T> operator|(const QSet<T> &other)
+ { QSet<T> result = *this; result |= other; return result; }
+ inline QSet<T> operator&(const QSet<T> &other)
+ { QSet<T> result = *this; result &= other; return result; }
+ inline QSet<T> operator+(const QSet<T> &other)
+ { QSet<T> result = *this; result += other; return result; }
+ inline QSet<T> operator-(const QSet<T> &other)
+ { QSet<T> result = *this; result -= other; return result; }
+#endif
+
+ QList<T> toList() const;
+ inline QList<T> values() const { return toList(); }
+
+ static QSet<T> fromList(const QList<T> &list);
+
+private:
+ Hash q_hash;
+};
+
+template <class T>
+Q_INLINE_TEMPLATE void QSet<T>::reserve(int asize) { q_hash.reserve(asize); }
+
+template <class T>
+Q_INLINE_TEMPLATE QSet<T> &QSet<T>::unite(const QSet<T> &other)
+{
+ QSet<T> copy(other);
+ typename QSet<T>::const_iterator i = copy.constEnd();
+ while (i != copy.constBegin()) {
+ --i;
+ insert(*i);
+ }
+ return *this;
+}
+
+template <class T>
+Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other)
+{
+ QSet<T> copy1(*this);
+ QSet<T> copy2(other);
+ typename QSet<T>::const_iterator i = copy1.constEnd();
+ while (i != copy1.constBegin()) {
+ --i;
+ if (!copy2.contains(*i))
+ remove(*i);
+ }
+ return *this;
+}
+
+template <class T>
+Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other)
+{
+ QSet<T> copy1(*this);
+ QSet<T> copy2(other);
+ typename QSet<T>::const_iterator i = copy1.constEnd();
+ while (i != copy1.constBegin()) {
+ --i;
+ if (copy2.contains(*i))
+ remove(*i);
+ }
+ return *this;
+}
+
+template <class T>
+Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const
+{
+ typename QSet<T>::const_iterator i = other.constBegin();
+ while (i != other.constEnd()) {
+ if (!contains(*i))
+ return false;
+ ++i;
+ }
+ return true;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
+{
+ QList<T> result;
+ result.reserve(size());
+ typename QSet<T>::const_iterator i = constBegin();
+ while (i != constEnd()) {
+ result.append(*i);
+ ++i;
+ }
+ return result;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QSet<T> QList<T>::toSet() const
+{
+ QSet<T> result;
+ result.reserve(size());
+ for (int i = 0; i < size(); ++i)
+ result.insert(at(i));
+ return result;
+}
+
+template <typename T>
+QSet<T> QSet<T>::fromList(const QList<T> &list)
+{
+ return list.toSet();
+}
+
+template <typename T>
+QList<T> QList<T>::fromSet(const QSet<T> &set)
+{
+ return set.toList();
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(Set)
+
+template <typename T>
+class QMutableSetIterator
+{
+ typedef typename QSet<T>::iterator iterator;
+ QSet<T> *c;
+ iterator i, n;
+ inline bool item_exists() const { return c->constEnd() != n; }
+
+public:
+ inline QMutableSetIterator(QSet<T> &container)
+ : c(&container)
+ { c->setSharable(false); i = c->begin(); n = c->end(); }
+ inline ~QMutableSetIterator()
+ { c->setSharable(true); }
+ inline QMutableSetIterator &operator=(QSet<T> &container)
+ { c->setSharable(true); c = &container; c->setSharable(false);
+ i = c->begin(); n = c->end(); return *this; }
+ inline void toFront() { i = c->begin(); n = c->end(); }
+ inline void toBack() { i = c->end(); n = i; }
+ inline bool hasNext() const { return c->constEnd() != i; }
+ inline const T &next() { n = i++; return *n; }
+ inline const T &peekNext() const { return *i; }
+ inline bool hasPrevious() const { return c->constBegin() != i; }
+ inline const T &previous() { n = --i; return *n; }
+ inline const T &peekPrevious() const { iterator p = i; return *--p; }
+ inline void remove()
+ { if (c->constEnd() != n) { i = c->erase(n); n = c->end(); } }
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; }
+ inline bool findNext(const T &t)
+ { while (c->constEnd() != (n = i)) if (*i++ == t) return true; return false; }
+ inline bool findPrevious(const T &t)
+ { while (c->constBegin() != i) if (*(n = --i) == t) return true;
+ n = c->end(); return false; }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSET_H
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
new file mode 100644
index 0000000000..8748fd94bd
--- /dev/null
+++ b/src/corelib/tools/qset.qdoc
@@ -0,0 +1,946 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSet
+ \brief The QSet class is a template class that provides a hash-table-based set.
+
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+
+ QSet<T> is one of Qt's generic \l{container classes}. It stores
+ values in an unspecified order and provides very fast lookup of
+ the values. Internally, QSet<T> is implemented as a QHash.
+
+ Here's an example QSet with QString values:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 0
+
+ To insert a value into the set, use insert():
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 1
+
+ Another way to insert items into the set is to use operator<<():
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 2
+
+ To test whether an item belongs to the set or not, use contains():
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 3
+
+ If you want to navigate through all the values stored in a QSet,
+ you can use an iterator. QSet supports both \l{Java-style
+ iterators} (QSetIterator and QMutableSetIterator) and \l{STL-style
+ iterators} (QSet::iterator and QSet::const_iterator). Here's how
+ to iterate over a QSet<QWidget *> using a Java-style iterator:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 4
+
+ Here's the same code, but using an STL-style iterator:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 5
+
+ 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}:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 6
+
+ Items can be removed from the set using remove(). There is also a
+ clear() function that removes all items.
+
+ QSet's value data type must be an \l{assignable data type}. You
+ cannot, for example, store a QWidget as a value; instead, store a
+ QWidget *. In addition, the type must provide \c operator==(), and
+ there must also be a global qHash() function that returns a hash
+ value for an argument of the key's type. See the QHash
+ documentation for a list of types supported by qHash().
+
+ Internally, QSet uses a hash table to perform lookups. The hash
+ table automatically grows and shrinks to provide fast lookups
+ without wasting memory. You can still control the size of the hash
+ table by calling reserve(), if you already know approximately how
+ many elements the QSet will contain, but this isn't necessary to
+ obtain good performance. You can also call capacity() to retrieve
+ the hash table's size.
+
+ \sa QSetIterator, QMutableSetIterator, QHash, QMap
+*/
+
+/*!
+ \fn QSet::QSet()
+
+ Constructs an empty set.
+
+ \sa clear()
+*/
+
+/*!
+ \fn QSet::QSet(const QSet<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QSet is
+ \l{implicitly shared}. This makes returning a QSet 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 QSet<T> &QSet::operator=(const QSet<T> &other)
+
+ Assigns the \a other set to this set and returns a reference to
+ this set.
+*/
+
+/*!
+ \fn void QSet::swap(QSet<T> &other)
+
+ Swaps set \a other with this set. This operation is very fast and
+ never fails.
+*/
+
+/*!
+ \fn bool QSet::operator==(const QSet<T> &other) const
+
+ Returns true if the \a other set is equal to this set; otherwise
+ returns false.
+
+ Two sets are considered equal if they contain the same elements.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSet::operator!=(const QSet<T> &other) const
+
+ Returns true if the \a other set is not equal to this set; otherwise
+ returns false.
+
+ Two sets are considered equal if they contain the same elements.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator==()
+*/
+
+/*!
+ \fn int QSet::size() const
+
+ Returns the number of items in the set.
+
+ \sa isEmpty(), count()
+*/
+
+/*!
+ \fn bool QSet::isEmpty() const
+
+ Returns true if the set contains no elements; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*!
+ \fn int QSet::capacity() const
+
+ Returns the number of buckets in the set's internal hash
+ table.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QSet's memory usage. In general, you will rarely ever need
+ to call this function. If you want to know how many items are in
+ the set, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QSet::reserve(int size)
+
+ Ensures that the set's internal hash table consists of at
+ least \a size buckets.
+
+ This function is useful for code that needs to build a huge set
+ and wants to avoid repeated reallocation. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 7
+
+ Ideally, \a size should be slightly more than the maximum number
+ of elements expected in the set. \a size doesn't have to be prime,
+ because QSet will use a prime number internally anyway. If \a size
+ is an underestimate, the worst that will happen is that the QSet
+ will be a bit slower.
+
+ In general, you will rarely ever need to call this function.
+ QSet's internal hash table automatically shrinks or grows to
+ provide good performance without wasting too much memory.
+
+ \sa squeeze(), capacity()
+*/
+
+/*!
+ \fn void QSet::squeeze()
+
+ Reduces the size of the set's internal hash table to save
+ memory.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QSet's memory usage. In general, you will rarely ever
+ need to call this function.
+
+ \sa reserve(), capacity()
+*/
+
+/*!
+ \fn void QSet::detach()
+
+ \internal
+
+ Detaches this set from any other sets with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn bool QSet::isDetached() const
+
+ \internal
+
+ Returns true if the set's internal data isn't shared with any
+ other set object; otherwise returns false.
+
+ \sa detach()
+*/
+
+/*!
+ \fn void QSet::setSharable(bool sharable)
+ \internal
+*/
+
+/*!
+ \fn void QSet::clear()
+
+ Removes all elements from the set.
+
+ \sa remove()
+*/
+
+/*!
+ \fn bool QSet::remove(const T &value)
+
+ Removes any occurrence of item \a value from the set. Returns
+ true if an item was actually removed; otherwise returns false.
+
+ \sa contains(), insert()
+*/
+
+/*!
+ \fn QSet::iterator QSet::erase(iterator pos)
+ \since 4.2
+
+ Removes the item at the iterator position \a pos from the set, and
+ returns an iterator positioned at the next item in the set.
+
+ Unlike remove(), this function never causes QSet to rehash its
+ 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()
+*/
+
+/*! \fn QSet::const_iterator QSet::find(const T &value) const
+ \since 4.2
+
+ Returns a const iterator positioned at the item \a value in the
+ set. If the set contains no item \a value, the function returns
+ constEnd().
+
+ \sa constFind(), contains()
+*/
+
+/*! \fn QSet::iterator QSet::find(const T &value)
+ \since 4.2
+ \overload
+
+ Returns a non-const iterator positioned at the item \a value in
+ the set. If the set contains no item \a value, the function
+ returns end().
+*/
+
+/*! \fn QSet::const_iterator QSet::constFind(const T &value) const
+ \since 4.2
+
+ Returns a const iterator positioned at the item \a value in the
+ set. If the set contains no item \a value, the function returns
+ constEnd().
+
+ \sa find(), contains()
+*/
+
+/*!
+ \fn bool QSet::contains(const T &value) const
+
+ Returns true if the set contains item \a value; otherwise returns
+ false.
+
+ \sa insert(), remove(), find()
+*/
+
+/*!
+ \fn bool QSet::contains(const QSet<T> &other) const
+ \since 4.6
+
+ Returns true if the set contains all items from the \a other set;
+ otherwise returns false.
+
+ \sa insert(), remove(), find()
+*/
+
+/*! \fn QSet::const_iterator QSet::begin() const
+
+ Returns a const \l{STL-style iterator} positioned at the first
+ item in the set.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QSet::iterator QSet::begin()
+ \since 4.2
+ \overload
+
+ Returns a non-const \l{STL-style iterator} positioned at the first
+ item in the set.
+*/
+
+/*! \fn QSet::const_iterator QSet::constBegin() const
+
+ Returns a const \l{STL-style iterator} positioned at the first
+ item in the set.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QSet::const_iterator QSet::end() const
+
+ Returns a const \l{STL-style iterator} positioned at the imaginary
+ item after the last item in the set.
+
+ \sa constEnd(), begin()
+*/
+
+/*! \fn QSet::iterator QSet::end()
+ \since 4.2
+ \overload
+
+ Returns a non-const \l{STL-style iterator} pointing to the
+ imaginary item after the last item in the set.
+*/
+
+/*! \fn QSet::const_iterator QSet::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the set.
+
+ \sa constBegin(), end()
+*/
+
+/*!
+ \typedef QSet::Iterator
+ \since 4.2
+
+ Qt-style synonym for QSet::iterator.
+*/
+
+/*!
+ \typedef QSet::ConstIterator
+
+ Qt-style synonym for QSet::const_iterator.
+*/
+
+/*!
+ \typedef QSet::const_pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::const_reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::difference_type
+
+ Typedef for const ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::key_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::pointer
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \fn QSet::const_iterator QSet::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
+ item.
+
+ \sa operator<<(), remove(), contains()
+*/
+
+/*!
+ \fn QSet<T> &QSet::unite(const QSet<T> &other)
+
+ Each item in the \a other set that isn't already in this set is
+ inserted into this set. A reference to this set is returned.
+
+ \sa operator|=(), intersect(), subtract()
+*/
+
+/*!
+ \fn QSet<T> &QSet::intersect(const QSet<T> &other)
+
+ Removes all items from this set that are not contained in the
+ \a other set. A reference to this set is returned.
+
+ \sa operator&=(), unite(), subtract()
+*/
+
+/*!
+ \fn QSet<T> &QSet::subtract(const QSet<T> &other)
+
+ Removes all items from this set that are contained in the
+ \a other set. Returns a reference to this set.
+
+ \sa operator-=(), unite(), intersect()
+*/
+
+/*!
+ \fn bool QSet::empty() const
+
+ Returns true if the set is empty. This function is provided
+ for STL compatibility. It is equivalent to isEmpty().
+*/
+
+/*!
+ \fn bool QSet::count() const
+
+ Same as size().
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator<<(const T &value)
+ \fn QSet<T> &QSet::operator+=(const T &value)
+ \fn QSet<T> &QSet::operator|=(const T &value)
+
+ Inserts a new item \a value and returns a reference to the set.
+ If \a value already exists in the set, the set is left unchanged.
+
+ \sa insert()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator-=(const T &value)
+
+ Removes the occurrence of item \a value from the set, if
+ it is found, and returns a reference to the set. If the
+ \a value is not contained the set, nothing is removed.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator|=(const QSet<T> &other)
+ \fn QSet<T> &QSet::operator+=(const QSet<T> &other)
+
+ Same as unite(\a other).
+
+ \sa operator|(), operator&=(), operator-=()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator&=(const QSet<T> &other)
+
+ Same as intersect(\a other).
+
+ \sa operator&(), operator|=(), operator-=()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator&=(const T &value)
+
+ \overload
+
+ Same as intersect(\e{other}), if we consider \e{other} to be a set
+ that contains the singleton \a value.
+*/
+
+
+/*!
+ \fn QSet<T> &QSet::operator-=(const QSet<T> &other)
+
+ Same as subtract(\a{other}).
+
+ \sa operator-(), operator|=(), operator&=()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator|(const QSet<T> &other) const
+ \fn QSet<T> QSet::operator+(const QSet<T> &other) const
+
+ Returns a new QSet that is the union of this set and the
+ \a other set.
+
+ \sa unite(), operator|=(), operator&(), operator-()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator&(const QSet<T> &other) const
+
+ Returns a new QSet that is the intersection of this set and the
+ \a other set.
+
+ \sa intersect(), operator&=(), operator|(), operator-()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator-(const QSet<T> &other) const
+
+ Returns a new QSet that is the set difference of this set and
+ the \a other set, i.e., this set - \a other set.
+
+ \sa subtract(), operator-=(), operator|(), operator&()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator-(const QSet<T> &other)
+ \fn QSet<T> QSet::operator|(const QSet<T> &other)
+ \fn QSet<T> QSet::operator+(const QSet<T> &other)
+ \fn QSet<T> QSet::operator&(const QSet<T> &other)
+ \internal
+
+ These will go away in Qt 5.
+*/
+
+/*!
+ \class QSet::iterator
+ \since 4.2
+ \brief The QSet::iterator class provides an STL-style non-const iterator for QSet.
+
+ QSet 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.
+
+ QSet<T>::iterator allows you to iterate over a QSet and to remove
+ items (using QSet::erase()) while you iterate. (QSet doesn't let
+ you \e modify a value through an iterator, because that
+ would potentially require moving the value in the internal hash
+ table used by QSet.) If you want to iterate over a const QSet,
+ you should use QSet::const_iterator. It is generally good
+ practice to use QSet::const_iterator on a non-const QSet as well,
+ unless you need to change the QSet through the iterator. Const
+ iterators are slightly faster, and can improve code readability.
+
+ QSet\<T\>::iterator allows you to iterate over a QSet\<T\> and
+ modify it as you go (using QSet::erase()). However,
+
+ The default QSet::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a function like
+ QSet::begin(), QSet::end(), or QSet::insert() before you can
+ start iterating. Here's a typical loop that prints all the items
+ stored in a set:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 8
+
+ Here's a loop that removes certain items (all those that start
+ with 'J') from a set while iterating:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 9
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the set
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 10
+
+ Multiple iterators can be used on the same set. However, you may
+ not attempt to modify the container while iterating on it.
+
+ \sa QSet::const_iterator, QMutableSetIterator
+*/
+
+/*!
+ \class QSet::const_iterator
+ \brief The QSet::const_iterator class provides an STL-style const iterator for QSet.
+ \since 4.2
+
+ QSet 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.
+
+ QSet\<Key, T\>::const_iterator allows you to iterate over a QSet.
+ If you want to modify the QSet as you iterate over it, you must
+ use QSet::iterator instead. It is generally good practice to use
+ QSet::const_iterator on a non-const QSet as well, unless you need
+ to change the QSet through the iterator. Const iterators are
+ slightly faster, and can improve code readability.
+
+ The default QSet::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a function
+ like QSet::begin(), QSet::end(), or QSet::insert() before you can
+ start iterating. Here's a typical loop that prints all the items
+ stored in a set:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 11
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the set
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/doc_src_qset.cpp 12
+
+ Multiple iterators can be used on the same set. However, you may
+ not attempt to modify the container while iterating on it.
+
+ \sa QSet::iterator, QSetIterator
+*/
+
+/*!
+ \fn QSet::iterator::iterator()
+ \fn QSet::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QSet::begin(), QSet::end()
+*/
+
+/*!
+ \fn QSet::iterator::iterator(typename Hash::iterator i)
+ \fn QSet::const_iterator::const_iterator(typename Hash::const_iterator i)
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::iterator_category
+ \typedef QSet::const_iterator::iterator_category
+
+ Synonyms for \e {std::bidirectional_iterator_tag} indicating
+ these iterators are bidirectional iterators.
+ */
+
+/*!
+ \typedef QSet::iterator::difference_type
+ \typedef QSet::const_iterator::difference_type
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::value_type
+ \typedef QSet::const_iterator::value_type
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::pointer
+ \typedef QSet::const_iterator::pointer
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::reference
+ \typedef QSet::const_iterator::reference
+
+ \internal
+*/
+
+/*!
+ \fn QSet::iterator::iterator(const iterator &other)
+ \fn QSet::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QSet::const_iterator::const_iterator(const iterator &other)
+ \since 4.2
+ \overload
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator=(const iterator &other)
+ \fn QSet::const_iterator &QSet::const_iterator::operator=(const const_iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*!
+ \fn const T &QSet::iterator::operator*() const
+ \fn const T &QSet::const_iterator::operator*() const
+
+ Returns a reference to the current item.
+
+ \sa operator->()
+*/
+
+/*!
+ \fn const T *QSet::iterator::operator->() const
+ \fn const T *QSet::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*!
+ \fn bool QSet::iterator::operator==(const iterator &other) const
+ \fn bool QSet::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSet::iterator::operator==(const const_iterator &other) const
+ \fn bool QSet::iterator::operator!=(const const_iterator &other) const
+
+ \overload
+*/
+
+/*!
+ \fn bool QSet::iterator::operator!=(const iterator &other) const
+ \fn bool QSet::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator++()
+ \fn QSet::const_iterator &QSet::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the set and returns an iterator to the new current
+ item.
+
+ Calling this function on QSet::constEnd() leads to
+ undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator++(int)
+ \fn QSet::const_iterator QSet::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the set and returns an iterator to the previously
+ current item.
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator--()
+ \fn QSet::const_iterator &QSet::const_iterator::operator--()
+
+ 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 QSet::iterator QSet::iterator::operator--(int)
+ \fn QSet::const_iterator QSet::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator+(int j) const
+ \fn QSet::const_iterator QSet::const_iterator::operator+(int 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 QSet::iterator QSet::iterator::operator-(int j) const
+ \fn QSet::const_iterator QSet::const_iterator::operator-(int 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 QSet::iterator &QSet::iterator::operator+=(int j)
+ \fn QSet::const_iterator &QSet::const_iterator::operator+=(int 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 QSet::iterator &QSet::iterator::operator-=(int j)
+ \fn QSet::const_iterator &QSet::const_iterator::operator-=(int 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-()
+*/
+
+/*! \fn 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 doc/src/snippets/code/doc_src_qset.cpp 13
+
+ \sa fromList(), QList::fromSet(), qSort()
+*/
+
+/*! \fn 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().
+
+ \sa fromList(), QList::fromSet(), qSort()
+*/
+
+
+/*! \fn 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 doc/src/snippets/code/doc_src_qset.cpp 14
+
+ \sa toList(), QList::toSet()
+*/
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &out, const QSet<T> &set)
+ \relates QSet
+
+ Writes the \a set to stream \a out.
+
+ This function requires the value type to implement \c operator<<().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &in, QSet<T> &set)
+ \relates QSet
+
+ Reads a set from stream \a in into \a set.
+
+ This function requires the value type to implement \c operator>>().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
new file mode 100644
index 0000000000..1ef8e52cf2
--- /dev/null
+++ b/src/corelib/tools/qshareddata.cpp
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSharedData
+ \brief The QSharedData class is a base class for shared data objects.
+ \reentrant
+
+ QSharedData is designed to be used with QSharedDataPointer or
+ QExplicitlySharedDataPointer to implement custom \l{implicitly
+ shared} or explicitly shared classes. QSharedData provides
+ \l{thread-safe} reference counting.
+
+ See QSharedDataPointer and QExplicitlySharedDataPointer for details.
+*/
+
+/*! \fn QSharedData::QSharedData()
+ Constructs a QSharedData object with a reference count of 0.
+*/
+
+/*! \fn QSharedData::QSharedData(const QSharedData& other)
+ Constructs a QSharedData object with reference count 0.
+ \a other is ignored.
+*/
+
+/*!
+ \class QSharedDataPointer
+ \brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
+ \since 4.0
+ \reentrant
+
+ QSharedDataPointer\<T\> makes writing your own \l {implicitly
+ shared} classes easy. QSharedDataPointer implements \l {thread-safe}
+ reference counting, ensuring that adding QSharedDataPointers to your
+ \l {reentrant} classes won't make them non-reentrant.
+
+ \l {Implicit sharing} is used by many Qt classes to combine the
+ speed and memory efficiency of pointers with the ease of use of
+ classes. See the \l{Shared Classes} page for more information.
+
+ \target Employee example
+ Suppose you want to make an \c Employee class implicitly shared. The
+ procedure is:
+
+ \list
+
+ \o Define the class \c Employee to have a single data member of
+ type \c {QSharedDataPointer<EmployeeData>}.
+
+ \o Define the \c EmployeeData class derived from \l QSharedData to
+ contain all the data members you would normally have put in the
+ \c Employee class.
+
+ \endlist
+
+ To show this in practice, we review the source code for the
+ implicitly shared \c Employee class. In the header file we define the
+ two classes \c Employee and \c EmployeeData.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 0
+
+ In class \c Employee, note the single data member, a \e {d pointer}
+ of type \c {QSharedDataPointer<EmployeeData>}. All accesses of
+ employee data must go through the \e {d pointer's} \c
+ {operator->()}. For write accesses, \c {operator->()} will
+ automatically call detach(), which creates a copy of the shared data
+ object if the shared data object's reference count is greater than
+ 1. This ensures that writes to one \c Employee object don't affect
+ any other \c Employee objects that share the same \c EmployeeData
+ object.
+
+ Class \c EmployeeData inherits QSharedData, which provides the
+ \e{behind the scenes} reference counter. \c EmployeeData has a default
+ constructor, a copy constructor, and a destructor. Normally, trivial
+ implementations of these are all that is needed in the \e {data}
+ class for an implicitly shared class.
+
+ Implementing the two constructors for class \c Employee is also
+ straightforward. Both create a new instance of \c EmployeeData
+ and assign it to the \e{d pointer} .
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 1
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 2
+
+ Note that class \c Employee also has a trivial copy constructor
+ defined, which is not strictly required in this case.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 7
+
+ The copy constructor is not strictly required here, because class \c
+ EmployeeData is included in the same file as class \c Employee
+ (\c{employee.h}). However, including the private subclass of
+ QSharedData in the same file as the public class containing the
+ QSharedDataPointer is not typical. Normally, the idea is to hide the
+ private subclass of QSharedData from the user by putting it in a
+ separate file which would not be included in the public file. In
+ this case, we would normally put class \c EmployeeData in a separate
+ file, which would \e{not} be included in \c{employee.h}. Instead, we
+ would just predeclare the private subclass \c EmployeeData in \c
+ {employee.h} this way:
+
+ \code
+ class EmployeeData;
+ \endcode
+
+ If we had done it that way here, the copy constructor shown would be
+ required. Since the copy constructor is trivial, you might as well
+ just always include it.
+
+ Behind the scenes, QSharedDataPointer automatically increments the
+ reference count whenever an \c Employee object is copied, assigned,
+ or passed as a parameter. It decrements the reference count whenever
+ an \c Employee object is deleted or goes out of scope. The shared
+ \c EmployeeData object is deleted automatically if and when the
+ reference count reaches 0.
+
+ In a non-const member function of \c Employee, whenever the \e {d
+ pointer} is dereferenced, QSharedDataPointer automatically calls
+ detach() to ensure that the function operates on its own copy of the
+ data.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 3
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 4
+
+ Note that if detach() is called more than once in a member function
+ due to multiple dereferences of the \e {d pointer}, detach() will
+ only create a copy of the shared data the first time it is called,
+ if at all, because on the second and subsequent calls of detach(),
+ the reference count will be 1 again.
+
+ But note that in the second \c Employee constructor, which takes an
+ employee ID and a name, both setId() and setName() are called, but
+ they don't cause \e{copy on write}, because the reference count for
+ the newly constructed \c EmployeeData object has just been set to 1.
+
+ In \c Employee's \e const member functions, dereferencing the \e {d
+ pointer} does \e not cause detach() to be called.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 5
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 6
+
+ Notice that there is no need to implement a copy constructor or an
+ assignment operator for the \c Employee class, because the copy
+ constructor and assignment operator provided by the C++ compiler
+ will do the \e{member by member} shallow copy required. The only
+ member to copy is the \e {d pointer}, which is a QSharedDataPointer,
+ whose \c {operator=()} just increments the reference count of the
+ shared \c EmployeeData object.
+
+ \target Implicit vs Explicit Sharing
+ \section1 Implicit vs Explicit Sharing
+
+ Implicit sharing might not be right for the \c Employee class.
+ Consider a simple example that creates two instances of the
+ implicitly shared \c Employee class.
+
+ \snippet doc/src/snippets/sharedemployee/main.cpp 0
+
+ After the second employee e2 is created and e1 is assigned to it,
+ both \c e1 and \c e2 refer to Albrecht Durer, employee 1001. Both \c
+ Employee objects point to the same instance of \c EmployeeData,
+ which has reference count 2. Then \c {e1.setName("Hans Holbein")} is
+ called to change the employee name, but because the reference count
+ is greater than 1, a \e{copy on write} is performed before the name
+ is changed. Now \c e1 and \c e2 point to different \c EmployeeData
+ objects. They have different names, but both have ID 1001, which is
+ probably not what you want. You can, of course, just continue with
+ \c {e1.setId(1002)}, if you really mean to create a second, unique
+ employee, but if you only want to change the employee's name
+ everywhere, consider using \l {QExplicitlySharedDataPointer}
+ {explicit sharing} in the \c Employee class instead of implicit
+ sharing.
+
+ If you declare the \e {d pointer} in the \c Employee class to be
+ \c {QExplicitlySharedDataPointer<EmployeeData>}, then explicit
+ sharing is used and \e{copy on write} operations are not performed
+ automatically (i.e. detach() is not called in non-const
+ functions). In that case, after \c {e1.setName("Hans Holbein")}, the
+ employee's name has been changed, but both e1 and e2 still refer to
+ the same instance of \c EmployeeData, so there is only one employee
+ with ID 1001.
+
+ In the member function documentation, \e{d pointer} always refers
+ to the internal pointer to the shared data object.
+
+ \sa QSharedData, QExplicitlySharedDataPointer, QScopedPointer, QSharedPointer
+*/
+
+/*! \typedef QSharedDataPointer::Type
+ This is the type of the shared data object. The \e{d pointer}
+ points to an object of this type.
+ */
+
+/*! \typedef QSharedDataPointer::pointer
+ \internal
+ */
+
+/*! \fn T& QSharedDataPointer::operator*()
+ Provides access to the shared data object's members.
+ This function calls detach().
+*/
+
+/*! \fn const T& QSharedDataPointer::operator*() const
+ Provides const access to the shared data object's members.
+ This function does \e not call detach().
+*/
+
+/*! \fn T* QSharedDataPointer::operator->()
+ Provides access to the shared data object's members.
+ This function calls detach().
+*/
+
+/*! \fn const T* QSharedDataPointer::operator->() const
+ Provides const access to the shared data object's members.
+ This function does \e not call detach().
+*/
+
+/*! \fn QSharedDataPointer::operator T*()
+ Returns a pointer to the shared data object.
+ This function calls detach().
+
+ \sa data(), constData()
+*/
+
+/*! \fn QSharedDataPointer::operator const T*() const
+ Returns a pointer to the shared data object.
+ This function does \e not call detach().
+*/
+
+/*! \fn T* QSharedDataPointer::data()
+ Returns a pointer to the shared data object.
+ This function calls detach().
+
+ \sa constData()
+*/
+
+/*! \fn const T* QSharedDataPointer::data() const
+ Returns a pointer to the shared data object.
+ This function does \e not call detach().
+*/
+
+/*! \fn const T* QSharedDataPointer::constData() const
+ Returns a const pointer to the shared data object.
+ This function does \e not call detach().
+
+ \sa data()
+*/
+
+/*! \fn void QSharedDataPointer::swap(QSharedDataPointer &other)
+ Swap this instance's shared data pointer with the shared
+ data pointer in \a other.
+ */
+
+/*! \fn bool QSharedDataPointer::operator==(const QSharedDataPointer<T>& other) const
+ Returns true if \a other and \e this have the same \e{d pointer}.
+ This function does \e not call detach().
+*/
+
+/*! \fn bool QSharedDataPointer::operator!=(const QSharedDataPointer<T>& other) const
+ Returns true if \a other and \e this do \e not have the same
+ \e{d pointer}. This function does \e not call detach().
+*/
+
+/*! \fn QSharedDataPointer::QSharedDataPointer()
+ Constructs a QSharedDataPointer initialized with a null \e{d pointer}.
+*/
+
+/*! \fn QSharedDataPointer::~QSharedDataPointer()
+ Decrements the reference count of the shared data object.
+ If the reference count becomes 0, the shared data object
+ is deleted. \e This is then destroyed.
+*/
+
+/*! \fn QSharedDataPointer::QSharedDataPointer(T* sharedData)
+ Constructs a QSharedDataPointer with \e{d pointer} set to
+ \a sharedData and increments \a{sharedData}'s reference count.
+*/
+
+/*! \fn QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T>& other)
+ Sets the \e{d pointer} of \e this to the \e{d pointer} in
+ \a other and increments the reference count of the shared
+ data object.
+*/
+
+/*! \fn QSharedDataPointer<T>& QSharedDataPointer::operator=(const QSharedDataPointer<T>& other)
+ Sets the \e{d pointer} of \e this to the \e{d pointer} of
+ \a other and increments the reference count of the shared
+ data object. The reference count of the old shared data
+ object of \e this is decremented. If the reference count
+ of the old shared data object becomes 0, the old shared
+ data object is deleted.
+*/
+
+/*! \fn QSharedDataPointer& QSharedDataPointer::operator=(T* sharedData)
+ Sets the \e{d pointer} og \e this to \a sharedData and increments
+ \a{sharedData}'s reference count. The reference count of the old
+ shared data object of \e this is decremented. If the reference
+ count of the old shared data object becomes 0, the old shared data
+ object is deleted.
+*/
+
+/*! \fn bool QSharedDataPointer::operator!() const
+ Returns true if the \e{d pointer} of \e this is null.
+*/
+
+/*! \fn void QSharedDataPointer::detach()
+ If the shared data object's reference count is greater than 1, this
+ function creates a deep copy of the shared data object and sets the
+ \e{d pointer} of \e this to the copy.
+
+ This function is called automatically by non-const member
+ functions of QSharedDataPointer if \e{copy on write} is
+ required. You don't need to call it yourself.
+*/
+
+/*! \fn T *QSharedDataPointer::clone()
+ \since 4.5
+
+ Creates and returns a deep copy of the current data. This function
+ is called by detach() when the reference count is greater than 1 in
+ order to create the new copy. This function uses the \e {operator
+ new} and calls the copy constructor of the type T.
+
+ This function is provided so that you may support "virtual copy
+ constructors" for your own types. In order to so, you should declare
+ a template-specialization of this function for your own type, like
+ the example below:
+
+ \code
+ template<>
+ EmployeeData *QSharedDataPointer<EmployeeData>::clone()
+ {
+ return d->clone();
+ }
+ \endcode
+
+ In the example above, the template specialization for the clone()
+ function calls the \e {EmployeeData::clone()} virtual function. A
+ class derived from EmployeeData could override that function and
+ return the proper polymorphic type.
+*/
+
+/*!
+ \class QExplicitlySharedDataPointer
+ \brief The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object.
+ \since 4.4
+ \reentrant
+
+ QExplicitlySharedDataPointer\<T\> makes writing your own explicitly
+ shared classes easy. QExplicitlySharedDataPointer implements
+ \l {thread-safe} reference counting, ensuring that adding
+ QExplicitlySharedDataPointers to your \l {reentrant} classes won't
+ make them non-reentrant.
+
+ Except for one big difference, QExplicitlySharedDataPointer is just
+ like QSharedDataPointer. The big difference is that member functions
+ of QExplicitlySharedDataPointer \e{do not} do the automatic
+ \e{copy on write} operation (detach()) that non-const members of
+ QSharedDataPointer do before allowing the shared data object to be
+ modified. There is a detach() function available, but if you really
+ want to detach(), you have to call it yourself. This means that
+ QExplicitlySharedDataPointers behave like regular C++ pointers,
+ except that by doing reference counting and not deleting the shared
+ data object until the reference count is 0, they avoid the dangling
+ pointer problem.
+
+ It is instructive to compare QExplicitlySharedDataPointer with
+ QSharedDataPointer by way of an example. Consider the \l {Employee
+ example} in QSharedDataPointer, modified to use explicit sharing as
+ explained in the discussion \l {Implicit vs Explicit Sharing}.
+
+ Note that if you use this class but find you are calling detach() a
+ lot, you probably should be using QSharedDataPointer instead.
+
+ In the member function documentation, \e{d pointer} always refers
+ to the internal pointer to the shared data object.
+
+ \sa QSharedData, QSharedDataPointer
+*/
+
+/*! \fn T& QExplicitlySharedDataPointer::operator*() const
+ Provides access to the shared data object's members.
+*/
+
+/*! \fn T* QExplicitlySharedDataPointer::operator->()
+ Provides access to the shared data object's members.
+*/
+
+/*! \fn const T* QExplicitlySharedDataPointer::operator->() const
+ Provides const access to the shared data object's members.
+*/
+
+/*! \fn T* QExplicitlySharedDataPointer::data() const
+ Returns a pointer to the shared data object.
+*/
+
+/*! \fn const T* QExplicitlySharedDataPointer::constData() const
+ Returns a const pointer to the shared data object.
+
+ \sa data()
+*/
+
+/*! \fn void QExplicitlySharedDataPointer::swap(QExplicitlySharedDataPointer &other)
+ Swap this instance's explicitly shared data pointer with
+ the explicitly shared data pointer in \a other.
+ */
+
+/*! \fn bool QExplicitlySharedDataPointer::operator==(const QExplicitlySharedDataPointer<T>& other) const
+ Returns true if \a other and \e this have the same \e{d pointer}.
+*/
+
+/*! \fn bool QExplicitlySharedDataPointer::operator==(const T* ptr) const
+ Returns true if the \e{d pointer} of \e this is \a ptr.
+ */
+
+/*! \fn bool QExplicitlySharedDataPointer::operator!=(const QExplicitlySharedDataPointer<T>& other) const
+ Returns true if \a other and \e this do \e not have the same
+ \e{d pointer}.
+*/
+
+/*! \fn bool QExplicitlySharedDataPointer::operator!=(const T* ptr) const
+ Returns true if the \e{d pointer} of \e this is \e not \a ptr.
+ */
+
+/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer()
+ Constructs a QExplicitlySharedDataPointer initialized with a null
+ \e{d pointer}.
+*/
+
+/*! \fn QExplicitlySharedDataPointer::~QExplicitlySharedDataPointer()
+ Decrements the reference count of the shared data object.
+ If the reference count becomes 0, the shared data object
+ is deleted. \e This is then destroyed.
+*/
+
+/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(T* sharedData)
+ Constructs a QExplicitlySharedDataPointer with \e{d pointer}
+ set to \a sharedData and increments \a{sharedData}'s reference
+ count.
+*/
+
+/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T>& other)
+ This standard copy constructor sets the \e {d pointer} of \e this to
+ the \e {d pointer} in \a other and increments the reference count of
+ the shared data object.
+*/
+
+/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X>& other)
+ This copy constructor is different in that it allows \a other to be
+ a different type of explicitly shared data pointer but one that has
+ a compatible shared data object. It performs a static cast of the
+ \e{d pointer} in \a other and sets the \e {d pointer} of \e this to
+ the converted \e{d pointer}. It increments the reference count of
+ the shared data object.
+*/
+
+/*! \fn QExplicitlySharedDataPointer<T>& QExplicitlySharedDataPointer::operator=(const QExplicitlySharedDataPointer<T>& other)
+ Sets the \e{d pointer} of \e this to the \e{d pointer} of
+ \a other and increments the reference count of the shared
+ data object. The reference count of the old shared data
+ object of \e this is decremented. If the reference count
+ of the old shared data object becomes 0, the old shared
+ data object is deleted.
+*/
+
+/*! \fn QExplicitlySharedDataPointer& QExplicitlySharedDataPointer::operator=(T* sharedData)
+ Sets the \e{d pointer} of \e this to \a sharedData and
+ increments \a{sharedData}'s reference count. The reference
+ count of the old shared data object of \e this is decremented.
+ If the reference count of the old shared data object becomes
+ 0, the old shared data object is deleted.
+*/
+
+/*! \fn void QExplicitlySharedDataPointer::reset()
+ Resets \e this to be null. i.e., this function sets the
+ \e{d pointer} of \e this to 0, 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 QExplicitlySharedDataPointer::operator bool () const
+ Returns true if the \e{d pointer} of \e this is \e not null.
+ */
+
+/*! \fn bool QExplicitlySharedDataPointer::operator!() const
+ Returns true if the \e{d pointer} of \e this is null.
+*/
+
+/*! \fn void QExplicitlySharedDataPointer::detach()
+ If the shared data object's reference count is greater than 1, this
+ function creates a deep copy of the shared data object and sets the
+ \e{d pointer} of \e this to the copy.
+
+ Because QExplicitlySharedDataPointer does not do the automatic
+ \e{copy on write} operations that members of QSharedDataPointer do,
+ detach() is \e not called automatically anywhere in the member
+ functions of this class. If you find that you are calling detach()
+ everywhere in your code, consider using QSharedDataPointer instead.
+*/
+
+/*! \fn T *QExplicitlySharedDataPointer::clone()
+ \since 4.5
+
+ Creates and returns a deep copy of the current data. This function
+ is called by detach() when the reference count is greater than 1 in
+ order to create the new copy. This function uses the \e {operator
+ new} and calls the copy constructor of the type T.
+
+ See QSharedDataPointer::clone() for an explanation of how to use it.
+*/
+
+/*!
+ \typedef QExplicitlySharedDataPointer::Type
+
+ This is the type of the shared data object. The \e{d pointer}
+ points to an object of this type.
+*/
+
+/*! \typedef QExplicitlySharedDataPointer::pointer
+ \internal
+ */
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
new file mode 100644
index 0000000000..14943734c5
--- /dev/null
+++ b/src/corelib/tools/qshareddata.h
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHAREDDATA_H
+#define QSHAREDDATA_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T> class QSharedDataPointer;
+
+class Q_CORE_EXPORT QSharedData
+{
+public:
+ mutable QAtomicInt ref;
+
+ inline QSharedData() : ref(0) { }
+ inline QSharedData(const QSharedData &) : ref(0) { }
+
+private:
+ // using the assignment operator would lead to corruption in the ref-counting
+ QSharedData &operator=(const QSharedData &);
+};
+
+template <class T> class QSharedDataPointer
+{
+public:
+ typedef T Type;
+ typedef T *pointer;
+
+ inline void detach() { if (d && d->ref != 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 const T *data() 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 = 0; }
+ inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ explicit QSharedDataPointer(T *data);
+ 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;
+ 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;
+ }
+ return *this;
+ }
+#ifdef Q_COMPILER_RVALUE_REFS
+ QSharedDataPointer(QSharedDataPointer &&o) : d(o.d) { o.d = 0; }
+ inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline bool operator!() const { return !d; }
+
+ inline void swap(QSharedDataPointer &other)
+ { qSwap(d, other.d); }
+
+protected:
+ T *clone();
+
+private:
+ void detach_helper();
+
+ T *d;
+};
+
+template <class 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 const T *constData() const { return d; }
+
+ inline void detach() { if (d && d->ref != 1) detach_helper(); }
+
+ inline void reset()
+ {
+ if(d && !d->ref.deref())
+ delete d;
+
+ d = 0;
+ }
+
+ inline operator bool () const { return d != 0; }
+
+ 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 = 0; }
+ inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ explicit QExplicitlySharedDataPointer(T *data);
+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
+
+ template<class X>
+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data()))
+ {
+ 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;
+ 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;
+ }
+ return *this;
+ }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) : d(o.d) { o.d = 0; }
+ inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline bool operator!() const { return !d; }
+
+ inline void swap(QExplicitlySharedDataPointer &other)
+ { qSwap(d, other.d); }
+
+protected:
+ T *clone();
+
+private:
+ void detach_helper();
+
+ T *d;
+};
+
+template <class T>
+Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) : d(adata)
+{ if (d) d->ref.ref(); }
+
+template <class T>
+Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
+{
+ return new T(*d);
+}
+
+template <class T>
+Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
+{
+ T *x = clone();
+ x->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = x;
+}
+
+template <class T>
+Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
+{
+ return new T(*d);
+}
+
+template <class T>
+Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
+{
+ T *x = clone();
+ x->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = x;
+}
+
+template <class T>
+Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) : d(adata)
+{ if (d) d->ref.ref(); }
+
+template <class T>
+Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
+{ p1.swap(p2); }
+
+template <class T>
+Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
+{ p1.swap(p2); }
+
+#ifndef QT_NO_STL
+QT_END_NAMESPACE
+namespace std {
+ template <class T>
+ Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p2)
+ { p1.swap(p2); }
+
+ template <class T>
+ Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p2)
+ { p1.swap(p2); }
+}
+QT_BEGIN_NAMESPACE
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSHAREDDATA_H
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
new file mode 100644
index 0000000000..95256fb271
--- /dev/null
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -0,0 +1,1501 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedpointer.h"
+
+// to be sure we aren't causing a namespace clash:
+#include "qshareddata.h"
+
+/*!
+ \class QSharedPointer
+ \brief The QSharedPointer class holds a strong reference to a shared pointer
+ \since 4.5
+
+ \reentrant
+
+ The QSharedPointer is an automatic, shared pointer in C++. It
+ behaves exactly like a normal pointer for normal purposes,
+ including respect for constness.
+
+ QSharedPointer will delete the pointer it is holding when it goes
+ out of scope, provided no other QSharedPointer objects are
+ referencing it.
+
+ A QSharedPointer object can be created from a normal pointer,
+ another QSharedPointer object or by promoting a
+ QWeakPointer object to a strong reference.
+
+ \section1 Thread-Safety
+
+ QSharedPointer and QWeakPointer are thread-safe and operate
+ atomically on the pointer value. Different threads can also access
+ the QSharedPointer or QWeakPointer pointing to the same object at
+ the same time without need for locking mechanisms.
+
+ It should be noted that, while the pointer value can be accessed
+ in this manner, QSharedPointer and QWeakPointer provide no
+ guarantee about the object being pointed to. Thread-safety and
+ reentrancy rules for that object still apply.
+
+ \section1 Other Pointer Classes
+
+ Qt also provides two other pointer wrapper classes: QPointer and
+ QSharedDataPointer. They are incompatible with one another, since
+ each has its very different use case.
+
+ QSharedPointer holds a shared pointer by means of an external
+ reference count (i.e., a reference counter placed outside the
+ object). Like its name indicates, the pointer value is shared
+ among all instances of QSharedPointer and QWeakPointer. The
+ contents of the object pointed to by the pointer should not be
+ considered shared, however: there is only one object. For that
+ reason, QSharedPointer does not provide a way to detach or make
+ copies of the pointed object.
+
+ QSharedDataPointer, on the other hand, holds a pointer to shared
+ data (i.e., a class derived from QSharedData). It does so by means
+ of an internal reference count, placed in the QSharedData base
+ class. This class can, therefore, detach based on the type of
+ access made to the data being guarded: if it's a non-const access,
+ it creates a copy atomically for the operation to complete.
+
+ QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except
+ that it only detaches if QExplicitlySharedDataPointer::detach() is
+ explicitly called (hence the name).
+
+ QScopedPointer simply holds a pointer to a heap allocated object and
+ deletes it in its destructor. This class is useful when an object needs to
+ be heap allocated and deleted, but no more. QScopedPointer is lightweight,
+ it makes no use of additional structure or reference counting.
+
+ Finally, QPointer holds a pointer to a QObject-derived object, but it
+ does so weakly. QPointer can be replaced by QWeakPointer in almost all
+ cases, since they have the same functionality. See
+ \l{QWeakPointer#tracking-qobject} for more information.
+
+ \section1 Optional pointer tracking
+
+ A feature of QSharedPointer that can be enabled at compile-time for
+ debugging purposes is a pointer tracking mechanism. When enabled,
+ QSharedPointer registers in a global set all the pointers that it tracks.
+ This allows one to catch mistakes like assigning the same pointer to two
+ QSharedPointer objects.
+
+ This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS}
+ macro before including the QSharedPointer header.
+
+ It is safe to use this feature even with code compiled without the
+ feature. QSharedPointer will ensure that the pointer is removed from the
+ tracker even from code compiled without pointer tracking.
+
+ Note, however, that the pointer tracking feature has limitations on
+ multiple- or virtual-inheritance (that is, in cases where two different
+ pointer addresses can refer to the same object). In that case, if a
+ pointer is cast to a different type and its value changes,
+ QSharedPointer's pointer tracking mechanism may fail to detect that the
+ object being tracked is the same.
+
+ \omit
+ \secton1 QSharedPointer internals
+
+ QSharedPointer is in reality implemented by two ancestor classes:
+ QtSharedPointer::Basic and QtSharedPointer::ExternalRefCount. The reason
+ for having that split is now mostly legacy: in the beginning,
+ QSharedPointer was meant to support both internal reference counting and
+ external reference counting.
+
+ QtSharedPointer::Basic implements the basic functionality that is shared
+ between internal- and external-reference counting. That is, it's mostly
+ the accessor functions into QSharedPointer. Those are all inherited by
+ QSharedPointer, which adds another level of shared functionality (the
+ constructors and assignment operators). The Basic class has one member
+ variable, which is the actual pointer being tracked.
+
+ QtSharedPointer::ExternalRefCount implements the actual reference
+ counting and introduces the d-pointer for QSharedPointer. That d-pointer
+ itself is shared with other QSharedPointer objects as well as
+ QWeakPointer.
+
+ The reason for keeping the pointer value itself outside the d-pointer is
+ because of multiple inheritance needs. If you have two QSharedPointer
+ objects of different pointer types, but pointing to the same object in
+ memory, it could happen that the pointer values are different. The \tt
+ differentPointers autotest exemplifies this problem. The same thing could
+ happen in the case of virtual inheritance: a pointer of class matching
+ the virtual base has different address compared to the pointer of the
+ complete object. See the \tt virtualBaseDifferentPointers autotest for
+ this problem.
+
+ The d pointer is of type QtSharedPointer::ExternalRefCountData for simple
+ QSharedPointer objects, but could be of a derived type in some cases. It
+ is basically a reference-counted reference-counter.
+
+ \section2 d-pointer
+ \section3 QtSharedPointer::ExternalRefCountData
+
+ This class is basically a reference-counted reference-counter. It has two
+ members: \tt strongref and \tt weakref. The strong reference counter is
+ controlling the lifetime of the object tracked by QSharedPointer. a
+ positive value indicates that the object is alive. It's also the number
+ of QSharedObject instances that are attached to this Data.
+
+ When the strong reference count decreases to zero, the object is deleted
+ (see below for information on custom deleters). The strong reference
+ count 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
+ \l{QWeakPointer#tracking-qobject}{QWeakPointers tracking a QObject}.
+
+ The weak reference count controls the lifetime of the d-pointer itself.
+ It can be thought of as an internal/intrusive reference count for
+ ExternalRefCountData itself. This count is equal to the number of
+ QSharedPointers and QWeakPointers that are tracking this object. (In case
+ the object tracked derives from QObject, this number is increased by 1,
+ since QObjectPrivate tracks it too).
+
+ ExternalRefCountData is a virtual class: it has a virtual destructor and
+ a virtual destroy() function. The destroy() function is supposed to
+ delete the object being tracked and return true if it does so. Otherwise,
+ it returns false to indicate that the caller must simply call delete.
+ This allows the normal use-case of QSharedPointer without custom deleters
+ to use only one 12- or 16-byte (depending on whether it's a 32- or 64-bit
+ architecture) external descriptor structure, without paying the price for
+ the custom deleter that it isn't using.
+
+ \section3 QtSharedPointer::ExternalRefCountDataWithDestroyFn
+
+ This class is not used directly, per se. It only exists to enable the two
+ classes that derive from it. It adds one member variable, which is a
+ pointer to a function (which returns void and takes an
+ ExternalRefCountData* as a parameter). It also overrides the destroy()
+ function: it calls that function pointer with \tt this as parameter, and
+ returns true.
+
+ That means when ExternalRefCountDataWithDestroyFn is used, the \tt
+ destroyer field must be set to a valid function that \b will delete the
+ object tracked.
+
+ This class also adds an operator delete function to ensure that it simply
+ calls the global operator delete. That should be the behaviour in all
+ compilers already, but to be on the safe side, this class ensures that no
+ funny business happens.
+
+ On a 32-bit architecture, this class is 16 bytes in size, whereas it's 24
+ bytes on 64-bit. (On Itanium where function pointers contain the global
+ pointer, it can be 32 bytes).
+
+ \section3 QtSharedPointer::ExternalRefCountWithCustomDeleter
+
+ This class derives from ExternalRefCountDataWithDestroyFn and is a
+ template class. As template parameters, it has the type of the pointer
+ being tracked (\tt T) and a \tt Deleter, which is anything. It adds two
+ fields to its parent class, matching those template parameters: a member
+ of type \tt Deleter and a member of type \tt T*.
+
+ The purpose of this class is to store the pointer to be deleted and the
+ deleter code along with the d-pointer. This allows the last strong
+ reference to call any arbitrary function that disposes of the object. For
+ example, this allows calling QObject::deleteLater() on a given object.
+ The pointer to the object is kept here to avoid the extra cost of keeping
+ the deleter in the generic case.
+
+ This class is never instantiated directly: the constructors and
+ destructor are private. Only the create() function may be called to
+ return an object of this type. See below for construction details.
+
+ The size of this class depends on the size of \tt Deleter. If it's an
+ empty functor (i.e., no members), ABIs generally assign it the size of 1.
+ But given that it's followed by a pointer, up to 3 or 7 padding bytes may
+ be inserted: in that case, the size of this class is 16+4+4 = 24 bytes on
+ 32-bit architectures, or 24+8+8 = 40 bytes on 64-bit architectures (48
+ bytes on Itanium with global pointers stored). If \tt Deleter is a
+ function pointer, the size should be the same as the empty structure
+ case, except for Itanium where it may be 56 bytes due to another global
+ pointer. If \tt Deleter is a pointer to a member function (PMF), the size
+ will be even bigger and will depend on the ABI. For architectures using
+ the Itanium C++ ABI, a PMF is twice the size of a normal pointer, or 24
+ bytes on Itanium itself. In that case, the size of this structure will be
+ 16+8+4 = 28 bytes on 32-bit architectures, 24+16+8 = 48 bytes on 64-bit,
+ and 32+24+8 = 64 bytes on Itanium.
+
+ (Values for Itanium consider an LP64 architecture; for ILP32, pointers
+ are 32-bit in length, function pointers are 64-bit and PMF are 96-bit, so
+ the sizes are slightly less)
+
+ \section3 QtSharedPointer::ExternalRefCountWithContiguousData
+
+ This class also derives from ExternalRefCountDataWithDestroyFn and it is
+ also a template class. The template parameter is the type \tt T of the
+ class which QSharedPointer tracks. It adds only one member to its parent,
+ which is of type \tt T (the actual type, not a pointer to it).
+
+ The purpose of this class is to lay the \tt T object out next to the
+ reference counts, saving one memory allocation per shared pointer. This
+ is particularly interesting for small \tt T or for the cases when there
+ are few if any QWeakPointer tracking the object. This class exists to
+ implement the QSharedPointer::create() call.
+
+ 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++0x, we'd
+ delete them).
+
+ The size of this class depends on the size of \tt T.
+
+ \section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData
+
+ Like explained above, these classes have private constructors. Moreover,
+ they are not defined anywhere, so trying to call \tt{new ClassType} would
+ result in a compilation or linker error. Instead, these classes must be
+ constructed via their create() methods.
+
+ Instead of instantiating the class by the normal way, the create() method
+ calls \tt{operator new} directly with the size of the class, then calls
+ the parent class's constructor only (ExternalRefCountDataWithDestroyFn).
+ This ensures that the inherited members are initialised properly, as well
+ as the virtual table pointer, which must point to
+ ExternalRefCountDataWithDestroyFn's virtual table. That way, we also
+ ensure that the virtual destructor being called is
+ ExternalRefCountDataWithDestroyFn's.
+
+ After initialising the base class, the
+ ExternalRefCountWithCustomDeleter::create() function initialises the new
+ members directly, by using the placement \tt{operator new}. In the case
+ of the ExternalRefCountWithContiguousData::create() function, the address
+ to the still-uninitialised \tt T member is saved for the callee to use.
+ The member is only initialised in QSharedPointer::create(), so that we
+ avoid having many variants of the internal functions according to the
+ arguments in use for calling the constructor.
+
+ When initialising the parent class, the create() functions pass the
+ address of the static deleter() member function. That is, when the
+ virtual destroy() is called by QSharedPointer, the deleter() functions
+ are called instead. These functions static_cast the ExternalRefCountData*
+ parameter to their own type and execute their deletion: for the
+ ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's
+ custom deleter, then destroys the deleter; for
+ ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T
+ destructor directly.
+
+ By not calling the constructor of the derived classes, we avoid
+ instantiating their virtual tables. Since these classes are
+ template-based, there would be one virtual table per \tt T and \tt
+ Deleter type. (This is what Qt 4.5 did.)
+
+ Instead, only one non-inline function is required per template, which is
+ the deleter() static member. All the other functions can be inlined.
+ What's more, the address of deleter() is calculated only in code, which
+ can be resolved at link-time if the linker can determine that the
+ function lies in the current application or library module (since these
+ classes are not exported, that is the case for Windows or for builds with
+ \tt{-fvisibility=hidden}).
+
+ In contrast, a virtual table would require at least 3 relocations to be
+ resolved at module load-time, per module where these classes are used.
+ (In the Itanium C++ ABI, there would be more relocations, due to the
+ RTTI)
+
+ \section3 Modifications due to pointer-tracking
+
+ To ensure that pointers created with pointer-tracking enabled get
+ un-tracked when destroyed, even if destroyed by code compiled without the
+ feature, QSharedPointer modifies slightly the instructions of the
+ previous sections.
+
+ When ExternalRefCountWithCustomDeleter or
+ ExternalRefCountWithContiguousData are used, their create() functions
+ will set the ExternalRefCountDataWithDestroyFn::destroyer function
+ pointer to safetyCheckDeleter() instead. These static member functions
+ simply call internalSafetyCheckRemove2() before passing control to the
+ normal deleter() function.
+
+ If neither custom deleter nor QSharedPointer::create() are used, then
+ QSharedPointer uses a custom deleter of its own: the normalDeleter()
+ function, which simply calls \tt delete. By using a custom deleter, the
+ safetyCheckDeleter() procedure described above kicks in.
+
+ \endomit
+
+ \sa QSharedDataPointer, QWeakPointer, QScopedPointer
+*/
+
+/*!
+ \class QWeakPointer
+ \brief The QWeakPointer class holds a weak reference to a shared pointer
+ \since 4.5
+ \reentrant
+
+ The QWeakPointer is an automatic weak reference to a
+ pointer in C++. It cannot be used to dereference the pointer
+ directly, but it can be used to verify if the pointer has been
+ deleted or not in another context.
+
+ QWeakPointer objects can only be created by assignment from a
+ QSharedPointer. The exception is pointers derived from QObject: in that
+ case, QWeakPointer serves as a replacement to QPointer.
+
+ It's important to note that QWeakPointer provides no automatic casting
+ operators to prevent mistakes from happening. Even though QWeakPointer
+ tracks a pointer, it should not be considered a pointer itself, since it
+ doesn't guarantee that the pointed object remains valid.
+
+ Therefore, to access the pointer that QWeakPointer is tracking, you must
+ first promote it to QSharedPointer and verify if the resulting object is
+ null or not. QSharedPointer guarantees that the object isn't deleted, so
+ if you obtain a non-null object, you may use the pointer. See
+ QWeakPointer::toStrongRef() for an example.
+
+ QWeakPointer also provides the QWeakPointer::data() method that returns
+ the tracked pointer without ensuring that it remains valid. This function
+ is provided if you can guarantee by external means that the object will
+ not get deleted (or if you only need the pointer value) and the cost of
+ creating a QSharedPointer using toStrongRef() is too high.
+
+ That function can also be used to obtain the tracked pointer for
+ QWeakPointers that cannot be promoted to QSharedPointer, such as those
+ created directly from a QObject pointer (not via QSharedPointer).
+
+ \section1 Tracking QObject
+
+ QWeakPointer can be used to track deletion of classes that derive from QObject,
+ even if they are not managed by QSharedPointer. When used in that role,
+ QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer
+ is also more efficient than QPointer, so it should be preferred in all
+ new code.
+
+ To do that, QWeakPointer provides a special constructor that is only
+ available if the template parameter \tt T is either QObject or a class
+ deriving from it. Trying to use that constructor if \tt T does not derive
+ from QObject will result in compilation errors.
+
+ To obtain the QObject being tracked by QWeakPointer, you must use the
+ QWeakPointer::data() function, but only if you can guarantee that the
+ object cannot get deleted by another context. It should be noted that
+ QPointer had the same constraint, so use of QWeakPointer forces you to
+ consider whether the pointer is still valid.
+
+ QObject-derived classes can only be deleted in the thread they have
+ affinity to (which is the thread they were created in or moved to, using
+ QObject::moveToThread()). In special, QWidget-derived classes cannot be
+ created in non-GUI threads nor moved there. Therefore, guaranteeing that
+ the tracked QObject has affinity to the current thread is enough to also
+ guarantee that it won't be deleted asynchronously.
+
+ Note that QWeakPointer's size and data layout do not match QPointer, so
+ it cannot replace that class in a binary-compatible manner.
+
+ Care must also be taken with QWeakPointers created directly from QObject
+ pointers when dealing with code that was compiled with Qt versions prior
+ to 4.6. Those versions may not track the reference counters correctly, so
+ QWeakPointers created from QObject should never be passed to code that
+ hasn't been recompiled.
+
+ \omit
+ \secton1 QWeakPointer internals
+
+ QWeakPointer shares most of its internal functionality with
+ \l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that
+ class's internal documentation for more information.
+
+ QWeakPointer requires an external reference counter in order to operate.
+ Therefore, it is incompatible by design with \l QSharedData-derived
+ classes.
+
+ It has a special QObject constructor, which works by calling
+ QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the
+ d-pointer from QObjectPrivate. If one isn't set yet, that function
+ creates the d-pointer and atomically sets it.
+
+ If getAndRef needs to create a d-pointer, it sets the strongref to -1,
+ indicating that the QObject is not shared: QWeakPointer is used only to
+ determine whether the QObject has been deleted. In that case, it cannot
+ be upgraded to QSharedPointer (see the previous section).
+
+ \endomit
+
+ \sa QSharedPointer, QScopedPointer
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer()
+
+ Creates a QSharedPointer that points to null (0).
+*/
+
+/*!
+ \fn QSharedPointer::~QSharedPointer()
+
+ Destroys this QSharedPointer object. If it is the last reference to
+ the pointer stored, this will delete the pointer as well.
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(T *ptr)
+
+ Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
+ becomes managed by this QSharedPointer and must not be passed to
+ another QSharedPointer object or deleted outside this object.
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter)
+
+ Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
+ becomes managed by this QSharedPointer and must not be passed to
+ another QSharedPointer object or deleted outside this object.
+
+ The \a deleter parameter specifies the custom deleter for this
+ object. The custom deleter is called, instead of the operator delete(),
+ when the strong reference count drops to 0. This is useful,
+ for instance, for calling deleteLater() on a QObject instead:
+
+ \code
+ static void doDeleteLater(MyObject *obj)
+ {
+ obj->deleteLater();
+ }
+
+ void otherFunction()
+ {
+ QSharedPointer<MyObject> obj =
+ QSharedPointer<MyObject>(new MyObject, doDeleteLater);
+
+ // continue using obj
+ obj.clear(); // calls obj->deleteLater();
+ }
+ \endcode
+
+ It is also possible to specify a member function directly, as in:
+ \code
+ QSharedPointer<MyObject> obj =
+ QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
+ \endcode
+
+ \sa clear()
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(const QSharedPointer<T> &other)
+
+ Creates a QSharedPointer object that shares \a other's pointer.
+
+ If \tt T is a derived type of the template parameter of this class,
+ QSharedPointer will perform an automatic cast. Otherwise, you will
+ get a compiler error.
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(const QWeakPointer<T> &other)
+
+ Creates a QSharedPointer by promoting the weak reference \a other
+ to strong reference and sharing its pointer.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QSharedPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+
+ \sa QWeakPointer::toStrongRef()
+*/
+
+/*!
+ \fn QSharedPointer &QSharedPointer::operator=(const QSharedPointer<T> &other)
+
+ Makes this object share \a other's pointer. The current pointer
+ reference is discarded and, if it was the last, the pointer will
+ be deleted.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QSharedPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn QSharedPointer &QSharedPointer::operator=(const QWeakPointer<T> &other)
+
+ Promotes \a other to a strong reference and makes this object
+ share a reference to the pointer referenced by it. The current pointer
+ reference is discarded and, if it was the last, the pointer will
+ be deleted.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QSharedPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn T *QSharedPointer::data() const
+
+ Returns the value of the pointer referenced by this object.
+
+ Note: do not delete the pointer returned by this function or pass
+ it to another function that could delete it, including creating
+ QSharedPointer or QWeakPointer objects.
+*/
+
+/*!
+ \fn T &QSharedPointer::operator *() const
+
+ Provides access to the shared pointer's members.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QSharedPointer::operator ->() const
+
+ Provides access to the shared pointer's members.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QSharedPointer::isNull() const
+
+ Returns true if this object is holding a reference to a null
+ pointer.
+*/
+
+/*!
+ \fn QSharedPointer::operator bool() const
+
+ Returns true if this object is not null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \code
+ if (sharedptr) { ... }
+ \endcode
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QSharedPointer::operator !() const
+
+ Returns true if this object is null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \code
+ if (!sharedptr) { ... }
+ \endcode
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QSharedPointer<X> QSharedPointer::staticCast() const
+
+ Performs a static cast from this pointer's type to \tt X and returns
+ a QSharedPointer that shares the reference. This function can be
+ used for up- and for down-casting, but is more useful for
+ up-casting.
+
+ Note: the template type \c X must have the same const and volatile
+ qualifiers as the template of this object, or the cast will
+ fail. Use constCast() if you need to drop those qualifiers.
+
+ \sa dynamicCast(), constCast(), qSharedPointerCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> QSharedPointer::dynamicCast() const
+
+ Performs a dynamic cast from this pointer's type to \tt X and
+ returns a QSharedPointer that shares the reference. If this
+ function is used to up-cast, then QSharedPointer will perform a \tt
+ dynamic_cast, which means that if the object being pointed by this
+ QSharedPointer is not of type \tt X, the returned object will be
+ null.
+
+ Note: the template type \c X must have the same const and volatile
+ qualifiers as the template of this object, or the cast will
+ fail. Use constCast() if you need to drop those qualifiers.
+
+ \sa qSharedPointerDynamicCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> QSharedPointer::constCast() const
+
+ Performs a \tt const_cast from this pointer's type to \tt X and returns
+ a QSharedPointer that shares the reference. This function can be
+ used for up- and for down-casting, but is more useful for
+ up-casting.
+
+ \sa isNull(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> QSharedPointer::objectCast() const
+ \since 4.6
+
+ Performs a \l qobject_cast() from this pointer's type to \tt X and
+ returns a QSharedPointer that shares the reference. If this
+ function is used to up-cast, then QSharedPointer will perform a \tt
+ qobject_cast, which means that if the object being pointed by this
+ QSharedPointer is not of type \tt X, the returned object will be
+ null.
+
+ Note: the template type \c X must have the same const and volatile
+ qualifiers as the template of this object, or the cast will
+ fail. Use constCast() if you need to drop those qualifiers.
+
+ \sa qSharedPointerObjectCast()
+*/
+
+/*!
+ \fn QWeakPointer<T> QSharedPointer::toWeakRef() const
+
+ Returns a weak reference object that shares the pointer referenced
+ by this object.
+
+ \sa QWeakPointer::QWeakPointer()
+*/
+
+/*!
+ \fn void QSharedPointer::clear()
+
+ Clears this QSharedPointer object, dropping the reference that it
+ may have had to the pointer. If this was the last reference, then
+ the pointer itself will be deleted.
+*/
+
+/*!
+ \fn QWeakPointer::QWeakPointer()
+
+ Creates a QWeakPointer that points to nothing.
+*/
+
+/*!
+ \fn QWeakPointer::~QWeakPointer()
+
+ Destroys this QWeakPointer object. The pointer referenced
+ by this object will not be deleted.
+*/
+
+/*!
+ \fn QWeakPointer::QWeakPointer(const QWeakPointer<T> &other)
+
+ Creates a QWeakPointer that holds a weak reference to the
+ pointer referenced by \a other.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QWeakPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn QWeakPointer::QWeakPointer(const QSharedPointer<T> &other)
+
+ Creates a QWeakPointer that holds a weak reference to the
+ pointer referenced by \a other.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QWeakPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn QWeakPointer::QWeakPointer(const QObject *obj)
+ \since 4.6
+
+ Creates a QWeakPointer that holds a weak reference directly to the
+ QObject \a obj. This constructor is only available if the template type
+ \tt T is QObject or derives from it (otherwise a compilation error will
+ result).
+
+ You can use this constructor with any QObject, even if they were not
+ created with \l QSharedPointer.
+
+ Note that QWeakPointers created this way on arbitrary QObjects usually
+ cannot be promoted to QSharedPointer.
+
+ \sa QSharedPointer, QWeakPointer#tracking-qobject
+*/
+
+/*!
+ \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
+ \since 4.6
+
+ Makes this QWeakPointer hold a weak reference directly to the QObject
+ \a obj. This function is only available if the template type \tt T is
+ QObject or derives from it.
+
+ \sa QWeakPointer#tracking-qobject
+*/
+
+/*!
+ \fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other)
+
+ Makes this object share \a other's pointer. The current pointer
+ reference is discarded but is not deleted.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QWeakPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn QWeakPointer &QWeakPointer::operator=(const QSharedPointer<T> &other)
+
+ Makes this object share \a other's pointer. The current pointer
+ reference is discarded but is not deleted.
+
+ If \tt T is a derived type of the template parameter of this
+ class, QWeakPointer will perform an automatic cast. Otherwise,
+ you will get a compiler error.
+*/
+
+/*!
+ \fn bool QWeakPointer::isNull() const
+
+ Returns true if this object is holding a reference to a null
+ pointer.
+
+ Note that, due to the nature of weak references, the pointer that
+ QWeakPointer references can become null at any moment, so
+ the value returned from this function can change from false to
+ true from one call to the next.
+*/
+
+/*!
+ \fn QWeakPointer::operator bool() const
+
+ Returns true if this object is not null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \code
+ if (weakref) { ... }
+ \endcode
+
+ Note that, due to the nature of weak references, the pointer that
+ QWeakPointer references can become null at any moment, so
+ the value returned from this function can change from true to
+ false from one call to the next.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QWeakPointer::operator !() const
+
+ Returns true if this object is null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \code
+ if (!weakref) { ... }
+ \endcode
+
+ Note that, due to the nature of weak references, the pointer that
+ QWeakPointer references can become null at any moment, so
+ the value returned from this function can change from false to
+ true from one call to the next.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QWeakPointer::data() const
+ \since 4.6
+
+ Returns the value of the pointer being tracked by this QWeakPointer,
+ \b without ensuring that it cannot get deleted. To have that guarantee,
+ use toStrongRef(), which returns a QSharedPointer object. If this
+ function can determine that the pointer has already been deleted, it
+ returns 0.
+
+ It is ok to obtain the value of the pointer and using that value itself,
+ like for example in debugging statements:
+
+ \code
+ qDebug("Tracking %p", weakref.data());
+ \endcode
+
+ However, dereferencing the pointer is only allowed if you can guarantee
+ by external means that the pointer does not get deleted. For example,
+ if you can be certain that no other thread can delete it, nor the
+ functions that you may call.
+
+ If that is the case, then the following code is valid:
+
+ \code
+ // this pointer cannot be used in another thread
+ // so other threads cannot delete it
+ QWeakPointer<int> weakref = obtainReference();
+
+ Object *obj = weakref.data();
+ if (obj) {
+ // if the pointer wasn't deleted yet, we know it can't get
+ // deleted by our own code here nor the functions we call
+ otherFunction(obj);
+ }
+ \endcode
+
+ Use this function with care.
+
+ \sa isNull(), toStrongRef()
+*/
+
+/*!
+ \fn QSharedPointer<T> QWeakPointer::toStrongRef() const
+
+ Promotes this weak reference to a strong one and returns a
+ QSharedPointer object holding that reference. When promoting to
+ QSharedPointer, this function verifies if the object has been deleted
+ already or not. If it hasn't, this function increases the reference
+ count to the shared object, thus ensuring that it will not get
+ deleted.
+
+ Since this function can fail to obtain a valid strong reference to the
+ shared object, you should always verify if the conversion succeeded,
+ by calling QSharedPointer::isNull() on the returned object.
+
+ For example, the following code promotes a QWeakPointer that was held
+ to a strong reference and, if it succeeded, it prints the value of the
+ integer that was held:
+
+ \code
+ QWeakPointer<int> weakref;
+
+ // ...
+
+ QSharedPointer<int> strong = weakref.toStrongRef();
+ if (strong)
+ qDebug() << "The value is:" << *strong;
+ else
+ qDebug() << "The value has already been deleted";
+ \endcode
+
+ \sa QSharedPointer::QSharedPointer()
+*/
+
+/*!
+ \fn void QWeakPointer::clear()
+
+ Clears this QWeakPointer object, dropping the reference that it
+ may have had to the pointer.
+*/
+
+/*!
+ \fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer referenced by \a ptr1 is the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer referenced by \a ptr1 is not the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer referenced by \a ptr1 is the
+ same pointer as \a ptr2.
+
+ If \a ptr2's type is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ type is not a base or a derived type from this
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer referenced by \a ptr1 is not the
+ same pointer as \a ptr2.
+
+ If \a ptr2's type is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ type is not a base or a derived type from this
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer \a ptr1 is the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's type,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's type, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns true if the pointer \a ptr1 is not the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's type,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's type, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns true if the pointer referenced by \a ptr1 is the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns true if the pointer referenced by \a ptr1 is not the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns true if the pointer referenced by \a ptr1 is the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns true if the pointer referenced by \a ptr1 is not the
+ same pointer as that referenced by \a ptr2.
+
+ If \a ptr2's template parameter is different from \a ptr1's,
+ QSharedPointer will attempt to perform an automatic \tt static_cast
+ to ensure that the pointers being compared are equal. If \a ptr2's
+ template parameter is not a base or a derived type from
+ \a ptr1's, you will get a compiler error.
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+
+ Returns a shared pointer to the pointer held by \a other, cast to
+ type \tt X. The types \tt T and \tt X must belong to one
+ hierarchy for the \tt static_cast to succeed.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+
+ Returns a shared pointer to the pointer held by \a other, cast to
+ type \tt X. The types \tt T and \tt X must belong to one
+ hierarchy for the \tt static_cast to succeed.
+
+ The \a other object is converted first to a strong reference. If
+ that conversion fails (because the object it's pointing to has
+ already been deleted), this function returns a null
+ QSharedPointer.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ dynamic cast to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt dynamic_cast fails, the object
+ returned will be null.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ dynamic cast to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt dynamic_cast fails, the object
+ returned will be null.
+
+ The \a other object is converted first to a strong reference. If
+ that conversion fails (because the object it's pointing to has
+ already been deleted), this function also returns a null
+ QSharedPointer.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+
+ Returns a shared pointer to the pointer held by \a other, cast to
+ type \tt X. The types \tt T and \tt X must belong to one
+ hierarchy for the \tt const_cast to succeed. The \tt const and \tt
+ volatile differences between \tt T and \tt X are ignored.
+
+ \sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+
+ Returns a shared pointer to the pointer held by \a other, cast to
+ type \tt X. The types \tt T and \tt X must belong to one
+ hierarchy for the \tt const_cast to succeed. The \tt const and
+ \tt volatile differences between \tt T and \tt X are ignored.
+
+ The \a other object is converted first to a strong reference. If
+ that conversion fails (because the object it's pointing to has
+ already been deleted), this function returns a null
+ QSharedPointer.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+ \since 4.6
+
+ \brief The qSharedPointerObjectCast function is for casting a shared pointer.
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+ \since 4.6
+
+ \brief The qSharedPointerObjectCast function is for casting a shared pointer.
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ The \a other object is converted first to a strong reference. If
+ that conversion fails (because the object it's pointing to has
+ already been deleted), this function also returns a null
+ QSharedPointer.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+
+/*!
+ \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other)
+ \relates QWeakPointer
+
+ Returns a weak pointer to the pointer held by \a other, cast to
+ type \tt X. The types \tt T and \tt X must belong to one
+ hierarchy for the \tt static_cast to succeed.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+*/
+
+#include <qset.h>
+#include <qmutex.h>
+
+#if !defined(QT_NO_QOBJECT)
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ This function is called for a just-created QObject \a obj, to enable
+ the use of QSharedPointer and QWeakPointer.
+
+ When QSharedPointer is active in a QObject, the object must not be deleted
+ directly: the lifetime is managed by the QSharedPointer object. In that case,
+ the deleteLater() and parent-child relationship in QObject only decrease
+ the strong reference count, instead of deleting the object.
+*/
+void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool)
+{
+ Q_ASSERT(obj);
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+
+ if (d->sharedRefcount)
+ qFatal("QSharedPointer: pointer %p already has reference counting", obj);
+ d->sharedRefcount = this;
+
+ // QObject decreases the refcount too, so increase it up
+ weakref.ref();
+}
+
+QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
+{
+ Q_ASSERT(obj);
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+ Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
+
+ ExternalRefCountData *that = d->sharedRefcount;
+ if (that) {
+ that->weakref.ref();
+ return that;
+ }
+
+ // we can create the refcount data because it doesn't exist
+ ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
+ x->strongref = -1;
+ x->weakref = 2; // the QWeakPointer that called us plus the QObject itself
+ if (!d->sharedRefcount.testAndSetRelease(0, x)) {
+ delete x;
+ d->sharedRefcount->weakref.ref();
+ }
+ return d->sharedRefcount;
+}
+
+QT_END_NAMESPACE
+
+#endif
+
+
+
+//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT
+# ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT
+# if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
+# define BACKTRACE_SUPPORTED
+# elif defined(Q_OS_MACX)
+# define BACKTRACE_SUPPORTED
+# endif
+# endif
+
+# if defined(BACKTRACE_SUPPORTED)
+# include <sys/types.h>
+# include <execinfo.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/wait.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline QByteArray saveBacktrace() __attribute__((always_inline));
+static inline QByteArray saveBacktrace()
+{
+ static const int maxFrames = 32;
+
+ QByteArray stacktrace;
+ stacktrace.resize(sizeof(void*) * maxFrames);
+ int stack_size = backtrace((void**)stacktrace.data(), maxFrames);
+ stacktrace.resize(sizeof(void*) * stack_size);
+
+ return stacktrace;
+}
+
+static void printBacktrace(QByteArray stacktrace)
+{
+ void *const *stack = (void *const *)stacktrace.constData();
+ int stack_size = stacktrace.size() / sizeof(void*);
+ char **stack_symbols = backtrace_symbols(stack, stack_size);
+
+ int filter[2];
+ pid_t child = -1;
+ if (pipe(filter) != -1)
+ child = fork();
+ if (child == 0) {
+ // child process
+ dup2(fileno(stderr), fileno(stdout));
+ dup2(filter[0], fileno(stdin));
+ close(filter[0]);
+ close(filter[1]);
+ execlp("c++filt", "c++filt", "-n", NULL);
+
+ // execlp failed
+ execl("/bin/cat", "/bin/cat", NULL);
+ _exit(127);
+ }
+
+ // parent process
+ close(filter[0]);
+ FILE *output;
+ if (child == -1) {
+ // failed forking
+ close(filter[1]);
+ output = stderr;
+ } else {
+ output = fdopen(filter[1], "w");
+ }
+
+ fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n");
+ for (int i = 0; i < stack_size; ++i) {
+ if (strlen(stack_symbols[i]))
+ fprintf(output, "#%-2d %s\n", i, stack_symbols[i]);
+ else
+ fprintf(output, "#%-2d %p\n", i, stack[i]);
+ }
+
+ if (child != -1) {
+ fclose(output);
+ waitpid(child, 0, 0);
+ }
+}
+
+QT_END_NAMESPACE
+
+# endif // BACKTRACE_SUPPORTED
+
+namespace {
+ QT_USE_NAMESPACE
+ struct Data {
+ const volatile void *pointer;
+# ifdef BACKTRACE_SUPPORTED
+ QByteArray backtrace;
+# endif
+ };
+
+ class KnownPointers
+ {
+ public:
+ QMutex mutex;
+ QHash<const void *, Data> dPointers;
+ QHash<const volatile void *, const void *> dataPointers;
+ };
+}
+
+Q_GLOBAL_STATIC(KnownPointers, knownPointers)
+
+QT_BEGIN_NAMESPACE
+
+namespace QtSharedPointer {
+ Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *);
+ Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck();
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckAdd(const volatile void *)
+{
+ // Qt 4.5 compatibility
+ // this function is broken by design, so it was replaced with internalSafetyCheckAdd2
+ //
+ // it's broken because we tracked the pointers added and
+ // removed from QSharedPointer, converted to void*.
+ // That is, this is supposed to track the "top-of-object" pointer in
+ // case of multiple inheritance.
+ //
+ // However, it doesn't work well in some compilers:
+ // if you create an object with a class of type A and the last reference
+ // is dropped of type B, then the value passed to internalSafetyCheckRemove could
+ // be different than was added. That would leave dangling addresses.
+ //
+ // So instead, we track the pointer by the d-pointer instead.
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckRemove(const volatile void *)
+{
+ // Qt 4.5 compatibility
+ // see comments above
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr)
+{
+ // see comments above for the rationale for this function
+ KnownPointers *const kp = knownPointers();
+ if (!kp)
+ return; // end-game: the application is being destroyed already
+
+ 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);
+ if (other_d_ptr) {
+# ifdef BACKTRACE_SUPPORTED
+ printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace);
+# endif
+ qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked "
+ "by another QSharedPointer object %p", ptr, other_d_ptr);
+ }
+
+ Data data;
+ data.pointer = ptr;
+# ifdef BACKTRACE_SUPPORTED
+ data.backtrace = saveBacktrace();
+# endif
+
+ kp->dPointers.insert(d_ptr, data);
+ kp->dataPointers.insert(ptr, d_ptr);
+ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr)
+{
+ KnownPointers *const kp = knownPointers();
+ if (!kp)
+ return; // end-game: the application is being destroyed already
+
+ QMutexLocker lock(&kp->mutex);
+
+ QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr);
+ if (it == kp->dPointers.end()) {
+ qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. "
+ "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout "
+ "in your code.", d_ptr);
+ }
+
+ QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer);
+ Q_ASSERT(it2 != kp->dataPointers.end());
+
+ //qDebug("Removing d=%p value=%p", d_ptr, it->pointer);
+
+ // remove entries
+ kp->dataPointers.erase(it2);
+ kp->dPointers.erase(it);
+ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
+}
+
+/*!
+ \internal
+ Called by the QSharedPointer autotest
+*/
+void QtSharedPointer::internalSafetyCheckCleanCheck()
+{
+# ifdef QT_BUILD_INTERNAL
+ KnownPointers *const kp = knownPointers();
+ Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!");
+
+ if (kp->dPointers.size() != kp->dataPointers.size())
+ qFatal("Internal consistency error: the number of pointers is not equal!");
+
+ if (!kp->dPointers.isEmpty())
+ qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size());
+# endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
new file mode 100644
index 0000000000..a57abb3ab9
--- /dev/null
+++ b/src/corelib/tools/qsharedpointer.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHAREDPOINTER_H
+#define QSHAREDPOINTER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qshareddata.h>
+
+#ifndef Q_QDOC
+# include <QtCore/qsharedpointer_impl.h>
+#else
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// These classes are here to fool qdoc into generating a better documentation
+
+template <class T>
+class QSharedPointer
+{
+public:
+ // basic accessor functions
+ T *data() const;
+ bool isNull() const;
+ operator bool() const;
+ bool operator!() const;
+ T &operator*() const;
+ T *operator ->() const;
+
+ // constructors
+ QSharedPointer();
+ explicit QSharedPointer(T *ptr);
+ QSharedPointer(T *ptr, Deleter d);
+ QSharedPointer(const QSharedPointer<T> &other);
+ QSharedPointer(const QWeakPointer<T> &other);
+
+ ~QSharedPointer() { }
+
+ QSharedPointer<T> &operator=(const QSharedPointer<T> &other);
+ QSharedPointer<T> &operator=(const QWeakPointer<T> &other);
+
+ QWeakPointer<T> toWeakRef() const;
+
+ void clear();
+
+ // casts:
+ template <class X> QSharedPointer<X> staticCast() const;
+ template <class X> QSharedPointer<X> dynamicCast() const;
+ template <class X> QSharedPointer<X> constCast() const;
+ template <class X> QSharedPointer<X> objectCast() const;
+};
+
+template <class T>
+class QWeakPointer
+{
+public:
+ // basic accessor functions
+ bool isNull() const;
+ operator bool() const;
+ bool operator!() const;
+
+ // constructors:
+ QWeakPointer();
+ QWeakPointer(const QWeakPointer<T> &other);
+ QWeakPointer(const QSharedPointer<T> &other);
+
+ ~QWeakPointer();
+
+ QWeakPointer<T> operator=(const QWeakPointer<T> &other);
+ QWeakPointer<T> operator=(const QSharedPointer<T> &other);
+
+ QWeakPointer(const QObject *other);
+ QWeakPointer<T> operator=(const QObject *other);
+
+ T *data() const;
+ void clear();
+
+ QSharedPointer<T> toStrongRef() const;
+};
+
+template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2);
+template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2);
+template<class T, class X> bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
+template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2);
+template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2);
+
+template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other);
+template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other);
+template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src);
+
+template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q_QDOC
+
+#endif // QSHAREDPOINTER_H
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
new file mode 100644
index 0000000000..b29e5b69e3
--- /dev/null
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -0,0 +1,898 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q_QDOC
+
+#ifndef QSHAREDPOINTER_H
+#error Do not include qsharedpointer_impl.h directly
+#endif
+
+#if 0
+// These macros are duplicated here to make syncqt not complain a about
+// this header, as we have a "qt_sync_stop_processing" below, which in turn
+// is here because this file contains a template mess and duplicates the
+// classes found in qsharedpointer.h
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+QT_END_NAMESPACE
+QT_END_HEADER
+#pragma qt_sync_stop_processing
+#endif
+
+#include <new>
+#include <QtCore/qatomic.h>
+#include <QtCore/qobject.h> // for qobject_cast
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
+// generates a compiler error if the following construct isn't valid:
+// T *ptr1;
+// X *ptr2 = ptr1;
+//
+#ifdef QT_NO_DEBUG
+# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop()
+#else
+
+template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
+# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \
+ qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
+#endif
+
+//
+// forward declarations
+//
+template <class T> class QWeakPointer;
+template <class T> class QSharedPointer;
+
+template <class X, class T>
+QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
+template <class X, class T>
+QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
+template <class X, class T>
+QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
+
+#ifndef QT_NO_QOBJECT
+template <class X, class T>
+QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
+#endif
+
+namespace QtSharedPointer {
+ template <class T> class InternalRefCount;
+ template <class T> class ExternalRefCount;
+
+ template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
+
+ // used in debug mode to verify the reuse of pointers
+ Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *);
+
+ template <class T, typename Klass, typename RetVal>
+ inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
+ { (t->*memberDeleter)(); }
+ template <class T, typename Deleter>
+ inline void executeDeleter(T *t, Deleter d)
+ { d(t); }
+ template <class T> inline void normalDeleter(T *t) { delete t; }
+
+ // this uses partial template specialization
+ template <class T> struct RemovePointer;
+ template <class T> struct RemovePointer<T *> { typedef T Type; };
+ template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
+ template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
+
+ // This class provides the basic functionality of a pointer wrapper.
+ // Its existence is mostly legacy, since originally QSharedPointer
+ // could also be used for internally-refcounted objects.
+ template <class T>
+ class Basic
+ {
+#ifndef Q_CC_NOKIAX86
+ typedef T *Basic:: *RestrictedBool;
+#endif
+ public:
+ typedef T Type;
+ typedef T element_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;
+
+ inline T *data() const { return value; }
+ inline bool isNull() const { return !data(); }
+#ifndef Q_CC_NOKIAX86
+ inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; }
+#else
+ inline operator bool() const { return isNull() ? 0 : &Basic::value; }
+#endif
+ inline bool operator !() const { return isNull(); }
+ inline T &operator*() const { return *data(); }
+ inline T *operator->() const { return data(); }
+
+ protected:
+ inline Basic(T *ptr = 0) : value(ptr) { }
+ inline Basic(Qt::Initialization) { }
+ // ~Basic();
+
+ inline void internalConstruct(T *ptr)
+ {
+ value = ptr;
+ }
+
+#if defined(Q_NO_TEMPLATE_FRIENDS)
+ public:
+#else
+ template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
+#endif
+
+ Type *value;
+ };
+
+ // This class is the d-pointer of QSharedPointer and QWeakPointer.
+ //
+ // It is a reference-counted reference counter. "strongref" is the inner
+ // reference counter, and it tracks the lifetime of the pointer itself.
+ // "weakref" is the outer reference counter and it tracks the lifetime of
+ // the ExternalRefCountData object.
+ struct ExternalRefCountData
+ {
+ QBasicAtomicInt weakref;
+ QBasicAtomicInt strongref;
+
+ inline ExternalRefCountData()
+ {
+ strongref = 1;
+ weakref = 1;
+ }
+ inline ExternalRefCountData(Qt::Initialization) { }
+ virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); }
+
+ // overridden by derived classes
+ // returns false to indicate caller should delete the pointer
+ // returns true in case it has already done so
+ virtual inline bool destroy() { return false; }
+
+#ifndef QT_NO_QOBJECT
+ Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
+ Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
+#endif
+ inline void setQObjectShared(...) { }
+ };
+ // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
+
+ // This class extends ExternalRefCountData with a pointer
+ // to a function, which is called by the destroy() function.
+ struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
+ {
+ typedef void (*DestroyerFn)(ExternalRefCountData *);
+ DestroyerFn destroyer;
+
+ inline ExternalRefCountWithDestroyFn(DestroyerFn d)
+ : destroyer(d)
+ { }
+
+ inline bool destroy() { destroyer(this); return true; }
+ inline void operator delete(void *ptr) { ::operator delete(ptr); }
+ inline void operator delete(void *, void *) { }
+ };
+ // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
+
+ // This class extends ExternalRefCountWithDestroyFn and implements
+ // the static function that deletes the object. The pointer and the
+ // custom deleter are kept in the "extra" member.
+ template <class T, typename Deleter>
+ struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn
+ {
+ typedef ExternalRefCountWithCustomDeleter Self;
+ typedef ExternalRefCountWithDestroyFn BaseClass;
+
+ struct CustomDeleter
+ {
+ Deleter deleter;
+ T *ptr;
+
+ inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
+ };
+ CustomDeleter extra;
+ // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*)
+ // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
+ // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
+
+ static inline void deleter(ExternalRefCountData *self)
+ {
+ Self *realself = static_cast<Self *>(self);
+ executeDeleter(realself->extra.ptr, realself->extra.deleter);
+
+ // delete the deleter too
+ realself->extra.~CustomDeleter();
+ }
+ static void safetyCheckDeleter(ExternalRefCountData *self)
+ {
+ internalSafetyCheckRemove2(self);
+ deleter(self);
+ }
+
+ static inline Self *create(T *ptr, Deleter userDeleter)
+ {
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ DestroyerFn destroy = &safetyCheckDeleter;
+# else
+ DestroyerFn destroy = &deleter;
+# endif
+ Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
+
+ // initialize the two sub-objects
+ new (&d->extra) CustomDeleter(ptr, userDeleter);
+ new (d) BaseClass(destroy); // can't throw
+
+ return d;
+ }
+ private:
+ // prevent construction and the emission of virtual symbols
+ ExternalRefCountWithCustomDeleter();
+ ~ExternalRefCountWithCustomDeleter();
+ };
+
+ // This class extends ExternalRefCountWithDestroyFn and adds a "T"
+ // member. That way, when the create() function is called, we allocate
+ // memory for both QSharedPointer's d-pointer and the actual object being
+ // tracked.
+ template <class T>
+ struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn
+ {
+ typedef ExternalRefCountWithDestroyFn Parent;
+ T data;
+
+ static void deleter(ExternalRefCountData *self)
+ {
+ ExternalRefCountWithContiguousData *that =
+ static_cast<ExternalRefCountWithContiguousData *>(self);
+ that->data.~T();
+ }
+ static void safetyCheckDeleter(ExternalRefCountData *self)
+ {
+ internalSafetyCheckRemove2(self);
+ deleter(self);
+ }
+
+ static inline ExternalRefCountData *create(T **ptr)
+ {
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ DestroyerFn destroy = &safetyCheckDeleter;
+# else
+ DestroyerFn destroy = &deleter;
+# endif
+ ExternalRefCountWithContiguousData *d =
+ static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
+
+ // initialize the d-pointer sub-object
+ // leave d->data uninitialized
+ new (d) Parent(destroy); // can't throw
+
+ *ptr = &d->data;
+ return d;
+ }
+
+ private:
+ // prevent construction and the emission of virtual symbols
+ ExternalRefCountWithContiguousData();
+ ~ExternalRefCountWithContiguousData();
+ };
+
+ // This is the main body of QSharedPointer. It implements the
+ // external reference counting functionality.
+ template <class T>
+ class ExternalRefCount: public Basic<T>
+ {
+ protected:
+ typedef ExternalRefCountData Data;
+
+ inline void deref()
+ { deref(d, this->value); }
+ static inline void deref(Data *d, T *value)
+ {
+ if (!d) return;
+ if (!d->strongref.deref()) {
+ if (!d->destroy())
+ delete value;
+ }
+ if (!d->weakref.deref())
+ delete d;
+ }
+
+ inline void internalConstruct(T *ptr)
+ {
+#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ internalConstruct<void (*)(T *)>(ptr, normalDeleter);
+#else
+ if (ptr)
+ d = new Data;
+ else
+ d = 0;
+ internalFinishConstruction(ptr);
+#endif
+ }
+
+ template <typename Deleter>
+ inline void internalConstruct(T *ptr, Deleter deleter)
+ {
+ if (ptr)
+ d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
+ else
+ d = 0;
+ internalFinishConstruction(ptr);
+ }
+
+ inline void internalCreate()
+ {
+ T *ptr;
+ d = ExternalRefCountWithContiguousData<T>::create(&ptr);
+ Basic<T>::internalConstruct(ptr);
+ }
+
+ inline void internalFinishConstruction(T *ptr)
+ {
+ Basic<T>::internalConstruct(ptr);
+ if (ptr) d->setQObjectShared(ptr, true);
+#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ if (ptr) internalSafetyCheckAdd2(d, ptr);
+#endif
+ }
+
+ inline ExternalRefCount() : d(0) { }
+ inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { }
+
+ inline ExternalRefCount(T *ptr) : Basic<T>(Qt::Uninitialized) // throws
+ { internalConstruct(ptr); }
+ template <typename Deleter>
+ inline ExternalRefCount(T *ptr, Deleter deleter) : Basic<T>(Qt::Uninitialized) // throws
+ { internalConstruct(ptr, deleter); }
+
+ inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
+ { if (d) ref(); }
+ template <class X>
+ inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d)
+ { if (d) ref(); }
+ inline ~ExternalRefCount() { deref(); }
+
+ template <class X>
+ inline void internalCopy(const ExternalRefCount<X> &other)
+ {
+ Data *o = other.d;
+ T *actual = other.value;
+ if (o)
+ other.ref();
+ qSwap(d, o);
+ qSwap(this->value, actual);
+ deref(o, actual);
+ }
+
+ inline void internalSwap(ExternalRefCount &other)
+ {
+ qSwap(d, other.d);
+ qSwap(this->value, other.value);
+ }
+
+#if defined(Q_NO_TEMPLATE_FRIENDS)
+ public:
+#else
+ template <class X> friend class ExternalRefCount;
+ template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
+ template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
+#endif
+ inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
+
+ inline void internalSet(Data *o, T *actual)
+ {
+ if (o) {
+ // increase the strongref, but never up from zero
+ // or less (-1 is used by QWeakPointer on untracked QObject)
+ register int tmp = o->strongref;
+ while (tmp > 0) {
+ // try to increment from "tmp" to "tmp + 1"
+ if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
+ break; // succeeded
+ tmp = o->strongref; // failed, try again
+ }
+
+ if (tmp > 0)
+ o->weakref.ref();
+ else
+ o = 0;
+ }
+
+ qSwap(d, o);
+ qSwap(this->value, actual);
+ if (!d || d->strongref == 0)
+ this->value = 0;
+
+ // dereference saved data
+ deref(o, actual);
+ }
+
+ Data *d;
+
+ private:
+ template<class X> ExternalRefCount(const InternalRefCount<X> &);
+ };
+} // namespace QtSharedPointer
+
+template <class T>
+class QSharedPointer: public QtSharedPointer::ExternalRefCount<T>
+{
+ typedef typename QtSharedPointer::ExternalRefCount<T> BaseClass;
+public:
+ inline QSharedPointer() { }
+ // inline ~QSharedPointer() { }
+
+ inline explicit QSharedPointer(T *ptr) : BaseClass(ptr) // throws
+ { }
+
+ template <typename Deleter>
+ inline QSharedPointer(T *ptr, Deleter d) : BaseClass(ptr, d) // throws
+ { }
+
+ inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { }
+ inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
+ {
+ BaseClass::internalCopy(other);
+ return *this;
+ }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
+ {
+ QSharedPointer<T>::internalSwap(other);
+ return *this;
+ }
+#endif
+
+ template <class X>
+ inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
+ { }
+
+ template <class X>
+ inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
+ {
+ QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
+ BaseClass::internalCopy(other);
+ return *this;
+ }
+
+ template <class X>
+ inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
+ { this->d = 0; *this = other; }
+
+ template <class X>
+ inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
+ { BaseClass::internalSet(other.d, other.value); return *this; }
+
+ inline void swap(QSharedPointer &other)
+ { QSharedPointer<T>::internalSwap(other); }
+
+ template <class X>
+ QSharedPointer<X> staticCast() const
+ {
+ return qSharedPointerCast<X, T>(*this);
+ }
+
+ template <class X>
+ QSharedPointer<X> dynamicCast() const
+ {
+ return qSharedPointerDynamicCast<X, T>(*this);
+ }
+
+ template <class X>
+ QSharedPointer<X> constCast() const
+ {
+ return qSharedPointerConstCast<X, T>(*this);
+ }
+
+#ifndef QT_NO_QOBJECT
+ template <class X>
+ QSharedPointer<X> objectCast() const
+ {
+ return qSharedPointerObjectCast<X, T>(*this);
+ }
+#endif
+
+ inline void clear() { *this = QSharedPointer<T>(); }
+
+ QWeakPointer<T> toWeakRef() const;
+
+protected:
+ inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
+
+public:
+ static inline QSharedPointer<T> create()
+ {
+ QSharedPointer<T> result(Qt::Uninitialized);
+ result.internalCreate();
+
+ // now initialize the data
+ new (result.data()) T();
+ result.internalFinishConstruction(result.data());
+ return result;
+ }
+};
+
+template <class T>
+class QWeakPointer
+{
+#ifndef Q_CC_NOKIAX86
+ typedef T *QWeakPointer:: *RestrictedBool;
+#endif
+ typedef QtSharedPointer::ExternalRefCountData Data;
+
+public:
+ typedef T element_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;
+
+ inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; }
+#ifndef Q_CC_NOKIAX86
+ inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
+#else
+ inline operator bool() const { return isNull() ? 0 : &QWeakPointer::value; }
+#endif
+ inline bool operator !() const { return isNull(); }
+ inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; }
+
+ inline QWeakPointer() : d(0), value(0) { }
+ inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
+
+#ifndef QT_NO_QOBJECT
+ // special constructor that is enabled only if X derives from QObject
+ template <class X>
+ inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
+ { }
+#endif
+ template <class X>
+ inline QWeakPointer &operator=(X *ptr)
+ { return *this = QWeakPointer(ptr); }
+
+ inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
+ { if (d) d->weakref.ref(); }
+ inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
+ {
+ internalSet(o.d, o.value);
+ return *this;
+ }
+
+ inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
+ { if (d) d->weakref.ref();}
+ inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
+ {
+ internalSet(o.d, o.value);
+ return *this;
+ }
+
+ template <class X>
+ inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0)
+ { *this = o; }
+
+ template <class X>
+ inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
+ {
+ // conversion between X and T could require access to the virtual table
+ // so force the operation to go through QSharedPointer
+ *this = o.toStrongRef();
+ return *this;
+ }
+
+ template <class X>
+ inline bool operator==(const QWeakPointer<X> &o) const
+ { return d == o.d && value == static_cast<const T *>(o.value); }
+
+ template <class X>
+ inline bool operator!=(const QWeakPointer<X> &o) const
+ { return !(*this == o); }
+
+ template <class X>
+ inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0)
+ { *this = o; }
+
+ template <class X>
+ inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
+ {
+ QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
+ internalSet(o.d, o.data());
+ return *this;
+ }
+
+ template <class X>
+ inline bool operator==(const QSharedPointer<X> &o) const
+ { return d == o.d; }
+
+ template <class X>
+ inline bool operator!=(const QSharedPointer<X> &o) const
+ { return !(*this == o); }
+
+ inline void clear() { *this = QWeakPointer<T>(); }
+
+ inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+
+#if defined(QWEAKPOINTER_ENABLE_ARROW)
+ inline T *operator->() const { return data(); }
+#endif
+
+private:
+
+#if defined(Q_NO_TEMPLATE_FRIENDS)
+public:
+#else
+ template <class X> friend class QSharedPointer;
+#endif
+
+ inline void internalSet(Data *o, T *actual)
+ {
+ if (d == o) return;
+ if (o)
+ o->weakref.ref();
+ if (d && !d->weakref.deref())
+ delete d;
+ d = o;
+ value = actual;
+ }
+
+ Data *d;
+ T *value;
+};
+
+//
+// operator== and operator!=
+//
+template <class T, class X>
+bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() == ptr2.data();
+}
+template <class T, class X>
+bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() != ptr2.data();
+}
+
+template <class T, class X>
+bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
+{
+ return ptr1.data() == ptr2;
+}
+template <class T, class X>
+bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1 == ptr2.data();
+}
+template <class T, class X>
+bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
+{
+ return !(ptr1 == ptr2);
+}
+template <class T, class X>
+bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
+{
+ return !(ptr2 == ptr1);
+}
+
+template <class T, class X>
+bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+{
+ return ptr2 == ptr1;
+}
+template <class T, class X>
+bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+{
+ return ptr2 != ptr1;
+}
+
+//
+// operator-
+//
+template <class T, class X>
+Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() - ptr2.data();
+}
+template <class T, class X>
+Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
+{
+ return ptr1.data() - ptr2;
+}
+template <class T, class X>
+Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1 - ptr2.data();
+}
+
+//
+// operator<
+//
+template <class T, class X>
+Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() < ptr2.data();
+}
+template <class T, class X>
+Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
+{
+ return ptr1.data() < ptr2;
+}
+template <class T, class X>
+Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1 < ptr2.data();
+}
+
+//
+// qHash
+//
+template <class T> inline uint qHash(const T *key); // defined in qhash.h
+template <class T>
+Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr)
+{
+ return QT_PREPEND_NAMESPACE(qHash)<T>(ptr.data());
+}
+
+
+template <class T>
+Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
+{
+ return QWeakPointer<T>(*this);
+}
+
+template <class T>
+inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
+{
+ p1.swap(p2);
+}
+
+#ifndef QT_NO_STL
+QT_END_NAMESPACE
+namespace std {
+ template <class T>
+ inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
+ { p1.swap(p2); }
+}
+QT_BEGIN_NAMESPACE
+#endif
+
+namespace QtSharedPointer {
+// helper functions:
+ template <class X, class T>
+ Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
+ {
+ QSharedPointer<X> result;
+ result.internalSet(src.d, ptr);
+ return result;
+ }
+}
+
+// cast operators
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
+{
+ register X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
+}
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerCast<X, T>(src.toStrongRef());
+}
+
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
+{
+ register X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
+}
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
+}
+
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
+{
+ register X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
+}
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerConstCast<X, T>(src.toStrongRef());
+}
+
+template <class X, class T>
+Q_INLINE_TEMPLATE
+QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
+{
+ return qSharedPointerCast<X, T>(src).toWeakRef();
+}
+
+#ifndef QT_NO_QOBJECT
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
+{
+ register X *ptr = qobject_cast<X *>(src.data());
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
+}
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerObjectCast<X>(src.toStrongRef());
+}
+
+template <class X, class T>
+inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
+qobject_cast(const QSharedPointer<T> &src)
+{
+ return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
+}
+template <class X, class T>
+inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
+qobject_cast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, 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);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
new file mode 100644
index 0000000000..f96703d1e3
--- /dev/null
+++ b/src/corelib/tools/qsimd.cpp
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimd_p.h"
+#include <QByteArray>
+#include <stdio.h>
+
+#if defined(Q_OS_WINCE)
+#include <windows.h>
+#endif
+
+#if defined(Q_OS_WIN64) && !defined(Q_CC_GNU)
+#include <intrin.h>
+#endif
+
+#if defined(Q_OS_LINUX) && defined(__arm__)
+#include "private/qcore_unix_p.h"
+
+// the kernel header definitions for HWCAP_*
+// (the ones we need/may need anyway)
+
+// copied from <asm/hwcap.h> (ARM)
+#define HWCAP_IWMMXT 512
+#define HWCAP_CRUNCH 1024
+#define HWCAP_THUMBEE 2048
+#define HWCAP_NEON 4096
+#define HWCAP_VFPv3 8192
+#define HWCAP_VFPv3D16 16384
+
+// copied from <linux/auxvec.h>
+#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined (Q_OS_NACL)
+static inline uint detectProcessorFeatures()
+{
+ return 0;
+}
+#elif defined (Q_OS_WINCE)
+static inline uint detectProcessorFeatures()
+{
+ uint features = 0;
+
+#if defined (ARM)
+ if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX)) {
+ features = IWMMXT;
+ return features;
+ }
+#elif defined(_X86_)
+ features = 0;
+#if defined QT_HAVE_MMX
+ if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
+ features |= MMX;
+#endif
+#if defined QT_HAVE_3DNOW
+ if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
+ features |= MMX3DNOW;
+#endif
+ return features;
+#endif
+ features = 0;
+ return features;
+}
+
+#elif defined(__arm__) || defined(__arm) || defined(QT_HAVE_IWMMXT) || defined(QT_HAVE_NEON)
+static inline uint detectProcessorFeatures()
+{
+ uint features = 0;
+
+#if defined(Q_OS_LINUX)
+ 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 (vector[i+1] & HWCAP_IWMMXT)
+ features |= IWMMXT;
+ if (vector[i+1] & HWCAP_NEON)
+ features |= NEON;
+ break;
+ }
+ }
+
+ ::qt_safe_close(auxv);
+ return features;
+ }
+ // fall back if /proc/self/auxv wasn't found
+#endif
+
+#if defined(QT_HAVE_IWMMXT)
+ // runtime detection only available when running as a previlegied process
+ features = IWMMXT;
+#elif defined(QT_ALWAYS_HAVE_NEON)
+ features = NEON;
+#endif
+
+ return features;
+}
+
+#elif defined(__i386__) || defined(_M_IX86)
+static inline uint detectProcessorFeatures()
+{
+ uint features = 0;
+
+ unsigned int extended_result = 0;
+ unsigned int feature_result = 0;
+ uint result = 0;
+ /* see p. 118 of amd64 instruction set manual Vol3 */
+#if defined(Q_CC_GNU)
+ long cpuid_supported, tmp1;
+ asm ("pushf\n"
+ "pop %0\n"
+ "mov %0, %1\n"
+ "xor $0x00200000, %0\n"
+ "push %0\n"
+ "popf\n"
+ "pushf\n"
+ "pop %0\n"
+ "xor %1, %0\n" // %eax is now 0 if CPUID is not supported
+ : "=a" (cpuid_supported), "=r" (tmp1)
+ );
+ if (cpuid_supported) {
+ asm ("xchg %%ebx, %2\n"
+ "cpuid\n"
+ "xchg %%ebx, %2\n"
+ : "=c" (feature_result), "=d" (result), "=&r" (tmp1)
+ : "a" (1));
+
+ asm ("xchg %%ebx, %1\n"
+ "cpuid\n"
+ "cmp $0x80000000, %%eax\n"
+ "jnbe 1f\n"
+ "xor %0, %0\n"
+ "jmp 2f\n"
+ "1:\n"
+ "mov $0x80000001, %%eax\n"
+ "cpuid\n"
+ "2:\n"
+ "xchg %%ebx, %1\n"
+ : "=d" (extended_result), "=&r" (tmp1)
+ : "a" (0x80000000)
+ : "%ecx"
+ );
+ }
+
+#elif defined (Q_OS_WIN)
+ _asm {
+ push eax
+ push ebx
+ push ecx
+ push edx
+ pushfd
+ pop eax
+ mov ebx, eax
+ xor eax, 00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ mov edx, 0
+ xor eax, ebx
+ jz skip
+
+ mov eax, 1
+ cpuid
+ mov result, edx
+ mov feature_result, ecx
+ skip:
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ }
+
+ _asm {
+ push eax
+ push ebx
+ push ecx
+ push edx
+ pushfd
+ pop eax
+ mov ebx, eax
+ xor eax, 00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ mov edx, 0
+ xor eax, ebx
+ jz skip2
+
+ mov eax, 80000000h
+ cpuid
+ cmp eax, 80000000h
+ jbe skip2
+ mov eax, 80000001h
+ cpuid
+ mov extended_result, edx
+ skip2:
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ }
+#endif
+
+
+ // result now contains the standard feature bits
+ if (result & (1u << 15))
+ features |= CMOV;
+ if (result & (1u << 23))
+ features |= MMX;
+ if (extended_result & (1u << 22))
+ features |= MMXEXT;
+ if (extended_result & (1u << 31))
+ features |= MMX3DNOW;
+ if (extended_result & (1u << 30))
+ features |= MMX3DNOWEXT;
+ if (result & (1u << 25))
+ features |= SSE;
+ if (result & (1u << 26))
+ features |= SSE2;
+ if (feature_result & (1u))
+ features |= SSE3;
+ if (feature_result & (1u << 9))
+ features |= SSSE3;
+ if (feature_result & (1u << 19))
+ features |= SSE4_1;
+ if (feature_result & (1u << 20))
+ features |= SSE4_2;
+ if (feature_result & (1u << 28))
+ features |= AVX;
+
+ return features;
+}
+
+#elif defined(__x86_64) || defined(Q_OS_WIN64)
+static inline uint detectProcessorFeatures()
+{
+ uint features = MMX|SSE|SSE2|CMOV;
+ uint feature_result = 0;
+
+#if defined (Q_OS_WIN64)
+ {
+ int info[4];
+ __cpuid(info, 1);
+ feature_result = info[2];
+ }
+#elif defined(Q_CC_GNU)
+ quint64 tmp;
+ asm ("xchg %%rbx, %1\n"
+ "cpuid\n"
+ "xchg %%rbx, %1\n"
+ : "=c" (feature_result), "=&r" (tmp)
+ : "a" (1)
+ : "%edx"
+ );
+#endif
+
+ if (feature_result & (1u))
+ features |= SSE3;
+ if (feature_result & (1u << 9))
+ features |= SSSE3;
+ if (feature_result & (1u << 19))
+ features |= SSE4_1;
+ if (feature_result & (1u << 20))
+ features |= SSE4_2;
+ if (feature_result & (1u << 28))
+ features |= AVX;
+
+ return features;
+}
+
+#elif defined(__ia64__)
+static inline uint detectProcessorFeatures()
+{
+ return MMX|SSE|SSE2;
+}
+
+#else
+static inline uint detectProcessorFeatures()
+{
+ return 0;
+}
+#endif
+
+/*
+ * Use kdesdk/scripts/generate_string_table.pl to update the table below.
+ * Here's the data (don't forget the ONE leading space):
+ mmx
+ mmxext
+ mmx3dnow
+ mmx3dnowext
+ sse
+ sse2
+ cmov
+ iwmmxt
+ neon
+ sse3
+ ssse3
+ sse4.1
+ sse4.2
+ avx
+ */
+
+// begin generated
+static const char features_string[] =
+ " mmx\0"
+ " mmxext\0"
+ " mmx3dnow\0"
+ " mmx3dnowext\0"
+ " sse\0"
+ " sse2\0"
+ " cmov\0"
+ " iwmmxt\0"
+ " neon\0"
+ " sse3\0"
+ " ssse3\0"
+ " sse4.1\0"
+ " sse4.2\0"
+ " avx\0"
+ "\0";
+
+static const int features_indices[] = {
+ 0, 5, 13, 23, 36, 41, 47, 53,
+ 61, 67, 73, 80, 88, 96, -1
+};
+// end generated
+
+const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]);
+
+uint qDetectCPUFeatures()
+{
+ static QBasicAtomicInt features = Q_BASIC_ATOMIC_INITIALIZER(-1);
+ if (features != -1)
+ return features;
+
+ uint 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 &= ~(1 << i);
+ }
+ }
+
+ features = f;
+ return features;
+}
+
+void qDumpCPUFeatures()
+{
+ uint features = qDetectCPUFeatures();
+ printf("Processor features: ");
+ for (int i = 0; i < features_count; ++i) {
+ if (features & (1 << i))
+ printf("%s", features_string + features_indices[i]);
+ }
+ puts("");
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
new file mode 100644
index 0000000000..4647804603
--- /dev/null
+++ b/src/corelib/tools/qsimd_p.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMD_P_H
+#define QSIMD_P_H
+
+#include <qglobal.h>
+
+
+QT_BEGIN_HEADER
+
+
+#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
+// Disable MMX and SSE on Mac/PPC builds, or if the compiler
+// does not support -Xarch argument passing
+#undef QT_HAVE_SSE
+#undef QT_HAVE_SSE2
+#undef QT_HAVE_SSE3
+#undef QT_HAVE_SSSE3
+#undef QT_HAVE_SSE4_1
+#undef QT_HAVE_SSE4_2
+#undef QT_HAVE_AVX
+#undef QT_HAVE_3DNOW
+#undef QT_HAVE_MMX
+#endif
+
+// SSE intrinsics
+#if defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC))
+#if defined(QT_LINUXBASE)
+/// this is an evil hack - the posix_memalign declaration in LSB
+/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
+# define posix_memalign _lsb_hack_posix_memalign
+# include <emmintrin.h>
+# undef posix_memalign
+#else
+# ifdef Q_CC_MINGW
+# include <windows.h>
+# endif
+# include <emmintrin.h>
+#endif
+
+// SSE3 intrinsics
+#if defined(QT_HAVE_SSE3) && (defined(__SSE3__) || defined(Q_CC_MSVC))
+#include <pmmintrin.h>
+#endif
+
+// SSSE3 intrinsics
+#if defined(QT_HAVE_SSSE3) && (defined(__SSSE3__) || defined(Q_CC_MSVC))
+#include <tmmintrin.h>
+#endif
+
+// SSE4.1 intrinsics
+#if defined(QT_HAVE_SSE4_1) && (defined(__SSE4_1__) || defined(Q_CC_MSVC))
+#include <smmintrin.h>
+#endif
+
+// SSE4.2 intrinsics
+#if defined(QT_HAVE_SSE4_2) && (defined(__SSE4_2__) || defined(Q_CC_MSVC))
+#include <nmmintrin.h>
+#endif
+
+// AVX intrinsics
+#if defined(QT_HAVE_AVX) && (defined(__AVX__) || defined(Q_CC_MSVC))
+#include <immintrin.h>
+#endif
+
+
+#if !defined(QT_BOOTSTRAPPED) && (!defined(Q_CC_MSVC) || (defined(_M_X64) || _M_IX86_FP == 2))
+#define QT_ALWAYS_HAVE_SSE2
+#endif
+#endif // defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC))
+
+// NEON intrinsics
+#if defined __ARM_NEON__
+#define QT_ALWAYS_HAVE_NEON
+#include <arm_neon.h>
+#endif
+
+
+// IWMMXT intrinsics
+#if defined(QT_HAVE_IWMMXT)
+#include <mmintrin.h>
+#if defined(Q_OS_WINCE)
+# include "qplatformdefs.h"
+#endif
+#endif
+
+#if defined(QT_HAVE_IWMMXT)
+#if !defined(__IWMMXT__) && !defined(Q_OS_WINCE)
+# include <xmmintrin.h>
+#elif defined(Q_OS_WINCE_STD) && defined(_X86_)
+# pragma warning(disable: 4391)
+# include <xmmintrin.h>
+#endif
+#endif
+
+// 3D now intrinsics
+#if defined(QT_HAVE_3DNOW)
+#include <mm3dnow.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+enum CPUFeatures {
+ None = 0,
+ MMX = 0x1,
+ MMXEXT = 0x2,
+ MMX3DNOW = 0x4,
+ MMX3DNOWEXT = 0x8,
+ SSE = 0x10,
+ SSE2 = 0x20,
+ CMOV = 0x40,
+ IWMMXT = 0x80,
+ NEON = 0x100,
+ SSE3 = 0x200,
+ SSSE3 = 0x400,
+ SSE4_1 = 0x800,
+ SSE4_2 = 0x1000,
+ AVX = 0x2000
+};
+
+Q_CORE_EXPORT uint qDetectCPUFeatures();
+
+
+#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)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIMD_P_H
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
new file mode 100644
index 0000000000..6e2768f59a
--- /dev/null
+++ b/src/corelib/tools/qsize.cpp
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsize.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSize
+ \ingroup painting
+
+ \brief The QSize class defines the size of a two-dimensional
+ object using integer point precision.
+
+ A size is specified by a width() and a height(). It can be set in
+ the constructor and changed using the setWidth(), setHeight(), or
+ scale() functions, or using arithmetic operators. A size can also
+ be manipulated directly by retrieving references to the width and
+ height using the rwidth() and rheight() functions. Finally, the
+ width and height can be swapped using the transpose() function.
+
+ The isValid() function determines if a size is valid (a valid size
+ has both width and height greater than zero). The isEmpty()
+ function returns true if either of the width and height is less
+ than, or equal to, zero, while the isNull() function returns true
+ only if both the width and the height is zero.
+
+ Use the expandedTo() function to retrieve a size which holds the
+ maximum height and width of \e this size and a given
+ size. Similarly, the boundedTo() function returns a size which
+ holds the minimum height and width of \e this size and a given
+ size.
+
+ QSize objects can be streamed as well as compared.
+
+ \sa QSizeF, QPoint, QRect
+*/
+
+
+/*****************************************************************************
+ QSize member functions
+ *****************************************************************************/
+
+/*!
+ \fn QSize::QSize()
+
+ Constructs a size with an invalid width and height (i.e., isValid()
+ returns false).
+
+ \sa isValid()
+*/
+
+/*!
+ \fn QSize::QSize(int width, int height)
+
+ Constructs a size with the given \a width and \a height.
+
+ \sa setWidth(), setHeight()
+*/
+
+/*!
+ \fn bool QSize::isNull() const
+
+ Returns true if both the width and height is 0; otherwise returns
+ false.
+
+ \sa isValid(), isEmpty()
+*/
+
+/*!
+ \fn bool QSize::isEmpty() const
+
+ Returns true if either of the width and height is less than or
+ equal to 0; otherwise returns false.
+
+ \sa isNull(), isValid()
+*/
+
+/*!
+ \fn bool QSize::isValid() const
+
+ Returns true if both the width and height is equal to or greater
+ than 0; otherwise returns false.
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn int QSize::width() const
+
+ Returns the width.
+
+ \sa height(), setWidth()
+*/
+
+/*!
+ \fn int QSize::height() const
+
+ Returns the height.
+
+ \sa width(), setHeight()
+*/
+
+/*!
+ \fn void QSize::setWidth(int width)
+
+ Sets the width to the given \a width.
+
+ \sa rwidth(), width(), setHeight()
+*/
+
+/*!
+ \fn void QSize::setHeight(int height)
+
+ Sets the height to the given \a height.
+
+ \sa rheight(), height(), setWidth()
+*/
+
+/*!
+ Swaps the width and height values.
+
+ \sa setWidth(), setHeight()
+*/
+
+void QSize::transpose()
+{
+ int tmp = wd;
+ wd = ht;
+ ht = tmp;
+}
+
+/*!
+ \fn void QSize::scale(int width, int height, Qt::AspectRatioMode mode)
+
+ Scales the size to a rectangle with the given \a width and \a
+ height, according to the specified \a mode:
+
+ \list
+ \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height).
+ \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle
+ as large as possible inside (\a width, \a height), preserving the aspect ratio.
+ \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle
+ as small as possible outside (\a width, \a height), preserving the aspect ratio.
+ \endlist
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 0
+
+ \sa setWidth(), setHeight()
+*/
+
+/*!
+ \fn void QSize::scale(const QSize &size, Qt::AspectRatioMode mode)
+ \overload
+
+ Scales the size to a rectangle with the given \a size, according to
+ the specified \a mode.
+*/
+void QSize::scale(const QSize &s, Qt::AspectRatioMode mode)
+{
+ if (mode == Qt::IgnoreAspectRatio || wd == 0 || ht == 0) {
+ wd = s.wd;
+ ht = s.ht;
+ } else {
+ bool useHeight;
+ qint64 rw = qint64(s.ht) * qint64(wd) / qint64(ht);
+
+ if (mode == Qt::KeepAspectRatio) {
+ useHeight = (rw <= s.wd);
+ } else { // mode == Qt::KeepAspectRatioByExpanding
+ useHeight = (rw >= s.wd);
+ }
+
+ if (useHeight) {
+ wd = rw;
+ ht = s.ht;
+ } else {
+ ht = qint32(qint64(s.wd) * qint64(ht) / qint64(wd));
+ wd = s.wd;
+ }
+ }
+}
+
+/*!
+ \fn int &QSize::rwidth()
+
+ Returns a reference to the width.
+
+ Using a reference makes it possible to manipulate the width
+ directly. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 1
+
+ \sa rheight(), setWidth()
+*/
+
+/*!
+ \fn int &QSize::rheight()
+
+ Returns a reference to the height.
+
+ Using a reference makes it possible to manipulate the height
+ directly. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 2
+
+ \sa rwidth(), setHeight()
+*/
+
+/*!
+ \fn QSize &QSize::operator+=(const QSize &size)
+
+ Adds the given \a size to \e this size, and returns a reference to
+ this size. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 3
+*/
+
+/*!
+ \fn QSize &QSize::operator-=(const QSize &size)
+
+ Subtracts the given \a size from \e this size, and returns a
+ reference to this size. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 4
+*/
+
+/*!
+ \fn QSize &QSize::operator*=(qreal factor)
+ \overload
+
+ Multiplies both the width and height by the given \a factor, and
+ returns a reference to the size.
+
+ Note that the result is rounded to the nearest integer.
+
+ \sa scale()
+*/
+
+/*!
+ \fn bool operator==(const QSize &s1, const QSize &s2)
+ \relates QSize
+
+ Returns true if \a s1 and \a s2 are equal; otherwise returns false.
+*/
+
+/*!
+ \fn bool operator!=(const QSize &s1, const QSize &s2)
+ \relates QSize
+
+ Returns true if \a s1 and \a s2 are different; otherwise returns false.
+*/
+
+/*!
+ \fn const QSize operator+(const QSize &s1, const QSize &s2)
+ \relates QSize
+
+ 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
+
+ Returns \a s2 subtracted from \a s1; each component is subtracted
+ separately.
+*/
+
+/*!
+ \fn const QSize operator*(const QSize &size, qreal factor)
+ \relates QSize
+
+ Multiplies the given \a size by the given \a factor, and returns
+ the result rounded to the nearest integer.
+
+ \sa QSize::scale()
+*/
+
+/*!
+ \fn const 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.
+*/
+
+/*!
+ \fn QSize &QSize::operator/=(qreal divisor)
+ \overload
+
+ Divides both the width and height by the given \a divisor, and
+ returns a reference to the size.
+
+ Note that the result is rounded to the nearest integer.
+
+ \sa QSize::scale()
+*/
+
+/*!
+ \fn const QSize operator/(const QSize &size, qreal divisor)
+ \relates QSize
+ \overload
+
+ Divides the given \a size by the given \a divisor, and returns the
+ result rounded to the nearest integer.
+
+ \sa QSize::scale()
+*/
+
+/*!
+ \fn QSize QSize::expandedTo(const QSize & otherSize) const
+
+ Returns a size holding the maximum width and height of this size
+ and the given \a otherSize.
+
+ \sa boundedTo(), scale()
+*/
+
+/*!
+ \fn QSize QSize::boundedTo(const QSize & otherSize) const
+
+ Returns a size holding the minimum width and height of this size
+ and the given \a otherSize.
+
+ \sa expandedTo(), scale()
+*/
+
+
+
+/*****************************************************************************
+ QSize stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QSize &size)
+ \relates QSize
+
+ Writes the given \a size to the given \a stream, and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QSize &sz)
+{
+ if (s.version() == 1)
+ s << (qint16)sz.width() << (qint16)sz.height();
+ else
+ s << (qint32)sz.width() << (qint32)sz.height();
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QSize &size)
+ \relates QSize
+
+ Reads a size from the given \a stream into the given \a size, and
+ returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QSize &sz)
+{
+ if (s.version() == 1) {
+ qint16 w, h;
+ s >> w; sz.rwidth() = w;
+ s >> h; sz.rheight() = h;
+ }
+ else {
+ qint32 w, h;
+ s >> w; sz.rwidth() = w;
+ s >> h; sz.rheight() = h;
+ }
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QSize &s) {
+ dbg.nospace() << "QSize(" << s.width() << ", " << s.height() << ')';
+ return dbg.space();
+}
+#endif
+
+
+
+/*!
+ \class QSizeF
+ \brief The QSizeF class defines the size of a two-dimensional object
+ using floating point precision.
+
+ \ingroup painting
+
+ A size is specified by a width() and a height(). It can be set in
+ the constructor and changed using the setWidth(), setHeight(), or
+ scale() functions, or using arithmetic operators. A size can also
+ be manipulated directly by retrieving references to the width and
+ height using the rwidth() and rheight() functions. Finally, the
+ width and height can be swapped using the transpose() function.
+
+ The isValid() function determines if a size is valid. A valid size
+ has both width and height greater than or equal to zero. The
+ isEmpty() function returns true if either of the width and height
+ is \e less than (or equal to) zero, while the isNull() function
+ returns true only if both the width and the height is zero.
+
+ Use the expandedTo() function to retrieve a size which holds the
+ maximum height and width of this size and a given
+ size. Similarly, the boundedTo() function returns a size which
+ holds the minimum height and width of this size and a given size.
+
+ The QSizeF class also provides the toSize() function returning a
+ QSize copy of this size, constructed by rounding the width and
+ height to the nearest integers.
+
+ QSizeF objects can be streamed as well as compared.
+
+ \sa QSize, QPointF, QRectF
+*/
+
+
+/*****************************************************************************
+ QSizeF member functions
+ *****************************************************************************/
+
+/*!
+ \fn QSizeF::QSizeF()
+
+ Constructs an invalid size.
+
+ \sa isValid()
+*/
+
+/*!
+ \fn QSizeF::QSizeF(const QSize &size)
+
+ Constructs a size with floating point accuracy from the given \a
+ size.
+
+ \sa toSize()
+*/
+
+/*!
+ \fn QSizeF::QSizeF(qreal width, qreal height)
+
+ Constructs a size with the given \a width and \a height.
+*/
+
+/*!
+ \fn bool QSizeF::isNull() const
+
+ Returns true if both the width and height are +0.0; otherwise returns
+ false.
+
+ \note Since this function treats +0.0 and -0.0 differently, sizes with
+ zero width and height where either or both values have a negative
+ sign are not defined to be null sizes.
+
+ \sa isValid(), isEmpty()
+*/
+
+/*!
+ \fn bool QSizeF::isEmpty() const
+
+ Returns true if either of the width and height is less than or
+ equal to 0; otherwise returns false.
+
+ \sa isNull(), isValid()
+*/
+
+/*!
+ \fn bool QSizeF::isValid() const
+
+ Returns true if both the width and height is equal to or greater
+ than 0; otherwise returns false.
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn int QSizeF::width() const
+
+ Returns the width.
+
+ \sa height(), setWidth()
+*/
+
+/*!
+ \fn int QSizeF::height() const
+
+ Returns the height.
+
+ \sa width(), setHeight()
+*/
+
+/*!
+ \fn void QSizeF::setWidth(qreal width)
+
+ Sets the width to the given \a width.
+
+ \sa width(), rwidth(), setHeight()
+*/
+
+/*!
+ \fn void QSizeF::setHeight(qreal height)
+
+ Sets the height to the given \a height.
+
+ \sa height(), rheight(), setWidth()
+*/
+
+/*!
+ \fn QSize QSizeF::toSize() const
+
+ Returns an integer based copy of this size.
+
+ Note that the coordinates in the returned size will be rounded to
+ the nearest integer.
+
+ \sa QSizeF()
+*/
+
+/*!
+ Swaps the width and height values.
+
+ \sa setWidth(), setHeight()
+*/
+
+void QSizeF::transpose()
+{
+ qreal tmp = wd;
+ wd = ht;
+ ht = tmp;
+}
+
+/*!
+ \fn void QSizeF::scale(qreal width, qreal height, Qt::AspectRatioMode mode)
+
+ Scales the size to a rectangle with the given \a width and \a
+ height, according to the specified \a mode.
+
+ \list
+ \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height).
+ \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle
+ as large as possible inside (\a width, \a height), preserving the aspect ratio.
+ \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle
+ as small as possible outside (\a width, \a height), preserving the aspect ratio.
+ \endlist
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 5
+
+ \sa setWidth(), setHeight()
+*/
+
+/*!
+ \fn void QSizeF::scale(const QSizeF &size, Qt::AspectRatioMode mode)
+ \overload
+
+ Scales the size to a rectangle with the given \a size, according to
+ the specified \a mode.
+*/
+void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode)
+{
+ if (mode == Qt::IgnoreAspectRatio || qIsNull(wd) || qIsNull(ht)) {
+ wd = s.wd;
+ ht = s.ht;
+ } else {
+ bool useHeight;
+ qreal rw = s.ht * wd / ht;
+
+ if (mode == Qt::KeepAspectRatio) {
+ useHeight = (rw <= s.wd);
+ } else { // mode == Qt::KeepAspectRatioByExpanding
+ useHeight = (rw >= s.wd);
+ }
+
+ if (useHeight) {
+ wd = rw;
+ ht = s.ht;
+ } else {
+ ht = s.wd * ht / wd;
+ wd = s.wd;
+ }
+ }
+}
+
+/*!
+ \fn int &QSizeF::rwidth()
+
+ Returns a reference to the width.
+
+ Using a reference makes it possible to manipulate the width
+ directly. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 6
+
+ \sa rheight(), setWidth()
+*/
+
+/*!
+ \fn int &QSizeF::rheight()
+
+ Returns a reference to the height.
+
+ Using a reference makes it possible to manipulate the height
+ directly. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 7
+
+ \sa rwidth(), setHeight()
+*/
+
+/*!
+ \fn QSizeF &QSizeF::operator+=(const QSizeF &size)
+
+ Adds the given \a size to this size and returns a reference to
+ this size. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 8
+*/
+
+/*!
+ \fn QSizeF &QSizeF::operator-=(const QSizeF &size)
+
+ Subtracts the given \a size from this size and returns a reference
+ to this size. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 9
+*/
+
+/*!
+ \fn QSizeF &QSizeF::operator*=(qreal factor)
+ \overload
+
+ Multiplies both the width and height by the given \a factor and
+ returns a reference to the size.
+
+ \sa scale()
+*/
+
+/*!
+ \fn bool operator==(const QSizeF &s1, const QSizeF &s2)
+ \relates QSizeF
+
+ Returns true if \a s1 and \a s2 are equal; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool operator!=(const QSizeF &s1, const QSizeF &s2)
+ \relates QSizeF
+
+ Returns true if \a s1 and \a s2 are different; otherwise returns false.
+*/
+
+/*!
+ \fn const QSizeF operator+(const QSizeF &s1, const QSizeF &s2)
+ \relates QSizeF
+
+ 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
+
+ Returns \a s2 subtracted from \a s1; each component is subtracted
+ separately.
+*/
+
+/*!
+ \fn const QSizeF operator*(const QSizeF &size, qreal factor)
+
+ \overload
+ \relates QSizeF
+
+ Multiplies the given \a size by the given \a factor and returns
+ the result.
+
+ \sa QSizeF::scale()
+*/
+
+/*!
+ \fn const QSizeF operator*(qreal factor, const QSizeF &size)
+
+ \overload
+ \relates QSizeF
+
+ Multiplies the given \a size by the given \a factor and returns
+ the result.
+*/
+
+/*!
+ \fn QSizeF &QSizeF::operator/=(qreal divisor)
+
+ \overload
+
+ Divides both the width and height by the given \a divisor and
+ returns a reference to the size.
+
+ \sa scale()
+*/
+
+/*!
+ \fn const QSizeF operator/(const QSizeF &size, qreal divisor)
+
+ \relates QSizeF
+ \overload
+
+ Divides the given \a size by the given \a divisor and returns the
+ result.
+
+ \sa QSizeF::scale()
+*/
+
+/*!
+ \fn QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const
+
+ Returns a size holding the maximum width and height of this size
+ and the given \a otherSize.
+
+ \sa boundedTo(), scale()
+*/
+
+/*!
+ \fn QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const
+
+ Returns a size holding the minimum width and height of this size
+ and the given \a otherSize.
+
+ \sa expandedTo(), scale()
+*/
+
+
+
+/*****************************************************************************
+ QSizeF stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QSizeF &size)
+ \relates QSizeF
+
+ Writes the given \a size to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QSizeF &sz)
+{
+ s << double(sz.width()) << double(sz.height());
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QSizeF &size)
+ \relates QSizeF
+
+ Reads a size from the given \a stream into the given \a size and
+ returns a reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QSizeF &sz)
+{
+ double w, h;
+ s >> w;
+ s >> h;
+ sz.setWidth(qreal(w));
+ sz.setHeight(qreal(h));
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QSizeF &s) {
+ dbg.nospace() << "QSizeF(" << s.width() << ", " << s.height() << ')';
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
new file mode 100644
index 0000000000..e317673c78
--- /dev/null
+++ b/src/corelib/tools/qsize.h
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIZE_H
+#define QSIZE_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QSize
+{
+public:
+ QSize();
+ QSize(int w, int h);
+
+ bool isNull() const;
+ bool isEmpty() const;
+ bool isValid() const;
+
+ int width() const;
+ int height() const;
+ void setWidth(int w);
+ void setHeight(int h);
+ void transpose();
+
+ void scale(int w, int h, Qt::AspectRatioMode mode);
+ void scale(const QSize &s, Qt::AspectRatioMode mode);
+
+ QSize expandedTo(const QSize &) const;
+ QSize boundedTo(const QSize &) const;
+
+ int &rwidth();
+ int &rheight();
+
+ QSize &operator+=(const QSize &);
+ QSize &operator-=(const QSize &);
+ QSize &operator*=(qreal c);
+ QSize &operator/=(qreal c);
+
+ friend inline bool operator==(const QSize &, const QSize &);
+ friend inline bool operator!=(const QSize &, const QSize &);
+ friend inline const QSize operator+(const QSize &, const QSize &);
+ friend inline const QSize operator-(const QSize &, const QSize &);
+ friend inline const QSize operator*(const QSize &, qreal);
+ friend inline const QSize operator*(qreal, const QSize &);
+ friend inline const QSize operator/(const QSize &, qreal);
+
+private:
+ int wd;
+ int ht;
+};
+Q_DECLARE_TYPEINFO(QSize, Q_MOVABLE_TYPE);
+
+/*****************************************************************************
+ QSize stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSize &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
+#endif
+
+
+/*****************************************************************************
+ QSize inline functions
+ *****************************************************************************/
+
+inline QSize::QSize()
+{ wd = ht = -1; }
+
+inline QSize::QSize(int w, int h)
+{ wd = w; ht = h; }
+
+inline bool QSize::isNull() const
+{ return wd==0 && ht==0; }
+
+inline bool QSize::isEmpty() const
+{ return wd<1 || ht<1; }
+
+inline bool QSize::isValid() const
+{ return wd>=0 && ht>=0; }
+
+inline int QSize::width() const
+{ return wd; }
+
+inline int QSize::height() const
+{ return ht; }
+
+inline void QSize::setWidth(int w)
+{ wd = w; }
+
+inline void QSize::setHeight(int h)
+{ ht = h; }
+
+inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode)
+{ scale(QSize(w, h), mode); }
+
+inline int &QSize::rwidth()
+{ return wd; }
+
+inline int &QSize::rheight()
+{ return ht; }
+
+inline QSize &QSize::operator+=(const QSize &s)
+{ wd+=s.wd; ht+=s.ht; return *this; }
+
+inline QSize &QSize::operator-=(const QSize &s)
+{ wd-=s.wd; ht-=s.ht; return *this; }
+
+inline QSize &QSize::operator*=(qreal c)
+{ wd = qRound(wd*c); ht = qRound(ht*c); return *this; }
+
+inline bool operator==(const QSize &s1, const QSize &s2)
+{ return s1.wd == s2.wd && s1.ht == s2.ht; }
+
+inline bool operator!=(const QSize &s1, const QSize &s2)
+{ return s1.wd != s2.wd || s1.ht != s2.ht; }
+
+inline const QSize operator+(const QSize & s1, const QSize & s2)
+{ return QSize(s1.wd+s2.wd, s1.ht+s2.ht); }
+
+inline const QSize operator-(const QSize &s1, const QSize &s2)
+{ return QSize(s1.wd-s2.wd, s1.ht-s2.ht); }
+
+inline const QSize operator*(const QSize &s, qreal c)
+{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
+
+inline const QSize operator*(qreal c, const QSize &s)
+{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
+
+inline QSize &QSize::operator/=(qreal c)
+{
+ Q_ASSERT(!qFuzzyIsNull(c));
+ wd = qRound(wd/c); ht = qRound(ht/c);
+ return *this;
+}
+
+inline const QSize operator/(const QSize &s, qreal c)
+{
+ Q_ASSERT(!qFuzzyIsNull(c));
+ return QSize(qRound(s.wd/c), qRound(s.ht/c));
+}
+
+inline QSize QSize::expandedTo(const QSize & otherSize) const
+{
+ return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
+}
+
+inline QSize QSize::boundedTo(const QSize & otherSize) const
+{
+ return QSize(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QSize &);
+#endif
+
+
+class Q_CORE_EXPORT QSizeF
+{
+public:
+ QSizeF();
+ QSizeF(const QSize &sz);
+ QSizeF(qreal w, qreal h);
+
+ bool isNull() const;
+ bool isEmpty() const;
+ bool isValid() const;
+
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal w);
+ void setHeight(qreal h);
+ void transpose();
+
+ void scale(qreal w, qreal h, Qt::AspectRatioMode mode);
+ void scale(const QSizeF &s, Qt::AspectRatioMode mode);
+
+ QSizeF expandedTo(const QSizeF &) const;
+ QSizeF boundedTo(const QSizeF &) const;
+
+ qreal &rwidth();
+ qreal &rheight();
+
+ QSizeF &operator+=(const QSizeF &);
+ QSizeF &operator-=(const QSizeF &);
+ QSizeF &operator*=(qreal c);
+ QSizeF &operator/=(qreal c);
+
+ friend inline bool operator==(const QSizeF &, const QSizeF &);
+ friend inline bool operator!=(const QSizeF &, const QSizeF &);
+ friend inline const QSizeF operator+(const QSizeF &, const QSizeF &);
+ friend inline const QSizeF operator-(const QSizeF &, const QSizeF &);
+ friend inline const QSizeF operator*(const QSizeF &, qreal);
+ friend inline const QSizeF operator*(qreal, const QSizeF &);
+ friend inline const QSizeF operator/(const QSizeF &, qreal);
+
+ inline QSize toSize() const;
+
+private:
+ qreal wd;
+ qreal ht;
+};
+Q_DECLARE_TYPEINFO(QSizeF, Q_MOVABLE_TYPE);
+
+
+/*****************************************************************************
+ QSizeF stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSizeF &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
+#endif
+
+
+/*****************************************************************************
+ QSizeF inline functions
+ *****************************************************************************/
+
+inline QSizeF::QSizeF()
+{ wd = ht = -1.; }
+
+inline QSizeF::QSizeF(const QSize &sz)
+ : wd(sz.width()), ht(sz.height())
+{
+}
+
+inline QSizeF::QSizeF(qreal w, qreal h)
+{ wd = w; ht = h; }
+
+inline bool QSizeF::isNull() const
+{ return qIsNull(wd) && qIsNull(ht); }
+
+inline bool QSizeF::isEmpty() const
+{ return wd <= 0. || ht <= 0.; }
+
+inline bool QSizeF::isValid() const
+{ return wd >= 0. && ht >= 0.; }
+
+inline qreal QSizeF::width() const
+{ return wd; }
+
+inline qreal QSizeF::height() const
+{ return ht; }
+
+inline void QSizeF::setWidth(qreal w)
+{ wd = w; }
+
+inline void QSizeF::setHeight(qreal h)
+{ ht = h; }
+
+inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode)
+{ scale(QSizeF(w, h), mode); }
+
+inline qreal &QSizeF::rwidth()
+{ return wd; }
+
+inline qreal &QSizeF::rheight()
+{ return ht; }
+
+inline QSizeF &QSizeF::operator+=(const QSizeF &s)
+{ wd += s.wd; ht += s.ht; return *this; }
+
+inline QSizeF &QSizeF::operator-=(const QSizeF &s)
+{ wd -= s.wd; ht -= s.ht; return *this; }
+
+inline QSizeF &QSizeF::operator*=(qreal c)
+{ wd *= c; ht *= c; return *this; }
+
+inline bool operator==(const QSizeF &s1, const QSizeF &s2)
+{ return qFuzzyCompare(s1.wd, s2.wd) && qFuzzyCompare(s1.ht, s2.ht); }
+
+inline bool operator!=(const QSizeF &s1, const QSizeF &s2)
+{ return !qFuzzyCompare(s1.wd, s2.wd) || !qFuzzyCompare(s1.ht, s2.ht); }
+
+inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2)
+{ return QSizeF(s1.wd+s2.wd, s1.ht+s2.ht); }
+
+inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2)
+{ return QSizeF(s1.wd-s2.wd, s1.ht-s2.ht); }
+
+inline const QSizeF operator*(const QSizeF &s, qreal c)
+{ return QSizeF(s.wd*c, s.ht*c); }
+
+inline const QSizeF operator*(qreal c, const QSizeF &s)
+{ return QSizeF(s.wd*c, s.ht*c); }
+
+inline QSizeF &QSizeF::operator/=(qreal c)
+{
+ Q_ASSERT(!qFuzzyIsNull(c));
+ wd = wd/c; ht = ht/c;
+ return *this;
+}
+
+inline const QSizeF operator/(const QSizeF &s, qreal c)
+{
+ Q_ASSERT(!qFuzzyIsNull(c));
+ return QSizeF(s.wd/c, s.ht/c);
+}
+
+inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const
+{
+ return QSizeF(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
+}
+
+inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const
+{
+ return QSizeF(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
+}
+
+inline QSize QSizeF::toSize() const
+{
+ return QSize(qRound(wd), qRound(ht));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QSizeF &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIZE_H
diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp
new file mode 100644
index 0000000000..f967b63d94
--- /dev/null
+++ b/src/corelib/tools/qstack.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QStack
+ \brief The QStack class is a template class that provides a stack.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QStack\<T\> is one of Qt's generic \l{container classes}. It implements
+ a stack data structure for items of a same type.
+
+ A stack is a last in, first out (LIFO) structure. Items are added
+ to the top of the stack using push() and retrieved from the top
+ using pop(). The top() function provides access to the topmost
+ item without removing it.
+
+ Example:
+
+ \snippet doc/src/snippets/qstack/main.cpp 0
+
+ The example will output 3, 2, 1 in that order.
+
+ QStack inherits from QVector. All of QVector's functionality also
+ applies to QStack. For example, you can use isEmpty() to test
+ whether the stack is empty, and you can traverse a QStack using
+ QVector's iterator classes (for example, QVectorIterator). But in
+ addition, QStack provides three convenience functions that make
+ it easy to implement LIFO semantics: push(), pop(), and top().
+
+ QStack's value type must be an \l{assignable data type}. This
+ covers most data types that are commonly used, but the compiler
+ won't let you, for example, store a QWidget as a value; instead,
+ store a QWidget *.
+
+ \sa QVector, QQueue
+*/
+
+/*!
+ \fn QStack::QStack()
+
+ Constructs an empty stack.
+*/
+
+/*!
+ \fn QStack::~QStack()
+
+ Destroys the stack. References to the values in the stack, and all
+ iterators over this stack, become invalid.
+*/
+
+/*!
+ \fn void QStack::swap(QStack<T> &other)
+ \since 4.8
+
+ Swaps stack \a other with this stack. This operation is very fast and
+ never fails.
+*/
+
+/*!
+ \fn void QStack::push(const T& t)
+
+ Adds element \a t to the top of the stack.
+
+ This is the same as QVector::append().
+
+ \sa pop(), top()
+*/
+
+/*!
+ \fn T& QStack::top()
+
+ Returns a reference to the stack's top item. This function
+ assumes that the stack isn't empty.
+
+ This is the same as QVector::last().
+
+ \sa pop(), push(), isEmpty()
+*/
+
+/*!
+ \fn const T& QStack::top() const
+
+ \overload
+
+ \sa pop(), push()
+*/
+
+/*!
+ \fn T QStack::pop()
+
+ Removes the top item from the stack and returns it. This function
+ assumes that the stack isn't empty.
+
+ \sa top(), push(), isEmpty()
+*/
diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h
new file mode 100644
index 0000000000..6e10103166
--- /dev/null
+++ b/src/corelib/tools/qstack.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTACK_H
+#define QSTACK_H
+
+#include <QtCore/qvector.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template<class T>
+class QStack : public QVector<T>
+{
+public:
+ inline QStack() {}
+ inline ~QStack() {}
+ inline void swap(QStack<T> &other) { QVector<T>::swap(other); } // prevent QVector<->QStack swaps
+ inline void push(const T &t) { QVector<T>::append(t); }
+ T pop();
+ T &top();
+ const T &top() const;
+};
+
+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
+
+QT_END_HEADER
+
+#endif // QSTACK_H
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
new file mode 100644
index 0000000000..5493ba915b
--- /dev/null
+++ b/src/corelib/tools/qstring.cpp
@@ -0,0 +1,9129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringlist.h"
+#include "qregexp.h"
+#include "qunicodetables_p.h"
+#ifndef QT_NO_TEXTCODEC
+#include <qtextcodec.h>
+#endif
+#include <private/qutfcodec_p.h>
+#include "qsimd_p.h"
+#include <qdatastream.h>
+#include <qlist.h>
+#include "qlocale.h"
+#include "qlocale_p.h"
+#include "qstringmatcher.h"
+#include "qvarlengtharray.h"
+#include "qtools_p.h"
+#include "qhash.h"
+#include "qdebug.h"
+#include "qendian.h"
+
+#ifdef Q_OS_MAC
+#include <private/qcore_mac_p.h>
+#endif
+
+#include <private/qfunctions_p.h>
+
+#if defined(Q_OS_WINCE)
+#include <windows.h>
+#include <winnls.h>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#include <e32cmn.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef truncate
+#undef truncate
+#endif
+
+#include "qchar.cpp"
+#include "qstringmatcher.cpp"
+
+#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
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_TEXTCODEC
+QTextCodec *QString::codecForCStrings;
+#endif
+
+#ifdef QT3_SUPPORT
+static QHash<void *, QByteArray> *asciiCache = 0;
+#endif
+
+#ifdef QT_USE_ICU
+// qlocale_icu.cpp
+extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result);
+extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale);
+extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale);
+#endif
+
+
+// internal
+int qFindString(const QChar *haystack, int haystackLen, int from,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle,
+ int from, Qt::CaseSensitivity cs);
+static inline int qt_string_count(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen,
+ Qt::CaseSensitivity cs);
+static inline int qt_string_count(const QChar *haystack, int haystackLen,
+ const QChar &needle, Qt::CaseSensitivity cs);
+static inline int qt_find_latin1_string(const QChar *hay, int size, const QLatin1String &needle,
+ int from, Qt::CaseSensitivity cs);
+static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
+ const QLatin1String &needle, Qt::CaseSensitivity cs);
+static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
+ const QLatin1String &needle, Qt::CaseSensitivity cs);
+
+// Unicode case-insensitive comparison
+static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be)
+{
+ if (a == b)
+ return (ae - be);
+ if (a == 0)
+ return 1;
+ if (b == 0)
+ return -1;
+
+ const ushort *e = ae;
+ if (be - b < ae - a)
+ e = a + (be - b);
+
+ uint alast = 0;
+ uint blast = 0;
+ while (a < e) {
+// qDebug() << hex << alast << blast;
+// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
+// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
+ int diff = foldCase(*a, alast) - foldCase(*b, blast);
+ if ((diff))
+ return diff;
+ ++a;
+ ++b;
+ }
+ if (a == ae) {
+ if (b == be)
+ return 0;
+ return -1;
+ }
+ return 1;
+}
+
+// Case-insensitive comparison between a Unicode string and a QLatin1String
+static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b)
+{
+ if (a == 0) {
+ if (b == 0)
+ return 0;
+ return 1;
+ }
+ if (b == 0)
+ return -1;
+
+ while (a < ae && *b) {
+ int diff = foldCase(*a) - foldCase(*b);
+ if ((diff))
+ return diff;
+ ++a;
+ ++b;
+ }
+ if (a == ae) {
+ if (!*b)
+ return 0;
+ return -1;
+ }
+ return 1;
+}
+
+// Unicode case-sensitive compare two same-sized strings
+static int ucstrncmp(const QChar *a, const QChar *b, int l)
+{
+ while (l-- && *a == *b)
+ a++,b++;
+ if (l==-1)
+ return 0;
+ return a->unicode() - b->unicode();
+}
+
+// Unicode case-sensitive comparison
+static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen)
+{
+ if (a == b && alen == blen)
+ return 0;
+ int l = qMin(alen, blen);
+ int cmp = ucstrncmp(a, b, l);
+ return cmp ? cmp : (alen-blen);
+}
+
+// Unicode case-insensitive compare two same-sized strings
+static int ucstrnicmp(const ushort *a, const ushort *b, int l)
+{
+ return ucstricmp(a, a + l, b, b + l);
+}
+
+// Benchmarking indicates that doing memcmp is much slower than
+// executing the comparison ourselves.
+//
+// The profiling was done on a population of calls to qMemEquals, generated
+// during a run of the demo browser. The profile of the data (32-bit x86
+// Linux) was:
+//
+// total number of comparisons: 21353
+// longest string compared: 95
+// average comparison length: 14.8786
+// cache-line crosses: 5661 (13.3%)
+// alignment histogram:
+// 0xXXX0 = 512 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXX2 = 15087 (35.3%) strings, 5145 (34.1%) of which same-aligned
+// 0xXXX4 = 525 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXX6 = 557 (1.3%) strings, 6 (1.1%) of which same-aligned
+// 0xXXX8 = 509 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXXa = 24358 (57.0%) strings, 9901 (40.6%) of which same-aligned
+// 0xXXXc = 557 (1.3%) strings, 0 (0.0%) of which same-aligned
+// 0xXXXe = 601 (1.4%) strings, 15 (2.5%) of which same-aligned
+// total = 42706 (100%) strings, 15067 (35.3%) of which same-aligned
+//
+// 92% of the strings have alignment of 2 or 10, which is due to malloc on
+// 32-bit Linux returning values aligned to 8 bytes, and offsetof(array, QString::Data) == 18.
+//
+// The profile on 64-bit will be different since offsetof(array, QString::Data) == 26.
+//
+// The benchmark results were, for a Core-i7 @ 2.67 GHz 32-bit, compiled with -O3 -funroll-loops:
+// 16-bit loads only: 872,301 CPU ticks [Qt 4.5 / memcmp]
+// 32- and 16-bit loads: 773,362 CPU ticks [Qt 4.6]
+// SSE2 "movdqu" 128-bit loads: 618,736 CPU ticks
+// SSE3 "lddqu" 128-bit loads: 619,954 CPU ticks
+// SSSE3 "palignr" corrections: 852,147 CPU ticks
+// SSE4.2 "pcmpestrm": 738,702 CPU ticks
+//
+// The same benchmark on an Atom N450 @ 1.66 GHz, is:
+// 16-bit loads only: 2,185,882 CPU ticks
+// 32- and 16-bit loads: 1,805,060 CPU ticks
+// SSE2 "movdqu" 128-bit loads: 2,529,843 CPU ticks
+// SSE3 "lddqu" 128-bit loads: 2,514,858 CPU ticks
+// SSSE3 "palignr" corrections: 2,160,325 CPU ticks
+// SSE4.2 not available
+//
+// The conclusion we reach is that alignment the SSE2 unaligned code can gain
+// 20% improvement in performance in some systems, but suffers a penalty due
+// to the unaligned loads on others.
+
+static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
+{
+ if (a == b || !length)
+ return true;
+
+ register union {
+ const quint16 *w;
+ const quint32 *d;
+ quintptr value;
+ } sa, sb;
+ sa.w = a;
+ sb.w = b;
+
+ // check alignment
+ if ((sa.value & 2) == (sb.value & 2)) {
+ // both addresses have the same alignment
+ if (sa.value & 2) {
+ // both addresses are not aligned to 4-bytes boundaries
+ // compare the first character
+ if (*sa.w != *sb.w)
+ return false;
+ --length;
+ ++sa.w;
+ ++sb.w;
+
+ // now both addresses are 4-bytes aligned
+ }
+
+ // both addresses are 4-bytes aligned
+ // do a fast 32-bit comparison
+ register const quint32 *e = sa.d + (length >> 1);
+ for ( ; sa.d != e; ++sa.d, ++sb.d) {
+ if (*sa.d != *sb.d)
+ return false;
+ }
+
+ // do we have a tail?
+ return (length & 1) ? *sa.w == *sb.w : true;
+ } else {
+ // one of the addresses isn't 4-byte aligned but the other is
+ register const quint16 *e = sa.w + length;
+ for ( ; sa.w != e; ++sa.w, ++sb.w) {
+ if (*sa.w != *sb.w)
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ \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 int findChar(const QChar *str, int len, QChar ch, int from,
+ Qt::CaseSensitivity cs)
+{
+ const ushort *s = (const ushort *)str;
+ ushort c = ch.unicode();
+ if (from < 0)
+ from = qMax(from + len, 0);
+ if (from < len) {
+ const ushort *n = s + from - 1;
+ const ushort *e = s + len;
+ if (cs == Qt::CaseSensitive) {
+ while (++n != e)
+ if (*n == c)
+ return n - s;
+ } else {
+ c = foldCase(c);
+ while (++n != e)
+ if (foldCase(*n) == c)
+ return n - s;
+ }
+ }
+ return -1;
+}
+
+#define REHASH(a) \
+ if (sl_minus_1 < (int)sizeof(int) * CHAR_BIT) \
+ hashHaystack -= (a) << sl_minus_1; \
+ hashHaystack <<= 1
+
+inline bool qIsUpper(char ch)
+{
+ return ch >= 'A' && ch <= 'Z';
+}
+
+inline bool qIsDigit(char ch)
+{
+ return ch >= '0' && ch <= '9';
+}
+
+inline char qToLower(char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ return ch - 'A' + 'a';
+ else
+ return ch;
+}
+
+const QString::Null QString::null = { };
+
+/*!
+ \macro QT_NO_CAST_FROM_ASCII
+ \relates QString
+
+ Disables automatic conversions from 8-bit strings (char *) to unicode QStrings
+
+ \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_BYTEARRAY
+*/
+
+/*!
+ \macro QT_NO_CAST_TO_ASCII
+ \relates QString
+
+ disables automatic conversion from QString to 8-bit strings (char *)
+
+ \sa QT_NO_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY
+*/
+
+/*!
+ \macro QT_ASCII_CAST_WARNINGS
+ \internal
+ \relates QString
+
+ This macro can be defined to force a warning whenever a function is
+ called that automatically converts between unicode and 8-bit encodings.
+
+ Note: This only works for compilers that support warnings for
+ deprecated API.
+
+ \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII
+*/
+
+/*!
+ \class QCharRef
+ \reentrant
+ \brief The QCharRef class is a helper class for QString.
+
+ \internal
+
+ \ingroup string-processing
+
+ When you get an object of type QCharRef, if you can assign to it,
+ the assignment will apply to the character in the string from
+ which you got the reference. That is its whole purpose in life.
+ The QCharRef becomes invalid once modifications are made to the
+ string: if you want to keep the character, copy it into a QChar.
+
+ Most of the QChar member functions also exist in QCharRef.
+ However, they are not explicitly documented here.
+
+ \sa QString::operator[]() QString::at() QChar
+*/
+
+/*!
+ \class QString
+ \reentrant
+
+ \brief The QString class provides a Unicode character string.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ QString stores a string of 16-bit \l{QChar}s, where each QChar
+ corresponds one Unicode 4.0 character. (Unicode characters
+ with code values above 65535 are stored using surrogate pairs,
+ i.e., 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
+ X3.4-1986) and Latin-1 (ISO 8859-1), and all the US-ASCII/Latin-1
+ characters are available at the same code positions.
+
+ Behind the scenes, QString uses \l{implicit sharing}
+ (copy-on-write) to reduce memory usage and to avoid the needless
+ copying of data. This also helps reduce the inherent overhead of
+ storing 16-bit characters instead of 8-bit characters.
+
+ In addition to QString, Qt also provides the QByteArray class to
+ 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 (e.g., with
+ \l{Qt for Embedded Linux}).
+
+ \tableofcontents
+
+ \section1 Initializing a String
+
+ One way to initialize a QString is simply to pass a \c{const char
+ *} to its constructor. For example, the following code creates a
+ QString of size 5 containing the data "Hello":
+
+ \snippet doc/src/snippets/qstring/main.cpp 0
+
+ QString converts the \c{const char *} data into Unicode using the
+ fromAscii() function. By default, fromAscii() treats character
+ above 128 as Latin-1 characters, but this can be changed by
+ calling QTextCodec::setCodecForCStrings().
+
+ 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. It is legal for the \c{const char
+ *} parameter to be 0.
+
+ You can also provide string data as an array of \l{QChar}s:
+
+ \snippet doc/src/snippets/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.)
+
+ 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
+ character that can be used on the left side of an assignment. For
+ example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 2
+
+ For read-only access, an alternative syntax is to use the at()
+ function:
+
+ \snippet doc/src/snippets/qstring/main.cpp 3
+
+ 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
+ at a time.
+
+ A QString can embed '\\0' characters (QChar::Null). The size()
+ function always returns the size of the whole string, including
+ embedded '\\0' characters.
+
+ After a call to the resize() function, newly allocated characters
+ have undefined values. To set all the characters in the string to
+ a particular value, use the fill() function.
+
+ QString provides dozens of overloads designed to simplify string
+ usage. For example, if you want to compare a QString with a string
+ literal, you can write code like this and it will work as expected:
+
+ \snippet doc/src/snippets/qstring/main.cpp 4
+
+ 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
+ which returns the given QString as a \c{const char *}. This is
+ equivalent to calling <QString>.toLocal8Bit().constData().
+
+ \section1 Manipulating String Data
+
+ QString provides the following basic functions for modifying the
+ character data: append(), prepend(), insert(), replace(), and
+ remove(). For example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 5
+
+ 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().
+
+ 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's a typical loop that finds all
+ occurrences of a particular substring:
+
+ \snippet doc/src/snippets/qstring/main.cpp 6
+
+ QString provides many functions for converting numbers into
+ strings and strings into numbers. See the arg() functions, the
+ 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
+ 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 QRegExp using the QStringList::filter()
+ function.
+
+ \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 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.
+
+ \section1 Converting Between 8-Bit Strings and Unicode Strings
+
+ QString provides the following four functions that return a
+ \c{const char *} version of the string as QByteArray: toAscii(),
+ toLatin1(), toUtf8(), and toLocal8Bit().
+
+ \list
+ \o toAscii() returns an 8-bit string encoded using the codec
+ specified by QTextCodec::codecForCStrings (by default, that is
+ Latin 1).
+ \o toLatin1() returns a Latin-1 (ISO 8859-1) encoded 8-bit string.
+ \o toUtf8() returns a UTF-8 encoded 8-bit string. UTF-8 is a
+ superset of US-ASCII (ANSI X3.4-1986) that supports the entire
+ Unicode character set through multibyte sequences.
+ \o toLocal8Bit() returns an 8-bit string using the system's local
+ encoding.
+ \endlist
+
+ To convert from one of these encodings, QString provides
+ fromAscii(), fromLatin1(), fromUtf8(), and fromLocal8Bit(). Other
+ encodings are supported through the QTextCodec class.
+
+ As mentioned above, QString provides a lot of functions and
+ operators that make it easy to interoperate with \c{const char *}
+ strings. But this functionality is a double-edged sword: It makes
+ QString more convenient to use if all strings are US-ASCII or
+ 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:
+
+ \list
+ \o \c QT_NO_CAST_FROM_ASCII disables automatic conversions from
+ C string literals and pointers to Unicode.
+ \o \c 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{qmake Project Files}{qmake project file}:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 0
+
+ You then need to explicitly call fromAscii(), fromLatin1(),
+ fromUtf8(), or fromLocal8Bit() to construct a QString from an
+ 8-bit string, or use the lightweight QLatin1String class, for
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 1
+
+ Similarly, you must call toAscii(), toLatin1(), toUtf8(), or
+ toLocal8Bit() explicitly to convert the QString to an 8-bit
+ string. (Other encodings are supported through the QTextCodec
+ class.)
+
+ \table 100 %
+ \header
+ \o Note for C Programmers
+
+ \row
+ \o
+ Due to C++'s type system and the fact that QString is
+ \l{implicitly shared}, QStrings may be treated like \c{int}s or
+ other basic types. For example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 7
+
+ 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
+ sharing.
+
+ \endtable
+
+ \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
+ initialized using QString's default constructor or by passing
+ (const char *)0 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:
+
+ \snippet doc/src/snippets/qstring/main.cpp 8
+
+ All functions except isNull() treat null strings the same as empty
+ strings. For example, toAscii().constData() returns a pointer to a
+ '\\0' character for a null string (\e not a null pointer), and
+ QString() compares equal to QString(""). We recommend that you
+ always use the isEmpty() function and avoid isNull().
+
+ \section1 Argument 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:
+
+ \table
+ \header \o Format \o Meaning
+ \row \o \c e \o format as [-]9.9e[+|-]999
+ \row \o \c E \o format as [-]9.9E[+|-]999
+ \row \o \c f \o format as [-]9.9
+ \row \o \c g \o use \c e or \c f format, whichever is the most concise
+ \row \o \c G \o use \c E or \c f format, whichever is the most concise
+ \endtable
+
+ 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).
+
+ \section1 More Efficient String Construction
+
+ Using the QString \c{'+'} operator, it is easy to construct a
+ complex string from multiple substrings. You will often write code
+ like this:
+
+ \snippet doc/src/snippets/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.
+
+ First, multiple uses of the \c{'+'} operator usually means
+ 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.
+
+ Second, QLatin1String does not store its length internally but
+ calls qstrlen() when it needs to know its length.
+
+ In 4.6, an internal template class \c{QStringBuilder} has been
+ added along with a few helper functions. 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
+ \c {src/corelib/tools/qstringbuilder.cpp} if you want to have a
+ look at it.
+
+ \c{QStringBuilder} uses expression templates and reimplements the
+ \c{'%'} operator so that when you use \c{'%'} for string
+ concatenation instead of \c{'+'}, multiple substring
+ concatenations will be postponed until the final result is about
+ to be assigned to a QString. At this point, the amount of memory
+ required for the final result is known. The memory allocator is
+ then called \e{once} to get the required space, and the substrings
+ are copied into it one by one.
+
+ \c{QLatin1Literal} is a second internal class that can replace
+ QLatin1String, which can't be changed for compatibility reasons.
+ \c{QLatin1Literal} stores its length, thereby saving time when
+ \c{QStringBuilder} computes the amount of memory required for the
+ final string.
+
+ Additional efficiency is gained by inlining and reduced reference
+ counting (the QString created from a \c{QStringBuilder} typically
+ has a ref count of 1, whereas QString::append() needs an extra
+ test).
+
+ There are three 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{'%'} operator instead of \c{'+'} when concatenating strings:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 5
+
+ A more global approach is to include this define:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 3
+
+ and use \c{'%'} instead of \c{'+'} for string concatenation
+ everywhere. The third approach, which is the most convenient but
+ not entirely source compatible, is to include two defines:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 4
+
+ and the \c{'+'} will automatically be performed as the
+ \c{QStringBuilder} \c{'%'} everywhere.
+
+ \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef
+*/
+
+/*!
+ \enum QString::SplitBehavior
+
+ This enum specifies how the split() function should behave with
+ respect to empty strings.
+
+ \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.
+
+ \sa split()
+*/
+
+QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_null.array, 0, 0, 0, 0, 0, 0, {0} };
+QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_empty.array, 0, 0, 0, 0, 0, 0, {0} };
+
+int QString::grow(int size)
+{
+ return qAllocMore(size * sizeof(QChar), sizeof(Data)) / sizeof(QChar);
+}
+
+/*! \typedef QString::ConstIterator
+
+ Qt-style synonym for QString::const_iterator.
+*/
+
+/*! \typedef QString::Iterator
+
+ Qt-style synonym for QString::iterator.
+*/
+
+/*! \typedef QString::const_iterator
+
+ The QString::const_iterator typedef provides an STL-style const
+ iterator for QString.
+
+ \sa QString::iterator
+*/
+
+/*! \typedef QString::iterator
+
+ The QString::iterator typedef provides an STL-style non-const
+ iterator for QString.
+
+ \sa QString::const_iterator
+*/
+
+/*! \fn QString::iterator QString::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first character in
+ the string.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QString::const_iterator QString::begin() const
+
+ \overload begin()
+*/
+
+/*! \fn QString::const_iterator QString::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first character
+ in the string.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QString::iterator QString::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary character
+ after the last character in the string.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QString::const_iterator QString::end() const
+
+ \overload end()
+*/
+
+/*! \fn QString::const_iterator QString::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the list.
+
+ \sa constBegin(), end()
+*/
+
+/*!
+ \fn QString::QString()
+
+ Constructs a null string. Null strings are also empty.
+
+ \sa isEmpty()
+*/
+
+/*! \fn QString::QString(const char *str)
+
+ Constructs a string initialized with the 8-bit string \a str. The
+ given const char pointer is converted to Unicode using the
+ fromAscii() function.
+
+ You can disable this constructor 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 fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8()
+*/
+
+/*! \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 fromAscii() function.
+
+ This constructor is only available if Qt is configured with STL
+ compatibility enabled.
+
+ \sa fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8()
+*/
+
+/*! \fn QString QString::fromStdWString(const std::wstring &str)
+
+ Returns a copy of the \a str string. The given string is assumed
+ to be encoded in utf16 if the size of wchar_t is 2 bytes (e.g. on
+ windows) and ucs4 if the size of wchar_t is 4 bytes (most Unix
+ systems).
+
+ This method is only available if Qt is configured with STL
+ compatibility enabled.
+
+ \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4()
+*/
+
+/*!
+ \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 ucs-2.
+
+ If \a size is -1 (default), the \a string has to be 0 terminated.
+
+ \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(), fromStdWString()
+*/
+QString QString::fromWCharArray(const wchar_t *string, int size)
+{
+ if (sizeof(wchar_t) == sizeof(QChar)) {
+ return fromUtf16((const ushort *)string, size);
+ } else {
+ return fromUcs4((uint *)string, size);
+ }
+}
+
+/*! \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
+ where wchar_t is 4 bytes wide (most Unix systems).
+
+ This operator is mostly useful to pass a QString to a function
+ that accepts a std::wstring object.
+
+ This operator is only available if Qt is configured with STL
+ compatibility enabled.
+
+ \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit()
+*/
+
+template<typename T> int toUcs4_helper(const unsigned short *uc, int length, T *out)
+{
+ int i = 0;
+ for (; i < length; ++i) {
+ uint u = uc[i];
+ if (QChar::isHighSurrogate(u) && i < length-1) {
+ ushort low = uc[i+1];
+ if (QChar::isLowSurrogate(low)) {
+ ++i;
+ u = QChar::surrogateToUcs4(u, low);
+ }
+ }
+ *out = T(u);
+ ++out;
+ }
+ return i;
+}
+
+/*!
+ \since 4.2
+
+ Fills the \a array with the data contained in this QString object.
+ The array is encoded in utf16 on platforms where
+ wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms
+ where wchar_t is 4 bytes wide (most Unix systems).
+
+ \a array has to be allocated by the caller and contain enough space to
+ hold the complete string (allocating the array with the same length as the
+ string is always sufficient).
+
+ returns the actual length of the string in \a array.
+
+ \note This function does not append a null character to the array.
+
+ \sa utf16(), toUcs4(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString()
+*/
+int QString::toWCharArray(wchar_t *array) const
+{
+ if (sizeof(wchar_t) == sizeof(QChar)) {
+ memcpy(array, utf16(), sizeof(wchar_t)*length());
+ return length();
+ } else {
+ return toUcs4_helper<wchar_t>(utf16(), length(), array);
+ }
+}
+
+/*! \fn QString::QString(const QString &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QString is
+ \l{implicitly shared}. This makes returning a QString from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*!
+ Constructs a string initialized with the first \a size characters
+ of the QChar array \a unicode.
+
+ QString makes a deep copy of the string data. The unicode data is copied as
+ is and the Byte Order Mark is preserved if present.
+*/
+QString::QString(const QChar *unicode, int size)
+{
+ if (!unicode) {
+ d = &shared_null;
+ d->ref.ref();
+ } else if (size <= 0) {
+ d = &shared_empty;
+ d->ref.ref();
+ } else {
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ memcpy(d->array, unicode, size * sizeof(QChar));
+ d->array[size] = '\0';
+ }
+}
+
+/*!
+ \since 4.7
+
+ Constructs a string initialized with the characters of the QChar array
+ \a unicode, which must be terminated with a 0.
+
+ QString makes a deep copy of the string data. The unicode data is copied as
+ is and the Byte Order Mark is preserved if present.
+*/
+QString::QString(const QChar *unicode)
+{
+ if (!unicode) {
+ d = &shared_null;
+ d->ref.ref();
+ } else {
+ int size = 0;
+ while (unicode[size] != 0)
+ ++size;
+ if (!size) {
+ d = &shared_empty;
+ d->ref.ref();
+ } else {
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ memcpy(d->array, unicode, size * sizeof(QChar));
+ d->array[size] = '\0';
+ }
+ }
+}
+
+
+/*!
+ Constructs a string of the given \a size with every character set
+ to \a ch.
+
+ \sa fill()
+*/
+QString::QString(int size, QChar ch)
+{
+ if (size <= 0) {
+ d = &shared_empty;
+ d->ref.ref();
+ } else {
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[size] = '\0';
+ ushort *i = d->array + size;
+ ushort *b = d->array;
+ const ushort value = ch.unicode();
+ while (i != b)
+ *--i = value;
+ }
+}
+
+/*! \fn QString::QString(int 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)
+{
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
+/*! \fn QString::QString(const QLatin1String &str)
+
+ Constructs a copy of the Latin-1 string \a str.
+
+ \sa fromLatin1()
+*/
+
+/*!
+ Constructs a string of size 1 containing the character \a ch.
+*/
+QString::QString(QChar ch)
+{
+ void *buf = qMalloc(sizeof(Data) + sizeof(QChar));
+ Q_CHECK_PTR(buf);
+ d = reinterpret_cast<Data *>(buf);
+ d->ref = 1;
+ d->alloc = d->size = 1;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[0] = ch.unicode();
+ d->array[1] = '\0';
+}
+
+/*! \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 fromAscii(). Stops
+ copying at the first 0 character, otherwise copies the entire byte
+ array.
+
+ You can disable this constructor 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 fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8()
+*/
+
+/*! \fn QString::QString(const Null &)
+ \internal
+*/
+
+/*! \fn QString &QString::operator=(const Null &)
+ \internal
+*/
+
+/*!
+ \fn QString::~QString()
+
+ Destroys the string.
+*/
+
+
+/*! \fn void QString::swap(QString &other)
+ \since 4.8
+
+ Swaps string \a other with this string. This operation is very fast and
+ never fails.
+*/
+
+/*! \fn void QString::detach()
+
+ \internal
+*/
+
+/*! \fn bool QString::isDetached() const
+
+ \internal
+*/
+
+/*! \fn bool QString::isSharedWith(const QString &other) const
+
+ \internal
+*/
+
+// ### Qt 5: rename freeData() to avoid confusion. See task 197625.
+void QString::free(Data *d)
+{
+#ifdef QT3_SUPPORT
+ if (d->asciiCache) {
+ Q_ASSERT(asciiCache);
+ asciiCache->remove(d);
+ }
+#endif
+ qFree(d);
+}
+
+/*!
+ Sets the size of the string to \a size characters.
+
+ If \a size is greater than the current size, the string is
+ 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 45
+
+ If you want to append a certain number of identical characters to
+ the string, use \l operator+=() as follows rather than resize():
+
+ \snippet doc/src/snippets/qstring/main.cpp 46
+
+ If you want to expand the string so that it reaches a certain
+ width and fill the new positions with a particular character, use
+ the leftJustified() function:
+
+ If \a size is negative, it is equivalent to passing zero.
+
+ \snippet doc/src/snippets/qstring/main.cpp 47
+
+ \sa truncate(), reserve()
+*/
+
+void QString::resize(int size)
+{
+ if (size < 0)
+ size = 0;
+
+ if (size == 0 && !d->capacity) {
+ Data *x = &shared_empty;
+ x->ref.ref();
+ if (!d->ref.deref())
+ QString::free(d);
+ d = x;
+ } else {
+ if (d->ref != 1 || size > d->alloc ||
+ (!d->capacity && size < d->size && size < d->alloc >> 1))
+ realloc(grow(size));
+ if (d->alloc >= size) {
+ d->size = size;
+ if (d->data == d->array) {
+ d->array[size] = '\0';
+ }
+ }
+ }
+}
+
+/*! \fn int QString::capacity() const
+
+ Returns the maximum number of characters that can be stored in
+ the string without forcing a reallocation.
+
+ 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 know how many
+ characters are in the string, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*!
+ \fn void QString::reserve(int 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.
+
+ 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().
+
+ This function is useful for code that needs to build up a long
+ string and wants to avoid repeated reallocation. In this example,
+ we want to add to the string until some condition is true, and
+ we're fairly sure that size is large enough to make a call to
+ reserve() worthwhile:
+
+ \snippet doc/src/snippets/qstring/main.cpp 44
+
+ \sa squeeze(), capacity()
+*/
+
+/*!
+ \fn void QString::squeeze()
+
+ Releases any memory not required to store the character data.
+
+ 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.
+
+ \sa reserve(), capacity()
+*/
+
+// ### Qt 5: rename reallocData() to avoid confusion. 197625
+void QString::realloc(int alloc)
+{
+ if (d->ref != 1 || d->data != d->array) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
+ Q_CHECK_PTR(x);
+ x->size = qMin(alloc, d->size);
+ ::memcpy(x->array, d->data, x->size * sizeof(QChar));
+ x->array[x->size] = 0;
+ x->asciiCache = 0;
+ x->ref = 1;
+ x->alloc = alloc;
+ x->clean = d->clean;
+ x->simpletext = d->simpletext;
+ x->righttoleft = d->righttoleft;
+ x->capacity = d->capacity;
+ x->data = x->array;
+ if (!d->ref.deref())
+ QString::free(d);
+ d = x;
+ } else {
+#ifdef QT3_SUPPORT
+ if (d->asciiCache) {
+ Q_ASSERT(asciiCache);
+ asciiCache->remove(d);
+ }
+#endif
+ Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
+ Q_CHECK_PTR(p);
+ d = p;
+ d->alloc = alloc;
+ d->data = d->array;
+ }
+}
+
+void QString::realloc()
+{
+ realloc(d->size);
+}
+
+void QString::expand(int i)
+{
+ int sz = d->size;
+ resize(qMax(i + 1, sz));
+ if (d->size - 1 > sz) {
+ ushort *n = d->data + d->size - 1;
+ ushort *e = d->data + sz;
+ while (n != e)
+ * --n = ' ';
+ }
+}
+
+/*! \fn void QString::clear()
+
+ Clears the contents of the string and makes it empty.
+
+ \sa resize(), isEmpty()
+*/
+
+/*! \fn QString &QString::operator=(const QString &other)
+
+ Assigns \a other to this string and returns a reference to this
+ string.
+*/
+
+QString &QString::operator=(const QString &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ QString::free(d);
+ d = other.d;
+ return *this;
+}
+
+
+/*! \fn QString &QString::operator=(const QLatin1String &str)
+
+ \overload operator=()
+
+ Assigns the Latin-1 string \a str to this string.
+*/
+
+/*! \fn QString &QString::operator=(const QByteArray &ba)
+
+ \overload operator=()
+
+ Assigns \a ba to this string. The byte array is converted to Unicode
+ using the fromAscii() function. This function stops conversion at the
+ first NUL character found, or the end of the \a ba 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.
+*/
+
+/*! \fn QString &QString::operator=(const char *str)
+
+ \overload operator=()
+
+ Assigns \a str to this string. The const char pointer is converted
+ to Unicode using the fromAscii() 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.
+*/
+
+/*! \fn QString &QString::operator=(char ch)
+
+ \overload operator=()
+
+ Assigns character \a ch to this string. The character is converted
+ to Unicode using the fromAscii() 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.
+*/
+
+/*!
+ \overload operator=()
+
+ Sets the string to contain the single character \a ch.
+*/
+QString &QString::operator=(QChar ch)
+{
+ return operator=(QString(ch));
+}
+
+/*!
+ \fn QString& QString::insert(int position, const QString &str)
+
+ Inserts the string \a str at the given index \a position and
+ returns a reference to this string.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 26
+
+ If the given \a position is greater than size(), the array is
+ first extended using resize().
+
+ \sa append(), prepend(), replace(), remove()
+*/
+
+
+/*!
+ \fn QString &QString::insert(int position, const QLatin1String &str)
+ \overload insert()
+
+ Inserts the Latin-1 string \a str at the given index \a position.
+*/
+QString &QString::insert(int i, const QLatin1String &str)
+{
+ const uchar *s = (const uchar *)str.latin1();
+ if (i < 0 || !s || !(*s))
+ return *this;
+
+ int len = qstrlen(str.latin1());
+ expand(qMax(d->size, i) + len - 1);
+
+ ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar));
+ for (int j = 0; j < len; ++j)
+ d->data[i + j] = s[j];
+ return *this;
+}
+
+/*!
+ \fn QString& QString::insert(int position, const QChar *unicode, int size)
+ \overload insert()
+
+ Inserts the first \a size characters of the QChar array \a unicode
+ at the given index \a position in the string.
+*/
+QString& QString::insert(int i, const QChar *unicode, int size)
+{
+ if (i < 0 || size <= 0)
+ return *this;
+
+ const ushort *s = (const ushort *)unicode;
+ if (s >= d->data && s < d->data + d->alloc) {
+ // Part of me - take a copy
+ ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar)));
+ Q_CHECK_PTR(tmp);
+ memcpy(tmp, s, size * sizeof(QChar));
+ insert(i, reinterpret_cast<const QChar *>(tmp), size);
+ qFree(tmp);
+ return *this;
+ }
+
+ expand(qMax(d->size, i) + size - 1);
+
+ ::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)
+ \overload insert()
+
+ Inserts \a ch at the given index \a position in the string.
+*/
+
+QString& QString::insert(int i, QChar ch)
+{
+ if (i < 0)
+ i += d->size;
+ if (i < 0)
+ return *this;
+ expand(qMax(i, d->size));
+ ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar));
+ d->data[i] = ch.unicode();
+ return *this;
+}
+
+/*!
+ Appends the string \a str onto the end of this string.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 9
+
+ This is the same as using the insert() function:
+
+ \snippet doc/src/snippets/qstring/main.cpp 10
+
+ The append() function is typically very fast (\l{constant time}),
+ because QString preallocates extra space at the end of the string
+ data so it can grow without reallocating the entire string each
+ time.
+
+ \sa operator+=(), prepend(), insert()
+*/
+QString &QString::append(const QString &str)
+{
+ if (str.d != &shared_null) {
+ if (d == &shared_null) {
+ operator=(str);
+ } else {
+ if (d->ref != 1 || d->size + str.d->size > d->alloc)
+ realloc(grow(d->size + str.d->size));
+ memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar));
+ d->size += str.d->size;
+ d->data[d->size] = '\0';
+ }
+ }
+ return *this;
+}
+
+/*!
+ \overload append()
+
+ Appends the Latin-1 string \a str to this string.
+*/
+QString &QString::append(const QLatin1String &str)
+{
+ const uchar *s = (const uchar *)str.latin1();
+ if (s) {
+ int len = qstrlen((char *)s);
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(grow(d->size + len));
+ ushort *i = d->data + d->size;
+ while ((*i++ = *s++))
+ ;
+ d->size += len;
+ }
+ return *this;
+}
+
+/*! \fn QString &QString::append(const QByteArray &ba)
+
+ \overload append()
+
+ Appends the byte array \a ba to this string. The given byte array
+ is converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*! \fn QString &QString::append(const char *str)
+
+ \overload append()
+
+ Appends the string \a str to this string. The given const char
+ pointer is converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*!
+ \overload append()
+
+ Appends the character \a ch to this string.
+*/
+QString &QString::append(QChar ch)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(grow(d->size + 1));
+ d->data[d->size++] = ch.unicode();
+ d->data[d->size] = '\0';
+ return *this;
+}
+
+/*! \fn QString &QString::prepend(const QString &str)
+
+ Prepends the string \a str to the beginning of this string and
+ returns a reference to this string.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 36
+
+ \sa append(), insert()
+*/
+
+/*! \fn QString &QString::prepend(const QLatin1String &str)
+
+ \overload prepend()
+
+ Prepends the Latin-1 string \a str to this string.
+*/
+
+/*! \fn QString &QString::prepend(const QByteArray &ba)
+
+ \overload prepend()
+
+ Prepends the byte array \a ba to this string. The byte array is
+ converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*! \fn QString &QString::prepend(const char *str)
+
+ \overload prepend()
+
+ Prepends the string \a str to this string. The const char pointer
+ is converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*! \fn QString &QString::prepend(QChar ch)
+
+ \overload prepend()
+
+ Prepends the character \a ch to this string.
+*/
+
+/*!
+ \fn QString &QString::remove(int position, int n)
+
+ Removes \a n characters from the string, starting at the given \a
+ position index, and returns a reference to the string.
+
+ If the specified \a position index is within the string, but \a
+ position + \a n is beyond the end of the string, the string is
+ truncated at the specified \a position.
+
+ \snippet doc/src/snippets/qstring/main.cpp 37
+
+ \sa insert(), replace()
+*/
+QString &QString::remove(int pos, int len)
+{
+ if (pos < 0) // count from end of string
+ pos += d->size;
+ if (pos < 0 || pos >= d->size) {
+ // range problems
+ } else if (len >= d->size - pos) {
+ resize(pos); // truncate
+ } else if (len > 0) {
+ detach();
+ memmove(d->data + pos, d->data + pos + len,
+ (d->size - pos - len + 1) * sizeof(ushort));
+ d->size -= len;
+ }
+ return *this;
+}
+
+/*!
+ 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.
+
+ This is the same as \c replace(str, "", cs).
+
+ \sa replace()
+*/
+QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
+{
+ if (str.d->size) {
+ int i = 0;
+ while ((i = indexOf(str, i, cs)) != -1)
+ remove(i, str.d->size);
+ }
+ return *this;
+}
+
+/*!
+ 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 38
+
+ This is the same as \c replace(ch, "", cs).
+
+ \sa replace()
+*/
+QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
+{
+ int i = 0;
+ ushort c = ch.unicode();
+ if (cs == Qt::CaseSensitive) {
+ while (i < d->size)
+ if (d->data[i] == ch)
+ remove(i, 1);
+ else
+ i++;
+ } else {
+ c = foldCase(c);
+ while (i < d->size)
+ if (foldCase(d->data[i]) == c)
+ remove(i, 1);
+ else
+ i++;
+ }
+ return *this;
+}
+
+/*!
+ \fn QString &QString::remove(const QRegExp &rx)
+
+ Removes every occurrence of the regular expression \a rx in the
+ string, and returns a reference to the string. For example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 39
+
+ \sa indexOf(), lastIndexOf(), replace()
+*/
+
+/*!
+ \fn QString &QString::replace(int position, int 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 40
+
+ \sa insert(), remove()
+*/
+QString &QString::replace(int pos, int len, const QString &after)
+{
+ QString copy = after;
+ return replace(pos, len, copy.constData(), copy.length());
+}
+
+/*!
+ \fn QString &QString::replace(int position, int n, const QChar *unicode, int size)
+ \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
+ reference to this string.
+*/
+QString &QString::replace(int pos, int len, const QChar *unicode, int size)
+{
+ if (pos < 0 || pos > d->size)
+ return *this;
+ if (pos + len > d->size)
+ len = d->size - pos;
+
+ uint index = pos;
+ replace_helper(&index, 1, len, unicode, size);
+ return *this;
+}
+
+/*!
+ \fn QString &QString::replace(int position, int 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)
+{
+ return replace(pos, len, &after, 1);
+}
+
+/*!
+ \overload replace()
+ 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 41
+
+ \note The replacement text is not rescanned after it is inserted.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 86
+*/
+QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs)
+{
+ return replace(before.constData(), before.size(), after.constData(), after.size(), cs);
+}
+
+/*!
+ \internal
+ */
+void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
+{
+ // copy *after in case it lies inside our own d->data area
+ // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.)
+ QChar *afterBuffer = const_cast<QChar *>(after);
+ if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) {
+ afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar)));
+ Q_CHECK_PTR(afterBuffer);
+ ::memcpy(afterBuffer, after, alen*sizeof(QChar));
+ }
+
+ QT_TRY {
+ if (blen == alen) {
+ // replace in place
+ detach();
+ for (int i = 0; i < nIndices; ++i)
+ memcpy(d->data + indices[i], afterBuffer, 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, afterBuffer, 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, afterBuffer, alen*sizeof(QChar));
+ moveend = movestart-blen;
+ }
+ }
+ } QT_CATCH(const std::bad_alloc &) {
+ if (afterBuffer != after)
+ qFree(afterBuffer);
+ QT_RETHROW;
+ }
+ if (afterBuffer != after)
+ qFree(afterBuffer);
+}
+
+/*!
+ \since 4.5
+ \overload replace()
+
+ Replaces each occurrence in this string of the first \a blen
+ 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.
+*/
+QString &QString::replace(const QChar *before, int blen,
+ const QChar *after, int alen,
+ Qt::CaseSensitivity cs)
+{
+ if (d->size == 0) {
+ if (blen)
+ return *this;
+ } else {
+ if (cs == Qt::CaseSensitive && before == after && blen == alen)
+ return *this;
+ }
+ if (alen == 0 && blen == 0)
+ return *this;
+
+ QStringMatcher matcher(before, blen, cs);
+
+ int index = 0;
+ while (1) {
+ uint indices[1024];
+ uint pos = 0;
+ while (pos < 1023) {
+ index = matcher.indexIn(*this, index);
+ if (index == -1)
+ break;
+ indices[pos++] = index;
+ index += blen;
+ // avoid infinite loop
+ if (!blen)
+ index++;
+ }
+ if (!pos)
+ break;
+
+ replace_helper(indices, pos, blen, after, alen);
+
+ if (index == -1)
+ break;
+ // index has to be adjusted in case we get back into the loop above.
+ index += pos*(alen-blen);
+ }
+
+ return *this;
+}
+
+/*!
+ \overload replace()
+ 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.
+*/
+QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs)
+{
+ if (after.d->size == 0)
+ return remove(ch, cs);
+
+ if (after.d->size == 1)
+ return replace(ch, after.d->data[0], cs);
+
+ if (d->size == 0)
+ return *this;
+
+ ushort 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 < 1023 && index < d->size) {
+ if (d->data[index] == cc)
+ indices[pos++] = index;
+ index++;
+ }
+ } else {
+ while (pos < 1023 && index < d->size) {
+ if (QChar::toCaseFolded(d->data[index]) == cc)
+ indices[pos++] = index;
+ index++;
+ }
+ }
+ if (!pos)
+ break;
+
+ replace_helper(indices, pos, 1, after.constData(), after.d->size);
+
+ if (index == -1)
+ break;
+ // index has to be adjusted in case we get back into the loop above.
+ index += pos*(after.d->size - 1);
+ }
+ return *this;
+}
+
+/*!
+ \overload replace()
+ 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.
+*/
+QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
+{
+ ushort a = after.unicode();
+ ushort b = before.unicode();
+ if (d->size) {
+ detach();
+ ushort *i = d->data;
+ const ushort *e = i + d->size;
+ if (cs == Qt::CaseSensitive) {
+ for (; i != e; ++i)
+ if (*i == b)
+ *i = a;
+ } else {
+ b = foldCase(b);
+ for (; i != e; ++i)
+ if (foldCase(*i) == b)
+ *i = a;
+ }
+ }
+ return *this;
+}
+
+/*!
+ \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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \note The text is not rescanned after a replacement.
+*/
+QString &QString::replace(const QLatin1String &before,
+ const QLatin1String &after,
+ Qt::CaseSensitivity cs)
+{
+ int alen = qstrlen(after.latin1());
+ QVarLengthArray<ushort> a(alen);
+ for (int i = 0; i < alen; ++i)
+ a[i] = (uchar)after.latin1()[i];
+ int blen = qstrlen(before.latin1());
+ QVarLengthArray<ushort> b(blen);
+ for (int i = 0; i < blen; ++i)
+ b[i] = (uchar)before.latin1()[i];
+ return replace((const QChar *)b.data(), blen, (const QChar *)a.data(), alen, 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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \note The text is not rescanned after a replacement.
+*/
+QString &QString::replace(const QLatin1String &before,
+ const QString &after,
+ Qt::CaseSensitivity cs)
+{
+ int blen = qstrlen(before.latin1());
+ QVarLengthArray<ushort> b(blen);
+ for (int i = 0; i < blen; ++i)
+ b[i] = (uchar)before.latin1()[i];
+ return replace((const QChar *)b.data(), blen, after.constData(), after.d->size, 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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \note The text is not rescanned after a replacement.
+*/
+QString &QString::replace(const QString &before,
+ const QLatin1String &after,
+ Qt::CaseSensitivity cs)
+{
+ int alen = qstrlen(after.latin1());
+ QVarLengthArray<ushort> a(alen);
+ for (int i = 0; i < alen; ++i)
+ a[i] = (uchar)after.latin1()[i];
+ return replace(before.constData(), before.d->size, (const QChar *)a.data(), alen, cs);
+}
+
+/*!
+ \since 4.5
+ \overload replace()
+
+ 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.
+
+ \note The text is not rescanned after a replacement.
+*/
+QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs)
+{
+ int alen = qstrlen(after.latin1());
+ QVarLengthArray<ushort> a(alen);
+ for (int i = 0; i < alen; ++i)
+ a[i] = (uchar)after.latin1()[i];
+ return replace(&c, 1, (const QChar *)a.data(), alen, cs);
+}
+
+
+/*!
+ Returns true if string \a other is equal to this string; otherwise
+ returns 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().
+*/
+bool QString::operator==(const QString &other) const
+{
+ if (d->size != other.d->size)
+ return false;
+
+ return qMemEquals(d->data, other.d->data, d->size);
+}
+
+/*!
+ \overload operator==()
+*/
+bool QString::operator==(const QLatin1String &other) const
+{
+ const ushort *uc = d->data;
+ const ushort *e = uc + d->size;
+ const uchar *c = (uchar *)other.latin1();
+
+ if (!c)
+ return isEmpty();
+
+ while (*c) {
+ if (uc == e || *uc != *c)
+ return false;
+ ++uc;
+ ++c;
+ }
+ return (uc == e);
+}
+
+/*! \fn bool QString::operator==(const QByteArray &other) const
+
+ \overload operator==()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() 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.
+*/
+
+/*! \fn bool QString::operator==(const char *other) const
+
+ \overload operator==()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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 true if this string is lexically less than string \a
+ other; otherwise returns 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 QString::operator<(const QString &other) const
+{
+ return ucstrcmp(constData(), length(), other.constData(), other.length()) < 0;
+}
+
+/*!
+ \overload operator<()
+*/
+bool QString::operator<(const QLatin1String &other) const
+{
+ const ushort *uc = d->data;
+ const ushort *e = uc + d->size;
+ const uchar *c = (uchar *) other.latin1();
+
+ if (!c || *c == 0)
+ return false;
+
+ while (*c) {
+ if (uc == e || *uc != *c)
+ break;
+ ++uc;
+ ++c;
+ }
+ return (uc == e ? *c : *uc < *c);
+}
+
+/*! \fn bool QString::operator<(const QByteArray &other) const
+
+ \overload operator<()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() function. 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
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*! \fn bool QString::operator<(const char *other) const
+
+ \overload operator<()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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.
+*/
+
+/*! \fn bool QString::operator<=(const QString &other) const
+
+ Returns true if this string is lexically less than or equal to
+ string \a other; otherwise returns 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().
+*/
+
+/*! \fn bool QString::operator<=(const QLatin1String &other) const
+
+ \overload operator<=()
+*/
+
+/*! \fn bool QString::operator<=(const QByteArray &other) const
+
+ \overload operator<=()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() function. 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
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*! \fn bool QString::operator<=(const char *other) const
+
+ \overload operator<=()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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.
+*/
+
+/*! \fn bool QString::operator>(const QString &other) const
+
+ Returns true if this string is lexically greater than string \a
+ other; otherwise returns 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().
+*/
+
+/*!
+ \overload operator>()
+*/
+bool QString::operator>(const QLatin1String &other) const
+{
+ const ushort *uc = d->data;;
+ const ushort *e = uc + d->size;
+ const uchar *c = (uchar *) other.latin1();
+
+ if (!c || *c == '\0')
+ return !isEmpty();
+
+ while (*c) {
+ if (uc == e || *uc != *c)
+ break;
+ ++uc;
+ ++c;
+ }
+ return (uc == e ? false : *uc > *c);
+}
+
+/*! \fn bool QString::operator>(const QByteArray &other) const
+
+ \overload operator>()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() function. 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
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*! \fn bool QString::operator>(const char *other) const
+
+ \overload operator>()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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.
+*/
+
+/*! \fn bool QString::operator>=(const QString &other) const
+
+ Returns true if this string is lexically greater than or equal to
+ string \a other; otherwise returns 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().
+*/
+
+/*! \fn bool QString::operator>=(const QLatin1String &other) const
+
+ \overload operator>=()
+*/
+
+/*! \fn bool QString::operator>=(const QByteArray &other) const
+
+ \overload operator>=()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() function. 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 can be useful if you want
+ to ensure that all user-visible strings go through QObject::tr(),
+ for example.
+*/
+
+/*! \fn bool QString::operator>=(const char *other) const
+
+ \overload operator>=()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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.
+*/
+
+/*! \fn bool QString::operator!=(const QString &other) const
+
+ Returns true if this string is not equal to string \a other;
+ otherwise returns 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().
+*/
+
+/*! \fn bool QString::operator!=(const QLatin1String &other) const
+
+ \overload operator!=()
+*/
+
+/*! \fn bool QString::operator!=(const QByteArray &other) const
+
+ \overload operator!=()
+
+ The \a other byte array is converted to a QString using the
+ fromAscii() function. 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 can be useful if you want
+ to ensure that all user-visible strings go through QObject::tr(),
+ for example.
+*/
+
+/*! \fn bool QString::operator!=(const char *other) const
+
+ \overload operator!=()
+
+ The \a other const char pointer is converted to a QString using
+ the fromAscii() 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 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.
+
+ Example:
+
+ \snippet doc/src/snippets/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.
+
+ \sa lastIndexOf(), contains(), count()
+*/
+int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
+{
+ return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
+}
+
+/*!
+ \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.
+
+ Example:
+
+ \snippet doc/src/snippets/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.
+
+ \sa lastIndexOf(), contains(), count()
+*/
+
+int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const
+{
+ return qt_find_latin1_string(unicode(), size(), str, from, cs);
+}
+
+int qFindString(
+ const QChar *haystack0, int haystackLen, int from,
+ const QChar *needle0, int needleLen, Qt::CaseSensitivity cs)
+{
+ const int l = haystackLen;
+ const int sl = needleLen;
+ if (from < 0)
+ from += l;
+ if (uint(sl + from) > (uint)l)
+ return -1;
+ if (!sl)
+ return from;
+ if (!l)
+ return -1;
+
+ if (sl == 1)
+ return findChar(haystack0, haystackLen, 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
+ hash function.
+ */
+ if (l > 500 && sl > 5)
+ return qFindStringBoyerMoore(haystack0, haystackLen, from,
+ needle0, needleLen, cs);
+
+ /*
+ We use some hashing for efficiency's sake. Instead of
+ comparing strings, we compare the hash value of str with that
+ of a part of this QString. Only if that matches, we call
+ ucstrncmp() or ucstrnicmp().
+ */
+ const ushort *needle = (const ushort *)needle0;
+ const ushort *haystack = (const ushort *)haystack0 + from;
+ const ushort *end = (const ushort *)haystack0 + (l-sl);
+ const int sl_minus_1 = sl-1;
+ int hashNeedle = 0, hashHaystack = 0, idx;
+
+ if (cs == Qt::CaseSensitive) {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + needle[idx]);
+ hashHaystack = ((hashHaystack<<1) + haystack[idx]);
+ }
+ hashHaystack -= haystack[sl_minus_1];
+
+ while (haystack <= end) {
+ hashHaystack += haystack[sl_minus_1];
+ if (hashHaystack == hashNeedle
+ && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0)
+ return haystack - (const ushort *)haystack0;
+
+ REHASH(*haystack);
+ ++haystack;
+ }
+ } else {
+ const ushort *haystack_start = (const ushort *)haystack0;
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle);
+ hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start);
+ }
+ hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start);
+
+ while (haystack <= end) {
+ hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
+ if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0)
+ return haystack - (const ushort *)haystack0;
+
+ REHASH(foldCase(haystack, haystack_start));
+ ++haystack;
+ }
+ }
+ return -1;
+}
+
+/*!
+ \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.
+*/
+int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
+{
+ return findChar(unicode(), length(), ch, from, cs);
+}
+
+/*!
+ \since 4.8
+
+ \overload indexOf()
+
+ Returns the index position of the first occurrence of the string
+ reference \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.
+*/
+int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
+{
+ return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
+}
+
+static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs)
+{
+ /*
+ See indexOf() for explanations.
+ */
+
+ const ushort *end = haystack;
+ haystack += from;
+ const int sl_minus_1 = sl-1;
+ const ushort *n = needle+sl_minus_1;
+ const ushort *h = haystack+sl_minus_1;
+ int hashNeedle = 0, hashHaystack = 0, idx;
+
+ if (cs == Qt::CaseSensitive) {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + *(n-idx));
+ hashHaystack = ((hashHaystack<<1) + *(h-idx));
+ }
+ hashHaystack -= *haystack;
+
+ while (haystack >= end) {
+ hashHaystack += *haystack;
+ if (hashHaystack == hashNeedle
+ && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(haystack[sl]);
+ }
+ } else {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + foldCase(n-idx, needle));
+ hashHaystack = ((hashHaystack<<1) + foldCase(h-idx, end));
+ }
+ hashHaystack -= foldCase(haystack, end);
+
+ while (haystack >= end) {
+ hashHaystack += foldCase(haystack, end);
+ if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(foldCase(haystack + sl, end));
+ }
+ }
+ return -1;
+}
+
+/*!
+ 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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 29
+
+ \sa indexOf(), contains(), count()
+*/
+int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
+{
+ const int sl = str.d->size;
+ if (sl == 1)
+ return lastIndexOf(QChar(str.d->data[0]), from, cs);
+
+ const int l = d->size;
+ if (from < 0)
+ from += l;
+ int delta = l-sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs);
+}
+
+/*!
+ \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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 29
+
+ \sa indexOf(), contains(), count()
+*/
+int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const
+{
+ const int sl = qstrlen(str.latin1());
+ if (sl == 1)
+ return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
+
+ const int l = d->size;
+ if (from < 0)
+ from += l;
+ int delta = l-sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ QVarLengthArray<ushort> s(sl);
+ for (int i = 0; i < sl; ++i)
+ s[i] = str.latin1()[i];
+
+ return lastIndexOfHelper(d->data, from, s.data(), sl, cs);
+}
+
+/*!
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the character
+ \a ch, searching backward from position \a from.
+*/
+int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
+{
+ return qt_last_index_of(unicode(), size(), ch, from, cs);
+ }
+
+/*!
+ \since 4.8
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the string
+ reference \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()
+*/
+int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
+{
+ const int sl = str.size();
+ if (sl == 1)
+ return lastIndexOf(str.at(0), from, cs);
+
+ const int l = d->size;
+ if (from < 0)
+ from += l;
+ int delta = l - sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()),
+ str.size(), cs);
+}
+
+#ifndef QT_NO_REGEXP
+struct QStringCapture
+{
+ int pos;
+ int len;
+ int no;
+};
+
+/*!
+ \overload replace()
+
+ Replaces every occurrence of the regular expression \a rx in the
+ string with \a after. Returns a reference to the string. For
+ example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 42
+
+ For regular expressions containing \l{capturing parentheses},
+ occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are replaced
+ with \a{rx}.cap(1), cap(2), ...
+
+ \snippet doc/src/snippets/qstring/main.cpp 43
+
+ \sa indexOf(), lastIndexOf(), remove(), QRegExp::cap()
+*/
+QString& QString::replace(const QRegExp &rx, const QString &after)
+{
+ QRegExp rx2(rx);
+
+ if (isEmpty() && rx2.indexIn(*this) == -1)
+ return *this;
+
+ realloc();
+
+ 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 <= length()) {
+ index = rx2.indexIn(*this, 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));
+ }
+
+ 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 *this;
+ }
+ }
+
+ /*
+ 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(*this, 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 = d->size;
+ int newlen = d->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(uc, d->data + copystart, size * sizeof(QChar));
+ uc += size;
+ memcpy(uc, after.d->data, al * sizeof(QChar));
+ uc += al;
+ copystart = copyend + replacements[i].length;
+ i++;
+ }
+ memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar));
+ newstring.resize(newlen);
+ *this = newstring;
+ caretMode = QRegExp::CaretWontMatch;
+ }
+ return *this;
+}
+#endif
+
+/*!
+ 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.
+
+ \sa contains(), indexOf()
+*/
+
+int QString::count(const QString &str, Qt::CaseSensitivity cs) const
+{
+ return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+}
+
+/*!
+ \overload count()
+
+ Returns the number of occurrences of character \a ch in the string.
+*/
+
+int QString::count(QChar ch, Qt::CaseSensitivity cs) const
+{
+ return qt_string_count(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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \sa contains(), indexOf()
+*/
+int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
+{
+ return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+}
+
+
+/*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+
+ Returns true if this string contains an occurrence of the string
+ \a str; otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ Example:
+ \snippet doc/src/snippets/qstring/main.cpp 17
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn bool QString::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+
+ \overload contains()
+
+ Returns true if this string contains an occurrence of the
+ character \a ch; otherwise returns false.
+*/
+
+/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 4.8
+
+ Returns true if this string contains an occurrence of the string
+ reference \a str; otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn bool QString::contains(const QRegExp &rx) const
+
+ \overload contains()
+
+ Returns true if the regular expression \a rx matches somewhere in
+ this string; otherwise returns false.
+*/
+
+/*! \fn bool QString::contains(QRegExp &rx) const
+ \overload contains()
+ \since 4.5
+
+ Returns true if the regular expression \a rx matches somewhere in
+ this string; otherwise returns false.
+
+ If there is a match, the \a rx regular expression will contain the
+ matched captures (see QRegExp::matchedLength, QRegExp::cap).
+*/
+
+#ifndef QT_NO_REGEXP
+/*!
+ \overload indexOf()
+
+ Returns the index position of the first match of the regular
+ expression \a rx in the string, searching forward from index
+ position \a from. Returns -1 if \a rx didn't match anywhere.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 25
+*/
+int QString::indexOf(const QRegExp& rx, int from) const
+{
+ QRegExp rx2(rx);
+ return rx2.indexIn(*this, from);
+}
+
+/*!
+ \overload indexOf()
+ \since 4.5
+
+ Returns the index position of the first match of the regular
+ expression \a rx in the string, searching forward from index
+ position \a from. Returns -1 if \a rx didn't match anywhere.
+
+ If there is a match, the \a rx regular expression will contain the
+ matched captures (see QRegExp::matchedLength, QRegExp::cap).
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 25
+*/
+int QString::indexOf(QRegExp& rx, int from) const
+{
+ return rx.indexIn(*this, from);
+}
+
+/*!
+ \overload lastIndexOf()
+
+ Returns the index position of the last match of the regular
+ expression \a rx in the string, searching backward from index
+ position \a from. Returns -1 if \a rx didn't match anywhere.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 30
+*/
+int QString::lastIndexOf(const QRegExp& rx, int from) const
+{
+ QRegExp rx2(rx);
+ return rx2.lastIndexIn(*this, from);
+}
+
+/*!
+ \overload lastIndexOf()
+ \since 4.5
+
+ Returns the index position of the last match of the regular
+ expression \a rx in the string, searching backward from index
+ position \a from. Returns -1 if \a rx didn't match anywhere.
+
+ If there is a match, the \a rx regular expression will contain the
+ matched captures (see QRegExp::matchedLength, QRegExp::cap).
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 30
+*/
+int QString::lastIndexOf(QRegExp& rx, int from) const
+{
+ return rx.lastIndexIn(*this, from);
+}
+
+/*!
+ \overload count()
+
+ Returns the number of times the regular expression \a rx matches
+ in the string.
+
+ This function counts overlapping matches, so in the example
+ below, there are four instances of "ana" or "ama":
+
+ \snippet doc/src/snippets/qstring/main.cpp 18
+
+*/
+int QString::count(const QRegExp& rx) const
+{
+ QRegExp rx2(rx);
+ int count = 0;
+ int index = -1;
+ int len = length();
+ while (index < len - 1) { // count overlapping matches
+ index = rx2.indexIn(*this, index + 1);
+ if (index == -1)
+ break;
+ count++;
+ }
+ return count;
+}
+#endif // QT_NO_REGEXP
+
+/*! \fn int QString::count() const
+
+ \overload count()
+
+ Same as size().
+*/
+
+
+/*!
+ \enum QString::SectionFlag
+
+ This enum specifies flags that can be used to affect various
+ aspects of the section() function's behavior with respect to
+ separators and empty fields.
+
+ \value SectionDefault Empty fields are counted, leading and
+ trailing separators are not included, and the separator is
+ compared case sensitively.
+
+ \value SectionSkipEmpty Treat empty fields as if they don't exist,
+ i.e. they are not considered as far as \e start and \e end are
+ concerned.
+
+ \value SectionIncludeLeadingSep Include the leading separator (if
+ any) in the result string.
+
+ \value SectionIncludeTrailingSep Include the trailing separator
+ (if any) in the result string.
+
+ \value SectionCaseInsensitiveSeps Compare the separator
+ case-insensitively.
+
+ \sa section()
+*/
+
+/*!
+ \fn QString QString::section(QChar sep, int start, int end = -1, SectionFlags flags) const
+
+ This function returns a section of the string.
+
+ This string is treated as a sequence of fields separated by the
+ character, \a sep. The returned string consists of the fields from
+ position \a start to position \a end inclusive. If \a end is not
+ specified, all fields from position \a start to the end of the
+ string are included. Fields are numbered 0, 1, 2, etc., counting
+ from the left, and -1, -2, etc., counting from right to left.
+
+ The \a flags argument can be used to affect some aspects of the
+ function's behavior, e.g. whether to be case sensitive, whether
+ to skip empty fields and how to deal with leading and trailing
+ separators; see \l{SectionFlags}.
+
+ \snippet doc/src/snippets/qstring/main.cpp 52
+
+ If \a start or \a end is negative, we count fields from the right
+ of the string, the right-most field being -1, the one from
+ right-most field being -2, and so on.
+
+ \snippet doc/src/snippets/qstring/main.cpp 53
+
+ \sa split()
+*/
+
+/*!
+ \overload section()
+
+ \snippet doc/src/snippets/qstring/main.cpp 51
+ \snippet doc/src/snippets/qstring/main.cpp 54
+
+ \sa split()
+*/
+
+QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const
+{
+ QStringList sections = split(sep, KeepEmptyParts,
+ (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
+ if (sections.isEmpty())
+ return QString();
+ if (!(flags & SectionSkipEmpty)) {
+ if (start < 0)
+ start += sections.count();
+ if (end < 0)
+ end += sections.count();
+ } else {
+ int skip = 0;
+ for (int k=0; k<sections.size(); ++k) {
+ if (sections.at(k).isEmpty())
+ skip++;
+ }
+ if (start < 0)
+ start += sections.count() - skip;
+ if (end < 0)
+ end += sections.count() - skip;
+ }
+ int x = 0;
+ QString ret;
+ int first_i = start, last_i = end;
+ for (int i = 0; x <= end && i < sections.size(); ++i) {
+ QString section = sections.at(i);
+ const bool empty = section.isEmpty();
+ if (x >= start) {
+ if(x == start)
+ first_i = i;
+ if(x == end)
+ last_i = i;
+ if(x > start)
+ ret += sep;
+ ret += section;
+ }
+ if (!empty || !(flags & SectionSkipEmpty))
+ x++;
+ }
+ if((flags & SectionIncludeLeadingSep) && first_i)
+ ret.prepend(sep);
+ if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1)
+ ret += sep;
+ return ret;
+}
+
+#ifndef QT_NO_REGEXP
+class qt_section_chunk {
+public:
+ qt_section_chunk(int l, QString s) { length = l; string = s; }
+ int length;
+ QString string;
+};
+
+/*!
+ \overload section()
+
+ This string is treated as a sequence of fields separated by the
+ regular expression, \a reg.
+
+ \snippet doc/src/snippets/qstring/main.cpp 55
+
+ \warning Using this QRegExp version is much more expensive than
+ the overloaded string and character versions.
+
+ \sa split() simplified()
+*/
+QString QString::section(const QRegExp &reg, int start, int end, SectionFlags flags) const
+{
+ const QChar *uc = unicode();
+ if(!uc)
+ return QString();
+
+ QRegExp sep(reg);
+ sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive
+ : Qt::CaseSensitive);
+
+ QList<qt_section_chunk> sections;
+ int n = length(), m = 0, last_m = 0, last_len = 0;
+ while ((m = sep.indexIn(*this, m)) != -1) {
+ sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
+ last_m = m;
+ last_len = sep.matchedLength();
+ m += qMax(sep.matchedLength(), 1);
+ }
+ sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
+
+ if(start < 0)
+ start += sections.count();
+ if(end < 0)
+ end += sections.count();
+
+ QString ret;
+ int x = 0;
+ int first_i = start, last_i = end;
+ for (int i = 0; x <= end && i < sections.size(); ++i) {
+ const qt_section_chunk &section = sections.at(i);
+ const bool empty = (section.length == section.string.length());
+ if (x >= start) {
+ if(x == start)
+ first_i = i;
+ if(x == end)
+ last_i = i;
+ if(x != start)
+ ret += section.string;
+ else
+ ret += section.string.mid(section.length);
+ }
+ if (!empty || !(flags & SectionSkipEmpty))
+ x++;
+ }
+ if((flags & SectionIncludeLeadingSep) && first_i < sections.size()) {
+ const qt_section_chunk &section = sections.at(first_i);
+ ret.prepend(section.string.left(section.length));
+ }
+ if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
+ const qt_section_chunk &section = sections.at(last_i+1);
+ ret += section.string.left(section.length);
+ }
+ return ret;
+}
+#endif
+
+/*!
+ Returns a substring that contains the \a n leftmost characters
+ of the string.
+
+ The entire string is returned if \a n is greater than size() or
+ less than zero.
+
+ \snippet doc/src/snippets/qstring/main.cpp 31
+
+ \sa right(), mid(), startsWith()
+*/
+QString QString::left(int n) const
+{
+ if (n >= d->size || n < 0)
+ return *this;
+ return QString((const QChar*) d->data, n);
+}
+
+/*!
+ Returns a substring that contains the \a n rightmost characters
+ of the string.
+
+ The entire string is returned if \a n is greater than size() or
+ less than zero.
+
+ \snippet doc/src/snippets/qstring/main.cpp 48
+
+ \sa left(), mid(), endsWith()
+*/
+QString QString::right(int n) const
+{
+ if (n >= d->size || n < 0)
+ return *this;
+ return QString((const QChar*) d->data + d->size - n, n);
+}
+
+/*!
+ Returns a string that contains \a n characters of this string,
+ starting at the specified \a position index.
+
+ Returns a null string if the \a position index exceeds the
+ length of the string. 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 that
+ are available from the specified \a position.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 34
+
+ \sa left(), right()
+*/
+
+QString QString::mid(int position, int n) const
+{
+ if (d == &shared_null || position >= d->size)
+ return QString();
+ if (n < 0)
+ n = d->size - position;
+ if (position < 0) {
+ n += position;
+ position = 0;
+ }
+ if (n + position > d->size)
+ n = d->size - position;
+ if (position == 0 && n == d->size)
+ return *this;
+ return QString((const QChar*) d->data + position, n);
+}
+
+/*!
+ Returns true if the string starts with \a s; otherwise returns
+ false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \snippet doc/src/snippets/qstring/main.cpp 65
+
+ \sa endsWith()
+*/
+bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
+{
+ return qt_starts_with(isNull() ? 0 : unicode(), size(),
+ s.isNull() ? 0 : s.unicode(), s.size(), cs);
+}
+
+/*!
+ \overload startsWith()
+ */
+bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const
+{
+ return qt_starts_with(isNull() ? 0 : unicode(), size(), s, cs);
+}
+
+/*!
+ \overload startsWith()
+
+ Returns true if the string starts with \a c; otherwise returns
+ false.
+*/
+bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const
+{
+ return d->size
+ && (cs == Qt::CaseSensitive
+ ? d->data[0] == c
+ : foldCase(d->data[0]) == foldCase(c.unicode()));
+}
+
+/*!
+ \since 4.8
+ \overload
+ Returns true if the string starts with the string reference \a s;
+ otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa endsWith()
+*/
+bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
+{
+ return qt_starts_with(isNull() ? 0 : unicode(), size(),
+ s.isNull() ? 0 : s.unicode(), s.size(), cs);
+}
+
+/*!
+ Returns true if the string ends with \a s; otherwise returns
+ false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \snippet doc/src/snippets/qstring/main.cpp 20
+
+ \sa startsWith()
+*/
+bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const
+{
+ return qt_ends_with(isNull() ? 0 : unicode(), size(),
+ s.isNull() ? 0 : s.unicode(), s.size(), cs);
+ }
+
+/*!
+ \since 4.8
+ \overload endsWith()
+ Returns true if the string ends with the string reference \a s;
+ otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa startsWith()
+*/
+bool QString::endsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
+{
+ return qt_ends_with(isNull() ? 0 : unicode(), size(),
+ s.isNull() ? 0 : s.unicode(), s.size(), cs);
+}
+
+
+/*!
+ \overload endsWith()
+*/
+bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const
+{
+ return qt_ends_with(isNull() ? 0 : unicode(), size(), s, cs);
+}
+
+/*!
+ Returns true if the string ends with \a c; otherwise returns
+ false.
+
+ \overload endsWith()
+ */
+bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const
+{
+ return d->size
+ && (cs == Qt::CaseSensitive
+ ? d->data[d->size - 1] == c
+ : foldCase(d->data[d->size - 1]) == foldCase(c.unicode()));
+}
+
+/*! \fn const char *QString::ascii() const
+ \nonreentrant
+
+ Use toAscii() instead.
+*/
+
+/*! \fn const char *QString::latin1() const
+ \nonreentrant
+
+ Use toLatin1() instead.
+*/
+
+/*! \fn const char *QString::utf8() const
+ \nonreentrant
+
+ Use toUtf8() instead.
+*/
+
+/*! \fn const char *QString::local8Bit() const
+ \nonreentrant
+
+ Use toLocal8Bit() instead.
+*/
+
+static QByteArray toLatin1_helper(const QChar *data, int length)
+{
+ QByteArray ba;
+ if (length) {
+ ba.resize(length);
+ const ushort *src = reinterpret_cast<const ushort *>(data);
+ uchar *dst = (uchar*) ba.data();
+#if defined(QT_ALWAYS_HAVE_SSE2)
+ if (length >= 16) {
+ const int chunkCount = length >> 4; // divided by 16
+ const __m128i questionMark = _mm_set1_epi16('?');
+ // SSE has no compare instruction for unsigned comparison.
+ // The variables must be shiffted + 0x8000 to be compared
+ const __m128i signedBitOffset = _mm_set1_epi16(0x8000);
+ const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000);
+ for (int i = 0; i < chunkCount; ++i) {
+ __m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
+ src += 8;
+ {
+ // each 16 bit is equal to 0xFF if the source is outside latin 1 (>0xff)
+ const __m128i signedChunk = _mm_add_epi16(chunk1, signedBitOffset);
+ const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
+
+ // offLimitQuestionMark contains '?' for each 16 bits that was off-limit
+ // the 16 bits that were correct contains zeros
+ const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
+
+ // correctBytes contains the bytes that were in limit
+ // the 16 bits that were off limits contains zeros
+ const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk1);
+
+ // merge offLimitQuestionMark and correctBytes to have the result
+ chunk1 = _mm_or_si128(correctBytes, offLimitQuestionMark);
+ }
+
+ __m128i chunk2 = _mm_loadu_si128((__m128i*)src); // load
+ src += 8;
+ {
+ // exactly the same operations as for the previous chunk of data
+ const __m128i signedChunk = _mm_add_epi16(chunk2, signedBitOffset);
+ const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
+ const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
+ const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk2);
+ chunk2 = _mm_or_si128(correctBytes, offLimitQuestionMark);
+ }
+
+ // pack the two vector to 16 x 8bits elements
+ const __m128i result = _mm_packus_epi16(chunk1, chunk2);
+
+ _mm_storeu_si128((__m128i*)dst, result); // store
+ dst += 16;
+ }
+ length = length % 16;
+ }
+#elif defined(QT_ALWAYS_HAVE_NEON)
+ // Refer to the documentation of the SSE2 implementation
+ // this use eactly 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 uint16x8_t questionMark = vdupq_n_u16('?'); // set
+ const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set
+ for (int i = 0; i < chunkCount; ++i) {
+ uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
+ src += 8;
+
+ const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
+ const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
+ const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
+ chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
+ const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing
+ vst1_u8(dst, result); // store
+ dst += 8;
+ }
+ length = length % 8;
+ }
+#endif
+ while (length--) {
+ *dst++ = (*src>0xff) ? '?' : (uchar) *src;
+ ++src;
+ }
+ }
+ return ba;
+}
+
+/*!
+ 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 fromLatin1(), toAscii(), toUtf8(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QString::toLatin1() const
+{
+ return toLatin1_helper(unicode(), length());
+}
+
+// ### Qt 5: Change the return type of at least toAscii(),
+// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE
+// isn't necessary in the header. See task 177402.
+
+/*!
+ Returns an 8-bit representation of the string as a QByteArray.
+
+ If a codec has been set using QTextCodec::setCodecForCStrings(),
+ it is used to convert Unicode to 8-bit char; otherwise this
+ function does the same as toLatin1().
+
+ Note that, despite the name, this function does not necessarily return an US-ASCII
+ (ANSI X3.4-1986) string and its result may not be US-ASCII compatible.
+
+ \sa fromAscii(), toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QString::toAscii() const
+{
+#ifndef QT_NO_TEXTCODEC
+ if (codecForCStrings)
+ return codecForCStrings->fromUnicode(*this);
+#endif // QT_NO_TEXTCODEC
+ return toLatin1();
+}
+
+#if !defined(Q_WS_MAC) && defined(Q_OS_UNIX)
+static QByteArray toLocal8Bit_helper(const QChar *data, int length)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QTextCodec::codecForLocale())
+ return QTextCodec::codecForLocale()->fromUnicode(data, length);
+#endif // QT_NO_TEXTCODEC
+ return toLatin1_helper(data, length);
+}
+#endif
+
+/*!
+ 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.
+
+ QTextCodec::codecForLocale() is used to perform the conversion from
+ Unicode. If the locale encoding could not be determined, this function
+ does the same as toLatin1().
+
+ 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.
+
+ \sa fromLocal8Bit(), toAscii(), toLatin1(), toUtf8(), QTextCodec
+*/
+QByteArray QString::toLocal8Bit() const
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QTextCodec::codecForLocale())
+ return QTextCodec::codecForLocale()->fromUnicode(*this);
+#endif // QT_NO_TEXTCODEC
+ return toLatin1();
+}
+
+/*!
+ 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.
+
+ However, in the Unicode range, there are certain codepoints that are not
+ considered characters. The Unicode standard reserves the last two
+ codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF,
+ U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF,
+ inclusive, as non-characters. If any of those appear in the string, they
+ may be discarded and will not appear in the UTF-8 representation, or they
+ may be replaced by one or more replacement characters.
+
+ \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QString::toUtf8() const
+{
+ if (isNull())
+ return QByteArray();
+
+ return QUtf8::convertFromUnicode(constData(), length(), 0);
+}
+
+/*!
+ \since 4.2
+
+ Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
+
+ UCS-4 is a Unicode codec and is lossless. All characters from this string
+ can be encoded in UCS-4. The vector is not null terminated.
+
+ \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray()
+*/
+QVector<uint> QString::toUcs4() const
+{
+ QVector<uint> v(length());
+ uint *a = v.data();
+ int len = toUcs4_helper<uint>(utf16(), length(), a);
+ v.resize(len);
+ return v;
+}
+
+QString::Data *QString::fromLatin1_helper(const char *str, int size)
+{
+ Data *d;
+ if (!str) {
+ d = &shared_null;
+ d->ref.ref();
+ } else if (size == 0 || (!*str && size < 0)) {
+ d = &shared_empty;
+ d->ref.ref();
+ } else {
+ if (size < 0)
+ size = qstrlen(str);
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[size] = '\0';
+ ushort *dst = d->data;
+ /* SIMD:
+ * Unpacking with SSE has been shown to improve performance on recent CPUs
+ * The same method gives no improvement with NEON.
+ */
+#if defined(QT_ALWAYS_HAVE_SSE2)
+ if (size >= 16) {
+ int chunkCount = size >> 4; // divided by 16
+ const __m128i nullMask = _mm_set1_epi32(0);
+ for (int i = 0; i < chunkCount; ++i) {
+ const __m128i chunk = _mm_loadu_si128((__m128i*)str); // load
+ str += 16;
+
+ // unpack the first 8 bytes, padding with zeros
+ const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
+ _mm_storeu_si128((__m128i*)dst, firstHalf); // store
+ dst += 8;
+
+ // unpack the last 8 bytes, padding with zeros
+ const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
+ _mm_storeu_si128((__m128i*)dst, secondHalf); // store
+ dst += 8;
+ }
+ size = size % 16;
+ }
+#endif
+ while (size--)
+ *dst++ = (uchar)*str++;
+ }
+ return d;
+}
+
+QString::Data *QString::fromAscii_helper(const char *str, int size)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (codecForCStrings) {
+ Data *d;
+ if (!str) {
+ d = &shared_null;
+ d->ref.ref();
+ } else if (size == 0 || (!*str && size < 0)) {
+ d = &shared_empty;
+ d->ref.ref();
+ } else {
+ if (size < 0)
+ size = qstrlen(str);
+ QString s = codecForCStrings->toUnicode(str, size);
+ d = s.d;
+ d->ref.ref();
+ }
+ return d;
+ }
+#endif
+ return fromLatin1_helper(str, 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 qstrlen(\a
+ str).
+
+ \sa toLatin1(), fromAscii(), fromUtf8(), fromLocal8Bit()
+*/
+QString QString::fromLatin1(const char *str, int size)
+{
+ return QString(fromLatin1_helper(str, size), 0);
+}
+
+
+#ifdef QT3_SUPPORT
+
+/*!
+ \internal
+*/
+const char *QString::ascii_helper() const
+{
+ if (!asciiCache)
+ asciiCache = new QHash<void *, QByteArray>();
+
+ d->asciiCache = true;
+ QByteArray ascii = toAscii();
+ QByteArray old = asciiCache->value(d);
+ if (old == ascii)
+ return old.constData();
+ asciiCache->insert(d, ascii);
+ return ascii.constData();
+}
+
+/*!
+ \internal
+*/
+const char *QString::latin1_helper() const
+{
+ if (!asciiCache)
+ asciiCache = new QHash<void *, QByteArray>();
+
+ d->asciiCache = true;
+ QByteArray ascii = toLatin1();
+ QByteArray old = asciiCache->value(d);
+ if (old == ascii)
+ return old.constData();
+ asciiCache->insert(d, ascii);
+ return ascii.constData();
+}
+
+#endif
+
+/*!
+ 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 qstrlen(\a
+ str).
+
+ QTextCodec::codecForLocale() is used to perform the conversion.
+
+ \sa toLocal8Bit(), fromAscii(), fromLatin1(), fromUtf8()
+*/
+QString QString::fromLocal8Bit(const char *str, int size)
+{
+ if (!str)
+ return QString();
+ if (size == 0 || (!*str && size < 0))
+ return QLatin1String("");
+#if !defined(QT_NO_TEXTCODEC)
+ if (size < 0)
+ size = qstrlen(str);
+ QTextCodec *codec = QTextCodec::codecForLocale();
+ if (codec)
+ return codec->toUnicode(str, size);
+#endif // !QT_NO_TEXTCODEC
+ return fromLatin1(str, size);
+}
+
+/*!
+ Returns a QString initialized with the first \a size characters
+ from the string \a str.
+
+ If \a size is -1 (default), it is taken to be qstrlen(\a
+ str).
+
+ Note that, despite the name, this function actually uses the codec
+ defined by QTextCodec::setCodecForCStrings() to convert \a str to
+ Unicode. Depending on the codec, it may not accept valid US-ASCII (ANSI
+ X3.4-1986) input. If no codec has been set, this function does the same
+ as fromLatin1().
+
+ \sa toAscii(), fromLatin1(), fromUtf8(), fromLocal8Bit()
+*/
+QString QString::fromAscii(const char *str, int size)
+{
+ return QString(fromAscii_helper(str, size), 0);
+}
+
+/*!
+ 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 qstrlen(\a
+ str).
+
+ 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
+ and, if any such are found, they will be replaced with one or more
+ "replacement characters", or suppressed. These include non-Unicode
+ sequences, non-characters, overlong sequences or surrogate codepoints
+ encoded into UTF-8.
+
+ Non-characters are codepoints that the Unicode standard reserves and must
+ not be used in text interchange. They are the last two codepoints in each
+ Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, etc.), as well
+ as 16 codepoints in the range U+FDD0..U+FDDF, inclusive.
+
+ \sa toUtf8(), fromAscii(), fromLatin1(), fromLocal8Bit()
+*/
+QString QString::fromUtf8(const char *str, int size)
+{
+ if (!str)
+ return QString();
+ if (size < 0)
+ size = qstrlen(str);
+
+ return QUtf8::convertToUnicode(str, size, 0);
+}
+
+/*!
+ Returns a QString initialized with the first \a size characters
+ of the Unicode string \a unicode (ISO-10646-UTF-16 encoded).
+
+ If \a size is -1 (default), \a unicode must be terminated
+ with a 0.
+
+ This function checks for a Byte Order Mark (BOM). If it is missing,
+ 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.
+
+ QString makes a deep copy of the Unicode data.
+
+ \sa utf16(), setUtf16()
+*/
+QString QString::fromUtf16(const ushort *unicode, int size)
+{
+ if (!unicode)
+ return QString();
+ if (size < 0) {
+ size = 0;
+ while (unicode[size] != 0)
+ ++size;
+ }
+ return QUtf16::convertToUnicode((const char *)unicode, size*2, 0);
+}
+
+
+/*!
+ \since 4.2
+
+ Returns a QString initialized with the first \a size characters
+ of the Unicode string \a unicode (ISO-10646-UCS-4 encoded).
+
+ If \a size is -1 (default), \a unicode must be terminated
+ with a 0.
+
+ \sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray()
+*/
+QString QString::fromUcs4(const uint *unicode, int size)
+{
+ if (!unicode)
+ return QString();
+ if (size < 0) {
+ size = 0;
+ while (unicode[size] != 0)
+ ++size;
+ }
+ return QUtf32::convertToUnicode((const char *)unicode, size*4, 0);
+}
+
+/*!
+ 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
+ resized to \a size.
+
+ \sa unicode(), setUtf16()
+*/
+QString& QString::setUnicode(const QChar *unicode, int size)
+{
+ resize(size);
+ if (unicode && size)
+ memcpy(d->data, unicode, size * sizeof(QChar));
+ return *this;
+}
+
+/*!
+ \fn QString &QString::setUtf16(const ushort *unicode, int 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
+ resized to \a size.
+
+ Note that unlike fromUtf16(), this function does not consider BOMs and
+ possibly differing byte ordering.
+
+ \sa utf16(), setUnicode()
+*/
+
+/*!
+ Returns a string that has whitespace removed from the start
+ and the end, and that has each sequence of internal whitespace
+ replaced with a single space.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 57
+
+ \sa trimmed()
+*/
+QString QString::simplified() const
+{
+ if (d->size == 0)
+ return *this;
+
+ const QChar * const start = reinterpret_cast<QChar *>(d->data);
+ const QChar *from = start;
+ const QChar *fromEnd = start + d->size;
+ forever {
+ QChar ch = *from;
+ if (!ch.isSpace())
+ break;
+ if (++from == fromEnd) {
+ // All-whitespace string
+ shared_empty.ref.ref();
+ return QString(&shared_empty, 0);
+ }
+ }
+ // This loop needs no underflow check, as we already determined that
+ // the string contains non-whitespace. If the string has exactly one
+ // non-whitespace, it will be checked twice - we can live with that.
+ while (fromEnd[-1].isSpace())
+ fromEnd--;
+ // The rest of the function depends on the fact that we already know
+ // that the last character in the source is no whitespace.
+ const QChar *copyFrom = from;
+ int copyCount;
+ forever {
+ if (++from == fromEnd) {
+ // Only leading and/or trailing whitespace, if any at all
+ return mid(copyFrom - start, from - copyFrom);
+ }
+ QChar ch = *from;
+ if (!ch.isSpace())
+ continue;
+ if (ch != QLatin1Char(' ')) {
+ copyCount = from - copyFrom;
+ break;
+ }
+ ch = *++from;
+ if (ch.isSpace()) {
+ copyCount = from - copyFrom - 1;
+ break;
+ }
+ }
+ // 'from' now points at the non-trailing whitespace which made the
+ // string not simplified in the first place. 'copyCount' is the number
+ // of already simplified characters - at least one, obviously -
+ // without a trailing space.
+ QString result((fromEnd - from) + copyCount, Qt::Uninitialized);
+ QChar *to = reinterpret_cast<QChar *>(result.d->data);
+ ::memcpy(to, copyFrom, copyCount * 2);
+ to += copyCount;
+ fromEnd--;
+ QChar ch;
+ forever {
+ *to++ = QLatin1Char(' ');
+ do {
+ ch = *++from;
+ } while (ch.isSpace());
+ if (from == fromEnd)
+ break;
+ do {
+ *to++ = ch;
+ ch = *++from;
+ if (from == fromEnd)
+ goto done;
+ } while (!ch.isSpace());
+ }
+ done:
+ *to++ = ch;
+ result.truncate(to - reinterpret_cast<QChar *>(result.d->data));
+ return result;
+}
+
+/*!
+ Returns a string that has whitespace removed from the start and
+ the end.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 82
+
+ Unlike simplified(), trimmed() leaves internal whitespace alone.
+
+ \sa simplified()
+*/
+QString QString::trimmed() const
+{
+ if (d->size == 0)
+ return *this;
+ const QChar *s = (const QChar*)d->data;
+ if (!s->isSpace() && !s[d->size-1].isSpace())
+ return *this;
+ int start = 0;
+ int end = d->size - 1;
+ while (start<=end && s[start].isSpace()) // skip white space from start
+ start++;
+ if (start <= end) { // only white space
+ while (end && s[end].isSpace()) // skip white space from end
+ end--;
+ }
+ int l = end - start + 1;
+ if (l <= 0) {
+ shared_empty.ref.ref();
+ return QString(&shared_empty, 0);
+ }
+ return QString(s + start, l);
+}
+
+/*! \fn const QChar QString::at(int position) const
+
+ Returns the character at the given index \a position in the
+ string.
+
+ The \a position must be a valid index position in the string
+ (i.e., 0 <= \a position < size()).
+
+ \sa operator[]()
+*/
+
+/*!
+ \fn QCharRef QString::operator[](int position)
+
+ Returns the character at the specified \a position in the string as a
+ modifiable reference.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 85
+
+ The return value is of type QCharRef, a helper class for QString.
+ When you get an object of type QCharRef, you can use it as if it
+ were a QChar &. If you assign to it, the assignment will apply to
+ the character in the QString from which you got the reference.
+
+ \sa at()
+*/
+
+/*!
+ \fn const QChar QString::operator[](int position) const
+
+ \overload operator[]()
+*/
+
+/*! \fn QCharRef QString::operator[](uint position)
+
+\overload operator[]()
+
+Returns the character at the specified \a position in the string as a
+modifiable reference. Equivalent to \c at(position).
+*/
+
+/*! \fn const QChar QString::operator[](uint position) const
+
+\overload operator[]()
+*/
+
+/*!
+ \fn void QString::truncate(int position)
+
+ Truncates the string at the given \a position index.
+
+ If the specified \a position index is beyond the end of the
+ string, nothing happens.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 83
+
+ If \a position is negative, it is equivalent to passing zero.
+
+ \sa chop(), resize(), left()
+*/
+
+void QString::truncate(int pos)
+{
+ if (pos < d->size)
+ resize(pos);
+}
+
+
+/*!
+ Removes \a n characters from the end of the string.
+
+ If \a n is greater than size(), the result is an empty string.
+
+ Example:
+ \snippet doc/src/snippets/qstring/main.cpp 15
+
+ If you want to remove characters from the \e beginning of the
+ string, use remove() instead.
+
+ \sa truncate(), resize(), remove()
+*/
+void QString::chop(int n)
+{
+ if (n > 0)
+ resize(d->size - n);
+}
+
+/*!
+ Sets every character in the string to character \a ch. If \a size
+ is different from -1 (default), the string is resized to \a
+ size beforehand.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 21
+
+ \sa resize()
+*/
+
+QString& QString::fill(QChar ch, int 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;
+ }
+ return *this;
+}
+
+/*!
+ \fn int QString::length() const
+
+ Returns the number of characters in this string. Equivalent to
+ size().
+
+ \sa resize()
+*/
+
+/*!
+ \fn int QString::size() const
+
+ Returns the number of characters in this string.
+
+ The last character in the string is at position size() - 1. In
+ addition, QString ensures that the character at position size()
+ is always '\\0', so that you can use the return value of data()
+ and constData() as arguments to functions that expect
+ '\\0'-terminated strings.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 58
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QString::isNull() const
+
+ Returns true if this string is null; otherwise returns false.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 28
+
+ Qt makes a distinction between null strings and empty strings for
+ historical reasons. For most applications, what matters is
+ whether or not a string contains any data, and this can be
+ determined using the isEmpty() function.
+
+ \sa isEmpty()
+*/
+
+/*! \fn bool QString::isEmpty() const
+
+ Returns true if the string has no characters; otherwise returns
+ false.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 27
+
+ \sa size()
+*/
+
+/*! \fn QString &QString::operator+=(const QString &other)
+
+ Appends the string \a other onto the end of this string and
+ returns a reference to this string.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 84
+
+ This operation is typically very fast (\l{constant time}),
+ because QString preallocates extra space at the end of the string
+ data so it can grow without reallocating the entire string each
+ time.
+
+ \sa append(), prepend()
+*/
+
+/*! \fn QString &QString::operator+=(const QLatin1String &str)
+
+ \overload operator+=()
+
+ Appends the Latin-1 string \a str to this string.
+*/
+
+/*! \fn QString &QString::operator+=(const QByteArray &ba)
+
+ \overload operator+=()
+
+ Appends the byte array \a ba to this string. The byte array is converted
+ to Unicode using the fromAscii() function. If any NUL characters ('\0')
+ 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
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*! \fn QString &QString::operator+=(const char *str)
+
+ \overload operator+=()
+
+ Appends the string \a str to this string. The const char pointer
+ is converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*! \fn QString &QString::operator+=(const QStringRef &str)
+
+ \overload operator+=()
+
+ Appends the string section referenced by \a str to this string.
+*/
+
+/*! \fn QString &QString::operator+=(char ch)
+
+ \overload operator+=()
+
+ Appends the character \a ch to this string. The character is
+ converted to Unicode using the fromAscii() function.
+
+ You can disable this function 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.
+*/
+
+/*! \fn QString &QString::operator+=(QChar ch)
+
+ \overload operator+=()
+
+ Appends the character \a ch to the string.
+*/
+
+/*! \fn QString &QString::operator+=(QChar::SpecialCharacter c)
+
+ \overload operator+=()
+
+ \internal
+*/
+
+/*!
+ \fn bool operator==(const char *s1, const QString &s2)
+
+ \overload operator==()
+ \relates QString
+
+ Returns true if \a s1 is equal to \a s2; otherwise returns false.
+ Note that no string is equal to \a s1 being 0.
+
+ Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}.
+
+ \sa QString::compare()
+*/
+
+/*!
+ \fn bool operator!=(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns true if \a s1 is not equal to \a s2; otherwise returns
+ 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.
+
+ \sa QString::compare()
+*/
+
+/*!
+ \fn bool operator<(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns true if \a s1 is lexically less than \a s2; otherwise
+ returns false. For \a s1 != 0, this is equivalent to \c
+ {compare(s1, s2) < 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 QString::compare()
+*/
+
+/*!
+ \fn bool operator<=(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns true if \a s1 is lexically less than or equal to \a s2;
+ otherwise returns false. For \a s1 != 0, this is equivalent to \c
+ {compare(s1, s2) <= 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 QString::compare()
+*/
+
+/*!
+ \fn bool operator>(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns true if \a s1 is lexically greater than \a s2; otherwise
+ returns false. Equivalent to \c {compare(s1, s2) > 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 QString::compare()
+*/
+
+/*!
+ \fn bool operator>=(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns true if \a s1 is lexically greater than or equal to \a s2;
+ otherwise returns false. For \a s1 != 0, this is equivalent to \c
+ {compare(s1, s2) >= 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.
+*/
+
+/*!
+ \fn const QString operator+(const QString &s1, const QString &s2)
+ \relates QString
+
+ Returns a string which is the result of concatenating \a s1 and \a
+ s2.
+*/
+
+/*!
+ \fn const QString operator+(const QString &s1, const char *s2)
+ \relates QString
+
+ Returns a string which is the result of concatenating \a s1 and \a
+ s2 (\a s2 is converted to Unicode using the QString::fromAscii()
+ function).
+
+ \sa QString::fromAscii()
+*/
+
+/*!
+ \fn const QString operator+(const char *s1, const QString &s2)
+ \relates QString
+
+ Returns a string which is the result of concatenating \a s1 and \a
+ s2 (\a s1 is converted to Unicode using the QString::fromAscii()
+ function).
+
+ \sa QString::fromAscii()
+*/
+
+/*!
+ \fn const QString operator+(const QString &s, char ch)
+ \relates QString
+
+ Returns a string which is the result of concatenating the string
+ \a s and the character \a ch.
+*/
+
+/*!
+ \fn const QString operator+(char ch, const QString &s)
+ \relates QString
+
+ Returns a string which is the result of concatenating the
+ character \a ch and the string \a s.
+*/
+
+/*!
+ \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.
+
+ If \a cs is Qt::CaseSensitive, 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
+ localeAwareCompare().
+
+ \snippet doc/src/snippets/qstring/main.cpp 16
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+/*!
+ \fn int QString::compare(const QString & s1, const QString & s2)
+
+ \overload compare()
+
+ Performs a case sensitive compare of \a s1 and \a s2.
+*/
+
+/*!
+ \fn int QString::compare(const QString &s1, const QLatin1String &s2, Qt::CaseSensitivity cs)
+ \since 4.2
+ \overload compare()
+
+ Performs a comparison of \a s1 and \a s2, using the case
+ sensitivity setting \a cs.
+*/
+
+/*!
+ \fn int QString::compare(const QLatin1String &s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+
+ \since 4.2
+ \overload compare()
+
+ Performs a comparison of \a s1 and \a s2, using the case
+ sensitivity setting \a cs.
+*/
+
+/*!
+ \overload compare()
+
+ 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.
+
+ Equivalent to \c {compare(*this, other)}.
+*/
+int QString::compare(const QString &other) const
+{
+ return ucstrcmp(constData(), length(), other.constData(), other.length());
+}
+
+/*!
+ \overload compare()
+ \since 4.2
+
+ Same as compare(*this, \a other, \a cs).
+*/
+int QString::compare(const QString &other, Qt::CaseSensitivity cs) const
+{
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(constData(), length(), other.constData(), other.length());
+ return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size);
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2,
+ Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(data1, length1, data2, length2);
+ register const ushort *s1 = reinterpret_cast<const ushort *>(data1);
+ register const ushort *s2 = reinterpret_cast<const ushort *>(data2);
+ return ucstricmp(s1, s1 + length1, s2, s2 + length2);
+}
+
+/*!
+ \overload compare()
+ \since 4.2
+
+ Same as compare(*this, \a other, \a cs).
+*/
+int QString::compare(const QLatin1String &other, Qt::CaseSensitivity cs) const
+{
+ return compare_helper(unicode(), length(), other, cs);
+}
+
+/*!
+ \fn int QString::compare(const QStringRef &ref, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \overload compare()
+
+ Compares the string reference, \a ref, with the string and returns
+ an integer less than, equal to, or greater than zero if the string
+ is less than, equal to, or greater than \a ref.
+*/
+
+/*!
+ \fn int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ \overload compare()
+*/
+
+/*!
+ \internal
+ \since 4.5
+*/
+int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
+ Qt::CaseSensitivity cs)
+{
+ const ushort *uc = reinterpret_cast<const ushort *>(data1);
+ const ushort *e = uc + length1;
+ const uchar *c = (uchar *)s2.latin1();
+
+ if (!c)
+ return length1;
+
+ if (cs == Qt::CaseSensitive) {
+ while (uc < e && *c && *uc == *c)
+ uc++, c++;
+
+ if (uc == e)
+ return -*c;
+
+ return *uc - *c;
+ } else {
+ return ucstricmp(uc, e, c);
+ }
+}
+
+/*!
+ \fn int QString::localeAwareCompare(const QString & s1, const QString & s2)
+
+ 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 Mac OS X since Qt 4.3, this function compares according the
+ "Order for sorted lists" setting in the International prefereces panel.
+
+ \sa compare(), QTextCodec::locale()
+*/
+
+/*!
+ \fn int QString::localeAwareCompare(const QStringRef &other) const
+ \since 4.5
+ \overload localeAwareCompare()
+
+ 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.
+
+ Same as \c {localeAwareCompare(*this, other)}.
+*/
+
+/*!
+ \fn int QString::localeAwareCompare(const QString &s1, const QStringRef &s2)
+ \since 4.5
+ \overload localeAwareCompare()
+
+ 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.
+*/
+
+
+#if !defined(CSTR_LESS_THAN)
+#define CSTR_LESS_THAN 1
+#define CSTR_EQUAL 2
+#define CSTR_GREATER_THAN 3
+#endif
+
+/*!
+ \overload localeAwareCompare()
+
+ 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.
+
+ Same as \c {localeAwareCompare(*this, other)}.
+*/
+int QString::localeAwareCompare(const QString &other) const
+{
+ return localeAwareCompare_helper(constData(), length(), other.constData(), other.length());
+}
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+QT_END_NAMESPACE
+#include "qt_windows.h"
+QT_BEGIN_NAMESPACE
+#endif
+
+/*!
+ \internal
+ \since 4.5
+*/
+int QString::localeAwareCompare_helper(const QChar *data1, int length1,
+ const QChar *data2, int length2)
+{
+ // do the right thing for null and empty
+ if (length1 == 0 || length2 == 0)
+ return ucstrcmp(data1, length1, data2, length2);
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2);
+
+ switch (res) {
+ case CSTR_LESS_THAN:
+ return -1;
+ case CSTR_GREATER_THAN:
+ return 1;
+ default:
+ return 0;
+ }
+#elif defined (Q_OS_MAC)
+ // Use CFStringCompare for comparing strings on Mac. This makes Qt order
+ // strings the same way as native applications do, and also respects
+ // the "Order for sorted lists" setting in the International preferences
+ // panel.
+ const CFStringRef thisString =
+ CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
+ reinterpret_cast<const UniChar *>(data1), length1, kCFAllocatorNull);
+ const CFStringRef otherString =
+ CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
+ reinterpret_cast<const UniChar *>(data2), length2, kCFAllocatorNull);
+
+ const int result = CFStringCompare(thisString, otherString, kCFCompareLocalized);
+ CFRelease(thisString);
+ CFRelease(otherString);
+ return result;
+#elif defined(Q_OS_SYMBIAN)
+ TPtrC p1 = TPtrC16(reinterpret_cast<const TUint16 *>(data1), length1);
+ TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2);
+ return p1.CompareC(p2);
+#elif defined(Q_OS_UNIX)
+# if defined(QT_USE_ICU)
+ int res;
+ if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) {
+ if (res == 0)
+ res = ucstrcmp(data1, length1, data2, length2);
+ return res;
+ } // else fall through
+# endif
+ // declared in <string.h>
+ int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2));
+ if (delta == 0)
+ delta = ucstrcmp(data1, length1, data2, length2);
+ return delta;
+#else
+ return ucstrcmp(data1, length1, data2, length2);
+#endif
+}
+
+
+/*!
+ \fn const QChar *QString::unicode() const
+
+ Returns a '\\0'-terminated Unicode representation of the string.
+ The result remains valid until the string is modified.
+
+ \sa utf16()
+*/
+
+/*!
+ \fn const ushort *QString::utf16() const
+
+ Returns the QString as a '\\0\'-terminated array of unsigned
+ shorts. The result remains valid until the string is modified.
+
+ The returned string is in host byte order.
+
+ \sa unicode()
+*/
+
+const ushort *QString::utf16() const
+{
+ if (d->data != d->array) {
+ QString *that = const_cast<QString*>(this);
+ that->realloc(); // ensure '\\0'-termination for ::fromRawData strings
+ return that->d->data;
+ }
+ return d->array;
+}
+
+/*!
+ Returns a string of size \a width that contains this string
+ padded by the \a fill character.
+
+ If \a truncate is false and the size() of the string is more than
+ \a width, then the returned string is a copy of the string.
+
+ \snippet doc/src/snippets/qstring/main.cpp 32
+
+ If \a truncate is true and the size() of the string is more than
+ \a width, then any characters in a copy of the string after
+ position \a width are removed, and the copy is returned.
+
+ \snippet doc/src/snippets/qstring/main.cpp 33
+
+ \sa rightJustified()
+*/
+
+QString QString::leftJustified(int width, QChar fill, bool truncate) const
+{
+ QString result;
+ int len = length();
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ if (len)
+ memcpy(result.d->data, d->data, sizeof(QChar)*len);
+ QChar *uc = (QChar*)result.d->data + len;
+ while (padlen--)
+ * uc++ = fill;
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+/*!
+ Returns a string of size() \a width that contains the \a fill
+ character followed by the string. For example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 49
+
+ If \a truncate is false and the size() of the string is more than
+ \a width, then the returned string is a copy of the string.
+
+ If \a truncate is true and the size() of the string is more than
+ \a width, then the resulting string is truncated at position \a
+ width.
+
+ \snippet doc/src/snippets/qstring/main.cpp 50
+
+ \sa leftJustified()
+*/
+
+QString QString::rightJustified(int width, QChar fill, bool truncate) const
+{
+ QString result;
+ int len = length();
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ QChar *uc = (QChar*)result.d->data;
+ while (padlen--)
+ * uc++ = fill;
+ if (len)
+ memcpy(uc, d->data, sizeof(QChar)*len);
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+/*!
+ Returns a lowercase copy of the string.
+
+ \snippet doc/src/snippets/qstring/main.cpp 75
+
+ \sa toUpper()
+*/
+
+QString QString::toLower() const
+{
+ const ushort *p = d->data;
+ if (!p)
+ return *this;
+ if (!d->size)
+ return *this;
+
+#ifdef QT_USE_ICU
+ {
+ QString result;
+ if (qt_u_strToLower(*this, &result, QLocale()))
+ return result;
+ // else fall through and use Qt's toUpper
+ }
+#endif
+
+ const ushort *e = d->data + d->size;
+
+ // this avoids one out of bounds check in the loop
+ if (QChar(*p).isLowSurrogate())
+ ++p;
+
+ while (p != e) {
+ uint c = *p;
+ if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(p - 1), c);
+ const QUnicodeTables::Properties *prop = qGetProp(c);
+ if (prop->lowerCaseDiff || prop->lowerCaseSpecial) {
+ QString s(d->size, Qt::Uninitialized);
+ memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
+ ushort *pp = s.d->data + (p - d->data);
+ while (p < e) {
+ uint c = *p;
+ if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(p - 1), c);
+ prop = qGetProp(c);
+ if (prop->lowerCaseSpecial) {
+ int pos = pp - s.d->data;
+ s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
+ pp = s.d->data + pos;
+ const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff;
+ while (*specialCase)
+ *pp++ = *specialCase++;
+ } else {
+ *pp++ = *p + prop->lowerCaseDiff;
+ }
+ ++p;
+ }
+ s.truncate(pp - s.d->data);
+ return s;
+ }
+ ++p;
+ }
+ return *this;
+}
+
+/*!
+ Returns the case folded equivalent of the string. For most Unicode
+ characters this is the same as toLower().
+*/
+QString QString::toCaseFolded() const
+{
+ if (!d->size)
+ return *this;
+
+ const ushort *p = d->data;
+ if (!p)
+ return *this;
+
+ const ushort *e = d->data + d->size;
+
+ uint last = 0;
+ while (p < e) {
+ ushort folded = foldCase(*p, last);
+ if (folded != *p) {
+ QString s(*this);
+ s.detach();
+ ushort *pp = s.d->data + (p - d->data);
+ const ushort *ppe = s.d->data + s.d->size;
+ last = pp > s.d->data ? *(pp - 1) : 0;
+ while (pp < ppe) {
+ *pp = foldCase(*pp, last);
+ ++pp;
+ }
+ return s;
+ }
+ p++;
+ }
+ return *this;
+}
+
+/*!
+ Returns an uppercase copy of the string.
+
+ \snippet doc/src/snippets/qstring/main.cpp 81
+
+ \sa toLower()
+*/
+
+QString QString::toUpper() const
+{
+ const ushort *p = d->data;
+ if (!p)
+ return *this;
+ if (!d->size)
+ return *this;
+
+#ifdef QT_USE_ICU
+ {
+ QString result;
+ if (qt_u_strToUpper(*this, &result, QLocale()))
+ return result;
+ // else fall through and use Qt's toUpper
+ }
+#endif
+
+ const ushort *e = d->data + d->size;
+
+ // this avoids one out of bounds check in the loop
+ if (QChar(*p).isLowSurrogate())
+ ++p;
+
+ while (p != e) {
+ uint c = *p;
+ if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(p - 1), c);
+ const QUnicodeTables::Properties *prop = qGetProp(c);
+ if (prop->upperCaseDiff || prop->upperCaseSpecial) {
+ QString s(d->size, Qt::Uninitialized);
+ memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
+ ushort *pp = s.d->data + (p - d->data);
+ while (p < e) {
+ uint c = *p;
+ if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(p - 1), c);
+ prop = qGetProp(c);
+ if (prop->upperCaseSpecial) {
+ int pos = pp - s.d->data;
+ s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
+ pp = s.d->data + pos;
+ const ushort *specialCase = specialCaseMap + prop->upperCaseDiff;
+ while (*specialCase)
+ *pp++ = *specialCase++;
+ } else {
+ *pp++ = *p + prop->upperCaseDiff;
+ }
+ ++p;
+ }
+ s.truncate(pp - s.d->data);
+ return s;
+ }
+ ++p;
+ }
+ return *this;
+}
+
+// ### Qt 5: Consider whether this function shouldn't be removed See task 202871.
+/*!
+ Safely builds a formatted string from the format string \a cformat
+ and an arbitrary list of arguments.
+
+ The %lc escape sequence expects a unicode character of type ushort
+ (as returned by QChar::unicode()). The %ls escape sequence expects
+ a pointer to a zero-terminated array of unicode characters of type
+ ushort (as returned by QString::utf16()).
+
+ \note This function expects a UTF-8 string for %s and Latin-1 for
+ the format string.
+
+ The format string supports most of the conversion specifiers
+ provided by printf() in the standard C++ library. It doesn't
+ honor the length modifiers (e.g. \c h for \c short, \c ll for
+ \c{long long}). If you need those, use the standard snprintf()
+ function instead:
+
+ \snippet doc/src/snippets/qstring/main.cpp 63
+
+ \warning We do not recommend using QString::sprintf() in new Qt
+ code. Instead, consider using QTextStream or arg(), both of
+ which support Unicode strings seamlessly and are type-safe.
+ Here's an example that uses QTextStream:
+
+ \snippet doc/src/snippets/qstring/main.cpp 64
+
+ For \l {QObject::tr()}{translations}, especially if the strings
+ contains more than one escape sequence, you should consider using
+ the arg() function instead. This allows the order of the
+ replacements to be controlled by the translator.
+
+ \sa arg()
+*/
+
+QString &QString::sprintf(const char *cformat, ...)
+{
+ va_list ap;
+ va_start(ap, cformat);
+ QString &s = vsprintf(cformat, ap);
+ va_end(ap);
+ return s;
+}
+
+/*!
+ Equivalent method to sprintf(), but takes a va_list \a ap
+ instead a list of variable arguments. See the sprintf()
+ documentation for an explanation of \a cformat.
+
+ This method does not call the va_end macro, the caller
+ is responsible to call va_end on \a ap.
+
+ \sa sprintf()
+*/
+
+QString &QString::vsprintf(const char* cformat, va_list ap)
+{
+ QLocale locale(QLocale::C);
+
+ if (!cformat || !*cformat) {
+ // Qt 1.x compat
+ *this = fromLatin1("");
+ return *this;
+ }
+
+ // Parse cformat
+
+ QString result;
+ const char *c = cformat;
+ for (;;) {
+ // Copy non-escape chars to result
+#ifndef QT_NO_TEXTCODEC
+ int i = 0;
+ while (*(c + i) != '\0' && *(c + i) != '%')
+ ++i;
+ if (codecForCStrings)
+ result.append(codecForCStrings->toUnicode(c, i));
+ else
+ result.append(fromLatin1(c, i));
+ c += i;
+#else
+ while (*c != '\0' && *c != '%')
+ result.append(QLatin1Char(*c++));
+#endif
+
+ if (*c == '\0')
+ break;
+
+ // Found '%'
+ const char *escape_start = c;
+ ++c;
+
+ if (*c == '\0') {
+ result.append(QLatin1Char('%')); // a % at the end of the string - treat as non-escape text
+ break;
+ }
+ if (*c == '%') {
+ result.append(QLatin1Char('%')); // %%
+ ++c;
+ continue;
+ }
+
+ // Parse flag characters
+ uint flags = 0;
+ bool no_more_flags = false;
+ do {
+ switch (*c) {
+ case '#': flags |= QLocalePrivate::Alternate; break;
+ case '0': flags |= QLocalePrivate::ZeroPadded; break;
+ case '-': flags |= QLocalePrivate::LeftAdjusted; break;
+ case ' ': flags |= QLocalePrivate::BlankBeforePositive; break;
+ case '+': flags |= QLocalePrivate::AlwaysShowSign; break;
+ case '\'': flags |= QLocalePrivate::ThousandsGroup; break;
+ default: no_more_flags = true; break;
+ }
+
+ if (!no_more_flags)
+ ++c;
+ } while (!no_more_flags);
+
+ if (*c == '\0') {
+ result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ break;
+ }
+
+ // Parse field width
+ int width = -1; // -1 means unspecified
+ if (qIsDigit(*c)) {
+ QString width_str;
+ while (*c != '\0' && qIsDigit(*c))
+ width_str.append(QLatin1Char(*c++));
+
+ // can't be negative - started with a digit
+ // contains at least one digit
+ width = width_str.toInt();
+ }
+ else if (*c == '*') {
+ width = va_arg(ap, int);
+ if (width < 0)
+ width = -1; // treat all negative numbers as unspecified
+ ++c;
+ }
+
+ if (*c == '\0') {
+ result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ break;
+ }
+
+ // Parse precision
+ int precision = -1; // -1 means unspecified
+ if (*c == '.') {
+ ++c;
+ if (qIsDigit(*c)) {
+ QString precision_str;
+ while (*c != '\0' && qIsDigit(*c))
+ precision_str.append(QLatin1Char(*c++));
+
+ // can't be negative - started with a digit
+ // contains at least one digit
+ precision = precision_str.toInt();
+ }
+ else if (*c == '*') {
+ precision = va_arg(ap, int);
+ if (precision < 0)
+ precision = -1; // treat all negative numbers as unspecified
+ ++c;
+ }
+ }
+
+ if (*c == '\0') {
+ result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ break;
+ }
+
+ // Parse the length modifier
+ enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t };
+ LengthMod length_mod = lm_none;
+ switch (*c) {
+ case 'h':
+ ++c;
+ if (*c == 'h') {
+ length_mod = lm_hh;
+ ++c;
+ }
+ else
+ length_mod = lm_h;
+ break;
+
+ case 'l':
+ ++c;
+ if (*c == 'l') {
+ length_mod = lm_ll;
+ ++c;
+ }
+ else
+ length_mod = lm_l;
+ break;
+
+ case 'L':
+ ++c;
+ length_mod = lm_L;
+ break;
+
+ case 'j':
+ ++c;
+ length_mod = lm_j;
+ break;
+
+ case 'z':
+ case 'Z':
+ ++c;
+ length_mod = lm_z;
+ break;
+
+ case 't':
+ ++c;
+ length_mod = lm_t;
+ break;
+
+ default: break;
+ }
+
+ if (*c == '\0') {
+ result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ break;
+ }
+
+ // Parse the conversion specifier and do the conversion
+ QString subst;
+ switch (*c) {
+ case 'd':
+ case 'i': {
+ qint64 i;
+ switch (length_mod) {
+ case lm_none: i = va_arg(ap, int); break;
+ case lm_hh: i = va_arg(ap, int); break;
+ case lm_h: i = va_arg(ap, int); break;
+ 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;
+ default: i = 0; break;
+ }
+ subst = locale.d()->longLongToString(i, precision, 10, width, flags);
+ ++c;
+ break;
+ }
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X': {
+ quint64 u;
+ switch (length_mod) {
+ case lm_none: u = va_arg(ap, uint); break;
+ case lm_hh: u = va_arg(ap, uint); break;
+ 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_z: u = va_arg(ap, size_t); break;
+ default: u = 0; break;
+ }
+
+ if (qIsUpper(*c))
+ flags |= QLocalePrivate::CapitalEorX;
+
+ int base = 10;
+ switch (qToLower(*c)) {
+ case 'o':
+ base = 8; break;
+ case 'u':
+ base = 10; break;
+ case 'x':
+ base = 16; break;
+ default: break;
+ }
+ subst = locale.d()->unsLongLongToString(u, precision, base, width, flags);
+ ++c;
+ break;
+ }
+ case 'E':
+ case 'e':
+ case 'F':
+ case 'f':
+ case 'G':
+ case 'g':
+ case 'A':
+ case 'a': {
+ double d;
+ if (length_mod == lm_L)
+ d = va_arg(ap, long double); // not supported - converted to a double
+ else
+ d = va_arg(ap, double);
+
+ if (qIsUpper(*c))
+ flags |= QLocalePrivate::CapitalEorX;
+
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ switch (qToLower(*c)) {
+ case 'e': form = QLocalePrivate::DFExponent; break;
+ case 'a': // not supported - decimal form used instead
+ case 'f': form = QLocalePrivate::DFDecimal; break;
+ case 'g': form = QLocalePrivate::DFSignificantDigits; break;
+ default: break;
+ }
+ subst = locale.d()->doubleToString(d, precision, form, width, flags);
+ ++c;
+ break;
+ }
+ case 'c': {
+ if (length_mod == lm_l)
+ subst = QChar((ushort) va_arg(ap, int));
+ else
+ subst = QLatin1Char((uchar) va_arg(ap, int));
+ ++c;
+ break;
+ }
+ case 's': {
+ if (length_mod == lm_l) {
+ const ushort *buff = va_arg(ap, const ushort*);
+ const ushort *ch = buff;
+ while (*ch != 0)
+ ++ch;
+ subst.setUtf16(buff, ch - buff);
+ } else
+ subst = QString::fromUtf8(va_arg(ap, const char*));
+ if (precision != -1)
+ subst.truncate(precision);
+ ++c;
+ break;
+ }
+ case 'p': {
+ void *arg = va_arg(ap, void*);
+#ifdef Q_OS_WIN64
+ quint64 i = reinterpret_cast<quint64>(arg);
+#else
+ quint64 i = reinterpret_cast<unsigned long>(arg);
+#endif
+ flags |= QLocalePrivate::Alternate;
+ subst = locale.d()->unsLongLongToString(i, precision, 16, width, flags);
+ ++c;
+ break;
+ }
+ case 'n':
+ switch (length_mod) {
+ case lm_hh: {
+ signed char *n = va_arg(ap, signed char*);
+ *n = result.length();
+ break;
+ }
+ case lm_h: {
+ short int *n = va_arg(ap, short int*);
+ *n = result.length();
+ break;
+ }
+ case lm_l: {
+ long int *n = va_arg(ap, long int*);
+ *n = result.length();
+ break;
+ }
+ case lm_ll: {
+ qint64 *n = va_arg(ap, qint64*);
+ volatile uint tmp = result.length(); // egcs-2.91.66 gets internal
+ *n = tmp; // compiler error without volatile
+ break;
+ }
+ default: {
+ int *n = va_arg(ap, int*);
+ *n = result.length();
+ break;
+ }
+ }
+ ++c;
+ break;
+
+ default: // bad escape, treat as non-escape text
+ for (const char *cc = escape_start; cc != c; ++cc)
+ result.append(QLatin1Char(*cc));
+ continue;
+ }
+
+ if (flags & QLocalePrivate::LeftAdjusted)
+ result.append(subst.leftJustified(width));
+ else
+ result.append(subst.rightJustified(width));
+ }
+
+ *this = result;
+
+ return *this;
+}
+
+/*!
+ 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 conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 74
+
+ \sa number(), toULongLong(), toInt()
+*/
+
+qint64 QString::toLongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QString::toLongLong: Invalid base (%d)", base);
+ base = 10;
+ }
+#endif
+
+ bool my_ok;
+ QLocale def_locale;
+ qint64 result = def_locale.d()->stringToLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
+ if (my_ok) {
+ if (ok != 0)
+ *ok = true;
+ return result;
+ }
+
+ QLocale c_locale(QLocale::C);
+ return c_locale.d()->stringToLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
+}
+
+/*!
+ 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 conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 79
+
+ \sa number(), toLongLong()
+*/
+
+quint64 QString::toULongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QString::toULongLong: Invalid base (%d)", base);
+ base = 10;
+ }
+#endif
+
+ bool my_ok;
+ QLocale def_locale;
+ quint64 result = def_locale.d()->stringToUnsLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
+ if (my_ok) {
+ if (ok != 0)
+ *ok = true;
+ return result;
+ }
+
+ QLocale c_locale(QLocale::C);
+ return c_locale.d()->stringToUnsLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
+}
+
+/*!
+ \fn long QString::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 conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 73
+
+ \sa number(), toULong(), toInt()
+*/
+
+long QString::toLong(bool *ok, int base) const
+{
+ qint64 v = toLongLong(ok, base);
+ if (v < LONG_MIN || v > LONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return (long)v;
+}
+
+/*!
+ \fn ulong QString::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 conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 78
+
+ \sa number()
+*/
+
+ulong QString::toULong(bool *ok, int base) const
+{
+ quint64 v = toULongLong(ok, base);
+ if (v > ULONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return (ulong)v;
+}
+
+
+/*!
+ 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 conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 72
+
+ \sa number(), toUInt(), toDouble()
+*/
+
+int QString::toInt(bool *ok, int base) const
+{
+ qint64 v = toLongLong(ok, base);
+ if (v < INT_MIN || v > INT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return v;
+}
+
+/*!
+ 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.
+
+ If a conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 77
+
+ \sa number(), toInt()
+*/
+
+uint QString::toUInt(bool *ok, int base) const
+{
+ quint64 v = toULongLong(ok, base);
+ if (v > UINT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return (uint)v;
+}
+
+/*!
+ 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.
+
+ If a conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 76
+
+ \sa number(), toUShort(), toInt()
+*/
+
+short QString::toShort(bool *ok, int base) const
+{
+ long v = toLongLong(ok, base);
+ if (v < SHRT_MIN || v > SHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return (short)v;
+}
+
+/*!
+ 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.
+
+ If a conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to 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.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 80
+
+ \sa number(), toShort()
+*/
+
+ushort QString::toUShort(bool *ok, int base) const
+{
+ ulong v = toULongLong(ok, base);
+ if (v > USHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return (ushort)v;
+}
+
+
+/*!
+ Returns the string converted to a \c double value.
+
+ Returns 0.0 if the conversion fails.
+
+ If a conversion error occurs, \c{*}\a{ok} is set to false;
+ otherwise \c{*}\a{ok} is set to true.
+
+ \snippet doc/src/snippets/qstring/main.cpp 66
+
+ Various string formats for floating point numbers can be converted
+ to double values:
+
+ \snippet doc/src/snippets/qstring/main.cpp 67
+
+ This function tries to interpret the string according to the
+ current locale. The current locale is determined from the
+ system at application startup and can be changed by calling
+ QLocale::setDefault(). If the string cannot be interpreted
+ according to the current locale, this function falls back
+ on the "C" locale.
+
+ \snippet doc/src/snippets/qstring/main.cpp 69
+ \snippet doc/src/snippets/qstring/main.cpp 70
+
+ Due to the ambiguity between the decimal point and thousands group
+ separator in various locales, this function does not handle
+ thousands group separators. If you need to convert such numbers,
+ see QLocale::toDouble().
+
+ \snippet doc/src/snippets/qstring/main.cpp 68
+
+ \sa number() QLocale::setDefault() QLocale::toDouble() trimmed()
+*/
+
+double QString::toDouble(bool *ok) const
+{
+ bool my_ok;
+ QLocale def_locale;
+ double result = def_locale.d()->stringToDouble(*this, &my_ok, QLocalePrivate::FailOnGroupSeparators);
+ if (my_ok) {
+ if (ok != 0)
+ *ok = true;
+ return result;
+ }
+
+ QLocale c_locale(QLocale::C);
+ return c_locale.d()->stringToDouble(*this, ok, QLocalePrivate::FailOnGroupSeparators);
+}
+
+/*!
+ Returns the string converted to a \c float value.
+
+ If a conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to true. Returns 0.0 if the conversion fails.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 71
+
+ \sa number(), toDouble(), toInt()
+*/
+
+#define QT_MAX_FLOAT 3.4028234663852886e+38
+
+float QString::toFloat(bool *ok) const
+{
+ bool myOk;
+ double d = toDouble(&myOk);
+ if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
+ if (ok != 0)
+ *ok = false;
+ return 0.0;
+ }
+ if (ok != 0)
+ *ok = true;
+ return (float) d;
+}
+
+/*! \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.
+
+ \snippet doc/src/snippets/qstring/main.cpp 56
+
+ 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.
+*/
+
+/*! \fn QString &QString::setNum(uint n, int base)
+
+ \overload
+*/
+
+/*! \fn QString &QString::setNum(long n, int base)
+
+ \overload
+*/
+
+/*! \fn QString &QString::setNum(ulong n, int base)
+
+ \overload
+*/
+
+/*!
+ \overload
+*/
+QString &QString::setNum(qlonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QString::setNum: Invalid base (%d)", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->longLongToString(n, -1, base);
+ return *this;
+}
+
+/*!
+ \overload
+*/
+QString &QString::setNum(qulonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QString::setNum: Invalid base (%d)", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->unsLongLongToString(n, -1, base);
+ return *this;
+}
+
+/*! \fn QString &QString::setNum(short n, int base)
+
+ \overload
+*/
+
+/*! \fn QString &QString::setNum(ushort n, int base)
+
+ \overload
+*/
+
+/*!
+ \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 'f', 'F', 'e', 'E', 'g' or 'G' (see the
+ arg() function documentation for an explanation of the formats).
+
+ Unlike QLocale::toString(), this function doesn't honor the
+ user's locale settings.
+*/
+
+QString &QString::setNum(double n, char f, int prec)
+{
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ uint flags = 0;
+
+ if (qIsUpper(f))
+ flags = QLocalePrivate::CapitalEorX;
+ f = qToLower(f);
+
+ switch (f) {
+ case 'f':
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case 'e':
+ form = QLocalePrivate::DFExponent;
+ break;
+ case 'g':
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ default:
+#if defined(QT_CHECK_RANGE)
+ qWarning("QString::setNum: Invalid format char '%c'", f);
+#endif
+ break;
+ }
+
+ QLocale locale(QLocale::C);
+ *this = locale.d()->doubleToString(n, prec, form, -1, flags);
+ return *this;
+}
+
+/*!
+ \fn QString &QString::setNum(float 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.
+*/
+
+
+/*!
+ \fn QString QString::number(long n, int base)
+
+ Returns a string equivalent of the number \a n according to the
+ specified \a base.
+
+ 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.
+
+ \snippet doc/src/snippets/qstring/main.cpp 35
+
+ \sa setNum()
+*/
+
+QString QString::number(long n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \fn QString QString::number(ulong n, int base)
+
+ \overload
+*/
+QString QString::number(ulong n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+*/
+QString QString::number(int n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+*/
+QString QString::number(uint n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+*/
+QString QString::number(qlonglong n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+*/
+QString QString::number(qulonglong n, int base)
+{
+ QString s;
+ s.setNum(n, base);
+ return s;
+}
+
+
+/*!
+ \fn QString QString::number(double n, char format, int precision)
+
+ 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.
+
+ Unlike QLocale::toString(), this function does not honor the
+ user's locale settings.
+
+ \sa setNum(), QLocale::toString()
+*/
+QString QString::number(double n, char f, int prec)
+{
+ QString s;
+ s.setNum(n, f, prec);
+ return s;
+}
+
+/*!
+ Splits the string into substrings wherever \a sep occurs, and
+ returns the list of those strings. If \a sep does not match
+ anywhere in the string, split() returns a single-element list
+ containing this string.
+
+ \a cs specifies whether \a sep should be matched case
+ sensitively or case insensitively.
+
+ If \a behavior is QString::SkipEmptyParts, empty entries don't
+ appear in the result. By default, empty entries are kept.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 62
+
+ \sa QStringList::join(), section()
+*/
+QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{
+ QStringList list;
+ int start = 0;
+ int extra = 0;
+ int end;
+ while ((end = indexOf(sep, start + extra, cs)) != -1) {
+ if (start != end || behavior == KeepEmptyParts)
+ list.append(mid(start, end - start));
+ start = end + sep.size();
+ extra = (sep.size() == 0 ? 1 : 0);
+ }
+ if (start != size() || behavior == KeepEmptyParts)
+ list.append(mid(start));
+ return list;
+}
+
+/*!
+ \overload
+*/
+QStringList QString::split(const QChar &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{
+ QStringList list;
+ int start = 0;
+ int end;
+ while ((end = indexOf(sep, start, cs)) != -1) {
+ if (start != end || behavior == KeepEmptyParts)
+ list.append(mid(start, end - start));
+ start = end + 1;
+ }
+ if (start != size() || behavior == KeepEmptyParts)
+ list.append(mid(start));
+ return list;
+}
+
+#ifndef QT_NO_REGEXP
+/*!
+ \overload
+
+ Splits the string into substrings wherever the regular expression
+ \a rx matches, and returns the list of those strings. If \a rx
+ does not match anywhere in the string, split() returns a
+ single-element list containing this string.
+
+ Here's an example where we extract the words in a sentence
+ using one or more whitespace characters as the separator:
+
+ \snippet doc/src/snippets/qstring/main.cpp 59
+
+ Here's a similar example, but this time we use any sequence of
+ non-word characters as the separator:
+
+ \snippet doc/src/snippets/qstring/main.cpp 60
+
+ Here's a third example where we use a zero-length assertion,
+ \bold{\\b} (word boundary), to split the string into an
+ alternating sequence of non-word and word tokens:
+
+ \snippet doc/src/snippets/qstring/main.cpp 61
+
+ \sa QStringList::join(), section()
+*/
+QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
+{
+ QRegExp rx2(rx);
+ QStringList list;
+ int start = 0;
+ int extra = 0;
+ int end;
+ while ((end = rx2.indexIn(*this, start + extra)) != -1) {
+ int matchedLen = rx2.matchedLength();
+ if (start != end || behavior == KeepEmptyParts)
+ list.append(mid(start, end - start));
+ start = end + matchedLen;
+ extra = (matchedLen == 0) ? 1 : 0;
+ }
+ if (start != size() || behavior == KeepEmptyParts)
+ list.append(mid(start));
+ return list;
+}
+#endif
+
+/*!
+ \enum QString::NormalizationForm
+
+ This enum describes the various normalized forms of Unicode text.
+
+ \value NormalizationForm_D Canonical Decomposition
+ \value NormalizationForm_C Canonical Decomposition followed by Canonical Composition
+ \value NormalizationForm_KD Compatibility Decomposition
+ \value NormalizationForm_KC Compatibility Decomposition followed by Canonical Composition
+
+ \sa normalized(),
+ {http://www.unicode.org/reports/tr15/}{Unicode Standard Annex #15}
+*/
+
+/*!
+ \fn QString QString::normalized(NormalizationForm mode) const
+ Returns the string in the given Unicode normalization \a mode.
+*/
+QString QString::normalized(QString::NormalizationForm mode) const
+{
+ return normalized(mode, UNICODE_DATA_VERSION);
+}
+
+/*!
+ \since 4.5
+
+ Returns a copy of this string repeated the specified number of \a times.
+
+ If \a times is less than 1, an empty string is returned.
+
+ Example:
+
+ \code
+ QString str("ab");
+ str.repeated(4); // returns "abababab"
+ \endcode
+*/
+QString QString::repeated(int times) const
+{
+ if (d->size == 0)
+ return *this;
+
+ if (times <= 1) {
+ if (times == 1)
+ return *this;
+ return QString();
+ }
+
+ const int resultSize = times * d->size;
+
+ QString result;
+ result.reserve(resultSize);
+ if (result.d->alloc != resultSize)
+ return QString(); // not enough memory
+
+ memcpy(result.d->data, d->data, d->size * sizeof(ushort));
+
+ int sizeSoFar = d->size;
+ ushort *end = result.d->data + sizeSoFar;
+
+ const int halfResultSize = resultSize >> 1;
+ while (sizeSoFar <= halfResultSize) {
+ memcpy(end, result.d->data, sizeSoFar * sizeof(ushort));
+ end += sizeSoFar;
+ sizeSoFar <<= 1;
+ }
+ memcpy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort));
+ result.d->data[resultSize] = '\0';
+ result.d->size = resultSize;
+ return result;
+}
+
+void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from);
+/*!
+ \overload
+ \fn QString QString::normalized(NormalizationForm mode, QChar::UnicodeVersion version) const
+
+ Returns the string in the given Unicode normalization \a mode,
+ according to the given \a version of the Unicode standard.
+*/
+QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const
+{
+ QString copy = *this;
+ qt_string_normalize(&copy, mode, version, 0);
+ return copy;
+}
+
+void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from)
+{
+ bool simple = true;
+ const QChar *p = data->constData();
+ int len = data->length();
+ for (int i = from; i < len; ++i) {
+ if (p[i].unicode() >= 0x80) {
+ simple = false;
+ break;
+ }
+ }
+ if (simple)
+ return;
+
+ if (version == QChar::Unicode_Unassigned) {
+ version = UNICODE_DATA_VERSION;
+ } else if (version != UNICODE_DATA_VERSION) {
+ const QString &s = *data;
+ QChar *d = 0;
+ for (int i = 0; i < NumNormalizationCorrections; ++i) {
+ const NormalizationCorrection &n = uc_normalization_corrections[i];
+ if (n.version > version) {
+ int pos = from;
+ if (QChar::requiresSurrogates(n.ucs4)) {
+ ushort ucs4High = QChar::highSurrogate(n.ucs4);
+ ushort ucs4Low = QChar::lowSurrogate(n.ucs4);
+ ushort oldHigh = QChar::highSurrogate(n.old_mapping);
+ ushort oldLow = QChar::lowSurrogate(n.old_mapping);
+ while (pos < s.length() - 1) {
+ if (s.at(pos).unicode() == ucs4High && s.at(pos + 1).unicode() == ucs4Low) {
+ if (!d)
+ d = data->data();
+ d[pos] = QChar(oldHigh);
+ d[++pos] = QChar(oldLow);
+ }
+ ++pos;
+ }
+ } else {
+ while (pos < s.length()) {
+ if (s.at(pos).unicode() == n.ucs4) {
+ if (!d)
+ d = data->data();
+ d[pos] = QChar(n.old_mapping);
+ }
+ ++pos;
+ }
+ }
+ }
+ }
+ }
+ decomposeHelper(data, mode < QString::NormalizationForm_KD, version, from);
+
+ canonicalOrderHelper(data, version, from);
+
+ if (mode == QString::NormalizationForm_D || mode == QString::NormalizationForm_KD)
+ return;
+
+ composeHelper(data, from);
+}
+
+
+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
+};
+
+static ArgEscapeData findArgEscapes(const QString &s)
+{
+ const QChar *uc_begin = s.unicode();
+ const QChar *uc_end = uc_begin + s.length();
+
+ ArgEscapeData d;
+
+ d.min_escape = INT_MAX;
+ d.occurrences = 0;
+ d.escape_len = 0;
+ d.locale_occurrences = 0;
+
+ const QChar *c = uc_begin;
+ while (c != uc_end) {
+ while (c != uc_end && c->unicode() != '%')
+ ++c;
+
+ if (c == uc_end)
+ break;
+ const QChar *escape_start = c;
+ if (++c == uc_end)
+ break;
+
+ bool locale_arg = false;
+ if (c->unicode() == 'L') {
+ locale_arg = true;
+ if (++c == uc_end)
+ break;
+ }
+
+ if (c->digitValue() == -1)
+ continue;
+
+ int escape = c->digitValue();
+ ++c;
+
+ if (c != uc_end && c->digitValue() != -1) {
+ escape = (10 * escape) + c->digitValue();
+ ++c;
+ }
+
+ if (escape > d.min_escape)
+ continue;
+
+ if (escape < d.min_escape) {
+ d.min_escape = escape;
+ d.occurrences = 0;
+ d.escape_len = 0;
+ d.locale_occurrences = 0;
+ }
+
+ ++d.occurrences;
+ if (locale_arg)
+ ++d.locale_occurrences;
+ d.escape_len += c - escape_start;
+ }
+ return d;
+}
+
+static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int field_width,
+ const QString &arg, const QString &larg, const QChar &fillChar = QLatin1Char(' '))
+{
+ const QChar *uc_begin = s.unicode();
+ const QChar *uc_end = uc_begin + s.length();
+
+ 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());
+
+ QString result(result_len, Qt::Uninitialized);
+ QChar *result_buff = (QChar*) result.unicode();
+
+ QChar *rc = result_buff;
+ const QChar *c = uc_begin;
+ int repl_cnt = 0;
+ 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. */
+
+ 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;
+ ++c;
+ }
+
+ int escape = c->digitValue();
+ if (escape != -1) {
+ if (c + 1 != uc_end && (c + 1)->digitValue() != -1) {
+ escape = (10 * escape) + (c + 1)->digitValue();
+ ++c;
+ }
+ }
+
+ if (escape != d.min_escape) {
+ memcpy(rc, text_start, (c - text_start)*sizeof(QChar));
+ rc += c - text_start;
+ }
+ else {
+ ++c;
+
+ 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();
+
+ if (field_width > 0) { // left padded
+ for (uint i = 0; i < pad_chars; ++i)
+ (rc++)->unicode() = fillChar.unicode();
+ }
+
+ if (locale_arg) {
+ memcpy(rc, larg.unicode(), larg.length()*sizeof(QChar));
+ rc += larg.length();
+ }
+ else {
+ memcpy(rc, arg.unicode(), arg.length()*sizeof(QChar));
+ rc += arg.length();
+ }
+
+ if (field_width < 0) { // right padded
+ for (uint i = 0; i < pad_chars; ++i)
+ (rc++)->unicode() = fillChar.unicode();
+ }
+
+ if (++repl_cnt == d.occurrences) {
+ memcpy(rc, c, (uc_end - c)*sizeof(QChar));
+ rc += uc_end - c;
+ Q_ASSERT(rc - result_buff == result_len);
+ c = uc_end;
+ }
+ }
+ }
+ Q_ASSERT(rc == result_buff + result_len);
+
+ return result;
+}
+
+/*!
+ 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.
+
+ \a fieldWidth specifies the minimum amount of space that argument \a
+ a shall occupy. If \a a requires less space than \a fieldWidth, it
+ is padded to \a fieldWidth with character \a fillChar. A positive
+ \a fieldWidth produces right-aligned text. A negative \a fieldWidth
+ produces left-aligned text.
+
+ This example shows how we might create a \c status string for
+ reporting progress while processing a list of files:
+
+ \snippet doc/src/snippets/qstring/main.cpp 11
+
+ First, \c arg(i) replaces \c %1. Then \c arg(total) replaces \c
+ %2. Finally, \c arg(fileName) replaces \c %3.
+
+ One advantage of using arg() over sprintf() is that the order of the
+ numbered place markers can change, if the application's strings are
+ translated into other languages, but each arg() will still replace
+ the lowest numbered unreplaced place marker, no matter where it
+ appears. Also, if place marker \c %i appears more than once in the
+ string, the arg() replaces all of them.
+
+ If there is no unreplaced place marker remaining, a warning message
+ is output and the result is undefined. Place marker numbers must be
+ in the range 1 to 99.
+*/
+QString QString::arg(const QString &a, int fieldWidth, const QChar &fillChar) const
+{
+ ArgEscapeData d = findArgEscapes(*this);
+
+ if (d.occurrences == 0) {
+ qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(),
+ a.toLocal8Bit().data());
+ return *this;
+ }
+ return replaceArgEscapes(*this, d, fieldWidth, a, a, 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 doc/src/snippets/qstring/main.cpp 13
+*/
+
+/*!
+ \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, const QChar &fillChar) const
+ \overload arg()
+
+ The \a a argument is expressed in base \a base, which is 10 by
+ default and must be between 2 and 36. For bases other than 10, \a a
+ is treated as an unsigned integer.
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ 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
+ ignored if \a base is not 10.
+
+ \snippet doc/src/snippets/qstring/main.cpp 12
+ \snippet doc/src/snippets/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.
+*/
+
+/*! \fn QString QString::arg(uint a, int fieldWidth, int base, const QChar &fillChar) const
+ \overload arg()
+
+ 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.
+*/
+
+/*! \fn QString QString::arg(long a, int fieldWidth, int base, const QChar &fillChar) const
+ \overload arg()
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ The \a a argument is expressed in the given \a base, which is 10 by
+ default and must be between 2 and 36.
+
+ 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. The default locale is determined from the
+ system's locale settings at application startup. It can be changed
+ using QLocale::setDefault(). The 'L' flag is ignored if \a base is
+ not 10.
+
+ \snippet doc/src/snippets/qstring/main.cpp 12
+ \snippet doc/src/snippets/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.
+*/
+
+/*! \fn QString QString::arg(ulong a, int fieldWidth, int base, const QChar &fillChar) const
+ \overload arg()
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ The \a base argument specifies the base to use when converting the
+ 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.
+*/
+
+/*!
+ \overload arg()
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ 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, 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.
+*/
+QString QString::arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
+{
+ ArgEscapeData d = findArgEscapes(*this);
+
+ if (d.occurrences == 0) {
+ qWarning() << "QString::arg: Argument missing:" << *this << ',' << a;
+ return *this;
+ }
+
+ unsigned flags = QLocalePrivate::NoFlags;
+ if (fillChar == QLatin1Char('0'))
+ flags = QLocalePrivate::ZeroPadded;
+
+ QString arg;
+ if (d.occurrences > d.locale_occurrences)
+ arg = QLocale::c().d()->longLongToString(a, -1, base, fieldWidth, flags);
+
+ QString locale_arg;
+ if (d.locale_occurrences > 0) {
+ QLocale locale;
+ if (!locale.numberOptions() & QLocale::OmitGroupSeparator)
+ flags |= QLocalePrivate::ThousandsGroup;
+ locale_arg = locale.d()->longLongToString(a, -1, base, fieldWidth, flags);
+ }
+
+ return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+}
+
+/*!
+ \overload arg()
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ The \a base argument specifies the base to use when converting the
+ 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.
+*/
+QString QString::arg(qulonglong a, int fieldWidth, int base, const QChar &fillChar) const
+{
+ ArgEscapeData d = findArgEscapes(*this);
+
+ if (d.occurrences == 0) {
+ qWarning() << "QString::arg: Argument missing:" << *this << ',' << a;
+ return *this;
+ }
+
+ unsigned flags = QLocalePrivate::NoFlags;
+ if (fillChar == QLatin1Char('0'))
+ flags = QLocalePrivate::ZeroPadded;
+
+ QString arg;
+ if (d.occurrences > d.locale_occurrences)
+ arg = QLocale::c().d()->unsLongLongToString(a, -1, base, fieldWidth, flags);
+
+ QString locale_arg;
+ if (d.locale_occurrences > 0) {
+ QLocale locale;
+ if (!locale.numberOptions() & QLocale::OmitGroupSeparator)
+ flags |= QLocalePrivate::ThousandsGroup;
+ locale_arg = locale.d()->unsLongLongToString(a, -1, base, fieldWidth, flags);
+ }
+
+ return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+}
+
+/*!
+ \overload arg()
+
+ \fn QString QString::arg(short a, int fieldWidth, int base, const QChar &fillChar) const
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ 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, 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.
+*/
+
+/*!
+ \fn QString QString::arg(ushort a, int fieldWidth, int base, const QChar &fillChar) const
+ \overload arg()
+
+ \a fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ 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, 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.
+*/
+
+/*!
+ \overload arg()
+*/
+QString QString::arg(QChar a, int fieldWidth, const QChar &fillChar) const
+{
+ QString c;
+ c += a;
+ return arg(c, fieldWidth, fillChar);
+}
+
+/*!
+ \overload arg()
+
+ The \a a argument is interpreted as a Latin-1 character.
+*/
+QString QString::arg(char a, int fieldWidth, const QChar &fillChar) const
+{
+ QString c;
+ c += QLatin1Char(a);
+ return arg(c, fieldWidth, fillChar);
+}
+
+/*!
+ \fn QString QString::arg(double a, int fieldWidth, char format, int precision, const 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 fieldWidth specifies the minimum amount of space that \a a is
+ padded to and filled with the character \a fillChar. A positive
+ value produces right-aligned text; a negative value produces
+ left-aligned text.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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::setDefaultLocale(). 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()
+*/
+QString QString::arg(double a, int fieldWidth, char fmt, int prec, const QChar &fillChar) const
+{
+ ArgEscapeData d = findArgEscapes(*this);
+
+ if (d.occurrences == 0) {
+ qWarning("QString::arg: Argument missing: %s, %g", toLocal8Bit().data(), a);
+ return *this;
+ }
+
+ unsigned flags = QLocalePrivate::NoFlags;
+ if (fillChar == QLatin1Char('0'))
+ flags = QLocalePrivate::ZeroPadded;
+
+ if (qIsUpper(fmt))
+ flags |= QLocalePrivate::CapitalEorX;
+ fmt = qToLower(fmt);
+
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ switch (fmt) {
+ case 'f':
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case 'e':
+ form = QLocalePrivate::DFExponent;
+ break;
+ case 'g':
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ default:
+#if defined(QT_CHECK_RANGE)
+ qWarning("QString::arg: Invalid format char '%c'", fmt);
+#endif
+ break;
+ }
+
+ QString arg;
+ if (d.occurrences > d.locale_occurrences)
+ arg = QLocale::c().d()->doubleToString(a, prec, form, fieldWidth, flags);
+
+ QString locale_arg;
+ if (d.locale_occurrences > 0) {
+ QLocale locale;
+
+ if (!locale.numberOptions() & QLocale::OmitGroupSeparator)
+ flags |= QLocalePrivate::ThousandsGroup;
+ locale_arg = locale.d()->doubleToString(a, prec, form, fieldWidth, flags);
+ }
+
+ return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+}
+
+static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999)
+{
+ int i = *pos;
+ ++i;
+ if (i < len && uc[i] == QLatin1Char('L'))
+ ++i;
+ if (i < len) {
+ int escape = uc[i].unicode() - '0';
+ if (uint(escape) >= 10U)
+ return -1;
+ ++i;
+ while (i < len) {
+ int digit = uc[i].unicode() - '0';
+ if (uint(digit) >= 10U)
+ break;
+ escape = (escape * 10) + digit;
+ ++i;
+ }
+ if (escape <= maxNumber) {
+ *pos = i;
+ return escape;
+ }
+ }
+ return -1;
+}
+
+QString QString::multiArg(int numArgs, const QString **args) const
+{
+ QString result;
+ QMap<int, int> numbersUsed;
+ const QChar *uc = (const QChar *) d->data;
+ const int len = d->size;
+ const int end = len - 1;
+ int lastNumber = -1;
+ int i = 0;
+
+ // populate the numbersUsed map with the %n's that actually occur in the string
+ while (i < end) {
+ if (uc[i] == QLatin1Char('%')) {
+ int number = getEscape(uc, &i, len);
+ if (number != -1) {
+ numbersUsed.insert(number, -1);
+ continue;
+ }
+ }
+ ++i;
+ }
+
+ // assign an argument number to each of the %n's
+ QMap<int, int>::iterator j = numbersUsed.begin();
+ QMap<int, int>::iterator jend = numbersUsed.end();
+ int arg = 0;
+ while (j != jend && arg < numArgs) {
+ *j = arg++;
+ lastNumber = j.key();
+ ++j;
+ }
+
+ // sanity
+ if (numArgs > arg) {
+ qWarning("QString::arg: %d argument(s) missing in %s", numArgs - arg, toLocal8Bit().data());
+ numArgs = arg;
+ }
+
+ i = 0;
+ while (i < len) {
+ if (uc[i] == QLatin1Char('%') && i != end) {
+ int number = getEscape(uc, &i, len, lastNumber);
+ int arg = numbersUsed[number];
+ if (number != -1 && arg != -1) {
+ result += *args[arg];
+ continue;
+ }
+ }
+ result += uc[i++];
+ }
+ return result;
+}
+
+static bool isStringRightToLeft(const ushort *p, const ushort *end)
+{
+ bool righttoleft = false;
+ while (p < end) {
+ switch(QChar::direction(*p))
+ {
+ case QChar::DirL:
+ goto end;
+ case QChar::DirR:
+ case QChar::DirAL:
+ righttoleft = true;
+ goto end;
+ default:
+ break;
+ }
+ ++p;
+ }
+ end:
+ return righttoleft;
+}
+
+/*! \internal
+ */
+void QString::updateProperties() const
+{
+ ushort *p = d->data;
+ ushort *end = p + d->size;
+ d->simpletext = true;
+ while (p < end) {
+ ushort uc = *p;
+ // sort out regions of complex text formatting
+ if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
+ d->simpletext = false;
+ }
+ p++;
+ }
+
+ d->righttoleft = isStringRightToLeft(d->data, d->data + d->size);
+ d->clean = true;
+}
+
+bool QString::isRightToLeft() const
+{
+ return isStringRightToLeft(d->data, d->data + d->size);
+}
+
+/*! \fn bool QString::isSimpleText() const
+
+ \internal
+*/
+
+/*! \fn bool QString::isRightToLeft() const
+
+ Returns true if the string is read right to left.
+*/
+
+
+/*! \fn QChar *QString::data()
+
+ Returns a pointer to the data stored in the QString. The pointer
+ can be used to access and modify the characters that compose the
+ string. For convenience, the data is '\\0'-terminated.
+
+ Example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 19
+
+ Note that the pointer remains valid only as long as the string is
+ not modified by other means. For read-only access, constData() is
+ faster because it never causes a \l{deep copy} to occur.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const QChar *QString::data() const
+
+ \overload
+*/
+
+/*! \fn const QChar *QString::constData() const
+
+ Returns a pointer to the data stored in the QString. The pointer
+ can be used to access the characters that compose the string. For
+ convenience, the data is '\\0'-terminated.
+
+ Note that the pointer remains valid only as long as the string is
+ not modified.
+
+ \sa data(), operator[]()
+*/
+
+/*! \fn void QString::push_front(const QString &other)
+
+ This function is provided for STL compatibility, prepending the
+ given \a other string to the beginning of this string. It is
+ equivalent to \c prepend(other).
+
+ \sa prepend()
+*/
+
+/*! \fn void QString::push_front(QChar ch)
+
+ \overload
+
+ Prepends the given \a ch character to the beginning of this string.
+*/
+
+/*! \fn void QString::push_back(const QString &other)
+
+ This function is provided for STL compatibility, appending the
+ given \a other string onto the end of this string. It is
+ equivalent to \c append(other).
+
+ \sa append()
+*/
+
+/*! \fn void QString::push_back(QChar ch)
+
+ \overload
+
+ Appends the given \a ch character onto the end of this string.
+*/
+
+/*!
+ \fn std::string QString::toStdString() const
+
+ Returns a std::string object with the data contained in this
+ QString. The Unicode data is converted into 8-bit characters using
+ the toAscii() function.
+
+ This operator is mostly useful to pass a QString to a function
+ that accepts a std::string object.
+
+ If the QString contains Unicode characters that the
+ QTextCodec::codecForCStrings() codec cannot handle, using this operator
+ can lead to loss of information.
+
+ This operator is only available if Qt is configured with STL
+ compatibility enabled.
+
+ \sa toAscii(), toLatin1(), toUtf8(), toLocal8Bit()
+*/
+
+/*!
+ Constructs a QString that uses the first \a size Unicode characters
+ in the array \a unicode. The data in \a unicode is \e not
+ copied. The caller must be able to guarantee that \a unicode will
+ not be deleted or modified as long as the QString (or an
+ unmodified copy of it) exists.
+
+ Any attempts to modify the QString or copies of it will cause it
+ to create a deep copy of the data, ensuring that the raw data
+ isn't modified.
+
+ Here's an example of how we can use a QRegExp on raw data in
+ memory without requiring to copy the data into a QString:
+
+ \snippet doc/src/snippets/qstring/main.cpp 22
+ \snippet doc/src/snippets/qstring/main.cpp 23
+
+ \warning A string created with fromRawData() is \e not
+ '\\0'-terminated, unless the raw data contains a '\\0' character
+ at position \a size. This means unicode() will \e not return a
+ '\\0'-terminated string (although utf16() does, at the cost of
+ copying the raw data).
+
+ \sa fromUtf16(), setRawData()
+*/
+QString QString::fromRawData(const QChar *unicode, int size)
+{
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
+ if (unicode) {
+ x->data = (ushort *)unicode;
+ } else {
+ x->data = x->array;
+ size = 0;
+ }
+ x->ref = 1;
+ x->alloc = x->size = size;
+ *x->array = '\0';
+ x->clean = x->asciiCache = x->simpletext = x->righttoleft = x->capacity = 0;
+ return QString(x, 0);
+}
+
+/*!
+ \since 4.7
+
+ Resets the QString to use the first \a size Unicode characters
+ in the array \a unicode. The data in \a unicode is \e not
+ copied. The caller must be able to guarantee that \a unicode will
+ not be deleted or modified as long as the QString (or an
+ unmodified copy of it) exists.
+
+ This function can be used instead of fromRawData() to re-use
+ existings QString objects to save memory re-allocations.
+
+ \sa fromRawData()
+*/
+QString &QString::setRawData(const QChar *unicode, int size)
+{
+ if (d->ref != 1 || (d->data == d->array && d->alloc)) {
+ *this = fromRawData(unicode, size);
+ } else {
+#ifdef QT3_SUPPORT
+ if (d->asciiCache) {
+ Q_ASSERT(asciiCache);
+ asciiCache->remove(d);
+ }
+#endif
+ if (unicode) {
+ d->data = (ushort *)unicode;
+ } else {
+ d->data = d->array;
+ size = 0;
+ }
+ d->alloc = d->size = size;
+ *d->array = '\0';
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ }
+ return *this;
+}
+
+/*! \class QLatin1String
+ \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 \link QString::insert()
+ insert() \endlink, \link QString::replace() replace()\endlink,
+ and \link QString::indexOf() indexOf()\endlink. 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 doc/src/snippets/code/src_corelib_tools_qstring.cpp 3
+
+ is much faster than
+
+ \snippet doc/src/snippets/code/src_corelib_tools_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 doc/src/snippets/code/src_corelib_tools_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(const QLatin1String &) constructor,
+ QLatin1String can be used everywhere a QString is expected. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6
+
+ \sa QString, QLatin1Char
+*/
+
+/*! \fn QLatin1String::QLatin1String(const char *str)
+
+ Constructs a QLatin1String object that stores \a str. Note that if
+ \a str is 0, an empty string is created; this case is handled by
+ QString.
+
+ 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()
+*/
+
+/*!
+ \since 4.1
+ \fn QLatin1String &QLatin1String::operator=(const QLatin1String &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn const char *QLatin1String::latin1() const
+
+ Returns the Latin-1 string stored in this object.
+*/
+
+/*! \fn bool QLatin1String::operator==(const QString &other) const
+
+ Returns true if this string is equal to string \a other;
+ otherwise returns 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::fromAscii() 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.
+*/
+
+/*! \fn bool QLatin1String::operator!=(const QString &other) const
+
+ Returns true if this string is not equal to string \a other;
+ otherwise returns 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::fromAscii() 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.
+*/
+
+/*!
+ \fn bool QLatin1String::operator>(const QString &other) const
+
+ Returns true if this string is lexically greater than string \a
+ other; otherwise returns 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::fromAscii() 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.
+*/
+
+/*!
+ \fn bool QLatin1String::operator<(const QString &other) const
+
+ Returns true if this string is lexically less than the \a other
+ string; otherwise returns 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::fromAscii() 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.
+*/
+
+/*!
+ \fn bool QLatin1String::operator>=(const QString &other) const
+
+ Returns true if this string is lexically greater than or equal
+ to string \a other; otherwise returns 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::fromAscii() 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.
+*/
+
+/*! \fn bool QLatin1String::operator<=(const QString &other) const
+
+ Returns true if this string is lexically less than or equal
+ to string \a other; otherwise returns 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::fromAscii() 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.
+*/
+
+
+
+/* \fn bool operator==(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically equal to string \a s2; otherwise
+ returns false.
+*/
+/* \fn bool operator!=(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically unequal to string \a s2; otherwise
+ returns false.
+*/
+/* \fn bool operator<(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically smaller than string \a s2; otherwise
+ returns false.
+*/
+/* \fn bool operator<=(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically smaller than or equal to string \a s2; otherwise
+ returns false.
+*/
+/* \fn bool operator>(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically greater than string \a s2; otherwise
+ returns false.
+*/
+/* \fn bool operator>=(const QLatin1String &s1, const QLatin1String &s2)
+ \relates QLatin1String
+
+ Returns true if string \a s1 is lexically greater than or equal to
+ string \a s2; otherwise returns false.
+*/
+
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QString &string)
+ \relates QString
+
+ Writes the given \a string to the specified \a stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &out, const QString &str)
+{
+ if (out.version() == 1) {
+ out << str.toLatin1();
+ } else {
+ if (!str.isNull() || out.version() < 3) {
+ if ((out.byteOrder() == QDataStream::BigEndian) == (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
+ out.writeBytes(reinterpret_cast<const char *>(str.unicode()), sizeof(QChar) * str.length());
+ } else {
+ QVarLengthArray<ushort> buffer(str.length());
+ const ushort *data = reinterpret_cast<const ushort *>(str.constData());
+ for (int i = 0; i < str.length(); i++) {
+ buffer[i] = qbswap(*data);
+ ++data;
+ }
+ out.writeBytes(reinterpret_cast<const char *>(buffer.data()), sizeof(ushort) * buffer.size());
+ }
+ } else {
+ // write null marker
+ out << (quint32)0xffffffff;
+ }
+ }
+ return out;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QString &string)
+ \relates QString
+
+ Reads a string from the specified \a stream into the given \a string.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QString &str)
+{
+#ifdef QT_QSTRING_UCS_4
+#if defined(Q_CC_GNU)
+#warning "operator>> not working properly"
+#endif
+#endif
+
+ if (in.version() == 1) {
+ QByteArray l;
+ in >> l;
+ str = QString::fromLatin1(l);
+ } else {
+ quint32 bytes = 0;
+ in >> bytes; // read size of string
+ if (bytes == 0xffffffff) { // null string
+ str.clear();
+ } else if (bytes > 0) { // not empty
+ if (bytes & 0x1) {
+ str.clear();
+ in.setStatus(QDataStream::ReadCorruptData);
+ return in;
+ }
+
+ const quint32 Step = 1024 * 1024;
+ quint32 len = bytes / 2;
+ quint32 allocated = 0;
+
+ while (allocated < len) {
+ int blockSize = qMin(Step, len - allocated);
+ str.resize(allocated + blockSize);
+ if (in.readRawData(reinterpret_cast<char *>(str.data()) + allocated * 2,
+ blockSize * 2) != blockSize * 2) {
+ str.clear();
+ in.setStatus(QDataStream::ReadPastEnd);
+ return in;
+ }
+ allocated += blockSize;
+ }
+
+ if ((in.byteOrder() == QDataStream::BigEndian)
+ != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
+ ushort *data = reinterpret_cast<ushort *>(str.data());
+ while (len--) {
+ *data = qbswap(*data);
+ ++data;
+ }
+ }
+ } else {
+ str = QLatin1String("");
+ }
+ }
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn void QString::setLength(int nl)
+
+ Use resize() instead.
+*/
+
+/*!
+ \fn QString QString::copy() const
+
+ Use simple assignment instead. QString is implicitly shared so if
+ a copy is modified only the copy is changed.
+*/
+
+/*!
+ \fn QString &QString::remove(QChar c, bool cs)
+
+ Use the remove(QChar, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString &QString::remove(const QString &s, bool cs)
+
+ Use the remove(QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString &QString::replace(QChar c, const QString &after, bool cs)
+
+ Use the replace(QChar, QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString &QString::replace(const QString &before, const QString &after, bool cs)
+
+ Use the replace(QString, QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString &QString::replace(char c, const QString &after, bool cs)
+
+ Use the replace(QChar, QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString &QString::replace(char c, const QString &after, Qt::CaseSensitivity cs)
+
+ Use the replace(QChar, QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn int QString::find(QChar c, int i = 0, bool cs = true) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QString::find(const QString &s, int i = 0, bool cs = true) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QString::findRev(QChar c, int i = -1, bool cs = true) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QString::findRev(const QString &s, int i = -1, bool cs = true) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QString::find(const QRegExp &rx, int i=0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QString::find(QRegExp &rx, int i=0) const
+ \internal
+ \since 4.5
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QString::findRev(const QRegExp &rx, int i=-1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QString::findRev(QRegExp &rx, int i=0) const
+ \internal
+ \since 4.5
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn QBool QString::contains(QChar c, bool cs) const
+
+ Use the contains(QChar, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QBool QString::contains(const QString &s, bool cs) const
+
+ Use the contains(QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn bool QString::startsWith(const QString &s, bool cs) const
+
+ Use the startsWith(QString, Qt::CaseSensitive) overload instead.
+*/
+
+
+/*!
+ \fn bool QString::endsWith(const QString &s, bool cs) const
+
+ Use the endsWith(QString, Qt::CaseSensitive) overload instead.
+*/
+
+/*!
+ \fn QString QString::leftJustify(int width, QChar fill = QLatin1Char(' '), bool trunc=false) const
+
+ Use leftJustified() instead.
+*/
+
+/*!
+ \fn QString QString::rightJustify(int width, QChar fill = QLatin1Char(' '), bool trunc=false) const
+
+ Use rightJustified() instead.
+*/
+
+/*!
+ \fn QString QString::lower() const
+
+ Use toLower() instead.
+*/
+
+/*!
+ \fn QString QString::upper() const
+
+ Use toUpper() instead.
+*/
+
+/*!
+ \fn QString QString::stripWhiteSpace() const
+
+ Use trimmed() instead.
+*/
+
+/*!
+ \fn QString QString::simplifyWhiteSpace() const
+
+ Use simplified() instead.
+*/
+
+/*!
+ \fn QString &QString::setUnicodeCodes(const ushort *unicode_as_ushorts, int size)
+
+ Use setUtf16() instead.
+*/
+
+/*!
+ \fn ushort *QString::ucs2() const
+
+ Use utf16() instead.
+*/
+
+/*!
+ \fn QString QString::fromUcs2(const ushort *unicode, int size = -1)
+
+ Use fromUtf16() instead.
+*/
+
+/*!
+ \fn QString &QString::setAscii(const char *str, int len = -1)
+
+ Use fromAscii() instead.
+*/
+
+/*!
+ \fn QString &QString::setLatin1(const char *str, int len = -1)
+
+ Use fromLatin1() instead.
+*/
+
+/*!
+ \fn QChar QString::constref(uint i) const
+
+ Use at() instead.
+*/
+
+/*!
+ \fn QChar &QString::ref(uint i);
+
+ Use operator[]() instead.
+*/
+
+/*!
+ \fn QString::operator const char *() const
+
+ Use toAscii().constData() instead.
+*/
+
+/*!
+ \class QConstString
+ \brief The QConstString class is a wrapper for constant Unicode string data.
+ \compat
+
+ In Qt 4, QConstString is replaced by QString::fromRawData(), a
+ static function that constructs a QString object based on Unicode
+ string data.
+
+ Because QString::fromRawData() has slightly more stringent
+ constraints than QConstString had in Qt 3, the new QConstString
+ class takes a deep copy of the string data.
+
+ \sa QString::fromRawData()
+*/
+
+/*!
+ \fn QConstString::QConstString(const QChar *unicode, int size)
+
+ Use QString(\a unicode, \a size) or
+ QString::fromRawData(\a unicode, \a size) instead.
+*/
+
+/*!
+ \fn const QString &QConstString::string() const
+
+ Returns \c *this. Not necessary in Qt 4.
+*/
+
+
+
+/*!
+ \class QStringRef
+ \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}
+*/
+
+
+/*!
+ \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 true if the string reference has no characters; otherwise returns
+ false.
+
+ A string reference is empty if its size is zero.
+
+ \sa size()
+*/
+
+/*!
+ \fn bool QStringRef::isNull() const
+
+ Returns true if string() returns a null pointer or a pointer to a
+ null string; otherwise returns 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
+ null-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().
+*/
+
+/*!
+ 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 (!m_string)
+ 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 true if string reference \a s1 is lexically equal to string reference \a s2; otherwise
+ returns false.
+*/
+bool operator==(const QStringRef &s1,const QStringRef &s2)
+{ return (s1.size() == s2.size() &&
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
+
+/*! \relates QStringRef
+
+ Returns true if string \a s1 is lexically equal to string reference \a s2; otherwise
+ returns false.
+*/
+bool operator==(const QString &s1,const QStringRef &s2)
+{ return (s1.size() == s2.size() &&
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
+
+/*! \relates QStringRef
+
+ Returns true if string \a s1 is lexically equal to string reference \a s2; otherwise
+ returns false.
+*/
+bool operator==(const QLatin1String &s1, const QStringRef &s2)
+{
+ const ushort *uc = reinterpret_cast<const ushort *>(s2.unicode());
+ const ushort *e = uc + s2.size();
+ const uchar *c = reinterpret_cast<const uchar *>(s1.latin1());
+ if (!c)
+ return s2.isEmpty();
+
+ while (*c) {
+ if (uc == e || *uc != *c)
+ return false;
+ ++uc;
+ ++c;
+ }
+ return (uc == e);
+}
+
+/*!
+ \relates QStringRef
+
+ Returns true if string reference \a s1 is lexically less than
+ string reference \a s2; otherwise returns 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)
+{
+ return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0;
+}
+
+/*!\fn bool operator<=(const QStringRef &s1,const QStringRef &s2)
+
+ \relates QStringRef
+
+ Returns true if string reference \a s1 is lexically less than
+ or equal to string reference \a s2; otherwise returns 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 true if string reference \a s1 is lexically greater than
+ or equal to string reference \a s2; otherwise returns 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 true if string reference \a s1 is lexically greater than
+ string reference \a s2; otherwise returns 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 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.
+*/
+
+/*!
+ \typedef QString::DataPtr
+ \internal
+*/
+
+/*!
+ \fn DataPtr & QString::data_ptr()
+ \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)}.
+
+ \sa QString::compare()
+*/
+
+/*!
+ \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)}.
+
+ \sa QString::compare()
+*/
+
+/*!
+ \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)}.
+
+ \sa QString::compare()
+*/
+
+/*!
+ \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 Mac OS X, this function compares according the
+ "Order for sorted lists" setting in the International prefereces panel.
+
+ \sa compare(), QTextCodec::locale()
+*/
+
+/*!
+ \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(const QStringRef &reference)
+ \since 4.4
+
+ Appends the given string \a reference to this string and returns the result.
+ */
+QString &QString::append(const QStringRef &str)
+{
+ if (str.string() == this) {
+ str.appendTo(this);
+ } else if (str.string()) {
+ int oldSize = size();
+ resize(oldSize + str.size());
+ memcpy(data() + oldSize, str.unicode(), str.size() * sizeof(QChar));
+ }
+ return *this;
+}
+
+/*!
+ \since 4.4
+
+ Returns a substring reference to the \a n leftmost characters
+ of the string.
+
+ If \a n is greater than size() or less than zero, a reference to the entire
+ string is returned.
+
+ \snippet doc/src/snippets/qstring/main.cpp leftRef
+
+ \sa left(), rightRef(), midRef(), startsWith()
+*/
+QStringRef QString::leftRef(int n) const
+{
+ if (n >= d->size || n < 0)
+ n = d->size;
+ return QStringRef(this, 0, n);
+}
+
+/*!
+ \since 4.4
+
+ Returns a substring reference to the \a n rightmost characters
+ of the string.
+
+ If \a n is greater than size() or less than zero, a reference to the entire
+ string is returned.
+
+ \snippet doc/src/snippets/qstring/main.cpp rightRef
+
+ \sa right(), leftRef(), midRef(), endsWith()
+*/
+QStringRef QString::rightRef(int n) const
+{
+ if (n >= d->size || n < 0)
+ n = d->size;
+ return QStringRef(this, d->size - n, n);
+}
+
+/*!
+ \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, an empty
+ 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 doc/src/snippets/qstring/main.cpp midRef
+
+ \sa mid(), leftRef(), rightRef()
+*/
+
+QStringRef QString::midRef(int position, int n) const
+{
+ if (d == &shared_null || position >= d->size)
+ return QStringRef();
+ if (n < 0)
+ n = d->size - position;
+ if (position < 0) {
+ n += position;
+ position = 0;
+ }
+ if (n + position > d->size)
+ n = d->size - position;
+ return QStringRef(this, position, n);
+}
+
+/*!
+ \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
+{
+ return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
+}
+
+/*!
+ \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
+{
+ return findChar(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
+{
+ return qt_find_latin1_string(unicode(), size(), str, from, cs);
+}
+
+/*!
+ \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
+{
+ return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs);
+}
+
+/*!
+ \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
+{
+ const int sl = str.size();
+ if (sl == 1)
+ return lastIndexOf(str.at(0), from, cs);
+
+ const int l = size();;
+ if (from < 0)
+ from += l;
+ int delta = l - sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from,
+ reinterpret_cast<const ushort*>(str.unicode()), str.size(), 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
+{
+ return qt_last_index_of(unicode(), size(), 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
+{
+ const int sl = qstrlen(str.latin1());
+ if (sl == 1)
+ return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
+
+ const int l = size();
+ if (from < 0)
+ from += l;
+ int delta = l - sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ QVarLengthArray<ushort> s(sl);
+ for (int i = 0; i < sl; ++i)
+ s[i] = str.latin1()[i];
+
+ return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, s.data(), sl, 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
+{
+ const int sl = str.size();
+ if (sl == 1)
+ return lastIndexOf(str.at(0), from, cs);
+
+ const int l = size();
+ if (from < 0)
+ from += l;
+ int delta = l - sl;
+ if (from == l && sl == 0)
+ return from;
+ if (from < 0 || from >= l || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from,
+ reinterpret_cast<const ushort*>(str.unicode()),
+ str.size(), cs);
+}
+
+/*!
+ \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
+{
+ return qt_string_count(unicode(), size(), 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
+{
+ return qt_string_count(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
+{
+ return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+}
+
+/*!
+ \since 4.8
+
+ Returns true if the string reference starts with \a str; otherwise
+ returns 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(isNull() ? 0 : unicode(), size(),
+ str.isNull() ? 0 : str.unicode(), str.size(), cs);
+}
+
+/*!
+ \since 4.8
+ \overload startsWith()
+ \sa QString::startsWith(), endsWith()
+*/
+bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const
+{
+ return qt_starts_with(isNull() ? 0 : unicode(), size(), str, cs);
+}
+
+/*!
+ \since 4.8
+ \overload startsWith()
+ \sa QString::startsWith(), endsWith()
+*/
+bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
+{
+ return qt_starts_with(isNull() ? 0 : unicode(), size(),
+ str.isNull() ? 0 : str.unicode(), str.size(), cs);
+}
+
+/*!
+ \since 4.8
+ \overload startsWith()
+
+ Returns true if the string reference starts with \a ch; otherwise
+ returns 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
+{
+ if (!isEmpty()) {
+ const ushort *data = reinterpret_cast<const ushort*>(unicode());
+ return (cs == Qt::CaseSensitive
+ ? data[0] == ch
+ : foldCase(data[0]) == foldCase(ch.unicode()));
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \since 4.8
+ Returns true if the string reference ends with \a str; otherwise
+ returns 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(isNull() ? 0 : unicode(), size(),
+ str.isNull() ? 0 : str.unicode(), str.size(), cs);
+}
+
+/*!
+ \since 4.8
+ \overload endsWith()
+
+ Returns true if the string reference ends with \a ch; otherwise
+ returns 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
+{
+ if (!isEmpty()) {
+ const ushort *data = reinterpret_cast<const ushort*>(unicode());
+ const int size = length();
+ return (cs == Qt::CaseSensitive
+ ? data[size - 1] == ch
+ : foldCase(data[size - 1]) == foldCase(ch.unicode()));
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \since 4.8
+ \overload endsWith()
+ \sa QString::endsWith(), endsWith()
+*/
+bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const
+{
+ return qt_ends_with(isNull() ? 0 : unicode(), size(), str, cs);
+}
+
+/*!
+ \since 4.8
+ \overload endsWith()
+ \sa QString::endsWith(), endsWith()
+*/
+bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
+{
+ return qt_ends_with(isNull() ? 0 : unicode(), size(),
+ str.isNull() ? 0 : str.unicode(), str.size(), cs);
+}
+
+
+/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+
+ \since 4.8
+ Returns true if this string reference contains an occurrence of
+ the string \a str; otherwise returns 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(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+
+ \overload contains()
+ \since 4.8
+
+ Returns true if this string contains an occurrence of the
+ character \a ch; otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+*/
+
+/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \overload contains()
+ \since 4.8
+
+ Returns true if this string reference contains an occurrence of
+ the string reference \a str; otherwise returns 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(QLatin1String str, Qt::CaseSensitivity cs) const
+ \since 4,8
+ \overload contains()
+
+ Returns true if this string reference contains an occurrence of
+ the string \a str; otherwise returns false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), count()
+*/
+
+static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle,
+ int from, Qt::CaseSensitivity cs)
+{
+ ushort c = needle.unicode();
+ if (from < 0)
+ from += haystackLen;
+ if (from < 0 || from >= haystackLen)
+ return -1;
+ if (from >= 0) {
+ const ushort *b = reinterpret_cast<const ushort*>(haystack);
+ const ushort *n = b + from;
+ if (cs == Qt::CaseSensitive) {
+ for (; n >= b; --n)
+ if (*n == c)
+ return n - b;
+ } else {
+ c = foldCase(c);
+ for (; n >= b; --n)
+ if (foldCase(*n) == c)
+ return n - b;
+ }
+ }
+ return -1;
+
+
+}
+
+static inline int qt_string_count(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen,
+ Qt::CaseSensitivity cs)
+{
+ int num = 0;
+ int i = -1;
+ if (haystackLen > 500 && needleLen > 5) {
+ QStringMatcher matcher(needle, needleLen, cs);
+ while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1)
+ ++num;
+ } else {
+ while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1)
+ ++num;
+ }
+ return num;
+}
+
+static inline int qt_string_count(const QChar *unicode, int size, const QChar &ch,
+ Qt::CaseSensitivity cs)
+{
+ ushort c = ch.unicode();
+ int num = 0;
+ const ushort *b = reinterpret_cast<const ushort*>(unicode);
+ const ushort *i = b + size;
+ if (cs == Qt::CaseSensitive) {
+ while (i != b)
+ if (*--i == c)
+ ++num;
+ } else {
+ c = foldCase(c);
+ while (i != b)
+ if (foldCase(*(--i)) == c)
+ ++num;
+ }
+ return num;
+}
+
+static inline int qt_find_latin1_string(const QChar *haystack, int size,
+ const QLatin1String &needle,
+ int from, Qt::CaseSensitivity cs)
+{
+ const char *latin1 = needle.latin1();
+ int len = qstrlen(latin1);
+ QVarLengthArray<ushort> s(len);
+ for (int i = 0; i < len; ++i)
+ s[i] = latin1[i];
+
+ return qFindString(haystack, size, from,
+ reinterpret_cast<const QChar*>(s.constData()), len, cs);
+}
+
+static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+{
+ if (!haystack)
+ return !needle;
+ if (haystackLen == 0)
+ return needleLen == 0;
+ if (needleLen > haystackLen)
+ return false;
+
+ const ushort *h = reinterpret_cast<const ushort*>(haystack);
+ const ushort *n = reinterpret_cast<const ushort*>(needle);
+
+ if (cs == Qt::CaseSensitive) {
+ return qMemEquals(h, n, needleLen);
+ } else {
+ uint last = 0;
+ uint olast = 0;
+ for (int i = 0; i < needleLen; ++i)
+ if (foldCase(h[i], last) != foldCase(n[i], olast))
+ return false;
+ }
+ return true;
+}
+
+static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
+ const QLatin1String &needle, Qt::CaseSensitivity cs)
+{
+ if (!haystack)
+ return !needle.latin1();
+ if (haystackLen == 0)
+ return !needle.latin1() || *needle.latin1() == 0;
+ const int slen = qstrlen(needle.latin1());
+ if (slen > haystackLen)
+ return false;
+ const ushort *data = reinterpret_cast<const ushort*>(haystack);
+ const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1());
+ if (cs == Qt::CaseSensitive) {
+ for (int i = 0; i < slen; ++i)
+ if (data[i] != latin[i])
+ return false;
+ } else {
+ for (int i = 0; i < slen; ++i)
+ if (foldCase(data[i]) != foldCase((ushort)latin[i]))
+ return false;
+ }
+ return true;
+}
+
+static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+{
+ if (!haystack)
+ return !needle;
+ if (haystackLen == 0)
+ return needleLen == 0;
+ const int pos = haystackLen - needleLen;
+ if (pos < 0)
+ return false;
+
+ const ushort *h = reinterpret_cast<const ushort*>(haystack);
+ const ushort *n = reinterpret_cast<const ushort*>(needle);
+
+ if (cs == Qt::CaseSensitive) {
+ return qMemEquals(h + pos, n, needleLen);
+ } else {
+ uint last = 0;
+ uint olast = 0;
+ for (int i = 0; i < needleLen; i++)
+ if (foldCase(h[pos+i], last) != foldCase(n[i], olast))
+ return false;
+ }
+ return true;
+}
+
+
+static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
+ const QLatin1String &needle, Qt::CaseSensitivity cs)
+{
+ if (!haystack)
+ return !needle.latin1();
+ if (haystackLen == 0)
+ return !needle.latin1() || *needle.latin1() == 0;
+ const int slen = qstrlen(needle.latin1());
+ int pos = haystackLen - slen;
+ if (pos < 0)
+ return false;
+ const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1());
+ const ushort *data = reinterpret_cast<const ushort*>(haystack);
+ if (cs == Qt::CaseSensitive) {
+ for (int i = 0; i < slen; i++)
+ if (data[pos+i] != latin[i])
+ return false;
+ } else {
+ for (int i = 0; i < slen; i++)
+ if (foldCase(data[pos+i]) != foldCase((ushort)latin[i]))
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \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 toAscii(), toUtf8(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QStringRef::toLatin1() const
+{
+ return toLatin1_helper(unicode(), length());
+}
+
+/*!
+ \since 4.8
+
+ Returns an 8-bit representation of the string as a QByteArray.
+
+ If a codec has been set using QTextCodec::setCodecForCStrings(),
+ it is used to convert Unicode to 8-bit char; otherwise this
+ function does the same as toLatin1().
+
+ Note that, despite the name, this function does not necessarily return an US-ASCII
+ (ANSI X3.4-1986) string and its result may not be US-ASCII compatible.
+
+ \sa toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QStringRef::toAscii() const
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings)
+ return QString::codecForCStrings->fromUnicode(unicode(), length());
+#endif // QT_NO_TEXTCODEC
+ return toLatin1();
+}
+
+/*!
+ \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.
+
+ QTextCodec::codecForLocale() is used to perform the conversion from
+ Unicode. If the locale encoding could not be determined, this function
+ does the same as toLatin1().
+
+ 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.
+
+ \sa toAscii(), toLatin1(), toUtf8(), QTextCodec
+*/
+QByteArray QStringRef::toLocal8Bit() const
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QTextCodec::codecForLocale())
+ return QTextCodec::codecForLocale()->fromUnicode(unicode(), length());
+#endif // QT_NO_TEXTCODEC
+ return toLatin1();
+}
+
+/*!
+ \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.
+
+ However, in the Unicode range, there are certain codepoints that are not
+ considered characters. The Unicode standard reserves the last two
+ codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF,
+ U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF,
+ inclusive, as non-characters. If any of those appear in the string, they
+ may be discarded and will not appear in the UTF-8 representation, or they
+ may be replaced by one or more replacement characters.
+
+ \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec
+*/
+QByteArray QStringRef::toUtf8() const
+{
+ if (isNull())
+ return QByteArray();
+
+ return QUtf8::convertFromUnicode(constData(), length(), 0);
+}
+
+/*!
+ \since 4.8
+
+ Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
+
+ UCS-4 is a Unicode codec and is lossless. All characters from this string
+ can be encoded in UCS-4.
+
+ \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray()
+*/
+QVector<uint> QStringRef::toUcs4() const
+{
+ QVector<uint> v(length());
+ uint *a = v.data();
+ int len = toUcs4_helper<uint>(reinterpret_cast<const unsigned short *>(unicode()), length(), a);
+ v.resize(len);
+ return v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
new file mode 100644
index 0000000000..66cfa744df
--- /dev/null
+++ b/src/corelib/tools/qstring.h
@@ -0,0 +1,1295 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRING_H
+#define QSTRING_H
+
+#include <QtCore/qchar.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qnamespace.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <Qt3Support/q3cstring.h>
+#endif
+
+#ifndef QT_NO_STL
+# include <string>
+
+# ifndef QT_NO_STL_WCHAR
+// workaround for some headers not typedef'ing std::wstring
+typedef std::basic_string<wchar_t> QStdWString;
+# endif // QT_NO_STL_WCHAR
+
+#endif // QT_NO_STL
+
+#include <stdarg.h>
+
+#ifdef truncate
+#error qstring.h must be included before any header file that defines truncate
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QCharRef;
+class QRegExp;
+class QStringList;
+class QTextCodec;
+class QLatin1String;
+class QStringRef;
+template <typename T> class QVector;
+
+class Q_CORE_EXPORT QString
+{
+public:
+ inline QString();
+ QString(const QChar *unicode, int size); // Qt5: don't cap size < 0
+ explicit QString(const QChar *unicode); // Qt5: merge with the above
+ QString(QChar c);
+ QString(int size, QChar c);
+ inline QString(const QLatin1String &latin1);
+ inline QString(const QString &);
+ inline ~QString();
+ QString &operator=(QChar c);
+ QString &operator=(const QString &);
+ inline QString &operator=(const QLatin1String &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QString &operator=(QString &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QString &other) { qSwap(d, other.d); }
+ inline int size() const { return d->size; }
+ inline int count() const { return d->size; }
+ inline int length() const;
+ inline bool isEmpty() const;
+ void resize(int size);
+
+ QString &fill(QChar c, int size = -1);
+ void truncate(int pos);
+ void chop(int n);
+
+ int capacity() const;
+ inline void reserve(int size);
+ inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;}
+
+ inline const QChar *unicode() const;
+ inline QChar *data();
+ inline const QChar *data() const;
+ inline const QChar *constData() const;
+
+ inline void detach();
+ inline bool isDetached() const;
+ inline bool isSharedWith(const QString &other) const { return d == other.d; }
+ void clear();
+
+ inline const QChar at(int i) const;
+ const QChar operator[](int i) const;
+ QCharRef operator[](int i);
+ const QChar operator[](uint i) const;
+ QCharRef operator[](uint i);
+
+ QString arg(qlonglong a, int fieldwidth=0, int base=10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(qulonglong a, int fieldwidth=0, int base=10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(long a, int fieldwidth=0, int base=10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(ulong a, int fieldwidth=0, int base=10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(int a, int fieldWidth = 0, int base = 10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(uint a, int fieldWidth = 0, int base = 10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(short a, int fieldWidth = 0, int base = 10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(ushort a, int fieldWidth = 0, int base = 10,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(double a, int fieldWidth = 0, char fmt = 'g', int prec = -1,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(char a, int fieldWidth = 0,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(QChar a, int fieldWidth = 0,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a, int fieldWidth = 0,
+ const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2, const QString &a3) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4, const QString &a5) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4, const QString &a5, const QString &a6) const Q_REQUIRED_RESULT;
+ QString arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4, const QString &a5, const QString &a6,
+ const QString &a7) const Q_REQUIRED_RESULT;
+ 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 Q_REQUIRED_RESULT;
+ 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 Q_REQUIRED_RESULT;
+
+ QString &vsprintf(const char *format, va_list ap)
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 2, 0)))
+#endif
+ ;
+ QString &sprintf(const char *format, ...)
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+
+ int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int indexOf(const QLatin1String &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int lastIndexOf(const QLatin1String &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ inline QBool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+#ifndef QT_NO_REGEXP
+ int indexOf(const QRegExp &, int from = 0) const;
+ int lastIndexOf(const QRegExp &, int from = -1) const;
+ inline QBool contains(const QRegExp &rx) const { return QBool(indexOf(rx) != -1); }
+ int count(const QRegExp &) const;
+
+ int indexOf(QRegExp &, int from = 0) const;
+ int lastIndexOf(QRegExp &, int from = -1) const;
+ inline QBool contains(QRegExp &rx) const { return QBool(indexOf(rx) != -1); }
+#endif
+
+ enum SectionFlag {
+ SectionDefault = 0x00,
+ SectionSkipEmpty = 0x01,
+ SectionIncludeLeadingSep = 0x02,
+ SectionIncludeTrailingSep = 0x04,
+ SectionCaseInsensitiveSeps = 0x08
+ };
+ 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;
+#ifndef QT_NO_REGEXP
+ QString section(const QRegExp &reg, int start, int end = -1, SectionFlags flags = SectionDefault) const;
+#endif
+
+ 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;
+ QStringRef leftRef(int n) const Q_REQUIRED_RESULT;
+ QStringRef rightRef(int n) const Q_REQUIRED_RESULT;
+ QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT;
+
+ bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ 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 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 Q_REQUIRED_RESULT;
+
+ QString &insert(int i, QChar c);
+ QString &insert(int i, const QChar *uc, int len);
+ inline QString &insert(int i, const QString &s) { return insert(i, s.constData(), s.length()); }
+ QString &insert(int i, const QLatin1String &s);
+ QString &append(QChar c);
+ QString &append(const QString &s);
+ QString &append(const QStringRef &s);
+ QString &append(const QLatin1String &s);
+ inline QString &prepend(QChar c) { return insert(0, c); }
+ inline QString &prepend(const QString &s) { return insert(0, s); }
+ inline QString &prepend(const QLatin1String &s) { return insert(0, s); }
+
+ inline QString &operator+=(QChar c) {
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(grow(d->size + 1));
+ d->data[d->size++] = c.unicode();
+ d->data[d->size] = '\0';
+ return *this;
+ }
+
+ inline QString &operator+=(QChar::SpecialCharacter c) { return append(QChar(c)); }
+ inline QString &operator+=(const QString &s) { return append(s); }
+ inline QString &operator+=(const QStringRef &s) { return append(s); }
+ inline QString &operator+=(const QLatin1String &s) { return append(s); }
+
+ QString &remove(int i, int len);
+ QString &remove(QChar c, 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 &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(const QLatin1String &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(const QString &before, const QLatin1String &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, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+#ifndef QT_NO_REGEXP
+ QString &replace(const QRegExp &rx, const QString &after);
+ inline QString &remove(const QRegExp &rx)
+ { return replace(rx, QString()); }
+#endif
+
+ enum SplitBehavior { KeepEmptyParts, SkipEmptyParts };
+
+ QStringList split(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
+ QStringList split(const QChar &sep, SplitBehavior behavior = KeepEmptyParts,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
+#ifndef QT_NO_REGEXP
+ QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
+#endif
+
+ enum NormalizationForm {
+ NormalizationForm_D,
+ NormalizationForm_C,
+ NormalizationForm_KD,
+ NormalizationForm_KC
+ };
+ QString normalized(NormalizationForm mode) const Q_REQUIRED_RESULT;
+ QString normalized(NormalizationForm mode, QChar::UnicodeVersion version) const Q_REQUIRED_RESULT;
+
+ QString repeated(int times) const;
+
+ const ushort *utf16() const;
+
+ QByteArray toAscii() const Q_REQUIRED_RESULT;
+ QByteArray toLatin1() const Q_REQUIRED_RESULT;
+ QByteArray toUtf8() const Q_REQUIRED_RESULT;
+ QByteArray toLocal8Bit() const Q_REQUIRED_RESULT;
+ QVector<uint> toUcs4() const Q_REQUIRED_RESULT;
+
+ static QString fromAscii(const char *, int size = -1);
+ static QString fromLatin1(const char *, int size = -1);
+ static QString fromUtf8(const char *, int size = -1);
+ static QString fromLocal8Bit(const char *, int size = -1);
+ static QString fromUtf16(const ushort *, int size = -1);
+ static QString fromUcs4(const uint *, int size = -1);
+ static QString fromRawData(const QChar *, int size);
+
+ int toWCharArray(wchar_t *array) const;
+ static QString fromWCharArray(const wchar_t *, int size = -1);
+
+ QString &setRawData(const QChar *unicode, int size);
+ QString &setUnicode(const QChar *unicode, int size);
+ inline QString &setUtf16(const ushort *utf16, int size);
+
+ // ### Qt 5: merge these two functions
+ int compare(const QString &s) const;
+ int compare(const QString &s, Qt::CaseSensitivity cs) const;
+
+ int compare(const QLatin1String &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ // ### Qt 5: merge these two functions
+ static inline int compare(const QString &s1, const QString &s2)
+ { return s1.compare(s2); }
+ static inline int compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
+ { return s1.compare(s2, cs); }
+
+ static inline int compare(const QString& s1, const QLatin1String &s2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ { return s1.compare(s2, cs); }
+ static inline int compare(const QLatin1String& s1, const QString &s2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ { return -s2.compare(s1, cs); }
+
+ int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ static int compare(const QString &s1, const QStringRef &s2,
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+
+ int localeAwareCompare(const QString& s) const;
+ static int localeAwareCompare(const QString& s1, const QString& s2)
+ { return s1.localeAwareCompare(s2); }
+
+ int localeAwareCompare(const QStringRef &s) const;
+ static int localeAwareCompare(const QString& s1, const QStringRef& s2);
+
+ short toShort(bool *ok=0, int base=10) const;
+ ushort toUShort(bool *ok=0, int base=10) const;
+ int toInt(bool *ok=0, int base=10) const;
+ uint toUInt(bool *ok=0, int base=10) const;
+ long toLong(bool *ok=0, int base=10) const;
+ ulong toULong(bool *ok=0, int base=10) const;
+ qlonglong toLongLong(bool *ok=0, int base=10) const;
+ qulonglong toULongLong(bool *ok=0, int base=10) const;
+ float toFloat(bool *ok=0) const;
+ double toDouble(bool *ok=0) 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);
+ 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);
+
+ static QString number(int, int base=10);
+ static QString number(uint, int base=10);
+ static QString number(long, int base=10);
+ 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);
+
+ bool operator==(const QString &s) const;
+ bool operator<(const QString &s) const;
+ inline bool operator>(const QString &s) const { return s < *this; }
+ inline bool operator!=(const QString &s) const { return !operator==(s); }
+ inline bool operator<=(const QString &s) const { return !operator>(s); }
+ inline bool operator>=(const QString &s) const { return !operator<(s); }
+
+ bool operator==(const QLatin1String &s) const;
+ bool operator<(const QLatin1String &s) const;
+ bool operator>(const QLatin1String &s) const;
+ inline bool operator!=(const QLatin1String &s) const { return !operator==(s); }
+ inline bool operator<=(const QLatin1String &s) const { return !operator>(s); }
+ inline bool operator>=(const QLatin1String &s) const { return !operator<(s); }
+
+ // ASCII compatibility
+#ifndef QT_NO_CAST_FROM_ASCII
+ inline QT_ASCII_CAST_WARN_CONSTRUCTOR QString(const char *ch) : d(fromAscii_helper(ch))
+ {}
+ inline QT_ASCII_CAST_WARN_CONSTRUCTOR QString(const QByteArray &a)
+ : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size())))
+ {}
+ inline QT_ASCII_CAST_WARN QString &operator=(const char *ch)
+ { return (*this = fromAscii(ch)); }
+ inline QT_ASCII_CAST_WARN QString &operator=(const QByteArray &a)
+ { return (*this = fromAscii(a.constData(), qstrnlen(a.constData(), a.size()))); }
+ inline QT_ASCII_CAST_WARN QString &operator=(char c)
+ { return (*this = QChar::fromAscii(c)); }
+
+ // these are needed, so it compiles with STL support enabled
+ inline QT_ASCII_CAST_WARN QString &prepend(const char *s)
+ { return prepend(QString::fromAscii(s)); }
+ inline QT_ASCII_CAST_WARN QString &prepend(const QByteArray &s)
+ { return prepend(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); }
+ inline QT_ASCII_CAST_WARN QString &append(const char *s)
+ { return append(QString::fromAscii(s)); }
+ inline QT_ASCII_CAST_WARN QString &append(const QByteArray &s)
+ { return append(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); }
+ inline QT_ASCII_CAST_WARN QString &operator+=(const char *s)
+ { return append(QString::fromAscii(s)); }
+ inline QT_ASCII_CAST_WARN QString &operator+=(const QByteArray &s)
+ { return append(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); }
+ inline QT_ASCII_CAST_WARN QString &operator+=(char c)
+ { return append(QChar::fromAscii(c)); }
+
+ 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 *s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>(const char *s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>=(const char *s2) 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
+ { return *this < QString::fromAscii(s.constData(), s.size()); }
+ inline QT_ASCII_CAST_WARN bool operator>(const QByteArray &s) const
+ { return *this > QString::fromAscii(s.constData(), s.size()); }
+ inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &s) const
+ { return *this <= QString::fromAscii(s.constData(), s.size()); }
+ inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &s) const
+ { return *this >= QString::fromAscii(s.constData(), s.size()); }
+#endif
+
+ typedef QChar *iterator;
+ typedef const QChar *const_iterator;
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ iterator begin();
+ const_iterator begin() const;
+ const_iterator constBegin() const;
+ iterator end();
+ const_iterator end() const;
+ const_iterator constEnd() const;
+
+ // STL compatibility
+ typedef const QChar & const_reference;
+ typedef QChar & reference;
+ typedef QChar value_type;
+ inline void push_back(QChar c) { append(c); }
+ inline void push_back(const QString &s) { append(s); }
+ inline void push_front(QChar c) { prepend(c); }
+ inline void push_front(const QString &s) { prepend(s); }
+
+#ifndef QT_NO_STL
+ static inline QString fromStdString(const std::string &s);
+ inline std::string toStdString() const;
+# ifdef qdoc
+ static inline QString fromStdWString(const std::wstring &s);
+ inline std::wstring toStdWString() const;
+# else
+# ifndef QT_NO_STL_WCHAR
+ static inline QString fromStdWString(const QStdWString &s);
+ inline QStdWString toStdWString() const;
+# endif // QT_NO_STL_WCHAR
+# endif // qdoc
+#endif
+
+ // compatibility
+ struct Null { };
+ static const Null null;
+ inline QString(const Null &): d(&shared_null) { d->ref.ref(); }
+ inline QString &operator=(const Null &) { *this = QString(); return *this; }
+ inline bool isNull() const { return d == &shared_null; }
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT const char *ascii() const { return ascii_helper(); }
+ inline QT3_SUPPORT const char *latin1() const { return latin1_helper(); }
+ inline QT3_SUPPORT QByteArray utf8() const { return toUtf8(); }
+ inline QT3_SUPPORT QByteArray local8Bit() const{ return toLocal8Bit(); }
+ inline QT3_SUPPORT void setLength(int nl) { resize(nl); }
+ inline QT3_SUPPORT QString copy() const { return *this; }
+ inline QT3_SUPPORT QString &remove(QChar c, bool cs)
+ { return remove(c, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT QString &remove(const QString &s, bool cs)
+ { return remove(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT QString &replace(QChar c, const QString &after, bool cs)
+ { return replace(c, after, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT QString &replace(const QString &before, const QString &after, bool cs)
+ { return replace(before, after, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+#ifndef QT_NO_CAST_FROM_ASCII
+ inline QT3_SUPPORT QString &replace(char c, const QString &after, bool cs)
+ { return replace(QChar::fromAscii(c), after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); }
+ // strange overload, required to avoid GCC 3.3 error
+ inline QT3_SUPPORT QString &replace(char c, const QString &after, Qt::CaseSensitivity cs)
+ { return replace(QChar::fromAscii(c), after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); }
+#endif
+ inline QT3_SUPPORT int find(QChar c, int i = 0, bool cs = true) const
+ { return indexOf(c, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT int find(const QString &s, int i = 0, bool cs = true) const
+ { return indexOf(s, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT int findRev(QChar c, int i = -1, bool cs = true) const
+ { return lastIndexOf(c, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT int findRev(const QString &s, int i = -1, bool cs = true) const
+ { return lastIndexOf(s, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+#ifndef QT_NO_REGEXP
+ inline QT3_SUPPORT int find(const QRegExp &rx, int i=0) const
+ { return indexOf(rx, i); }
+ inline QT3_SUPPORT int findRev(const QRegExp &rx, int i=-1) const
+ { return lastIndexOf(rx, i); }
+ inline QT3_SUPPORT int find(QRegExp &rx, int i=0) const
+ { return indexOf(rx, i); }
+ inline QT3_SUPPORT int findRev(QRegExp &rx, int i=-1) const
+ { return lastIndexOf(rx, i); }
+#endif
+ inline QT3_SUPPORT QBool contains(QChar c, bool cs) const
+ { return contains(c, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT QBool contains(const QString &s, bool cs) const
+ { return contains(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT bool startsWith(const QString &s, bool cs) const
+ { return startsWith(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT bool endsWith(const QString &s, bool cs) const
+ { return endsWith(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); }
+ inline QT3_SUPPORT QChar constref(uint i) const
+ { return at(i); }
+ QT3_SUPPORT QChar &ref(uint i);
+ inline QT3_SUPPORT QString leftJustify(int width, QChar aFill = QLatin1Char(' '), bool trunc=false) const
+ { return leftJustified(width, aFill, trunc); }
+ inline QT3_SUPPORT QString rightJustify(int width, QChar aFill = QLatin1Char(' '), bool trunc=false) const
+ { return rightJustified(width, aFill, trunc); }
+ inline QT3_SUPPORT QString lower() const { return toLower(); }
+ inline QT3_SUPPORT QString upper() const { return toUpper(); }
+ inline QT3_SUPPORT QString stripWhiteSpace() const { return trimmed(); }
+ inline QT3_SUPPORT QString simplifyWhiteSpace() const { return simplified(); }
+ inline QT3_SUPPORT QString &setUnicodeCodes(const ushort *unicode_as_ushorts, int aSize)
+ { return setUtf16(unicode_as_ushorts, aSize); }
+ inline QT3_SUPPORT const ushort *ucs2() const { return utf16(); }
+ inline static QT3_SUPPORT QString fromUcs2(const ushort *unicode, int size = -1)
+ { return fromUtf16(unicode, size); }
+ inline QT3_SUPPORT QString &setAscii(const char *str, int len = -1)
+ { *this = fromAscii(str, len); return *this; }
+ inline QT3_SUPPORT QString &setLatin1(const char *str, int len = -1)
+ { *this = fromLatin1(str, len); return *this; }
+protected:
+ friend class QObject;
+ const char *ascii_helper() const;
+ const char *latin1_helper() const;
+public:
+#ifndef QT_NO_CAST_TO_ASCII
+ inline QT3_SUPPORT operator const char *() const { return ascii_helper(); }
+private:
+ QT3_SUPPORT operator QNoImplicitBoolCast() const;
+public:
+#endif
+#endif
+
+ bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
+ bool isRightToLeft() const;
+
+ QString(int size, Qt::Initialization);
+
+private:
+#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
+ QString &operator+=(const char *s);
+ QString &operator+=(const QByteArray &s);
+ QString(const char *ch);
+ QString(const QByteArray &a);
+ QString &operator=(const char *ch);
+ QString &operator=(const QByteArray &a);
+#endif
+
+ struct Data {
+ QBasicAtomicInt ref;
+ int alloc, size;
+ ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then
+ ushort clean : 1;
+ ushort simpletext : 1;
+ ushort righttoleft : 1;
+ ushort asciiCache : 1;
+ ushort capacity : 1;
+ ushort reserved : 11;
+ // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit
+ ushort array[1];
+ };
+ static Data shared_null;
+ static Data shared_empty;
+ Data *d;
+ QString(Data *dd, int /*dummy*/) : d(dd) {}
+#ifndef QT_NO_TEXTCODEC
+ static QTextCodec *codecForCStrings;
+#endif
+ static int grow(int);
+ static void free(Data *);
+ void realloc();
+ void realloc(int alloc);
+ void expand(int i);
+ void updateProperties() const;
+ QString multiArg(int numArgs, const QString **args) const;
+ static int compare_helper(const QChar *data1, int length1,
+ const QChar *data2, int length2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ static int compare_helper(const QChar *data1, int length1,
+ QLatin1String s2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ static int localeAwareCompare_helper(const QChar *data1, int length1,
+ const QChar *data2, int length2);
+ static Data *fromLatin1_helper(const char *str, int size = -1);
+ static Data *fromAscii_helper(const char *str, int size = -1);
+ void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen);
+ friend class QCharRef;
+ friend class QTextCodec;
+ friend class QStringRef;
+ friend struct QAbstractConcatenable;
+ friend inline bool qStringComparisonHelper(const QString &s1, const char *s2);
+ friend inline bool qStringComparisonHelper(const QStringRef &s1, const char *s2);
+public:
+ typedef Data * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+
+class Q_CORE_EXPORT QLatin1String
+{
+public:
+ inline explicit QLatin1String(const char *s) : chars(s) {}
+ inline QLatin1String &operator=(const QLatin1String &other)
+ { chars = other.chars; return *this; }
+
+ inline const char *latin1() const { return chars; }
+
+ inline bool operator==(const QString &s) const
+ { return s == *this; }
+ inline bool operator!=(const QString &s) const
+ { return s != *this; }
+ inline bool operator>(const QString &s) const
+ { return s < *this; }
+ inline bool operator<(const QString &s) const
+ { return s > *this; }
+ inline bool operator>=(const QString &s) const
+ { return s <= *this; }
+ inline bool operator<=(const QString &s) const
+ { return s >= *this; }
+
+ inline QT_ASCII_CAST_WARN bool operator==(const char *s) const
+ { return QString::fromAscii(s) == *this; }
+ inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const
+ { return QString::fromAscii(s) != *this; }
+ inline QT_ASCII_CAST_WARN bool operator<(const char *s) const
+ { return QString::fromAscii(s) > *this; }
+ inline QT_ASCII_CAST_WARN bool operator>(const char *s) const
+ { return QString::fromAscii(s) < *this; }
+ inline QT_ASCII_CAST_WARN bool operator<=(const char *s) const
+ { return QString::fromAscii(s) >= *this; }
+ inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const
+ { return QString::fromAscii(s) <= *this; }
+private:
+ const char *chars;
+};
+
+
+
+inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1()))
+{ }
+inline int QString::length() const
+{ return d->size; }
+inline const QChar QString::at(int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const QChar QString::operator[](int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const QChar QString::operator[](uint i) const
+{ Q_ASSERT(i < uint(size())); return 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->ref != 1 || d->data != d->array) realloc(); }
+inline bool QString::isDetached() const
+{ return d->ref == 1; }
+inline QString &QString::operator=(const QLatin1String &s)
+{
+ *this = fromLatin1(s.latin1());
+ return *this;
+}
+inline void QString::clear()
+{ if (!isNull()) *this = QString(); }
+inline QString::QString(const QString &other) : d(other.d)
+{ Q_ASSERT(&other != this); d->ref.ref(); }
+inline int QString::capacity() const
+{ return d->alloc; }
+inline QString &QString::setNum(short n, int base)
+{ return setNum(qlonglong(n), base); }
+inline QString &QString::setNum(ushort n, int base)
+{ return setNum(qulonglong(n), base); }
+inline QString &QString::setNum(int n, int base)
+{ return setNum(qlonglong(n), base); }
+inline QString &QString::setNum(uint n, int base)
+{ return setNum(qulonglong(n), base); }
+inline QString &QString::setNum(long n, int base)
+{ return setNum(qlonglong(n), base); }
+inline QString &QString::setNum(ulong n, int base)
+{ return setNum(qulonglong(n), base); }
+inline 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, const QChar &fillChar) const
+{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(uint a, int fieldWidth, int base, const QChar &fillChar) const
+{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(long a, int fieldWidth, int base, const QChar &fillChar) const
+{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(ulong a, int fieldWidth, int base, const QChar &fillChar) const
+{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(short a, int fieldWidth, int base, const QChar &fillChar) const
+{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(ushort a, int fieldWidth, int base, const QChar &fillChar) const
+{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
+inline QString QString::arg(const QString &a1, const QString &a2) const
+{ const QString *args[2] = { &a1, &a2 }; return multiArg(2, args); }
+inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3) const
+{ const QString *args[3] = { &a1, &a2, &a3 }; return multiArg(3, args); }
+inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4) const
+{ const QString *args[4] = { &a1, &a2, &a3, &a4 }; return multiArg(4, args); }
+inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4, const QString &a5) const
+{ const QString *args[5] = { &a1, &a2, &a3, &a4, &a5 }; return multiArg(5, args); }
+inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
+ const QString &a4, const QString &a5, const QString &a6) const
+{ const QString *args[6] = { &a1, &a2, &a3, &a4, &a5, &a6 }; return multiArg(6, args); }
+inline 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
+{ const QString *args[7] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; return multiArg(7, args); }
+inline 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
+{ const QString *args[8] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; return multiArg(8, args); }
+inline 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
+{ const QString *args[9] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9 }; return multiArg(9, args); }
+
+inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const
+{ return section(QString(asep), astart, aend, aflags); }
+
+
+class Q_CORE_EXPORT QCharRef {
+ QString &s;
+ int i;
+ inline QCharRef(QString &str, int idx)
+ : s(str),i(idx) {}
+ friend class QString;
+public:
+
+ // most QChar operations repeated here
+
+ // all this is not documented: We just say "like QChar" and let it be.
+ inline operator QChar() const
+ { return i < s.d->size ? s.d->data[i] : 0; }
+ inline QCharRef &operator=(const QChar &c)
+ { if (i >= s.d->size) s.expand(i); else s.detach();
+ s.d->data[i] = c.unicode(); return *this; }
+
+ // An operator= for each QChar cast constructors
+#ifndef QT_NO_CAST_FROM_ASCII
+ inline QT_ASCII_CAST_WARN QCharRef &operator=(char c)
+ { return operator=(QChar::fromAscii(c)); }
+ inline QT_ASCII_CAST_WARN QCharRef &operator=(uchar c)
+ { return operator=(QChar::fromAscii(c)); }
+#endif
+ inline QCharRef &operator=(const QCharRef &c) { return operator=(QChar(c)); }
+ inline QCharRef &operator=(ushort rc) { return operator=(QChar(rc)); }
+ inline QCharRef &operator=(short rc) { return operator=(QChar(rc)); }
+ inline QCharRef &operator=(uint rc) { return operator=(QChar(rc)); }
+ inline QCharRef &operator=(int rc) { return operator=(QChar(rc)); }
+
+ // each function...
+ inline bool isNull() const { return QChar(*this).isNull(); }
+ inline bool isPrint() const { return QChar(*this).isPrint(); }
+ inline bool isPunct() const { return QChar(*this).isPunct(); }
+ inline bool isSpace() const { return QChar(*this).isSpace(); }
+ inline bool isMark() const { return QChar(*this).isMark(); }
+ inline bool isLetter() const { return QChar(*this).isLetter(); }
+ inline bool isNumber() const { return QChar(*this).isNumber(); }
+ inline bool isLetterOrNumber() { return QChar(*this).isLetterOrNumber(); }
+ inline bool isDigit() const { return QChar(*this).isDigit(); }
+ inline bool isLower() const { return QChar(*this).isLower(); }
+ inline bool isUpper() const { return QChar(*this).isUpper(); }
+ inline bool isTitleCase() const { return QChar(*this).isTitleCase(); }
+
+ inline int digitValue() const { return QChar(*this).digitValue(); }
+ QChar toLower() const { return QChar(*this).toLower(); }
+ QChar toUpper() const { return QChar(*this).toUpper(); }
+ QChar toTitleCase () const { return QChar(*this).toTitleCase(); }
+
+ QChar::Category category() const { return QChar(*this).category(); }
+ QChar::Direction direction() const { return QChar(*this).direction(); }
+ QChar::Joining joining() const { return QChar(*this).joining(); }
+ bool hasMirrored() const { return QChar(*this).hasMirrored(); }
+ QChar mirroredChar() const { return QChar(*this).mirroredChar(); }
+ QString decomposition() const { return QChar(*this).decomposition(); }
+ QChar::Decomposition decompositionTag() const { return QChar(*this).decompositionTag(); }
+ uchar combiningClass() const { return QChar(*this).combiningClass(); }
+
+ QChar::UnicodeVersion unicodeVersion() const { return QChar(*this).unicodeVersion(); }
+
+ inline uchar cell() const { return QChar(*this).cell(); }
+ inline uchar row() const { return QChar(*this).row(); }
+ inline void setCell(uchar cell);
+ inline void setRow(uchar row);
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const char toAscii() const { return QChar(*this).toAscii(); }
+ const char toLatin1() const { return QChar(*this).toLatin1(); }
+ const ushort unicode() const { return QChar(*this).unicode(); }
+#else
+ char toAscii() const { return QChar(*this).toAscii(); }
+ char toLatin1() const { return QChar(*this).toLatin1(); }
+ ushort unicode() const { return QChar(*this).unicode(); }
+#endif
+ ushort& unicode() { return s.data()[i].unicode(); }
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool mirrored() const { return hasMirrored(); }
+ inline QT3_SUPPORT QChar lower() const { return QChar(*this).toLower(); }
+ inline QT3_SUPPORT QChar upper() const { return QChar(*this).toUpper(); }
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const QT3_SUPPORT char latin1() const { return QChar(*this).toLatin1(); }
+ const QT3_SUPPORT char ascii() const { return QChar(*this).toAscii(); }
+#else
+ QT3_SUPPORT char latin1() const { return QChar(*this).toLatin1(); }
+ QT3_SUPPORT char ascii() const { return QChar(*this).toAscii(); }
+#endif
+#endif
+};
+
+inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); }
+inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
+
+
+inline QString::QString() : d(&shared_null) { d->ref.ref(); }
+inline QString::~QString() { if (!d->ref.deref()) free(d); }
+inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;}
+inline QString &QString::setUtf16(const ushort *autf16, int asize)
+{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
+inline QCharRef QString::operator[](int i)
+{ Q_ASSERT(i >= 0); return QCharRef(*this, i); }
+inline QCharRef QString::operator[](uint i)
+{ return QCharRef(*this, i); }
+inline QString::iterator QString::begin()
+{ detach(); return reinterpret_cast<QChar*>(d->data); }
+inline QString::const_iterator QString::begin() const
+{ return reinterpret_cast<const QChar*>(d->data); }
+inline QString::const_iterator QString::constBegin() const
+{ return reinterpret_cast<const QChar*>(d->data); }
+inline QString::iterator QString::end()
+{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); }
+inline QString::const_iterator QString::end() const
+{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+inline QString::const_iterator QString::constEnd() const
+{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(s, 0, cs) != -1); }
+inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(s, 0, cs) != -1); }
+inline QBool QString::contains(QChar c, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(c, 0, cs) != -1); }
+
+
+inline bool operator==(QString::Null, QString::Null) { return true; }
+inline bool operator==(QString::Null, const QString &s) { return s.isNull(); }
+inline bool operator==(const QString &s, QString::Null) { return s.isNull(); }
+inline bool operator!=(QString::Null, QString::Null) { return false; }
+inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); }
+inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); }
+
+#ifndef QT_NO_CAST_FROM_ASCII
+inline bool qStringComparisonHelper(const QString &s1, const char *s2)
+{
+# ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings) return (s1 == QString::fromAscii(s2));
+# endif
+ return (s1 == QLatin1String(s2));
+}
+inline bool QString::operator==(const char *s) const
+{ return qStringComparisonHelper(*this, s); }
+inline bool QString::operator!=(const char *s) const
+{ return !qStringComparisonHelper(*this, s); }
+inline bool QString::operator<(const char *s) const
+{ return *this < QString::fromAscii(s); }
+inline bool QString::operator>(const char *s) const
+{ return *this > QString::fromAscii(s); }
+inline bool QString::operator<=(const char *s) const
+{ return *this <= QString::fromAscii(s); }
+inline bool QString::operator>=(const char *s) const
+{ return *this >= QString::fromAscii(s); }
+
+inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QString &s2)
+{ return qStringComparisonHelper(s2, s1); }
+inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2)
+{ return !qStringComparisonHelper(s2, s1); }
+inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QString &s2)
+{ return (QString::fromAscii(s1) < s2); }
+inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2)
+{ return (QString::fromAscii(s1) > s2); }
+inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QString &s2)
+{ return (QString::fromAscii(s1) <= s2); }
+inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2)
+{ return (QString::fromAscii(s1) >= s2); }
+
+inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QLatin1String &s2)
+{ return QString::fromAscii(s1) == s2; }
+inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QLatin1String &s2)
+{ return QString::fromAscii(s1) != s2; }
+inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QLatin1String &s2)
+{ return (QString::fromAscii(s1) < s2); }
+inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QLatin1String &s2)
+{ return (QString::fromAscii(s1) > s2); }
+inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QLatin1String &s2)
+{ return (QString::fromAscii(s1) <= s2); }
+inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QLatin1String &s2)
+{ return (QString::fromAscii(s1) >= s2); }
+
+inline bool operator==(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) == 0); }
+inline bool operator!=(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) != 0); }
+inline bool operator<(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) < 0); }
+inline bool operator<=(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) <= 0); }
+inline bool operator>(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) > 0); }
+inline bool operator>=(const QLatin1String &s1, const QLatin1String &s2)
+{ return (qstrcmp(s1.latin1(), s2.latin1()) >= 0); }
+
+
+inline bool QString::operator==(const QByteArray &s) const
+{ return qStringComparisonHelper(*this, s.constData()); }
+inline bool QString::operator!=(const QByteArray &s) const
+{ return !qStringComparisonHelper(*this, s.constData()); }
+
+inline bool QByteArray::operator==(const QString &s) const
+{ return qStringComparisonHelper(s, constData()); }
+inline bool QByteArray::operator!=(const QString &s) const
+{ return !qStringComparisonHelper(s, constData()); }
+inline bool QByteArray::operator<(const QString &s) const
+{ return QString::fromAscii(constData(), size()) < s; }
+inline bool QByteArray::operator>(const QString &s) const
+{ return QString::fromAscii(constData(), size()) > s; }
+inline bool QByteArray::operator<=(const QString &s) const
+{ return QString::fromAscii(constData(), size()) <= s; }
+inline bool QByteArray::operator>=(const QString &s) const
+{ return QString::fromAscii(constData(), size()) >= s; }
+#endif // QT_NO_CAST_FROM_ASCII
+
+#ifndef QT_NO_CAST_TO_ASCII
+inline QByteArray &QByteArray::append(const QString &s)
+{ return append(s.toAscii()); }
+inline QByteArray &QByteArray::insert(int i, const QString &s)
+{ return insert(i, s.toAscii()); }
+inline QByteArray &QByteArray::replace(char c, const QString &after)
+{ return replace(c, after.toAscii()); }
+inline QByteArray &QByteArray::replace(const QString &before, const char *after)
+{ return replace(before.toAscii(), after); }
+inline QByteArray &QByteArray::replace(const QString &before, const QByteArray &after)
+{ return replace(before.toAscii(), after); }
+inline QByteArray &QByteArray::operator+=(const QString &s)
+{ return operator+=(s.toAscii()); }
+inline int QByteArray::indexOf(const QString &s, int from) const
+{ return indexOf(s.toAscii(), from); }
+inline int QByteArray::lastIndexOf(const QString &s, int from) const
+{ return lastIndexOf(s.toAscii(), from); }
+# ifdef QT3_SUPPORT
+inline int QByteArray::find(const QString &s, int from) const
+{ return indexOf(s.toAscii(), from); }
+inline int QByteArray::findRev(const QString &s, int from) const
+{ return lastIndexOf(s.toAscii(), from); }
+# endif // QT3_SUPPORT
+#endif // QT_NO_CAST_TO_ASCII
+
+#ifndef QT_USE_FAST_OPERATOR_PLUS
+# ifndef QT_USE_FAST_CONCATENATION
+inline const QString operator+(const QString &s1, const QString &s2)
+{ QString t(s1); t += s2; return t; }
+inline const QString operator+(const QString &s1, QChar s2)
+{ QString t(s1); t += s2; return t; }
+inline const QString operator+(QChar s1, const QString &s2)
+{ QString t(s1); t += s2; return t; }
+# ifndef QT_NO_CAST_FROM_ASCII
+inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2)
+{ QString t(s1); t += QString::fromAscii(s2); return t; }
+inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2)
+{ QString t = QString::fromAscii(s1); t += s2; return t; }
+inline QT_ASCII_CAST_WARN const QString operator+(char c, const QString &s)
+{ QString t = s; t.prepend(QChar::fromAscii(c)); return t; }
+inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, char c)
+{ QString t = s; t += QChar::fromAscii(c); return t; }
+inline QT_ASCII_CAST_WARN const QString operator+(const QByteArray &ba, const QString &s)
+{ QString t = QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); t += s; return t; }
+inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteArray &ba)
+{ QString t(s); t += QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); return t; }
+# endif // QT_NO_CAST_FROM_ASCII
+# endif // QT_USE_FAST_CONCATENATION
+#endif // QT_USE_FAST_OPERATOR_PLUS
+
+#ifndef QT_NO_STL
+inline std::string QString::toStdString() const
+{ const QByteArray asc = toAscii(); return std::string(asc.constData(), asc.length()); }
+
+inline QString QString::fromStdString(const std::string &s)
+{ return fromAscii(s.data(), int(s.size())); }
+
+# ifndef QT_NO_STL_WCHAR
+inline QStdWString QString::toStdWString() const
+{
+ QStdWString str;
+ str.resize(length());
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ // VS2005 crashes if the string is empty
+ if (!length())
+ return str;
+#endif
+
+ str.resize(toWCharArray(&(*str.begin())));
+ return str;
+}
+inline QString QString::fromStdWString(const QStdWString &s)
+{ return fromWCharArray(s.data(), int(s.size())); }
+# endif
+#endif
+
+#ifdef QT3_SUPPORT
+inline QChar &QString::ref(uint i)
+{
+ if (int(i) > d->size || d->ref != 1)
+ resize(qMax(int(i), d->size));
+ return reinterpret_cast<QChar&>(d->data[i]);
+}
+#endif
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
+#endif
+
+#ifdef QT3_SUPPORT
+class QConstString : public QString
+{
+public:
+ inline QT3_SUPPORT_CONSTRUCTOR QConstString(const QChar *aUnicode, int aSize)
+ :QString(aUnicode, aSize){} // cannot use fromRawData() due to changed semantics
+ inline QT3_SUPPORT const QString &string() const { return *this; }
+};
+#endif
+
+Q_DECLARE_TYPEINFO(QString, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QString)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags)
+
+
+class Q_CORE_EXPORT QStringRef {
+ const QString *m_string;
+ int m_position;
+ int m_size;
+public:
+ inline QStringRef():m_string(0), m_position(0), m_size(0){}
+ inline QStringRef(const QString *string, int position, int size);
+ inline QStringRef(const QString *string);
+ inline QStringRef(const QStringRef &other)
+ :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size)
+ {}
+
+ inline ~QStringRef(){}
+ 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; }
+
+ inline QStringRef &operator=(const QStringRef &other) {
+ m_string = other.m_string; m_position = other.m_position;
+ m_size = other.m_size; return *this;
+ }
+
+ int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ 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;
+ int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ 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;
+ int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ 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;
+
+ bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ inline QStringRef &operator=(const QString *string);
+
+ inline const QChar *unicode() const {
+ if (!m_string)
+ return reinterpret_cast<const QChar *>(QString::shared_null.data);
+ return m_string->unicode() + m_position;
+ }
+ inline const QChar *data() const { return unicode(); }
+ inline const QChar *constData() const { return unicode(); }
+
+ QByteArray toAscii() const Q_REQUIRED_RESULT;
+ QByteArray toLatin1() const Q_REQUIRED_RESULT;
+ QByteArray toUtf8() const Q_REQUIRED_RESULT;
+ QByteArray toLocal8Bit() const Q_REQUIRED_RESULT;
+ QVector<uint> toUcs4() const Q_REQUIRED_RESULT;
+
+ inline void clear() { m_string = 0; m_position = m_size = 0; }
+ QString toString() const;
+ inline bool isEmpty() const { return m_size == 0; }
+ inline bool isNull() const { return m_string == 0 || m_string->isNull(); }
+
+ QStringRef appendTo(QString *string) const;
+
+ inline const QChar at(int i) const
+ { Q_ASSERT(i >= 0 && i < size()); return m_string->at(i + m_position); }
+
+ int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ static int compare(const QStringRef &s1, const QString &s2,
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+ static int compare(const QStringRef &s1, const QStringRef &s2,
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+ static int compare(const QStringRef &s1, QLatin1String s2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+
+ 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);
+};
+
+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){}
+
+Q_CORE_EXPORT bool operator==(const QStringRef &s1,const QStringRef &s2);
+inline bool operator!=(const QStringRef &s1,const QStringRef &s2)
+{ return !(s1 == s2); }
+Q_CORE_EXPORT bool operator==(const QString &s1,const QStringRef &s2);
+inline bool operator!=(const QString &s1,const QStringRef &s2)
+{ return !(s1 == s2); }
+inline bool operator==(const QStringRef &s1,const QString &s2)
+{ return s2 == s1; }
+inline bool operator!=(const QStringRef &s1,const QString &s2)
+{ return s2 != s1; }
+Q_CORE_EXPORT bool operator==(const QLatin1String &s1, const QStringRef &s2);
+inline bool operator!=(const QLatin1String &s1,const QStringRef &s2)
+{ return !(s1 == s2); }
+inline bool operator==(const QStringRef &s1,const QLatin1String &s2)
+{ return s2 == s1; }
+inline bool operator!=(const QStringRef &s1,const QLatin1String &s2)
+{ return s2 != s1; }
+
+Q_CORE_EXPORT bool operator<(const QStringRef &s1,const QStringRef &s2);
+inline bool operator>(const QStringRef &s1, const QStringRef &s2)
+{ return s2 < s1; }
+inline bool operator<=(const QStringRef &s1, const QStringRef &s2)
+{ return !(s1 > s2); }
+inline bool operator>=(const QStringRef &s1, const QStringRef &s2)
+{ return !(s1 < s2); }
+
+inline bool qStringComparisonHelper(const QStringRef &s1, const char *s2)
+{
+# ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings) return (s1 == QString::fromAscii(s2));
+# endif
+ return (s1 == QLatin1String(s2));
+}
+
+inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QStringRef &s2)
+{ return qStringComparisonHelper(s2, s1); }
+inline QT_ASCII_CAST_WARN bool operator==(const QStringRef &s1, const char *s2)
+{ return qStringComparisonHelper(s1, s2); }
+inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QStringRef &s2)
+{ return !qStringComparisonHelper(s2, s1); }
+inline QT_ASCII_CAST_WARN bool operator!=(const QStringRef &s1, const char *s2)
+{ return !qStringComparisonHelper(s1, s2); }
+
+inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const
+{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
+inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs)
+{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
+inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const
+{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
+inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const
+{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
+inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const
+{ return QString::compare_helper(constData(), length(), s, cs); }
+inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs)
+{ 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)
+{ 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)
+{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); }
+
+inline int QString::localeAwareCompare(const QStringRef &s) const
+{ return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); }
+inline int QString::localeAwareCompare(const QString& s1, const QStringRef& 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()); }
+
+inline QBool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(s, 0, cs) != -1); }
+inline QBool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(s, 0, cs) != -1); }
+inline QBool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(c, 0, cs) != -1); }
+inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
+{ return QBool(indexOf(s, 0, cs) != -1); }
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#ifdef QT_USE_FAST_CONCATENATION
+#include <QtCore/qstringbuilder.h>
+#endif
+
+#endif // QSTRING_H
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
new file mode 100644
index 0000000000..a5dff88f43
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringbuilder.h"
+#include <QtCore/qtextcodec.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QLatin1Literal
+ \internal
+ \reentrant
+ \since 4.6
+
+ \brief The QLatin1Literal class provides a thin wrapper around string
+ literals used in source code.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+
+ Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size
+ without iterating over the literal.
+
+ The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
+ to reduce the number of reallocations needed to build up a string from
+ smaller chunks.
+
+ \sa QStringBuilder, QLatin1String, QString, QStringRef
+*/
+
+/*! \fn int QLatin1Literal::size() const
+
+ Returns the number of characters in the literal \e{excluding} the trailing
+ NULL char.
+*/
+
+/*! \fn QLatin1Literal::QLatin1Literal(const char str)
+
+ Constructs a new literal from the string \a str.
+*/
+
+/*! \fn const char *QLatin1Literal::data() const
+
+ Returns a pointer to the first character of the string literal.
+ The string literal is terminated by a NUL character.
+*/
+
+/*!
+ \class QStringBuilder
+ \internal
+ \reentrant
+ \since 4.6
+
+ \brief The QStringBuilder class is a template class that provides a facility to build up QStrings from smaller chunks.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+
+ To build a QString by multiple concatenations, QString::operator+()
+ is typically used. This causes \e{n - 1} reallocations when building
+ a string from \e{n} chunks.
+
+ QStringBuilder uses expression templates to collect the individual
+ chunks, compute the total size, allocate the required amount of
+ memory for the final QString object, and copy the chunks into the
+ allocated memory.
+
+ The QStringBuilder class is not to be used explicitly in user
+ code. Instances of the class are created as return values of the
+ operator%() function, acting on objects of type QString,
+ QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef,
+ QLatin1Char, and \c char.
+
+ Concatenating strings with operator%() generally yields better
+ performance then using \c QString::operator+() on the same chunks
+ if there are three or more of them, and performs equally well in other
+ cases.
+
+ \sa QLatin1Literal, QString
+*/
+
+/*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b)
+ Constructs a QStringBuilder from \a a and \a b.
+ */
+
+/* \fn QStringBuilder::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 QLatin1Literal, \c QStringRef,
+ \c QChar, \c QCharRef, \c QLatin1Char, and \c char.
+*/
+
+/*! \fn QByteArray QStringBuilder::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 QStringBuilder::operator QString() const
+
+ Converts the \c QLatin1Literal into a \c QString object.
+*/
+
+/*! \internal
+ Note: The len contains the ending \0
+ */
+void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings && len) {
+ QString tmp = QString::fromAscii(a, len > 0 ? len - 1 : -1);
+ memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
+ out += tmp.length();
+ return;
+ }
+#endif
+ if (len == -1) {
+ while (*a)
+ *out++ = QLatin1Char(*a++);
+ } else {
+ for (int i = 0; i < len - 1; ++i)
+ *out++ = QLatin1Char(a[i]);
+ }
+}
+
+/*! \internal */
+void QAbstractConcatenable::convertToAscii(const QChar* a, int len, char*& out)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings) {
+ QByteArray tmp = QString::codecForCStrings->fromUnicode(a, len);
+ memcpy(out, tmp.constData(), tmp.size());
+ out += tmp.length();
+ return;
+ }
+#endif
+ if (len == -1) {
+ while (a->unicode())
+ convertToLatin1(*a++, out);
+ } else {
+ for (int i = 0; i < len; ++i)
+ convertToLatin1(a[i], out);
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
new file mode 100644
index 0000000000..2d3475fed9
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.h
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGBUILDER_H
+#define QSTRINGBUILDER_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+
+#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
+# include <QtCore/qmap.h>
+# endif
+#endif
+
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// ### Qt 5: merge with QLatin1String
+class QLatin1Literal
+{
+public:
+ int size() const { return m_size; }
+ const char *data() const { return m_data; }
+
+ template <int N>
+ QLatin1Literal(const char (&str)[N])
+ : m_size(N - 1), m_data(str) {}
+
+private:
+ const int m_size;
+ const char * const m_data;
+};
+
+struct Q_CORE_EXPORT QAbstractConcatenable
+{
+protected:
+ static void convertFromAscii(const char *a, int len, QChar *&out);
+ static void convertToAscii(const QChar *a, int len, char *&out);
+ static inline void convertFromAscii(char a, QChar *&out)
+ {
+#ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings)
+ *out++ = QChar::fromAscii(a);
+ else
+#endif
+ *out++ = QLatin1Char(a);
+ }
+
+ static inline void convertToAscii(QChar a, char *&out)
+ {
+#ifndef QT_NO_TEXTCODEC
+ if (QString::codecForCStrings)
+ *out++ = a.toAscii(); //###
+ else
+#endif
+ convertToLatin1(a, out);
+ }
+
+ static inline void convertToLatin1(QChar a, char *&out)
+ {
+ *out++ = a.unicode() > 0xff ? '?' : char(a.unicode());
+ }
+};
+
+template <typename T> struct QConcatenable {};
+
+template <typename A, typename B>
+class QStringBuilder
+{
+public:
+ QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
+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);
+
+ typename T::iterator d = s.data();
+ typename T::const_iterator const start = d;
+ QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
+
+ 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(d - start);
+ }
+ return s;
+ }
+
+ typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
+ typedef typename Concatenable::ConvertTo ConvertTo;
+public:
+ operator ConvertTo() const { return convertTo<ConvertTo>(); }
+
+ QByteArray toLatin1() const { return convertTo<QString>().toLatin1(); }
+ int size() const { return Concatenable::size(*this); }
+
+ const A &a;
+ const B &b;
+};
+
+template <>
+class QStringBuilder <QString, QString>
+{
+ public:
+ QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
+
+ operator QString() const
+ { QString r(a); r += b; return r; }
+ QByteArray toLatin1() const { return QString(*this).toLatin1(); }
+
+ const QString &a;
+ const QString &b;
+};
+
+template <>
+class QStringBuilder <QByteArray, QByteArray>
+{
+ public:
+ QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
+
+ operator QByteArray() const
+ { QByteArray r(a); r += b; return r; }
+
+ const QByteArray &a;
+ const QByteArray &b;
+};
+
+
+template <> struct QConcatenable<char> : private QAbstractConcatenable
+{
+ typedef char type;
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = true };
+ static int size(const char) { return 1; }
+#ifndef QT_NO_CAST_FROM_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
+ {
+ QAbstractConcatenable::convertFromAscii(c, out);
+ }
+#endif
+ static inline void appendTo(const char c, char *&out)
+ { *out++ = c; }
+};
+
+template <> struct QConcatenable<QLatin1Char>
+{
+ typedef QLatin1Char type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int 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)
+ { *out++ = c.toLatin1(); }
+};
+
+template <> struct QConcatenable<QChar> : private QAbstractConcatenable
+{
+ typedef QChar type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const QChar) { return 1; }
+ static inline void appendTo(const QChar c, QChar *&out)
+ { *out++ = c; }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const QChar c, char *&out)
+ { convertToAscii(c, out); }
+#endif
+};
+
+template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
+{
+ typedef QCharRef type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const QCharRef &) { return 1; }
+ static inline void appendTo(const QCharRef &c, QChar *&out)
+ { *out++ = QChar(c); }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const QCharRef &c, char *&out)
+ { convertToAscii(c, out); }
+#endif
+};
+
+template <> struct QConcatenable<QLatin1String>
+{
+ typedef QLatin1String type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
+ static inline void appendTo(const QLatin1String &a, QChar *&out)
+ {
+ for (const char *s = a.latin1(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+ static inline void appendTo(const QLatin1String &a, char *&out)
+ {
+ for (const char *s = a.latin1(); *s; )
+ *out++ = *s++;
+ }
+};
+
+template <> struct QConcatenable<QLatin1Literal>
+{
+ typedef QLatin1Literal type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const QLatin1Literal &a) { return a.size(); }
+ static inline void appendTo(const QLatin1Literal &a, QChar *&out)
+ {
+ for (const char *s = a.data(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+ static inline void appendTo(const QLatin1Literal &a, char *&out)
+ {
+ for (const char *s = a.data(); *s; )
+ *out++ = *s++;
+ }
+};
+
+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 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;
+ }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const QString &a, char *&out)
+ { convertToAscii(a.constData(), a.length(), out); }
+#endif
+};
+
+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);
+ out += n;
+ }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const QStringRef &a, char *&out)
+ { convertToAscii(a.constData(), a.length(), out); }
+#endif
+
+};
+
+template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
+{
+ typedef char type[N];
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = false };
+ static int 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)
+ {
+ QAbstractConcatenable::convertFromAscii(a, N, out);
+ }
+#endif
+ static inline void appendTo(const char a[N], char *&out)
+ {
+ while (*a)
+ *out++ = *a++;
+ }
+};
+
+template <int 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; }
+#ifndef QT_NO_CAST_FROM_ASCII
+ static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
+ {
+ QAbstractConcatenable::convertFromAscii(a, N, out);
+ }
+#endif
+ static inline void appendTo(const char a[N], char *&out)
+ {
+ while (*a)
+ *out++ = *a++;
+ }
+};
+
+template <> struct QConcatenable<const char *> : private QAbstractConcatenable
+{
+ typedef char const *type;
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = false };
+ static int 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); }
+#endif
+ static inline void appendTo(const char *a, char *&out)
+ {
+ while (*a)
+ *out++ = *a++;
+ }
+};
+
+template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
+{
+ typedef QByteArray type;
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = false };
+ static int size(const QByteArray &ba) { return ba.size(); }
+#ifndef QT_NO_CAST_FROM_ASCII
+ static inline void appendTo(const QByteArray &ba, QChar *&out)
+ {
+ // adding 1 because convertFromAscii expects the size including the null-termination
+ QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size() + 1, 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++;
+ }
+};
+
+namespace QtStringBuilder {
+ template <typename A, typename B> struct ConvertToTypeHelper
+ { typedef A ConvertTo; };
+ template <typename T> struct ConvertToTypeHelper<T, QString>
+ { typedef QString ConvertTo; };
+}
+
+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)
+ {
+ return QConcatenable<A>::size(p.a) + QConcatenable<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);
+ }
+};
+
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator%(const A &a, const B &b)
+{
+ return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
+}
+
+#ifdef QT_USE_FAST_OPERATOR_PLUS
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator+(const A &a, const B &b)
+{
+ return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
+}
+#endif
+
+template <typename A, typename B>
+QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
+{
+#ifndef QT_NO_CAST_TO_ASCII
+ if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
+ //it is not save to optimize as in utf8 it is not possible to compute the size
+ return a += QString(b);
+ }
+#endif
+ int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
+ a.reserve(len);
+ 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
+ return a;
+}
+
+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);
+ QChar *it = a.data() + a.size();
+ QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
+ a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
+ return a;
+}
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTRINGBUILDER_H
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
new file mode 100644
index 0000000000..21269a8e7b
--- /dev/null
+++ b/src/corelib/tools/qstringlist.cpp
@@ -0,0 +1,692 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qstringlist.h>
+#include <qset.h>
+
+QT_BEGIN_NAMESPACE
+
+/*! \typedef QStringListIterator
+ \relates QStringList
+
+ The QStringListIterator type definition provides a Java-style const
+ iterator for QStringList.
+
+ QStringList provides both \l{Java-style iterators} and
+ \l{STL-style iterators}. The Java-style const iterator is simply
+ a type definition for QListIterator<QString>.
+
+ \sa QMutableStringListIterator, QStringList::const_iterator
+*/
+
+/*! \typedef QMutableStringListIterator
+ \relates QStringList
+
+ The QStringListIterator type definition provides a Java-style
+ non-const iterator for QStringList.
+
+ QStringList provides both \l{Java-style iterators} and
+ \l{STL-style iterators}. The Java-style non-const iterator is
+ simply a type definition for QMutableListIterator<QString>.
+
+ \sa QStringListIterator, QStringList::iterator
+*/
+
+/*!
+ \class QStringList
+ \brief The QStringList class provides a list of strings.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ \reentrant
+
+ QStringList inherits from QList<QString>. Like QList, QStringList is
+ \l{implicitly shared}. It provides fast index-based access as well as fast
+ insertions and removals. Passing string lists as value parameters is both
+ fast and safe.
+
+ All of QList's functionality also applies to QStringList. For example, you
+ can use isEmpty() to test whether the list is empty, and you can call
+ functions like append(), prepend(), insert(), replace(), removeAll(),
+ removeAt(), removeFirst(), removeLast(), and removeOne() to modify a
+ QStringList. In addition, QStringList provides a few convenience
+ functions that make handling lists of strings easier:
+
+ \tableofcontents
+
+ \section1 Adding strings
+
+ Strings can be added to a list using the \l
+ {QList::append()}{append()}, \l
+ {QList::operator+=()}{operator+=()} and \l
+ {QStringList::operator<<()}{operator<<()} functions. For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 0
+
+ \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 doc/src/snippets/qstringlist/main.cpp 1
+
+ Java-style iterator:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 2
+
+ STL-style iterator:
+
+ \snippet doc/src/snippets/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>.
+
+ \section1 Manipulating the strings
+
+ QStringList provides several functions allowing you to manipulate
+ the contents of a list. You can concatenate all the strings in a
+ string list into a single string (with an optional separator)
+ using the join() function. For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 4
+
+ To break up a string into a string list, use the QString::split()
+ function:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 6
+
+ The argument to split can be a single character, a string, or a
+ QRegExp.
+
+ In addition, the \l {QStringList::operator+()}{operator+()}
+ function allows you to concatenate two string lists into one. To
+ sort a string list, use the sort() function.
+
+ QString list also provides the filter() function which lets you
+ to extract a new list which contains only those strings which
+ contain a particular substring (or match a particular regular
+ expression):
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 7
+
+ The contains() function tells you whether the list contains a
+ given string, while the indexOf() function returns the index of
+ the first occurrence of the given string. The lastIndexOf()
+ function on the other hand, returns the index of the last
+ occurrence of the string.
+
+ Finally, the replaceInStrings() function calls QString::replace()
+ on each string in the string list in turn. For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 8
+
+ \sa QString
+*/
+
+/*!
+ \fn QStringList::QStringList()
+
+ Constructs an empty string list.
+*/
+
+/*!
+ \fn QStringList::QStringList(const QString &str)
+
+ Constructs a string list that contains the given string, \a
+ str. Longer lists are easily created like this:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 9
+
+ \sa append()
+*/
+
+/*!
+ \fn QStringList::QStringList(const QStringList &other)
+
+ Constructs a copy of the \a other string list.
+
+ This operation takes \l{constant time} because QStringList is
+ \l{implicitly shared}, making the process of returning a
+ QStringList from a function very fast. If a shared instance is
+ modified, it will be copied (copy-on-write), and that takes
+ \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QStringList::QStringList(const QList<QString> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QStringList is
+ \l{implicitly shared}. This makes returning a QStringList from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*!
+ \fn void QStringList::sort()
+
+ Sorts the list of strings in ascending order (case sensitively).
+
+ Sorting is performed using Qt's qSort() algorithm,
+ which operates in \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
+
+ If you want to sort your strings in an arbitrary order, consider
+ using the QMap class. For example, you could use a QMap<QString,
+ QString> to create a case-insensitive ordering (e.g. with the keys
+ being lower-case versions of the strings, and the values being the
+ strings), or a QMap<int, QString> to sort the strings by some
+ integer index.
+
+ \sa qSort()
+*/
+void QtPrivate::QStringList_sort(QStringList *that)
+{
+ qSort(*that);
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn QStringList QStringList::split(const QChar &sep, const QString &str, bool allowEmptyEntries)
+
+ \overload
+
+ This version of the function uses a QChar as separator.
+
+ \sa join() QString::section()
+*/
+
+/*!
+ \fn QStringList QStringList::split(const QString &sep, const QString &str, bool allowEmptyEntries)
+
+ \overload
+
+ This version of the function uses a QString as separator.
+
+ \sa join() QString::section()
+*/
+#ifndef QT_NO_REGEXP
+/*!
+ \fn QStringList QStringList::split(const QRegExp &sep, const QString &str, bool allowEmptyEntries)
+
+ Use QString::split(\a sep, QString::SkipEmptyParts) or
+ QString::split(\a sep, QString::KeepEmptyParts) instead.
+
+ Be aware that the QString::split()'s return value is a
+ QStringList that always contains at least one element, even if \a
+ str is empty.
+
+ \sa join() QString::section()
+*/
+#endif
+#endif // QT3_SUPPORT
+
+/*!
+ \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.
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 5
+ \snippet doc/src/snippets/qstringlist/main.cpp 10
+
+ This is equivalent to
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 11
+ \snippet doc/src/snippets/qstringlist/main.cpp 12
+
+ \sa contains()
+*/
+QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString &str,
+ 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;
+}
+
+
+/*!
+ \fn QBool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
+
+ Returns true if the list contains the string \a str; otherwise
+ returns false. The search is case insensitive if \a cs is
+ Qt::CaseInsensitive; the search is case sensitive by default.
+
+ \sa indexOf(), lastIndexOf(), QString::contains()
+ */
+QBool QtPrivate::QStringList_contains(const QStringList *that, const QString &str,
+ Qt::CaseSensitivity cs)
+{
+ for (int i = 0; i < that->size(); ++i) {
+ const QString & string = that->at(i);
+ if (string.length() == str.length() && str.compare(string, cs) == 0)
+ return QBool(true);
+ }
+ return QBool(false);
+}
+
+#ifndef QT_NO_REGEXP
+/*!
+ \fn QStringList QStringList::filter(const QRegExp &rx) const
+
+ \overload
+
+ Returns a list of all the strings that match the regular
+ expression \a rx.
+*/
+QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegExp &rx)
+{
+ QStringList res;
+ for (int i = 0; i < that->size(); ++i)
+ if (that->at(i).contains(rx))
+ res << that->at(i);
+ return res;
+}
+#endif
+
+/*!
+ \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.
+
+ For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 5
+ \snippet doc/src/snippets/qstringlist/main.cpp 13
+
+ \sa QString::replace()
+*/
+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);
+}
+
+
+#ifndef QT_NO_REGEXP
+/*!
+ \fn QStringList &QStringList::replaceInStrings(const QRegExp &rx, const QString &after)
+ \overload
+
+ 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.
+
+ For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 5
+ \snippet doc/src/snippets/qstringlist/main.cpp 14
+
+ For regular expressions that contain \l{capturing parentheses},
+ occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are
+ replaced with \a{rx}.cap(1), \a{rx}.cap(2), ...
+
+ For example:
+
+ \snippet doc/src/snippets/qstringlist/main.cpp 5
+ \snippet doc/src/snippets/qstringlist/main.cpp 15
+*/
+void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &rx, const QString &after)
+{
+ for (int i = 0; i < that->size(); ++i)
+ (*that)[i].replace(rx, after);
+}
+#endif
+
+/*!
+ \fn QString QStringList::join(const QString &separator) const
+
+ Joins all the string list's strings into a single string with each
+ element separated by the given \a separator (which can be an
+ empty string).
+
+ \sa QString::split()
+*/
+QString QtPrivate::QStringList_join(const QStringList *that, const QString &sep)
+{
+ int totalLength = 0;
+ const int size = that->size();
+
+ for (int i = 0; i < size; ++i)
+ totalLength += that->at(i).size();
+
+ if(size > 0)
+ totalLength += sep.size() * (size - 1);
+
+ QString res;
+ if (totalLength == 0)
+ return res;
+ res.reserve(totalLength);
+ for (int i = 0; i < that->size(); ++i) {
+ if (i)
+ res += sep;
+ res += that->at(i);
+ }
+ return res;
+}
+
+/*!
+ \fn QStringList QStringList::operator+(const QStringList &other) const
+
+ Returns a string list that is the concatenation of this string
+ list with the \a other string list.
+
+ \sa append()
+*/
+
+/*!
+ \fn QStringList &QStringList::operator<<(const QString &str)
+
+ Appends the given string, \a str, to this string list and returns
+ a reference to the string list.
+
+ \sa append()
+*/
+
+/*!
+ \fn QStringList &QStringList::operator<<(const QStringList &other)
+
+ \overload
+
+ Appends the \a other string list to the string list and returns a reference to
+ the latter string list.
+*/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator>>(QDataStream &in, QStringList &list)
+ \relates QStringList
+
+ Reads a string list from the given \a in stream into the specified
+ \a list.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &out, const QStringList &list)
+ \relates QStringList
+
+ Writes the given string \a list to the specified \a out stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn QStringList QStringList::grep(const QString &str, bool cs = true) const
+
+ Use filter() instead.
+*/
+
+/*!
+ \fn QStringList QStringList::grep(const QRegExp &rx) const
+
+ Use filter() instead.
+*/
+
+/*!
+ \fn QStringList &QStringList::gres(const QString &before, const QString &after, bool cs = true)
+
+ Use replaceInStrings() instead.
+*/
+
+/*!
+ \fn QStringList &QStringList::gres(const QRegExp &rx, const QString &after)
+
+ Use replaceInStrings() instead.
+*/
+
+/*!
+ \fn Iterator QStringList::fromLast()
+
+ Use end() instead.
+
+ \oldcode
+ QStringList::Iterator i = list.fromLast();
+ \newcode
+ QStringList::Iterator i = list.isEmpty() ? list.end() : --list.end();
+ \endcode
+*/
+
+/*!
+ \fn ConstIterator QStringList::fromLast() const
+
+ Use end() instead.
+
+ \oldcode
+ QStringList::ConstIterator i = list.fromLast();
+ \newcode
+ QStringList::ConstIterator i = list.isEmpty() ? list.end() : --list.end();
+ \endcode
+*/
+
+
+#ifndef QT_NO_REGEXP
+static int indexOfMutating(const QStringList *that, QRegExp &rx, int from)
+{
+ if (from < 0)
+ from = qMax(from + that->size(), 0);
+ for (int i = from; i < that->size(); ++i) {
+ if (rx.exactMatch(that->at(i)))
+ return i;
+ }
+ return -1;
+}
+
+static int lastIndexOfMutating(const QStringList *that, QRegExp &rx, int from)
+{
+ if (from < 0)
+ from += that->size();
+ else if (from >= that->size())
+ from = that->size() - 1;
+ for (int i = from; i >= 0; --i) {
+ if (rx.exactMatch(that->at(i)))
+ return i;
+ }
+ return -1;
+}
+
+/*!
+ \fn int QStringList::indexOf(const QRegExp &rx, int from) const
+
+ Returns the index position of the first exact match of \a rx in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ By default, this function is case sensitive.
+
+ \sa lastIndexOf(), contains(), QRegExp::exactMatch()
+*/
+int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegExp &rx, int from)
+{
+ QRegExp rx2(rx);
+ return indexOfMutating(that, rx2, from);
+}
+
+/*!
+ \fn int QStringList::indexOf(QRegExp &rx, int from) const
+ \overload indexOf()
+ \since 4.5
+
+ Returns the index position of the first exact match of \a rx in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ By default, this function is case sensitive.
+
+ If an item matched, the \a rx regular expression will contain the
+ matched objects (see QRegExp::matchedLength, QRegExp::cap).
+
+ \sa lastIndexOf(), contains(), QRegExp::exactMatch()
+*/
+int QtPrivate::QStringList_indexOf(const QStringList *that, QRegExp &rx, int from)
+{
+ return indexOfMutating(that, rx, from);
+}
+
+/*!
+ \fn int QStringList::lastIndexOf(const QRegExp &rx, int from) const
+
+ Returns the index position of the last exact match of \a rx 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.
+
+ By default, this function is case sensitive.
+
+ \sa indexOf(), contains(), QRegExp::exactMatch()
+*/
+int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegExp &rx, int from)
+{
+ QRegExp rx2(rx);
+ return lastIndexOfMutating(that, rx2, from);
+}
+
+/*!
+ \fn int QStringList::lastIndexOf(QRegExp &rx, int from) const
+ \overload lastIndexOf()
+ \since 4.5
+
+ Returns the index position of the last exact match of \a rx 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.
+
+ By default, this function is case sensitive.
+
+ If an item matched, the \a rx regular expression will contain the
+ matched objects (see QRegExp::matchedLength, QRegExp::cap).
+
+ \sa indexOf(), contains(), QRegExp::exactMatch()
+*/
+int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from)
+{
+ return lastIndexOfMutating(that, rx, from);
+}
+#endif
+
+/*!
+ \fn int QStringList::indexOf(const QString &value, int from = 0) const
+
+ Returns the index position of the first occurrence of \a value in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ \sa lastIndexOf(), contains(), QList::indexOf()
+*/
+
+/*!
+ \fn int QStringList::lastIndexOf(const QString &value, int from = -1) const
+
+ Returns the index position of the last occurrence of \a value 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.
+
+ By default, this function is case sensitive.
+
+ \sa indexOf(), QList::lastIndexOf()
+*/
+
+/*!
+ \fn int QStringList::removeDuplicates()
+
+ \since 4.5
+
+ This function removes duplicate entries from a list.
+ The entries do not have to be sorted. They will retain their
+ original order.
+
+ Returns the number of removed entries.
+*/
+int QtPrivate::QStringList_removeDuplicates(QStringList *that)
+{
+ int n = that->size();
+ int j = 0;
+ QSet<QString> seen;
+ seen.reserve(n);
+ for (int i = 0; i < n; ++i) {
+ const QString &s = that->at(i);
+ if (seen.contains(s))
+ continue;
+ seen.insert(s);
+ if (j != i)
+ (*that)[j] = s;
+ ++j;
+ }
+ if (n != j)
+ that->erase(that->begin() + j, that->end());
+ return n - j;
+}
+
+/*! \fn QStringList::QStringList(std::initializer_list<QString> args)
+ \since 4.8
+
+ Construct a list from a std::initilizer_list.
+
+ This constructor is only enabled if the compiler supports C++0x
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
new file mode 100644
index 0000000000..a0290bc265
--- /dev/null
+++ b/src/corelib/tools/qstringlist.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGLIST_H
+#define QSTRINGLIST_H
+
+#include <QtCore/qalgorithms.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qregexp.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringmatcher.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <Qt3Support/q3valuelist.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QRegExp;
+
+typedef QListIterator<QString> QStringListIterator;
+typedef QMutableListIterator<QString> QMutableStringListIterator;
+
+class QStringList : public QList<QString>
+{
+public:
+ inline QStringList() { }
+ inline explicit QStringList(const QString &i) { append(i); }
+ inline QStringList(const QStringList &l) : QList<QString>(l) { }
+ inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QStringList(std::initializer_list<QString> args) : QList(args) { }
+#endif
+
+ inline void sort();
+ inline int removeDuplicates();
+
+ inline QString join(const QString &sep) const;
+
+ inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline QBool contains(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 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; }
+
+#ifndef QT_NO_REGEXP
+ inline QStringList filter(const QRegExp &rx) const;
+ inline QStringList &replaceInStrings(const QRegExp &rx, const QString &after);
+ inline int indexOf(const QRegExp &rx, int from = 0) const;
+ inline int lastIndexOf(const QRegExp &rx, int from = -1) const;
+ inline int indexOf(QRegExp &rx, int from = 0) const;
+ inline int lastIndexOf(QRegExp &rx, int from = -1) const;
+#endif
+#if !defined(Q_NO_USING_KEYWORD)
+ using QList<QString>::indexOf;
+ using QList<QString>::lastIndexOf;
+#else
+ inline int indexOf(const QString &str, int from = 0) const
+ { return QList<QString>::indexOf(str, from); }
+ inline int lastIndexOf(const QString &str, int from = -1) const
+ { return QList<QString>::lastIndexOf(str, from); }
+#endif
+#ifdef QT3_SUPPORT
+ static inline QT3_SUPPORT QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries = false);
+ static inline QT3_SUPPORT QStringList split(const QChar &sep, const QString &str, bool allowEmptyEntries = false);
+ inline QT3_SUPPORT QStringList grep(const QString &str, bool cs = true) const
+ { return filter(str, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); }
+
+#ifndef QT_NO_REGEXP
+ static inline QT3_SUPPORT QStringList split(const QRegExp &sep, const QString &str, bool allowEmptyEntries = false);
+ inline QT3_SUPPORT QStringList grep(const QRegExp &rx) const { return filter(rx); }
+ inline QT3_SUPPORT QStringList &gres(const QRegExp &rx, const QString &after)
+ { return replaceInStrings(rx, after); }
+#endif
+ inline QT3_SUPPORT QStringList &gres(const QString &before, const QString &after, bool cs = true)
+ { return replaceInStrings(before, after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); }
+
+ inline Iterator QT3_SUPPORT fromLast() { return (isEmpty() ? end() : --end()); }
+ inline ConstIterator QT3_SUPPORT fromLast() const { return (isEmpty() ? end() : --end()); }
+#endif
+};
+
+namespace QtPrivate {
+ void Q_CORE_EXPORT QStringList_sort(QStringList *that);
+ int Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that);
+ QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QString &sep);
+ QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str,
+ Qt::CaseSensitivity cs);
+
+ QBool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs);
+ void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QString &before, const QString &after,
+ Qt::CaseSensitivity cs);
+
+#ifndef QT_NO_REGEXP
+ void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QRegExp &rx, const QString &after);
+ QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QRegExp &re);
+ int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegExp &rx, int from);
+ int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegExp &rx, int from);
+ int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, QRegExp &rx, int from);
+ int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from);
+#endif
+}
+
+inline void QStringList::sort()
+{
+ QtPrivate::QStringList_sort(this);
+}
+
+inline int QStringList::removeDuplicates()
+{
+ return QtPrivate::QStringList_removeDuplicates(this);
+}
+
+inline QString QStringList::join(const QString &sep) const
+{
+ return QtPrivate::QStringList_join(this, sep);
+}
+
+inline QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const
+{
+ return QtPrivate::QStringList_filter(this, str, cs);
+}
+
+inline QBool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
+{
+ return QtPrivate::QStringList_contains(this, str, cs);
+}
+
+inline QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
+{
+ QtPrivate::QStringList_replaceInStrings(this, before, after, cs);
+ return *this;
+}
+
+#ifndef QT_NO_REGEXP
+inline QStringList &QStringList::replaceInStrings(const QRegExp &rx, const QString &after)
+{
+ QtPrivate::QStringList_replaceInStrings(this, rx, after);
+ return *this;
+}
+
+inline QStringList QStringList::filter(const QRegExp &rx) const
+{
+ return QtPrivate::QStringList_filter(this, rx);
+}
+
+inline int QStringList::indexOf(const QRegExp &rx, int from) const
+{
+ return QtPrivate::QStringList_indexOf(this, rx, from);
+}
+
+inline int QStringList::lastIndexOf(const QRegExp &rx, int from) const
+{
+ return QtPrivate::QStringList_lastIndexOf(this, rx, from);
+}
+
+inline int QStringList::indexOf(QRegExp &rx, int from) const
+{
+ return QtPrivate::QStringList_indexOf(this, rx, from);
+}
+
+inline int QStringList::lastIndexOf(QRegExp &rx, int from) const
+{
+ return QtPrivate::QStringList_lastIndexOf(this, rx, from);
+}
+#endif
+
+
+#ifdef QT3_SUPPORT
+inline QStringList QStringList::split(const QChar &sep, const QString &str, bool allowEmptyEntries)
+{
+ if (str.isEmpty())
+ return QStringList();
+ return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts
+ : QString::SkipEmptyParts);
+}
+
+inline QStringList QStringList::split(const QString &sep, const QString &str, bool allowEmptyEntries)
+{
+ if (str.isEmpty())
+ return QStringList();
+ return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts
+ : QString::SkipEmptyParts);
+}
+
+#ifndef QT_NO_REGEXP
+inline QStringList QStringList::split(const QRegExp &sep, const QString &str, bool allowEmptyEntries)
+{
+ if (str.isEmpty())
+ return QStringList();
+ return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts
+ : QString::SkipEmptyParts);
+}
+#endif // QT_NO_REGEXP
+
+#endif // QT3_SUPPORT
+
+
+#ifndef QT_NO_DATASTREAM
+inline QDataStream &operator>>(QDataStream &in, QStringList &list)
+{
+ return operator>>(in, static_cast<QList<QString> &>(list));
+}
+inline QDataStream &operator<<(QDataStream &out, const QStringList &list)
+{
+ return operator<<(out, static_cast<const QList<QString> &>(list));
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTRINGLIST_H
diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp
new file mode 100644
index 0000000000..7533827a40
--- /dev/null
+++ b/src/corelib/tools/qstringmatcher.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringmatcher.h"
+
+QT_BEGIN_NAMESPACE
+
+static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs)
+{
+ int l = qMin(len, 255);
+ memset(skiptable, l, 256*sizeof(uchar));
+ uc += len - l;
+ if (cs == Qt::CaseSensitive) {
+ while (l--) {
+ skiptable[*uc & 0xff] = l;
+ uc++;
+ }
+ } else {
+ const ushort *start = uc;
+ while (l--) {
+ skiptable[foldCase(uc, start) & 0xff] = l;
+ uc++;
+ }
+ }
+}
+
+static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl,
+ const uchar *skiptable, Qt::CaseSensitivity cs)
+{
+ if (pl == 0)
+ return index > (int)l ? -1 : index;
+ const uint pl_minus_one = pl - 1;
+
+ register const ushort *current = uc + index + pl_minus_one;
+ const ushort *end = uc + l;
+ if (cs == Qt::CaseSensitive) {
+ while (current < end) {
+ uint skip = skiptable[*current & 0xff];
+ if (!skip) {
+ // possible match
+ while (skip < pl) {
+ if (*(current - skip) != puc[pl_minus_one-skip])
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) // we have a match
+ return (current - uc) - pl_minus_one;
+
+ // 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[*(current - skip) & 0xff] == pl)
+ skip = pl - skip;
+ else
+ skip = 1;
+ }
+ if (current > end - skip)
+ break;
+ current += skip;
+ }
+ } else {
+ while (current < end) {
+ uint 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))
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) // we have a match
+ return (current - uc) - pl_minus_one;
+ // 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;
+ else
+ skip = 1;
+ }
+ if (current > end - skip)
+ break;
+ current += skip;
+ }
+ }
+ return -1; // not found
+}
+
+/*!
+ \class QStringMatcher
+ \brief The QStringMatcher class holds a sequence of characters that
+ can be quickly matched in a Unicode string.
+
+ \ingroup tools
+ \ingroup string-processing
+
+ This class is useful when you have a sequence of \l{QChar}s that
+ you want to repeatedly match against some strings (perhaps in a
+ loop), or when you want to search for the same sequence of
+ characters multiple times in the same string. Using a matcher
+ object and indexIn() is faster than matching a plain QString with
+ QString::indexOf() if repeated matching takes place. This class
+ offers no benefit if you are doing one-off string matches.
+
+ Create the QStringMatcher with the QString you want to search
+ for. Then call indexIn() on the QString that you want to search.
+
+ \sa QString, QByteArrayMatcher, QRegExp
+*/
+
+/*!
+ Constructs an empty string matcher that won't match anything.
+ Call setPattern() to give it a pattern to match.
+*/
+QStringMatcher::QStringMatcher()
+ : d_ptr(0), q_cs(Qt::CaseSensitive)
+{
+ qMemSet(q_data, 0, sizeof(q_data));
+}
+
+/*!
+ Constructs a string matcher that will search for \a pattern, with
+ case sensitivity \a cs.
+
+ Call indexIn() to perform a search.
+*/
+QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs)
+ : d_ptr(0), q_pattern(pattern), q_cs(cs)
+{
+ p.uc = pattern.unicode();
+ p.len = pattern.size();
+ bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs);
+}
+
+/*!
+ \fn QStringMatcher::QStringMatcher(const QChar *uc, int 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)
+ : d_ptr(0), q_cs(cs)
+{
+ p.uc = uc;
+ p.len = len;
+ bm_init_skiptable((const ushort *)p.uc, len, p.q_skiptable, cs);
+}
+
+/*!
+ Copies the \a other string matcher to this string matcher.
+*/
+QStringMatcher::QStringMatcher(const QStringMatcher &other)
+ : d_ptr(0)
+{
+ operator=(other);
+}
+
+/*!
+ Destroys the string matcher.
+*/
+QStringMatcher::~QStringMatcher()
+{
+}
+
+/*!
+ Assigns the \a other string matcher to this string matcher.
+*/
+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));
+ }
+ return *this;
+}
+
+/*!
+ Sets the string that this string matcher will search for to \a
+ pattern.
+
+ \sa pattern(), setCaseSensitivity(), indexIn()
+*/
+void QStringMatcher::setPattern(const QString &pattern)
+{
+ q_pattern = pattern;
+ p.uc = pattern.unicode();
+ p.len = pattern.size();
+ bm_init_skiptable((const ushort *)pattern.unicode(), pattern.size(), p.q_skiptable, q_cs);
+}
+
+/*!
+ \fn QString QStringMatcher::pattern() const
+
+ Returns the string pattern that this string matcher will search
+ for.
+
+ \sa setPattern()
+*/
+
+QString QStringMatcher::pattern() const
+{
+ if (!q_pattern.isEmpty())
+ return q_pattern;
+ return QString(p.uc, p.len);
+}
+
+/*!
+ Sets the case sensitivity setting of this string matcher to \a
+ cs.
+
+ \sa caseSensitivity(), setPattern(), indexIn()
+*/
+void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs)
+{
+ if (cs == q_cs)
+ return;
+ bm_init_skiptable((const ushort *)q_pattern.unicode(), q_pattern.size(), p.q_skiptable, cs);
+ q_cs = cs;
+}
+
+/*!
+ 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
+ call to setPattern(). Returns the position where the pattern()
+ matched in \a str, or -1 if no match was found.
+
+ \sa setPattern(), setCaseSensitivity()
+*/
+int QStringMatcher::indexIn(const QString &str, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find((const ushort *)str.unicode(), str.size(), from,
+ (const ushort *)p.uc, p.len,
+ p.q_skiptable, q_cs);
+}
+
+/*!
+ \since 4.5
+
+ Searches the string starting at \a str (of length \a length) 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 call to setPattern(). Returns
+ the position where the pattern() matched in \a str, or -1 if no
+ match was found.
+
+ \sa setPattern(), setCaseSensitivity()
+*/
+int QStringMatcher::indexIn(const QChar *str, int length, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find((const ushort *)str, length, from,
+ (const ushort *)p.uc, p.len,
+ p.q_skiptable, q_cs);
+}
+
+/*!
+ \fn Qt::CaseSensitivity QStringMatcher::caseSensitivity() const
+
+ Returns the case sensitivity setting for this string matcher.
+
+ \sa setCaseSensitivity()
+*/
+
+/*!
+ \internal
+*/
+
+int qFindStringBoyerMoore(
+ const QChar *haystack, int haystackLen, int haystackOffset,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+{
+ uchar skiptable[256];
+ bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs);
+ if (haystackOffset < 0)
+ haystackOffset = 0;
+ return bm_find((const ushort *)haystack, haystackLen, haystackOffset,
+ (const ushort *)needle, needleLen, skiptable, cs);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h
new file mode 100644
index 0000000000..d72c5ca4ee
--- /dev/null
+++ b/src/corelib/tools/qstringmatcher.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGMATCHER_H
+#define QSTRINGMATCHER_H
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QStringMatcherPrivate;
+
+class Q_CORE_EXPORT QStringMatcher
+{
+public:
+ QStringMatcher();
+ QStringMatcher(const QString &pattern,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QStringMatcher(const QChar *uc, int len,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QStringMatcher(const QStringMatcher &other);
+ ~QStringMatcher();
+
+ QStringMatcher &operator=(const QStringMatcher &other);
+
+ 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;
+ QString pattern() const;
+ inline Qt::CaseSensitivity caseSensitivity() const { return q_cs; }
+
+private:
+ QStringMatcherPrivate *d_ptr;
+ QString q_pattern;
+ Qt::CaseSensitivity q_cs;
+#ifdef Q_CC_RVCT
+// explicitly allow anonymous unions for RVCT to prevent compiler warnings
+# pragma push
+# pragma anon_unions
+#endif
+ struct Data {
+ uchar q_skiptable[256];
+ const QChar *uc;
+ int len;
+ };
+ union {
+ uint q_data[256];
+ Data p;
+ };
+#ifdef Q_CC_RVCT
+# pragma pop
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTRINGMATCHER_H
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
new file mode 100644
index 0000000000..34bc406309
--- /dev/null
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/qtextboundaryfinder.h>
+#include <QtCore/qvarlengtharray.h>
+#include <private/qunicodetables_p.h>
+#include <qdebug.h>
+#include "private/qharfbuzz_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextBoundaryFinderPrivate
+{
+public:
+ HB_CharAttributes attributes[1];
+};
+
+static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, HB_CharAttributes *attributes)
+{
+ QVarLengthArray<HB_ScriptItem> scriptItems;
+
+ const ushort *string = reinterpret_cast<const ushort *>(chars);
+ const ushort *unicode = string;
+ // correctly assign script, isTab and isObject to the script analysis
+ const ushort *uc = unicode;
+ const ushort *e = uc + length;
+ int script = QUnicodeTables::Common;
+ int lastScript = QUnicodeTables::Common;
+ const ushort *start = uc;
+ while (uc < e) {
+ int s = QUnicodeTables::script(*uc);
+ if (s != QUnicodeTables::Inherited)
+ script = s;
+ if (*uc == QChar::ObjectReplacementCharacter || *uc == QChar::LineSeparator || *uc == 9)
+ script = QUnicodeTables::Common;
+ if (script != lastScript) {
+ if (uc != start) {
+ HB_ScriptItem item;
+ item.pos = start - string;
+ item.length = uc - start;
+ item.script = (HB_Script)lastScript;
+ item.bidiLevel = 0; // ### what's the proper value?
+ scriptItems.append(item);
+ start = uc;
+ }
+ lastScript = script;
+ }
+ ++uc;
+ }
+ if (uc != start) {
+ HB_ScriptItem item;
+ item.pos = start - string;
+ item.length = uc - start;
+ item.script = (HB_Script)lastScript;
+ item.bidiLevel = 0; // ### what's the proper value?
+ scriptItems.append(item);
+ }
+
+ qGetCharAttributes(string, length, scriptItems.data(), scriptItems.count(), attributes);
+ if (type == QTextBoundaryFinder::Word)
+ HB_GetWordBoundaries(string, length, scriptItems.data(), scriptItems.count(), attributes);
+ else if (type == QTextBoundaryFinder::Sentence)
+ HB_GetSentenceBoundaries(string, length, scriptItems.data(), scriptItems.count(), attributes);
+}
+
+/*!
+ \class QTextBoundaryFinder
+
+ \brief The QTextBoundaryFinder class provides a way of finding Unicode text boundaries in a string.
+
+ \since 4.4
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+ \reentrant
+
+ QTextBoundaryFinder allows to find Unicode text boundaries in a
+ string, similar to the Unicode text boundary specification (see
+ http://www.unicode.org/reports/tr29/tr29-11.html).
+
+ QTextBoundaryFinder can operate on a QString in four possible
+ modes depending on the value of \a BoundaryType.
+
+ Units of Unicode characters that make up what the user thinks of
+ as a character or basic unit of the language are here called
+ Grapheme clusters. The two unicode characters 'A' + diaeresis do
+ 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.
+
+ Word boundaries are there to locate the start and end of what a
+ language considers to be a word.
+
+ Line break boundaries give possible places where a line break
+ might happen and sentence boundaries will show the beginning and
+ end of whole sentences.
+
+ The first position in a string is always a valid boundary and
+ refers to the position before the first character. The last
+ position at the length of the string is also valid and refers
+ to the position after the last character.
+*/
+
+/*!
+ \enum QTextBoundaryFinder::BoundaryType
+
+ \value Grapheme Finds a grapheme which is the smallest boundary. It
+ including letters, punctation marks, numerals and more.
+ \value Word Finds a word.
+ \value Line Finds possible positions for breaking the text into multiple
+ lines.
+ \value Sentence Finds sentence boundaries. These include periods, question
+ marks etc.
+*/
+
+/*!
+ \enum QTextBoundaryFinder::BoundaryReason
+
+ \value NotAtBoundary The boundary finder is not at a boundary position.
+ \value StartWord The boundary finder is at the start of a word.
+ \value EndWord The boundary finder is at the end of a word.
+*/
+
+/*!
+ Constructs an invalid QTextBoundaryFinder object.
+*/
+QTextBoundaryFinder::QTextBoundaryFinder()
+ : t(Grapheme)
+ , chars(0)
+ , length(0)
+ , freePrivate(true)
+ , d(0)
+{
+}
+
+/*!
+ Copies the QTextBoundaryFinder object, \a other.
+*/
+QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other)
+ : t(other.t)
+ , s(other.s)
+ , chars(other.chars)
+ , length(other.length)
+ , pos(other.pos)
+ , freePrivate(true)
+{
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
+ memcpy(d, other.d, length*sizeof(HB_CharAttributes));
+}
+
+/*!
+ Assigns the object, \a other, to another QTextBoundaryFinder object.
+*/
+QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &other)
+{
+ if (&other == this)
+ return *this;
+
+ t = other.t;
+ s = other.s;
+ chars = other.chars;
+ length = other.length;
+ pos = other.pos;
+ freePrivate = true;
+
+ QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
+ realloc(d, length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(newD);
+ d = newD;
+ memcpy(d, other.d, length*sizeof(HB_CharAttributes));
+
+ return *this;
+}
+
+/*!
+ Destructs the QTextBoundaryFinder object.
+*/
+QTextBoundaryFinder::~QTextBoundaryFinder()
+{
+ if (freePrivate)
+ free(d);
+}
+
+/*!
+ Creates a QTextBoundaryFinder object of \a type operating on \a string.
+*/
+QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &string)
+ : t(type)
+ , s(string)
+ , chars(string.unicode())
+ , length(string.length())
+ , pos(0)
+ , freePrivate(true)
+{
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
+ init(t, chars, length, d->attributes);
+}
+
+/*!
+ Creates a QTextBoundaryFinder object of \a type operating on \a chars
+ with \a length.
+
+ \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, it will use this instead of allocating its own buffer.
+
+ \warning QTextBoundaryFinder does not create a copy of \a chars. 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)
+ : t(type)
+ , chars(chars)
+ , length(length)
+ , pos(0)
+{
+ if (buffer && (uint)bufferSize >= length*sizeof(HB_CharAttributes)) {
+ d = (QTextBoundaryFinderPrivate *)buffer;
+ freePrivate = false;
+ } else {
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
+ freePrivate = true;
+ }
+ init(t, chars, length, d->attributes);
+}
+
+/*!
+ Moves the finder to the start of the string. This is equivalent to setPosition(0).
+
+ \sa setPosition(), position()
+*/
+void QTextBoundaryFinder::toStart()
+{
+ pos = 0;
+}
+
+/*!
+ Moves the finder to the end of the string. This is equivalent to setPosition(string.length()).
+
+ \sa setPosition(), position()
+*/
+void QTextBoundaryFinder::toEnd()
+{
+ pos = length;
+}
+
+/*!
+ Returns the current position of the QTextBoundaryFinder.
+
+ The range is from 0 (the beginning of the string) to the length of
+ the string inclusive.
+
+ \sa setPosition()
+*/
+int QTextBoundaryFinder::position() const
+{
+ return pos;
+}
+
+/*!
+ Sets the current position of the QTextBoundaryFinder to \a position.
+
+ If \a position is out of bounds, it will be bound to only valid
+ positions. In this case, valid positions are from 0 to the length of
+ the string inclusive.
+
+ \sa position()
+*/
+void QTextBoundaryFinder::setPosition(int position)
+{
+ pos = qBound(0, position, length);
+}
+
+/*! \fn QTextBoundaryFinder::BoundaryType QTextBoundaryFinder::type() const
+
+ Returns the type of the QTextBoundaryFinder.
+*/
+
+/*! \fn bool QTextBoundaryFinder::isValid() const
+
+ Returns true if the text boundary finder is valid; otherwise returns false.
+ A default QTextBoundaryFinder is invalid.
+*/
+
+/*!
+ Returns the string the QTextBoundaryFinder object operates on.
+*/
+QString QTextBoundaryFinder::string() const
+{
+ if (chars == s.unicode() && length == s.length())
+ return s;
+ return QString(chars, length);
+}
+
+
+/*!
+ Moves the QTextBoundaryFinder to the next boundary position and returns that position.
+
+ Returns -1 if there is no next boundary.
+*/
+int QTextBoundaryFinder::toNextBoundary()
+{
+ if (!d) {
+ pos = -1;
+ return pos;
+ }
+
+ if (pos < 0 || pos >= length) {
+ pos = -1;
+ return pos;
+ }
+ ++pos;
+ if (pos == length)
+ return pos;
+
+ switch(t) {
+ case Grapheme:
+ while (pos < length && !d->attributes[pos].charStop)
+ ++pos;
+ break;
+ case Word:
+ while (pos < length && !d->attributes[pos].wordBoundary)
+ ++pos;
+ break;
+ case Sentence:
+ while (pos < length && !d->attributes[pos].sentenceBoundary)
+ ++pos;
+ break;
+ case Line:
+ Q_ASSERT(pos);
+ while (pos < length && d->attributes[pos-1].lineBreakType < HB_Break)
+ ++pos;
+ break;
+ }
+
+ return pos;
+}
+
+/*!
+ Moves the QTextBoundaryFinder to the previous boundary position and returns that position.
+
+ Returns -1 if there is no previous boundary.
+*/
+int QTextBoundaryFinder::toPreviousBoundary()
+{
+ if (!d) {
+ pos = -1;
+ return pos;
+ }
+
+ if (pos <= 0 || pos > length) {
+ pos = -1;
+ return pos;
+ }
+ --pos;
+ if (pos == 0)
+ return pos;
+
+ switch(t) {
+ case Grapheme:
+ while (pos > 0 && !d->attributes[pos].charStop)
+ --pos;
+ break;
+ case Word:
+ while (pos > 0 && !d->attributes[pos].wordBoundary)
+ --pos;
+ break;
+ case Sentence:
+ while (pos > 0 && !d->attributes[pos].sentenceBoundary)
+ --pos;
+ break;
+ case Line:
+ while (pos > 0 && d->attributes[pos-1].lineBreakType < HB_Break)
+ --pos;
+ break;
+ }
+
+ return pos;
+}
+
+/*!
+ Returns true if the object's position() is currently at a valid text boundary.
+*/
+bool QTextBoundaryFinder::isAtBoundary() const
+{
+ if (!d || pos < 0)
+ return false;
+
+ if (pos == length)
+ return true;
+
+ switch(t) {
+ case Grapheme:
+ return d->attributes[pos].charStop;
+ case Word:
+ return d->attributes[pos].wordBoundary;
+ case Line:
+ return (pos > 0) ? d->attributes[pos-1].lineBreakType >= HB_Break : true;
+ case Sentence:
+ return d->attributes[pos].sentenceBoundary;
+ }
+ return false;
+}
+
+/*!
+ Returns the reasons for the boundary finder to have chosen the current position as a boundary.
+*/
+QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() const
+{
+ if (!d)
+ return NotAtBoundary;
+ if (! isAtBoundary())
+ return NotAtBoundary;
+ if (pos == 0) {
+ if (d->attributes[pos].whiteSpace)
+ return NotAtBoundary;
+ return StartWord;
+ }
+ if (pos == length) {
+ if (d->attributes[length-1].whiteSpace)
+ return NotAtBoundary;
+ return EndWord;
+ }
+
+ const bool nextIsSpace = d->attributes[pos].whiteSpace;
+ const bool prevIsSpace = d->attributes[pos - 1].whiteSpace;
+
+ if (prevIsSpace && !nextIsSpace)
+ return StartWord;
+ else if (!prevIsSpace && nextIsSpace)
+ return EndWord;
+ else if (!prevIsSpace && !nextIsSpace)
+ return BoundaryReasons(StartWord | EndWord);
+ else
+ return NotAtBoundary;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qtextboundaryfinder.h b/src/corelib/tools/qtextboundaryfinder.h
new file mode 100644
index 0000000000..3833b9d267
--- /dev/null
+++ b/src/corelib/tools/qtextboundaryfinder.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTBOUNDARYFINDER_H
+#define QTEXTBOUNDARYFINDER_H
+
+#include <QtCore/qchar.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QTextBoundaryFinderPrivate;
+
+class Q_CORE_EXPORT QTextBoundaryFinder
+{
+public:
+ QTextBoundaryFinder();
+ QTextBoundaryFinder(const QTextBoundaryFinder &other);
+ QTextBoundaryFinder &operator=(const QTextBoundaryFinder &other);
+ ~QTextBoundaryFinder();
+
+ enum BoundaryType {
+ Grapheme,
+ Word,
+ Line,
+ Sentence
+ };
+
+ enum BoundaryReason {
+ NotAtBoundary = 0,
+ StartWord = 1,
+ EndWord = 2
+ //Hyphen
+ };
+ Q_DECLARE_FLAGS( BoundaryReasons, BoundaryReason )
+
+ QTextBoundaryFinder(BoundaryType type, const QString &string);
+ QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer = 0, int bufferSize = 0);
+
+ inline bool isValid() const { return d; }
+
+ inline BoundaryType type() const { return t; }
+ QString string() const;
+
+ void toStart();
+ void toEnd();
+ int position() const;
+ void setPosition(int position);
+
+ int toNextBoundary();
+ int toPreviousBoundary();
+
+ bool isAtBoundary() const;
+ BoundaryReasons boundaryReasons() const;
+
+private:
+ BoundaryType t;
+ QString s;
+ const QChar *chars;
+ int length;
+ int pos;
+ uint freePrivate : 1;
+ uint unused : 31;
+ QTextBoundaryFinderPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
new file mode 100644
index 0000000000..b6c3897903
--- /dev/null
+++ b/src/corelib/tools/qtimeline.cpp
@@ -0,0 +1,787 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtimeline.h"
+
+#include <private/qobject_p.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qelapsedtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTimeLinePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QTimeLine)
+public:
+ inline QTimeLinePrivate()
+ : startTime(0), duration(1000), startFrame(0), endFrame(0),
+ updateInterval(1000 / 25),
+ totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
+ direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
+ state(QTimeLine::NotRunning)
+ { }
+
+ int startTime;
+ int duration;
+ int startFrame;
+ int endFrame;
+ int updateInterval;
+ int totalLoopCount;
+ int currentLoopCount;
+
+ int currentTime;
+ int timerId;
+ QElapsedTimer timer;
+
+ QTimeLine::Direction direction;
+ QEasingCurve easingCurve;
+ QTimeLine::State state;
+ inline void setState(QTimeLine::State newState)
+ {
+ Q_Q(QTimeLine);
+ if (newState != state)
+ emit q->stateChanged(state = newState);
+ }
+
+ void setCurrentTime(int msecs);
+};
+
+/*!
+ \internal
+*/
+void QTimeLinePrivate::setCurrentTime(int msecs)
+{
+ Q_Q(QTimeLine);
+
+ qreal lastValue = q->currentValue();
+ int lastFrame = q->currentFrame();
+
+ // Determine if we are looping.
+ int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
+ int loopCount = elapsed / duration;
+
+ bool looping = (loopCount != currentLoopCount);
+#ifdef QTIMELINE_DEBUG
+ qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
+ << "currentLoopCount" << currentLoopCount
+ << "looping" << looping;
+#endif
+ if (looping)
+ currentLoopCount = loopCount;
+
+ // Normalize msecs to be between 0 and duration, inclusive.
+ currentTime = elapsed % duration;
+ if (direction == QTimeLine::Backward)
+ currentTime = duration - currentTime;
+
+ // Check if we have reached the end of loopcount.
+ bool finished = false;
+ if (totalLoopCount && currentLoopCount >= totalLoopCount) {
+ finished = true;
+ currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
+ currentLoopCount = totalLoopCount - 1;
+ }
+
+ int currentFrame = q->frameForTime(currentTime);
+#ifdef QTIMELINE_DEBUG
+ qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
+#endif
+ if (!qFuzzyCompare(lastValue, q->currentValue()))
+ emit q->valueChanged(q->currentValue());
+ if (lastFrame != currentFrame) {
+ const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
+ if (looping && !finished && transitionframe != currentFrame) {
+#ifdef QTIMELINE_DEBUG
+ qDebug() << "QTimeLinePrivate::setCurrentTime: transitionframe";
+#endif
+ emit q->frameChanged(transitionframe);
+ }
+#ifdef QTIMELINE_DEBUG
+ else {
+ QByteArray reason;
+ if (!looping)
+ reason += " not looping";
+ if (finished) {
+ if (!reason.isEmpty())
+ reason += " and";
+ reason += " finished";
+ }
+ if (transitionframe == currentFrame) {
+ if (!reason.isEmpty())
+ reason += " and";
+ reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame);
+ }
+ qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s", reason.constData());
+ }
+#endif
+ emit q->frameChanged(currentFrame);
+ }
+ if (finished && state == QTimeLine::Running) {
+ q->stop();
+ emit q->finished();
+ }
+}
+
+/*!
+ \class QTimeLine
+ \brief The QTimeLine class provides a timeline for controlling animations.
+ \since 4.2
+ \ingroup animation
+
+ It's most commonly used to animate a GUI control by calling a slot
+ periodically. You can construct a timeline by passing its duration in
+ milliseconds to QTimeLine's constructor. The timeline's duration describes
+ for how long the animation will run. Then you set a suitable frame range
+ by calling setFrameRange(). Finally connect the frameChanged() signal to a
+ suitable slot in the widget you wish to animate (e.g., setValue() in
+ QProgressBar). When you proceed to calling start(), QTimeLine will enter
+ Running state, and start emitting frameChanged() at regular intervals,
+ causing your widget's connected property's value to grow from the lower
+ end to the upper and of your frame range, at a steady rate. You can
+ specify the update interval by calling setUpdateInterval(). When done,
+ QTimeLine enters NotRunning state, and emits finished().
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qtimeline.cpp 0
+
+ You can also use QTimeLine with the
+ \l{Graphics View}{Graphics View framework} for
+ animations. The QGraphicsItemAnimation class implements animation
+ of \l{QGraphicsItem}{QGraphicsItems} with a timeline.
+
+ By default the timeline runs once, from the beginning and towards the 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
+ changed, causing the timeline to run backward, by calling
+ 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
+ called at any time.
+
+ The frame interface is useful for standard widgets, but QTimeLine can be
+ used to control any type of animation. The heart of QTimeLine lies in the
+ valueForTime() function, which generates a \e value between 0 and 1 for a
+ given time. This value is typically used to describe the steps of an
+ animation, where 0 is the first step of an animation, and 1 is the last
+ 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().
+
+ 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.
+
+ \sa QProgressBar, QProgressDialog, QGraphicsItemAnimation
+*/
+
+/*!
+ \enum QTimeLine::State
+
+ This enum describes the state of the timeline.
+
+ \value NotRunning The timeline is not running. This is the initial state
+ of QTimeLine, and the state QTimeLine reenters when finished. The current
+ time, frame and value remain unchanged until either setCurrentTime() is
+ called, or the timeline is started by calling start().
+
+ \value Paused The timeline is paused (i.e., temporarily
+ suspended). Calling setPaused(false) will resume timeline activity.
+
+ \value Running The timeline is running. While control is in the event
+ loop, QTimeLine will update its current time at regular intervals,
+ emitting valueChanged() and frameChanged() when appropriate.
+
+ \sa state(), stateChanged()
+*/
+
+/*!
+ \enum QTimeLine::Direction
+
+ This enum describes the direction of the timeline when in \l Running state.
+
+ \value Forward The current time of the timeline increases with time (i.e.,
+ moves from 0 and towards the end / duration).
+
+ \value Backward The current time of the timeline decreases with time (i.e.,
+ moves from the end / duration and towards 0).
+
+ \sa setDirection()
+*/
+
+/*!
+ \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 QTimeLine::valueChanged(qreal value)
+
+ QTimeLine emits this signal at regular intervals when in \l Running state,
+ but only if the current value changes. \a value is the current value. \a value is
+ a number between 0.0 and 1.0
+
+ \sa QTimeLine::setDuration(), QTimeLine::valueForTime(), QTimeLine::updateInterval
+*/
+
+/*!
+ \fn QTimeLine::frameChanged(int frame)
+
+ QTimeLine emits this signal at regular intervals when in \l Running state,
+ but only if the current frame changes. \a frame is the current frame number.
+
+ \sa QTimeLine::setFrameRange(), QTimeLine::updateInterval
+*/
+
+/*!
+ \fn QTimeLine::stateChanged(QTimeLine::State newState)
+
+ This signal is emitted whenever QTimeLine's state changes. The new state
+ is \a newState.
+*/
+
+/*!
+ \fn QTimeLine::finished()
+
+ This signal is emitted when QTimeLine finishes (i.e., reaches the end of
+ its time line), and does not loop.
+*/
+
+/*!
+ Constructs a timeline with a duration of \a duration milliseconds. \a
+ parent is passed to QObject's constructor. The default duration is 1000
+ milliseconds.
+ */
+QTimeLine::QTimeLine(int duration, QObject *parent)
+ : QObject(*new QTimeLinePrivate, parent)
+{
+ setDuration(duration);
+}
+
+/*!
+ Destroys the timeline.
+ */
+QTimeLine::~QTimeLine()
+{
+ Q_D(QTimeLine);
+
+ if (d->state == Running)
+ stop();
+}
+
+/*!
+ Returns the state of the timeline.
+
+ \sa start(), setPaused(), stop()
+*/
+QTimeLine::State QTimeLine::state() const
+{
+ Q_D(const QTimeLine);
+ return d->state;
+}
+
+/*!
+ \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.
+
+ By default, this property contains a value of 1.
+*/
+int QTimeLine::loopCount() const
+{
+ Q_D(const QTimeLine);
+ return d->totalLoopCount;
+}
+void QTimeLine::setLoopCount(int count)
+{
+ Q_D(QTimeLine);
+ d->totalLoopCount = count;
+}
+
+/*!
+ \property QTimeLine::direction
+ \brief the direction of the timeline when QTimeLine is in \l Running
+ state.
+
+ This direction indicates whether the time moves from 0 towards the
+ timeline duration, or from the value of the duration and towards 0 after
+ start() has been called.
+
+ By default, this property is set to \l Forward.
+*/
+QTimeLine::Direction QTimeLine::direction() const
+{
+ Q_D(const QTimeLine);
+ return d->direction;
+}
+void QTimeLine::setDirection(Direction direction)
+{
+ Q_D(QTimeLine);
+ d->direction = direction;
+ d->startTime = d->currentTime;
+ d->timer.start();
+}
+
+/*!
+ \property QTimeLine::duration
+ \brief the total duration of the timeline in milliseconds.
+
+ By default, this value is 1000 (i.e., 1 second), but you can change this
+ by either passing a duration to QTimeLine's constructor, or by calling
+ setDuration(). The duration must be larger than 0.
+
+ \note Changing the duration does not cause the current time to be reset
+ to zero or the new duration. You also need to call setCurrentTime() with
+ the desired value.
+*/
+int QTimeLine::duration() const
+{
+ Q_D(const QTimeLine);
+ return d->duration;
+}
+void QTimeLine::setDuration(int duration)
+{
+ Q_D(QTimeLine);
+ if (duration <= 0) {
+ qWarning("QTimeLine::setDuration: cannot set duration <= 0");
+ return;
+ }
+ d->duration = duration;
+}
+
+/*!
+ Returns the start frame, which is the frame corresponding to the start of
+ the timeline (i.e., the frame for which the current value is 0).
+
+ \sa setStartFrame(), setFrameRange()
+*/
+int QTimeLine::startFrame() const
+{
+ Q_D(const QTimeLine);
+ return d->startFrame;
+}
+
+/*!
+ Sets the start frame, which is the frame corresponding to the start of the
+ timeline (i.e., the frame for which the current value is 0), to \a frame.
+
+ \sa startFrame(), endFrame(), setFrameRange()
+*/
+void QTimeLine::setStartFrame(int frame)
+{
+ Q_D(QTimeLine);
+ d->startFrame = frame;
+}
+
+/*!
+ Returns the end frame, which is the frame corresponding to the end of the
+ timeline (i.e., the frame for which the current value is 1).
+
+ \sa setEndFrame(), setFrameRange()
+*/
+int QTimeLine::endFrame() const
+{
+ Q_D(const QTimeLine);
+ return d->endFrame;
+}
+
+/*!
+ Sets the end frame, which is the frame corresponding to the end of the
+ timeline (i.e., the frame for which the current value is 1), to \a frame.
+
+ \sa endFrame(), startFrame(), setFrameRange()
+*/
+void QTimeLine::setEndFrame(int frame)
+{
+ Q_D(QTimeLine);
+ d->endFrame = frame;
+}
+
+/*!
+ Sets the timeline's frame counter to start at \a startFrame, and end and
+ \a endFrame. For each time value, QTimeLine will find the corresponding
+ frame when you call currentFrame() or frameForTime() by interpolating,
+ using the return value of valueForTime().
+
+ When in Running state, QTimeLine also emits the frameChanged() signal when
+ the frame changes.
+
+ \sa startFrame(), endFrame(), start(), currentFrame()
+*/
+void QTimeLine::setFrameRange(int startFrame, int endFrame)
+{
+ Q_D(QTimeLine);
+ d->startFrame = startFrame;
+ d->endFrame = endFrame;
+}
+
+/*!
+ \property QTimeLine::updateInterval
+ \brief the time in milliseconds between each time QTimeLine updates its
+ current time.
+
+ When updating the current time, QTimeLine will emit valueChanged() if the
+ current value changed, and frameChanged() if the frame changed.
+
+ By default, the interval is 40 ms, which corresponds to a rate of 25
+ updates per second.
+*/
+int QTimeLine::updateInterval() const
+{
+ Q_D(const QTimeLine);
+ return d->updateInterval;
+}
+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;
+}
+
+void QTimeLine::setCurveShape(CurveShape shape)
+{
+ switch (shape) {
+ default:
+ case EaseInOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InOutSine));
+ break;
+ case EaseInCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InCurve));
+ break;
+ case EaseOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
+ break;
+ case LinearCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::Linear));
+ break;
+ case SineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::SineCurve));
+ break;
+ case CosineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
+ break;
+ }
+}
+
+/*!
+ \property QTimeLine::easingCurve
+
+ \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)
+*/
+
+QEasingCurve QTimeLine::easingCurve() const
+{
+ Q_D(const QTimeLine);
+ return d->easingCurve;
+}
+
+void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+{
+ Q_D(QTimeLine);
+ d->easingCurve = curve;
+}
+
+/*!
+ \property QTimeLine::currentTime
+ \brief the current time of the time line.
+
+ When QTimeLine is in Running state, this value is updated continuously as
+ a function of the duration and direction of the timeline. Otherwise, it is
+ value that was current when stop() was called last, or the value set by
+ setCurrentTime().
+
+ By default, this property contains a value of 0.
+*/
+int QTimeLine::currentTime() const
+{
+ Q_D(const QTimeLine);
+ return d->currentTime;
+}
+void QTimeLine::setCurrentTime(int msec)
+{
+ Q_D(QTimeLine);
+ d->startTime = 0;
+ d->currentLoopCount = 0;
+ d->timer.restart();
+ d->setCurrentTime(msec);
+}
+
+/*!
+ Returns the frame corresponding to the current time.
+
+ \sa currentTime(), frameForTime(), setFrameRange()
+*/
+int QTimeLine::currentFrame() const
+{
+ Q_D(const QTimeLine);
+ return frameForTime(d->currentTime);
+}
+
+/*!
+ Returns the value corresponding to the current time.
+
+ \sa valueForTime(), currentFrame()
+*/
+qreal QTimeLine::currentValue() const
+{
+ Q_D(const QTimeLine);
+ return valueForTime(d->currentTime);
+}
+
+/*!
+ Returns the frame corresponding to the time \a msec. This value is
+ calculated using a linear interpolation of the start and end frame, based
+ on the value returned by valueForTime().
+
+ \sa valueForTime(), setFrameRange()
+*/
+int QTimeLine::frameForTime(int msec) const
+{
+ Q_D(const QTimeLine);
+ if (d->direction == Forward)
+ return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec));
+ return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec));
+}
+
+/*!
+ Returns the timeline value for the time \a msec. The returned value, which
+ varies depending on the curve shape, is always between 0 and 1. If \a msec
+ is 0, the default implementation always returns 0.
+
+ Reimplement this function to provide a custom curve shape for your
+ timeline.
+
+ \sa CurveShape, frameForTime()
+*/
+qreal QTimeLine::valueForTime(int msec) const
+{
+ Q_D(const QTimeLine);
+ msec = qMin(qMax(msec, 0), d->duration);
+
+ qreal value = msec / qreal(d->duration);
+ return d->easingCurve.valueForProgress(value);
+}
+
+/*!
+ Starts the timeline. QTimeLine will enter Running state, and once it
+ enters the event loop, it will update its current time, frame and value at
+ regular intervals. The default interval is 40 ms (i.e., 25 times per
+ second). You can change the update interval by calling
+ setUpdateInterval().
+
+ The timeline will start from position 0, or the end if going backward.
+ If you want to resume a stopped timeline without restarting, you can call
+ resume() instead.
+
+ \sa resume(), updateInterval(), frameChanged(), valueChanged()
+*/
+void QTimeLine::start()
+{
+ Q_D(QTimeLine);
+ if (d->timerId) {
+ qWarning("QTimeLine::start: already running");
+ return;
+ }
+ int curTime = 0;
+ if (d->direction == Backward)
+ curTime = d->duration;
+ d->timerId = startTimer(d->updateInterval);
+ d->startTime = curTime;
+ d->currentLoopCount = 0;
+ d->timer.start();
+ d->setState(Running);
+ d->setCurrentTime(curTime);
+}
+
+/*!
+ Resumes the timeline from the current time. QTimeLine will reenter Running
+ state, and once it enters the event loop, it will update its current time,
+ frame and value at regular intervals.
+
+ In contrast to start(), this function does not restart the timeline before
+ it resumes.
+
+ \sa start(), updateInterval(), frameChanged(), valueChanged()
+*/
+void QTimeLine::resume()
+{
+ Q_D(QTimeLine);
+ if (d->timerId) {
+ qWarning("QTimeLine::resume: already running");
+ return;
+ }
+ d->timerId = startTimer(d->updateInterval);
+ d->startTime = d->currentTime;
+ d->timer.start();
+ d->setState(Running);
+}
+
+/*!
+ Stops the timeline, causing QTimeLine to enter NotRunning state.
+
+ \sa start()
+*/
+void QTimeLine::stop()
+{
+ Q_D(QTimeLine);
+ if (d->timerId)
+ killTimer(d->timerId);
+ d->setState(NotRunning);
+ d->timerId = 0;
+}
+
+/*!
+ If \a paused is true, the timeline is paused, causing QTimeLine to enter
+ Paused state. No updates will be signaled until either start() or
+ setPaused(false) is called. If \a paused is false, the timeline is resumed
+ and continues where it left.
+
+ \sa state(), start()
+*/
+void QTimeLine::setPaused(bool paused)
+{
+ Q_D(QTimeLine);
+ if (d->state == NotRunning) {
+ qWarning("QTimeLine::setPaused: Not running");
+ return;
+ }
+ if (paused && d->state != Paused) {
+ d->startTime = d->currentTime;
+ killTimer(d->timerId);
+ d->timerId = 0;
+ d->setState(Paused);
+ } else if (!paused && d->state == Paused) {
+ d->timerId = startTimer(d->updateInterval);
+ d->setState(Running);
+ }
+}
+
+/*!
+ Toggles the direction of the timeline. If the direction was Forward, it
+ becomes Backward, and vice verca.
+
+ \sa setDirection()
+*/
+void QTimeLine::toggleDirection()
+{
+ Q_D(QTimeLine);
+ setDirection(d->direction == Forward ? Backward : Forward);
+}
+
+/*!
+ \reimp
+*/
+void QTimeLine::timerEvent(QTimerEvent *event)
+{
+ Q_D(QTimeLine);
+ if (event->timerId() != d->timerId) {
+ event->ignore();
+ return;
+ }
+ event->accept();
+
+ if (d->direction == Forward) {
+ d->setCurrentTime(d->startTime + d->timer.elapsed());
+ } else {
+ d->setCurrentTime(d->startTime - d->timer.elapsed());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
new file mode 100644
index 0000000000..df65c9d163
--- /dev/null
+++ b/src/corelib/tools/qtimeline.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTIMELINE_H
+#define QTIMELINE_H
+
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+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)
+public:
+ enum State {
+ NotRunning,
+ Paused,
+ Running
+ };
+ enum Direction {
+ Forward,
+ Backward
+ };
+ enum CurveShape {
+ EaseInCurve,
+ EaseOutCurve,
+ EaseInOutCurve,
+ LinearCurve,
+ SineCurve,
+ CosineCurve
+ };
+
+ explicit QTimeLine(int duration = 1000, QObject *parent = 0);
+ virtual ~QTimeLine();
+
+ State state() const;
+
+ int loopCount() const;
+ void setLoopCount(int count);
+
+ Direction direction() const;
+ void setDirection(Direction direction);
+
+ int duration() const;
+ void setDuration(int duration);
+
+ int startFrame() const;
+ void setStartFrame(int frame);
+ int endFrame() const;
+ void setEndFrame(int frame);
+ void setFrameRange(int startFrame, int endFrame);
+
+ int updateInterval() const;
+ void setUpdateInterval(int interval);
+
+ CurveShape curveShape() const;
+ void setCurveShape(CurveShape shape);
+
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &curve);
+
+ int currentTime() const;
+ int currentFrame() const;
+ qreal currentValue() const;
+
+ int frameForTime(int msec) const;
+ virtual qreal valueForTime(int msec) const;
+
+public Q_SLOTS:
+ void start();
+ void resume();
+ void stop();
+ void setPaused(bool paused);
+ void setCurrentTime(int msec);
+ void toggleDirection();
+
+Q_SIGNALS:
+ void valueChanged(qreal x);
+ void frameChanged(int);
+ void stateChanged(QTimeLine::State newState);
+ void finished();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ Q_DISABLE_COPY(QTimeLine)
+ Q_DECLARE_PRIVATE(QTimeLine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
new file mode 100644
index 0000000000..e6ab6d2077
--- /dev/null
+++ b/src/corelib/tools/qtools_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTOOLS_P_H
+#define QTOOLS_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/qglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+// implemented in qbytearray.cpp
+int Q_CORE_EXPORT qAllocMore(int alloc, int extra);
+
+QT_END_NAMESPACE
+
+#endif // QTOOLS_P_H
diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp
new file mode 100644
index 0000000000..f532d80a8f
--- /dev/null
+++ b/src/corelib/tools/qunicodetables.cpp
@@ -0,0 +1,9486 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* This file is autogenerated from the Unicode 5.0 database. Do not edit */
+
+QT_BEGIN_NAMESPACE
+
+static const unsigned short uc_property_trie[] = {
+ // 0 - 0x11000
+
+ 6256, 6288, 6320, 6352, 6384, 6416, 6448, 6480,
+ 6512, 6544, 6576, 6608, 6640, 6672, 6704, 6736,
+ 6768, 6800, 6832, 6864, 6896, 6928, 6960, 6992,
+ 7024, 7056, 7088, 7120, 7152, 7184, 7216, 7248,
+ 7280, 7312, 7344, 6512, 7376, 6512, 7408, 7440,
+ 7472, 7504, 7536, 7568, 7600, 7632, 7664, 7696,
+ 7728, 7760, 7792, 7824, 7856, 7888, 7920, 7952,
+ 7984, 8016, 8048, 8080, 8112, 8144, 8176, 8208,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 8272, 8304, 8336, 8368, 8400, 8432, 8464, 8496,
+ 8528, 8560, 8592, 8624, 8656, 8688, 8720, 8752,
+ 8400, 8784, 8816, 8848, 8880, 8912, 8944, 8976,
+ 9008, 9040, 9072, 9104, 9136, 9168, 9200, 9232,
+ 9136, 9264, 9296, 9104, 9328, 9360, 9392, 9424,
+ 9456, 9488, 9520, 9552, 9584, 9616, 9648, 9552,
+ 9680, 9712, 9744, 9776, 9808, 9840, 9872, 9552,
+
+ 9904, 9936, 9968, 9552, 9552, 10000, 10032, 10064,
+ 10096, 10096, 10128, 10160, 10160, 10192, 10224, 10256,
+ 10288, 10320, 10352, 10320, 10384, 10416, 10448, 10480,
+ 10512, 10320, 10544, 10576, 10608, 10320, 10320, 10640,
+ 10672, 10320, 10320, 10320, 10320, 10320, 10320, 10320,
+ 10320, 10320, 10320, 10320, 10320, 10320, 10320, 10320,
+ 10320, 10320, 10320, 10704, 10736, 10320, 10320, 10768,
+ 10800, 10832, 10864, 10896, 9904, 10928, 10960, 10992,
+ 11024, 10320, 11056, 11088, 10320, 11120, 9552, 9552,
+ 11152, 11184, 11216, 11248, 11280, 11312, 11344, 11376,
+ 11408, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 11440, 11472, 11504, 11536, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 11568, 11600, 11632, 11664, 11696, 11728, 11760, 11792,
+ 6512, 6512, 6512, 6512, 11824, 6512, 6512, 11856,
+ 11888, 11920, 11952, 11984, 12016, 12048, 12080, 12112,
+
+ 12144, 12176, 12208, 12240, 12272, 12304, 12336, 12368,
+ 12400, 12432, 12464, 12496, 12528, 12560, 12592, 12624,
+ 12656, 12688, 12720, 12752, 12784, 12816, 12848, 12880,
+ 12912, 12944, 12976, 13008, 13040, 13072, 13104, 13136,
+ 13168, 13200, 13232, 13264, 13296, 13328, 13360, 13392,
+ 13168, 13168, 13168, 13168, 13424, 13456, 13488, 13520,
+ 13552, 13168, 13168, 13584, 13616, 13648, 9552, 9552,
+ 13680, 13712, 13744, 13776, 13808, 13840, 13872, 13904,
+ 13936, 13936, 13936, 13936, 13936, 13936, 13936, 13936,
+ 13968, 13968, 13968, 13968, 14000, 14032, 14064, 14096,
+ 13968, 14128, 13968, 14160, 14192, 14224, 14256, 14288,
+ 14320, 14352, 9552, 9552, 9552, 9552, 9552, 9552,
+ 14384, 14416, 14448, 14480, 14512, 14512, 14512, 14544,
+ 14576, 14608, 14640, 14672, 14704, 14736, 14736, 9552,
+ 14768, 9552, 9552, 9552, 14800, 14832, 14832, 14864,
+ 14832, 14832, 14832, 14832, 14832, 14832, 14896, 14928,
+
+ 14960, 14992, 15024, 15056, 15088, 15120, 15152, 15184,
+ 15216, 15248, 15280, 15280, 15312, 15344, 15376, 15408,
+ 15440, 15472, 15504, 15536, 15472, 15568, 15600, 15632,
+ 15664, 15664, 15664, 15696, 15664, 15664, 15728, 15760,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792,
+ 15792, 15792, 15792, 15792, 15792, 15824, 11376, 11376,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 15856, 15856, 15856, 15856, 15888, 9552, 9552,
+
+ 15920, 15952, 15952, 15952, 15952, 15952, 15952, 15952,
+ 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952,
+ 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952,
+ 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952,
+ 15952, 15952, 15952, 15952, 15984, 16016, 16048, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 16080, 16112, 9552, 9552, 9552, 9552, 9552, 9552,
+ 16144, 16176, 16208, 16240, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+
+ 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304,
+ 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336,
+ 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368,
+ 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400,
+ 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432,
+ 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464,
+ 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272,
+ 16304, 16336, 16368, 16400, 16432, 16496, 9552, 9552,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+ 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528,
+
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560,
+ 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856,
+ 15856, 16592, 16624, 16656, 16688, 16688, 16720, 9552,
+ 16752, 16784, 16816, 16848, 16848, 16880, 16912, 16848,
+ 16848, 16848, 16848, 16848, 16848, 16848, 16848, 16848,
+ 16848, 16944, 16976, 16848, 17008, 16848, 17040, 17072,
+ 17104, 17136, 17168, 17200, 16848, 16848, 16848, 17232,
+ 17264, 17296, 17328, 17360, 17392, 17424, 17456, 17488,
+
+ 17520, 17552, 17584, 9552, 17616, 17616, 17616, 17648,
+ 17680, 17712, 17744, 17776, 17808, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 17840, 17872, 17904, 9552, 17936, 14640, 17968, 9552,
+ 18000, 18032, 18064, 17616, 18096, 18128, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552,
+ 18160, 18192, 8240, 8240, 8240, 8240, 8240, 8240,
+ 18224, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 18256, 18288, 18320, 8240, 8240, 8240, 8240, 8240,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+ 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240,
+
+ // 0x11000 - 0x110000
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18608, 18608, 18608, 18864, 19120, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 19376, 19632, 19888, 20144, 20400, 20656, 20912, 21168,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680,
+ 21680, 21680, 21680, 21680, 21680, 21680, 21936, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 21680, 21680, 22192, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 22448, 22704, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352,
+ 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 23216,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960,
+ 22960, 22960, 22960, 22960, 22960, 22960, 22960, 23216,
+
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6, 6, 6, 7,
+
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 14, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 9,
+
+ 14, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 39, 40, 41, 42, 43,
+
+ 42, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 39, 45, 41, 36, 0,
+
+ 0, 0, 0, 0, 0, 46, 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,
+
+ 47, 14, 48, 12, 12, 12, 49, 49,
+ 42, 49, 50, 51, 36, 52, 49, 42,
+ 53, 54, 55, 56, 57, 58, 49, 59,
+ 42, 60, 50, 61, 62, 62, 62, 14,
+
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 36,
+ 38, 38, 38, 38, 38, 38, 38, 63,
+
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 36,
+ 44, 44, 44, 44, 44, 44, 44, 64,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 67, 68, 65, 66, 65, 66, 65, 66,
+ 50, 65, 66, 65, 66, 65, 66, 65,
+
+ 66, 65, 66, 65, 66, 65, 66, 65,
+ 66, 69, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 70, 65, 66, 65, 66, 65, 66, 71,
+
+ 72, 73, 65, 66, 65, 66, 74, 65,
+ 66, 75, 75, 65, 66, 50, 76, 77,
+ 78, 65, 66, 75, 79, 80, 81, 82,
+ 65, 66, 83, 50, 81, 84, 85, 86,
+
+ 65, 66, 65, 66, 65, 66, 87, 65,
+ 66, 87, 50, 50, 65, 66, 87, 65,
+ 66, 88, 88, 65, 66, 65, 66, 89,
+ 65, 66, 50, 90, 65, 66, 50, 91,
+
+ 90, 90, 90, 90, 92, 93, 94, 92,
+ 93, 94, 92, 93, 94, 65, 66, 65,
+ 66, 65, 66, 65, 66, 65, 66, 65,
+ 66, 65, 66, 65, 66, 95, 65, 66,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 96, 92, 93, 94, 65, 66, 97, 98,
+ 99, 100, 65, 66, 65, 66, 65, 66,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 99, 100, 99, 100, 99, 100, 99, 100,
+
+ 101, 102, 99, 100, 99, 100, 99, 100,
+ 99, 100, 99, 100, 99, 100, 99, 100,
+ 99, 100, 99, 100, 102, 102, 102, 103,
+ 103, 103, 104, 105, 106, 107, 108, 103,
+
+ 103, 105, 109, 110, 111, 112, 113, 109,
+ 113, 109, 113, 109, 113, 109, 113, 109,
+ 50, 50, 50, 114, 115, 50, 116, 116,
+ 50, 117, 50, 118, 50, 50, 50, 50,
+
+ 116, 50, 50, 119, 50, 50, 50, 50,
+ 120, 121, 50, 122, 50, 50, 50, 121,
+ 50, 50, 123, 50, 50, 124, 50, 50,
+ 50, 50, 50, 50, 50, 125, 50, 50,
+
+ 126, 50, 50, 126, 50, 50, 50, 50,
+ 126, 127, 128, 128, 129, 50, 50, 50,
+ 50, 50, 130, 50, 90, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50,
+
+ 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 131, 131, 131, 131, 131, 102, 102,
+ 132, 132, 132, 132, 132, 132, 132, 132,
+ 132, 133, 133, 134, 134, 134, 134, 134,
+
+ 132, 132, 42, 42, 42, 42, 133, 133,
+ 135, 133, 133, 133, 135, 133, 133, 133,
+ 134, 134, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 136,
+
+ 132, 132, 132, 132, 132, 42, 42, 42,
+ 42, 42, 136, 136, 136, 136, 137, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138,
+
+ 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 140, 141, 141,
+ 141, 141, 140, 142, 141, 141, 141, 141,
+
+ 141, 143, 143, 141, 141, 141, 141, 143,
+ 143, 141, 141, 141, 141, 141, 141, 141,
+ 141, 141, 141, 141, 144, 144, 144, 144,
+ 144, 141, 141, 141, 141, 139, 139, 139,
+
+ 139, 139, 139, 139, 139, 145, 146, 147,
+ 147, 147, 146, 146, 146, 147, 147, 148,
+ 149, 149, 149, 150, 150, 150, 150, 149,
+ 151, 152, 152, 153, 154, 155, 155, 156,
+
+ 157, 157, 158, 159, 159, 159, 159, 159,
+ 159, 159, 159, 159, 159, 159, 159, 159,
+ 160, 160, 160, 160, 42, 42, 160, 160,
+ 160, 160, 132, 161, 161, 161, 34, 160,
+
+ 160, 160, 160, 160, 42, 42, 162, 14,
+ 163, 163, 163, 160, 164, 160, 165, 165,
+ 166, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+
+ 38, 38, 160, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 167, 168, 168, 168,
+ 169, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+
+ 44, 44, 170, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 171, 172, 172, 160,
+ 173, 174, 175, 175, 175, 176, 177, 131,
+ 178, 179, 65, 100, 65, 100, 65, 100,
+
+ 65, 100, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 180, 181, 182, 50, 183, 184, 185, 186,
+ 187, 188, 186, 187, 103, 189, 189, 189,
+
+ 190, 191, 191, 191, 191, 191, 191, 191,
+ 191, 191, 191, 191, 191, 190, 191, 191,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 192, 193, 193, 193, 193, 193, 193, 193,
+ 193, 193, 193, 193, 193, 192, 193, 193,
+
+ 65, 66, 194, 139, 139, 139, 139, 160,
+ 195, 195, 178, 179, 99, 100, 99, 100,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+
+ 196, 65, 66, 65, 66, 178, 179, 65,
+ 66, 178, 179, 65, 66, 178, 179, 197,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 99, 100, 65, 66,
+ 65, 66, 65, 66, 65, 66, 105, 106,
+ 65, 66, 113, 109, 113, 109, 113, 109,
+
+ 178, 179, 178, 179, 178, 179, 178, 179,
+ 178, 179, 178, 179, 178, 179, 178, 179,
+ 113, 109, 113, 109, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 198, 198, 198, 198, 198, 198, 198,
+ 198, 198, 198, 198, 198, 198, 198, 198,
+
+ 198, 198, 198, 198, 198, 198, 198, 198,
+ 198, 198, 198, 198, 198, 198, 198, 198,
+ 198, 198, 198, 198, 198, 198, 198, 160,
+ 160, 134, 199, 199, 200, 199, 200, 199,
+
+ 160, 201, 201, 201, 201, 201, 201, 201,
+ 201, 201, 201, 201, 201, 201, 201, 201,
+ 201, 201, 201, 201, 201, 201, 201, 201,
+ 201, 201, 201, 201, 201, 201, 201, 201,
+
+ 201, 201, 201, 201, 201, 201, 201, 202,
+ 160, 203, 204, 160, 160, 160, 160, 160,
+ 205, 206, 207, 207, 207, 207, 206, 207,
+ 207, 207, 208, 206, 207, 207, 207, 207,
+
+ 207, 207, 152, 206, 206, 206, 206, 206,
+ 207, 207, 206, 207, 207, 208, 209, 207,
+ 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225,
+
+ 226, 227, 228, 226, 207, 152, 229, 230,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+ 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231,
+
+ 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 205, 205, 205, 205, 205,
+ 231, 231, 231, 232, 233, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+
+ 234, 234, 234, 234, 235, 235, 235, 235,
+ 235, 235, 235, 236, 237, 238, 239, 239,
+ 149, 149, 149, 149, 149, 149, 235, 235,
+ 235, 235, 235, 240, 235, 235, 241, 242,
+
+ 235, 243, 244, 244, 244, 244, 245, 244,
+ 245, 244, 245, 245, 245, 245, 245, 244,
+ 244, 244, 244, 245, 245, 245, 245, 245,
+ 245, 245, 245, 235, 235, 235, 235, 235,
+
+ 246, 245, 245, 245, 245, 245, 245, 245,
+ 244, 245, 245, 247, 248, 249, 250, 251,
+ 252, 253, 254, 146, 146, 147, 150, 149,
+ 149, 153, 153, 153, 152, 153, 153, 235,
+
+ 255, 256, 257, 258, 259, 260, 261, 262,
+ 263, 264, 265, 266, 266, 267, 268, 268,
+ 269, 244, 244, 244, 243, 244, 244, 244,
+ 245, 245, 245, 245, 245, 245, 245, 245,
+
+ 245, 245, 245, 245, 245, 245, 245, 245,
+ 244, 244, 244, 244, 244, 244, 244, 244,
+ 244, 244, 244, 244, 244, 244, 244, 244,
+ 244, 244, 245, 245, 245, 245, 245, 245,
+
+ 245, 245, 245, 245, 245, 245, 245, 245,
+ 245, 245, 245, 245, 245, 245, 245, 245,
+ 245, 245, 245, 245, 245, 245, 245, 245,
+ 270, 270, 245, 245, 245, 245, 245, 270,
+
+ 244, 245, 245, 244, 244, 244, 244, 244,
+ 244, 244, 244, 244, 245, 244, 245, 271,
+ 245, 245, 244, 244, 242, 244, 139, 139,
+ 139, 139, 139, 139, 139, 272, 273, 139,
+
+ 139, 139, 139, 141, 139, 274, 274, 139,
+ 139, 49, 141, 139, 139, 141, 275, 275,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 270, 270, 270, 276, 276, 277,
+
+ 278, 278, 278, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 279, 235, 280,
+ 271, 281, 270, 270, 270, 271, 271, 271,
+ 271, 271, 270, 270, 270, 270, 271, 270,
+
+ 270, 270, 270, 270, 270, 270, 270, 270,
+ 271, 270, 271, 270, 271, 277, 277, 275,
+ 146, 147, 146, 146, 147, 146, 146, 147,
+ 147, 147, 146, 147, 147, 146, 147, 146,
+
+ 146, 146, 147, 146, 147, 146, 147, 146,
+ 147, 146, 146, 235, 235, 275, 277, 277,
+ 282, 282, 282, 282, 282, 282, 282, 282,
+ 282, 283, 283, 283, 282, 282, 282, 282,
+
+ 282, 282, 282, 282, 282, 282, 282, 282,
+ 282, 282, 282, 283, 283, 282, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+
+ 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284,
+
+ 284, 284, 284, 284, 284, 284, 285, 285,
+ 285, 285, 285, 285, 285, 285, 285, 285,
+ 285, 286, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+
+ 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 297, 297, 297, 297, 297,
+ 297, 297, 297, 297, 297, 297, 297, 297,
+ 297, 297, 297, 297, 297, 297, 297, 297,
+
+ 297, 297, 297, 297, 297, 297, 297, 297,
+ 297, 297, 297, 298, 298, 298, 298, 298,
+ 298, 298, 299, 298, 300, 300, 301, 302,
+ 303, 304, 305, 205, 205, 205, 205, 205,
+
+ 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+
+ 160, 306, 306, 307, 308, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 160, 160, 309, 90, 307, 307,
+
+ 307, 306, 306, 306, 306, 306, 306, 306,
+ 306, 307, 307, 307, 307, 310, 160, 160,
+ 90, 139, 141, 139, 139, 160, 160, 160,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 306, 306, 311, 311, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 199, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 322, 322, 323, 322, 322,
+
+ 160, 306, 307, 307, 160, 90, 90, 90,
+ 90, 90, 90, 90, 90, 160, 160, 90,
+ 90, 160, 160, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 160, 160, 160, 90, 90,
+ 90, 90, 160, 160, 309, 308, 324, 307,
+
+ 307, 306, 306, 306, 306, 160, 160, 307,
+ 307, 160, 160, 307, 307, 310, 323, 160,
+ 160, 160, 160, 160, 160, 160, 160, 324,
+ 160, 160, 160, 160, 90, 90, 160, 90,
+
+ 90, 90, 306, 306, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 90, 90, 12, 12, 325, 325, 325, 325,
+ 325, 325, 194, 160, 160, 160, 160, 160,
+
+ 160, 326, 306, 327, 160, 90, 90, 90,
+ 90, 90, 90, 160, 160, 160, 160, 90,
+ 90, 160, 160, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 160, 90, 90, 160,
+ 90, 90, 160, 160, 309, 160, 307, 307,
+
+ 307, 306, 306, 160, 160, 160, 160, 306,
+ 306, 160, 160, 306, 306, 310, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 90, 90, 90, 90, 160, 90, 160,
+
+ 160, 160, 160, 160, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 306, 306, 90, 90, 90, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 306, 306, 307, 160, 90, 90, 90,
+ 90, 90, 90, 90, 308, 90, 160, 90,
+ 90, 90, 160, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 160, 90, 90, 90,
+ 90, 90, 160, 160, 309, 90, 307, 307,
+
+ 307, 306, 306, 306, 306, 306, 160, 306,
+ 306, 307, 160, 307, 307, 310, 160, 160,
+ 90, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 90, 308, 326, 326, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 160, 328, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 160, 308, 90, 90,
+ 90, 90, 160, 160, 309, 90, 324, 306,
+
+ 307, 306, 306, 306, 160, 160, 160, 307,
+ 307, 160, 160, 307, 307, 310, 160, 160,
+ 160, 160, 160, 160, 160, 160, 306, 324,
+ 160, 160, 160, 160, 90, 90, 160, 90,
+
+ 90, 90, 160, 160, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 194, 308, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 306, 90, 160, 90, 90, 90,
+ 90, 90, 90, 160, 160, 160, 90, 90,
+ 90, 160, 90, 90, 90, 90, 160, 160,
+ 160, 90, 90, 160, 90, 160, 90, 90,
+
+ 160, 160, 160, 90, 90, 160, 160, 160,
+ 90, 90, 90, 160, 160, 160, 90, 90,
+ 90, 90, 90, 90, 90, 90, 323, 90,
+ 90, 90, 160, 160, 160, 160, 324, 307,
+
+ 306, 307, 307, 160, 160, 160, 307, 307,
+ 307, 160, 307, 307, 307, 310, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 324,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 329, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 325, 325, 325, 239, 239, 239, 239, 239,
+ 239, 328, 239, 160, 160, 160, 160, 160,
+
+ 160, 307, 307, 307, 160, 90, 90, 90,
+ 90, 90, 90, 90, 90, 160, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 160, 90, 90, 90,
+ 90, 90, 160, 160, 160, 160, 306, 306,
+
+ 306, 307, 307, 307, 307, 160, 306, 306,
+ 306, 160, 306, 306, 306, 310, 160, 160,
+ 160, 160, 160, 160, 160, 330, 331, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 90, 90, 160, 160, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 307, 307, 160, 90, 90, 90,
+ 90, 90, 90, 90, 90, 160, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 160, 90, 90, 90,
+ 90, 90, 160, 160, 332, 308, 307, 333,
+
+ 307, 307, 324, 307, 307, 160, 333, 307,
+ 307, 160, 307, 307, 306, 310, 160, 160,
+ 160, 160, 160, 160, 160, 324, 324, 160,
+ 160, 160, 160, 160, 160, 160, 90, 160,
+
+ 90, 90, 334, 334, 160, 160, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321,
+ 160, 301, 301, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 160, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 160, 160, 160, 160, 324, 307,
+
+ 307, 306, 306, 306, 160, 160, 307, 307,
+ 307, 160, 307, 307, 307, 310, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 324,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 335, 335, 160, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 160,
+ 160, 160, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 160, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 160, 336, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 160,
+ 160, 160, 337, 160, 160, 160, 160, 338,
+ 335, 335, 285, 285, 285, 160, 285, 160,
+ 335, 335, 335, 335, 335, 335, 335, 338,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 335, 335, 339, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 340, 340, 340, 340, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340,
+
+ 340, 340, 340, 340, 340, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340,
+ 340, 341, 340, 340, 341, 341, 341, 341,
+ 342, 342, 343, 160, 160, 160, 160, 12,
+
+ 340, 340, 340, 340, 340, 340, 344, 341,
+ 345, 345, 345, 345, 341, 341, 341, 199,
+ 312, 313, 314, 315, 316, 317, 318, 319,
+ 320, 321, 346, 346, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 340, 340, 160, 340, 160, 160, 340,
+ 340, 160, 340, 160, 160, 340, 160, 160,
+ 160, 160, 160, 160, 340, 340, 340, 340,
+ 160, 340, 340, 340, 340, 340, 340, 340,
+
+ 160, 340, 340, 340, 160, 340, 160, 340,
+ 160, 160, 340, 340, 160, 340, 340, 340,
+ 340, 341, 340, 340, 341, 341, 341, 341,
+ 347, 347, 160, 341, 341, 340, 160, 160,
+
+ 340, 340, 340, 340, 340, 160, 344, 160,
+ 348, 348, 348, 348, 341, 341, 160, 160,
+ 312, 313, 314, 315, 316, 317, 318, 319,
+ 320, 321, 160, 160, 340, 340, 160, 160,
+
+ 349, 350, 350, 350, 351, 352, 351, 351,
+ 353, 351, 351, 354, 353, 355, 355, 355,
+ 355, 355, 353, 356, 357, 356, 356, 356,
+ 206, 206, 356, 356, 356, 356, 356, 356,
+
+ 358, 359, 360, 361, 362, 363, 364, 365,
+ 366, 367, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 369, 206, 356, 206,
+ 356, 370, 371, 372, 371, 372, 373, 373,
+
+ 349, 349, 349, 349, 349, 349, 349, 349,
+ 160, 349, 349, 349, 349, 349, 349, 349,
+ 349, 349, 349, 349, 349, 349, 349, 349,
+ 349, 349, 349, 349, 349, 349, 349, 349,
+
+ 349, 349, 349, 349, 349, 349, 349, 349,
+ 349, 349, 336, 160, 160, 160, 160, 160,
+ 160, 374, 375, 376, 377, 376, 376, 376,
+ 376, 376, 375, 375, 375, 375, 376, 378,
+
+ 375, 376, 207, 207, 379, 354, 207, 207,
+ 349, 349, 349, 349, 160, 160, 160, 160,
+ 376, 376, 376, 376, 376, 376, 285, 376,
+ 160, 376, 376, 376, 376, 376, 376, 376,
+
+ 376, 376, 376, 376, 376, 376, 376, 376,
+ 376, 376, 376, 376, 376, 376, 285, 285,
+ 285, 376, 376, 376, 376, 376, 376, 376,
+ 285, 376, 285, 285, 285, 160, 380, 380,
+
+ 381, 381, 381, 381, 381, 381, 147, 381,
+ 381, 381, 381, 381, 381, 160, 160, 381,
+ 382, 382, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 383, 383, 383, 383, 383, 383, 383, 383,
+ 383, 383, 383, 383, 383, 383, 383, 383,
+ 383, 383, 383, 383, 383, 383, 383, 383,
+ 383, 383, 383, 383, 383, 383, 383, 383,
+
+ 383, 383, 160, 383, 383, 383, 383, 383,
+ 160, 383, 383, 160, 384, 385, 385, 385,
+ 385, 384, 385, 160, 160, 160, 385, 386,
+ 384, 387, 160, 160, 160, 160, 160, 160,
+
+ 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 398, 398, 339, 339, 339, 339,
+ 383, 383, 383, 383, 383, 383, 384, 384,
+ 385, 385, 160, 160, 160, 160, 160, 160,
+
+ 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399,
+
+ 399, 399, 399, 399, 399, 399, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 400,
+ 400, 323, 323, 199, 401, 160, 160, 160,
+
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 402, 402, 402, 402, 402, 402,
+
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 402, 402, 402, 402, 402, 402,
+ 402, 402, 160, 160, 160, 160, 160, 402,
+
+ 403, 403, 403, 403, 403, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403,
+
+ 403, 403, 403, 160, 160, 160, 160, 160,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 404, 404, 404, 404, 404, 404,
+ 404, 404, 160, 160, 160, 160, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 160, 336, 336, 336, 336, 160, 160,
+ 336, 336, 336, 336, 336, 336, 336, 160,
+ 336, 160, 336, 336, 336, 336, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 160, 336, 336, 336, 336, 160, 160,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 160, 336, 336, 336, 336, 160, 160,
+ 336, 336, 336, 336, 336, 336, 336, 160,
+
+ 336, 160, 336, 336, 336, 336, 160, 160,
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 336, 336, 336, 336, 336, 336, 160,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 160, 336, 336, 336, 336, 160, 160,
+ 336, 336, 336, 336, 336, 336, 336, 323,
+
+ 336, 336, 336, 336, 336, 336, 336, 323,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 160, 160, 160, 160, 153,
+
+ 405, 406, 407, 339, 339, 339, 339, 407,
+ 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 417, 417, 417, 417, 417,
+ 417, 417, 417, 417, 417, 160, 160, 160,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 160, 160, 160, 160, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 339, 407, 336,
+ 336, 336, 336, 336, 336, 336, 336, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 419, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 420, 421, 160, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 406, 406, 406, 422, 422,
+ 422, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 400, 400, 400, 160, 400, 400,
+ 400, 400, 423, 423, 424, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 423, 423, 424, 425, 425, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 423, 423, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 400, 400, 400, 160, 400, 400,
+ 400, 160, 423, 423, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 383, 383, 383, 383, 383, 383, 383, 383,
+ 383, 383, 383, 383, 383, 383, 383, 383,
+ 383, 383, 383, 383, 426, 426, 384, 385,
+ 385, 385, 385, 385, 385, 385, 384, 384,
+
+ 384, 384, 384, 384, 384, 384, 385, 384,
+ 384, 385, 385, 385, 385, 385, 385, 385,
+ 385, 385, 387, 385, 406, 406, 427, 428,
+ 406, 339, 406, 429, 383, 430, 160, 160,
+
+ 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 160, 160, 160, 160, 160, 160,
+ 431, 431, 431, 431, 431, 431, 431, 431,
+ 431, 431, 160, 160, 160, 160, 160, 160,
+
+ 432, 432, 433, 434, 433, 433, 435, 432,
+ 433, 434, 432, 285, 285, 285, 436, 160,
+ 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 160, 160, 160, 160, 160, 160,
+
+ 336, 336, 336, 137, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 336, 336, 336, 336, 336, 336, 336, 336,
+ 336, 437, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 160, 160, 160,
+
+ 326, 326, 326, 327, 327, 327, 327, 326,
+ 326, 438, 438, 438, 160, 160, 160, 160,
+ 327, 327, 326, 327, 327, 327, 327, 327,
+ 327, 439, 149, 150, 160, 160, 160, 160,
+
+ 239, 160, 160, 160, 440, 440, 441, 442,
+ 443, 444, 445, 446, 447, 448, 449, 450,
+ 451, 451, 451, 451, 451, 451, 451, 451,
+ 451, 451, 451, 451, 451, 451, 451, 451,
+
+ 451, 451, 451, 451, 451, 451, 451, 451,
+ 451, 451, 451, 451, 451, 451, 160, 160,
+ 451, 451, 451, 451, 451, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 452, 452, 452, 452, 452, 452, 452, 452,
+ 452, 452, 452, 452, 452, 452, 452, 452,
+ 452, 452, 452, 452, 452, 452, 452, 452,
+ 452, 452, 452, 452, 452, 452, 452, 452,
+
+ 452, 452, 452, 452, 452, 452, 452, 452,
+ 452, 452, 160, 160, 160, 160, 160, 160,
+ 453, 453, 453, 453, 453, 453, 453, 453,
+ 453, 453, 453, 453, 453, 453, 453, 453,
+
+ 453, 452, 452, 452, 452, 452, 452, 452,
+ 453, 453, 160, 160, 160, 160, 160, 160,
+ 329, 454, 455, 456, 457, 458, 459, 460,
+ 461, 462, 160, 160, 160, 160, 463, 463,
+
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 153,
+ 152, 464, 464, 464, 160, 160, 465, 466,
+
+ 334, 334, 334, 334, 467, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 468, 467, 334, 334,
+ 334, 334, 334, 467, 334, 467, 467, 467,
+
+ 467, 467, 334, 467, 469, 322, 322, 322,
+ 322, 322, 322, 322, 160, 160, 160, 160,
+ 470, 471, 472, 473, 474, 475, 476, 477,
+ 478, 479, 480, 480, 481, 481, 480, 480,
+
+ 481, 482, 482, 482, 482, 482, 482, 482,
+ 482, 482, 482, 298, 299, 298, 298, 298,
+ 298, 298, 298, 298, 482, 482, 482, 482,
+ 482, 482, 482, 482, 482, 160, 160, 160,
+
+ 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102,
+
+ 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 483, 483, 483, 483,
+ 483, 483, 483, 483, 483, 483, 483, 483,
+ 483, 483, 483, 483, 483, 483, 483, 483,
+
+ 483, 483, 483, 483, 483, 483, 483, 483,
+ 483, 483, 483, 483, 483, 483, 483, 483,
+ 483, 483, 483, 483, 483, 483, 483, 483,
+ 483, 483, 483, 483, 483, 483, 483, 483,
+
+ 483, 483, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103,
+ 484, 103, 103, 103, 103, 485, 103, 103,
+
+ 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 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, 484,
+
+ 153, 153, 152, 153, 298, 298, 298, 298,
+ 298, 298, 299, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 298, 299,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 486, 487,
+ 488, 489, 490, 491, 160, 160, 160, 160,
+
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 160, 160, 160, 160, 160, 160,
+
+ 492, 492, 492, 492, 492, 492, 492, 492,
+ 493, 493, 493, 493, 493, 493, 493, 493,
+ 492, 492, 492, 492, 492, 492, 160, 160,
+ 493, 493, 493, 493, 493, 493, 160, 160,
+
+ 492, 492, 492, 492, 492, 492, 492, 492,
+ 493, 493, 493, 493, 493, 493, 493, 493,
+ 492, 492, 492, 492, 492, 492, 492, 492,
+ 493, 493, 493, 493, 493, 493, 493, 493,
+
+ 492, 492, 492, 492, 492, 492, 160, 160,
+ 493, 493, 493, 493, 493, 493, 160, 160,
+ 494, 492, 495, 492, 496, 492, 497, 492,
+ 160, 493, 160, 493, 160, 493, 160, 493,
+
+ 492, 492, 492, 492, 492, 492, 492, 492,
+ 493, 493, 493, 493, 493, 493, 493, 493,
+ 498, 498, 499, 499, 499, 499, 500, 500,
+ 501, 501, 502, 502, 503, 503, 160, 160,
+
+ 504, 505, 506, 507, 508, 509, 510, 511,
+ 512, 513, 514, 515, 516, 517, 518, 519,
+ 520, 521, 522, 523, 524, 525, 526, 527,
+ 528, 529, 530, 531, 532, 533, 534, 535,
+
+ 536, 537, 538, 539, 540, 541, 542, 543,
+ 544, 545, 546, 547, 548, 549, 550, 551,
+ 492, 492, 552, 553, 554, 160, 555, 556,
+ 493, 493, 557, 557, 558, 42, 559, 42,
+
+ 42, 42, 560, 561, 562, 160, 563, 564,
+ 565, 565, 565, 565, 566, 42, 42, 42,
+ 492, 492, 567, 166, 160, 160, 568, 569,
+ 493, 493, 570, 570, 160, 42, 42, 42,
+
+ 492, 492, 571, 169, 572, 182, 573, 574,
+ 493, 493, 575, 575, 576, 42, 42, 42,
+ 160, 160, 577, 578, 579, 160, 580, 581,
+ 582, 582, 583, 583, 584, 42, 42, 160,
+
+ 585, 585, 585, 585, 585, 585, 585, 586,
+ 585, 585, 585, 587, 588, 589, 590, 591,
+ 592, 593, 592, 592, 594, 595, 14, 14,
+ 596, 597, 598, 599, 596, 600, 598, 599,
+
+ 14, 14, 14, 14, 601, 601, 601, 602,
+ 603, 604, 605, 606, 607, 608, 609, 610,
+ 13, 13, 13, 13, 13, 611, 611, 611,
+ 14, 596, 600, 14, 612, 612, 14, 43,
+
+ 43, 14, 14, 14, 613, 16, 17, 614,
+ 615, 615, 432, 432, 432, 432, 616, 616,
+ 616, 616, 185, 617, 618, 619, 620, 616,
+ 620, 620, 620, 620, 619, 620, 620, 621,
+
+ 622, 623, 623, 623, 160, 160, 160, 160,
+ 160, 160, 624, 624, 624, 624, 624, 624,
+ 625, 626, 160, 160, 627, 628, 629, 630,
+ 631, 632, 633, 633, 36, 16, 17, 50,
+
+ 625, 60, 55, 56, 627, 628, 629, 630,
+ 631, 632, 633, 633, 36, 16, 17, 160,
+ 484, 484, 484, 484, 484, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 12, 12, 12, 12, 12, 12, 12, 48,
+ 12, 12, 12, 634, 635, 429, 429, 429,
+ 636, 636, 637, 637, 637, 637, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 139, 139, 144, 144, 139, 139, 139, 139,
+ 144, 144, 144, 139, 139, 273, 273, 273,
+
+ 273, 139, 195, 195, 638, 639, 639, 159,
+ 640, 159, 639, 641, 299, 299, 299, 299,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 49, 49, 175, 642, 49, 49, 49, 175,
+ 49, 642, 50, 175, 175, 175, 50, 50,
+ 175, 175, 175, 50, 49, 175, 643, 49,
+ 49, 175, 175, 175, 175, 175, 49, 49,
+
+ 49, 49, 49, 49, 175, 49, 644, 49,
+ 175, 49, 645, 646, 175, 175, 647, 50,
+ 175, 175, 648, 175, 50, 90, 90, 90,
+ 90, 131, 649, 239, 103, 626, 650, 650,
+
+ 185, 185, 185, 185, 185, 650, 626, 626,
+ 626, 626, 651, 185, 418, 301, 652, 160,
+ 160, 160, 160, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62,
+
+ 653, 653, 653, 653, 653, 653, 653, 653,
+ 653, 653, 653, 653, 653, 653, 653, 653,
+ 654, 654, 654, 654, 654, 654, 654, 654,
+ 654, 654, 654, 654, 654, 654, 654, 654,
+
+ 655, 655, 655, 99, 109, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 36, 36, 36, 36, 36, 49, 49, 49,
+ 49, 49, 36, 36, 49, 49, 49, 49,
+
+ 36, 49, 49, 36, 49, 49, 36, 49,
+ 49, 49, 49, 49, 49, 49, 36, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 36, 36,
+ 49, 49, 36, 49, 36, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 649, 649, 649, 649, 649,
+ 649, 649, 649, 649, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 656, 656, 656, 657, 657, 657, 36, 36,
+ 36, 36, 18, 54, 36, 658, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 659, 660, 36, 36,
+
+ 36, 36, 36, 661, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 659, 660, 659, 660, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+
+ 36, 36, 36, 36, 659, 660, 659, 660,
+ 659, 660, 659, 660, 36, 36, 659, 660,
+ 659, 660, 659, 660, 659, 660, 659, 660,
+ 659, 660, 659, 660, 659, 660, 659, 660,
+
+ 659, 660, 659, 660, 659, 660, 659, 660,
+ 659, 660, 659, 660, 36, 36, 36, 659,
+ 660, 659, 660, 36, 36, 36, 36, 36,
+ 662, 36, 36, 36, 36, 36, 36, 36,
+
+ 36, 36, 659, 660, 36, 36, 663, 36,
+ 664, 665, 36, 665, 36, 36, 36, 36,
+ 659, 660, 659, 660, 659, 660, 659, 660,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 659, 660, 659, 660, 666, 36, 36,
+ 659, 660, 36, 36, 36, 36, 659, 660,
+ 659, 660, 659, 660, 659, 660, 659, 660,
+
+ 659, 660, 659, 660, 659, 660, 659, 660,
+ 659, 660, 659, 660, 659, 660, 36, 36,
+ 659, 660, 667, 667, 667, 185, 668, 668,
+ 185, 185, 669, 669, 669, 670, 670, 185,
+
+ 49, 649, 49, 49, 49, 49, 49, 49,
+ 659, 660, 659, 660, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 36, 36, 49, 49, 49, 49, 49, 49,
+ 49, 16, 17, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 649, 185, 649, 649, 649,
+
+ 649, 649, 649, 649, 649, 649, 649, 649,
+ 649, 649, 649, 649, 649, 649, 649, 649,
+ 649, 649, 649, 649, 649, 381, 649, 649,
+ 649, 649, 649, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 651, 651, 651, 651,
+ 651, 651, 651, 651, 651, 651, 651, 651,
+
+ 651, 651, 651, 651, 651, 651, 651, 651,
+ 651, 651, 651, 651, 651, 651, 651, 239,
+ 239, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 671, 671, 671, 671,
+
+ 671, 671, 301, 301, 301, 301, 301, 301,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 649, 649, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 672, 673, 674, 675, 676, 677, 678, 679,
+ 680, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 672, 673, 674, 675,
+ 676, 677, 678, 679, 680, 62, 62, 62,
+
+ 62, 62, 62, 62, 62, 62, 62, 62,
+ 60, 55, 56, 627, 628, 629, 630, 631,
+ 632, 681, 681, 681, 681, 681, 681, 681,
+ 681, 681, 681, 681, 194, 194, 194, 194,
+
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 194, 194, 194, 682, 682,
+ 682, 682, 682, 682, 682, 682, 682, 682,
+
+ 682, 682, 682, 682, 682, 682, 682, 682,
+ 682, 682, 682, 682, 682, 682, 682, 682,
+ 683, 683, 683, 683, 683, 683, 683, 683,
+ 683, 683, 683, 683, 683, 683, 683, 683,
+
+ 683, 683, 683, 683, 683, 683, 683, 683,
+ 683, 683, 684, 685, 685, 685, 685, 685,
+ 685, 685, 685, 685, 685, 686, 687, 688,
+ 689, 690, 691, 692, 693, 694, 685, 695,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 651, 651,
+ 651, 651, 651, 651, 651, 651, 651, 651,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 36,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 36, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 649, 649, 649, 649, 649, 649, 649, 649,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 239, 239, 651, 651,
+ 418, 649, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 36,
+ 649, 649, 651, 651, 651, 651, 651, 651,
+ 651, 651, 651, 651, 651, 651, 418, 418,
+
+ 651, 651, 651, 651, 651, 651, 651, 651,
+ 651, 651, 239, 239, 239, 239, 239, 239,
+ 239, 239, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 160, 160, 160,
+
+ 239, 239, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 405, 418, 418, 418,
+ 418, 418, 301, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 49, 49, 49, 49, 160, 49, 49,
+ 49, 49, 160, 160, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 160, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 160, 49, 160, 49,
+ 49, 49, 49, 160, 160, 160, 49, 160,
+ 49, 49, 49, 696, 696, 696, 696, 160,
+
+ 160, 49, 697, 697, 49, 49, 49, 49,
+ 698, 699, 698, 699, 698, 699, 698, 699,
+ 698, 699, 698, 699, 698, 699, 672, 673,
+ 674, 675, 676, 677, 678, 679, 680, 62,
+
+ 672, 673, 674, 675, 676, 677, 678, 679,
+ 680, 62, 672, 673, 674, 675, 676, 677,
+ 678, 679, 680, 62, 49, 160, 160, 160,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 160, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 160,
+
+ 700, 700, 700, 701, 702, 703, 704, 671,
+ 671, 671, 671, 160, 160, 160, 160, 160,
+ 185, 185, 185, 185, 185, 705, 706, 185,
+ 185, 185, 185, 185, 185, 705, 706, 185,
+
+ 185, 185, 705, 706, 705, 706, 698, 699,
+ 698, 699, 698, 699, 160, 160, 160, 160,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 381, 381, 381, 381, 381, 381, 381, 381,
+ 381, 381, 381, 381, 381, 381, 381, 381,
+ 381, 381, 381, 381, 381, 381, 381, 381,
+ 381, 381, 381, 381, 381, 381, 381, 381,
+
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 698, 699, 698, 699, 698,
+ 699, 698, 699, 698, 699, 707, 708, 709,
+ 710, 698, 699, 698, 699, 698, 699, 698,
+ 699, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 711, 185, 185, 185, 185, 185, 185, 185,
+
+ 705, 706, 185, 185, 705, 706, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 705,
+ 706, 705, 706, 185, 705, 706, 185, 185,
+ 698, 699, 698, 699, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 712, 185, 185,
+ 705, 706, 185, 185, 698, 699, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 705, 706, 705, 706, 185,
+ 185, 185, 185, 185, 705, 706, 185, 185,
+ 185, 185, 185, 185, 705, 706, 185, 185,
+
+ 185, 185, 185, 185, 705, 706, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 705, 706, 185, 185, 705, 706, 705,
+
+ 706, 705, 706, 705, 706, 185, 185, 185,
+ 185, 185, 185, 705, 706, 185, 185, 185,
+ 185, 705, 706, 705, 706, 705, 706, 705,
+ 706, 705, 706, 705, 706, 185, 185, 185,
+
+ 185, 705, 706, 185, 185, 185, 705, 706,
+ 705, 706, 705, 706, 705, 706, 185, 705,
+ 706, 185, 185, 705, 706, 185, 185, 185,
+ 185, 185, 185, 705, 706, 705, 706, 705,
+
+ 706, 705, 706, 705, 706, 705, 706, 185,
+ 185, 185, 185, 185, 185, 705, 706, 705,
+ 706, 705, 706, 705, 706, 705, 706, 185,
+ 185, 185, 185, 185, 185, 185, 713, 185,
+
+ 185, 185, 185, 714, 715, 714, 185, 185,
+ 185, 185, 185, 185, 705, 706, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 705,
+ 706, 705, 706, 185, 185, 185, 185, 185,
+
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 418, 418,
+ 418, 418, 418, 418, 301, 301, 301, 301,
+ 301, 301, 301, 160, 160, 160, 160, 160,
+
+ 301, 301, 301, 301, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716,
+
+ 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 716, 160,
+ 717, 717, 717, 717, 717, 717, 717, 717,
+ 717, 717, 717, 717, 717, 717, 717, 717,
+
+ 717, 717, 717, 717, 717, 717, 717, 717,
+ 717, 717, 717, 717, 717, 717, 717, 717,
+ 717, 717, 717, 717, 717, 717, 717, 717,
+ 717, 717, 717, 717, 717, 717, 717, 160,
+
+ 113, 109, 718, 719, 720, 721, 722, 113,
+ 109, 113, 109, 113, 109, 160, 160, 160,
+ 160, 160, 160, 160, 723, 113, 109, 723,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 105, 106, 105, 106, 105, 106, 105, 106,
+ 105, 106, 105, 106, 105, 106, 105, 106,
+ 105, 106, 105, 106, 105, 106, 105, 106,
+ 105, 106, 105, 106, 105, 106, 105, 106,
+
+ 105, 106, 105, 106, 103, 418, 418, 418,
+ 418, 418, 418, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 620, 620, 620, 620, 724, 620, 620,
+
+ 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, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 401,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 323, 323, 323, 323, 323, 323, 323, 160,
+ 323, 323, 323, 323, 323, 323, 323, 160,
+ 323, 323, 323, 323, 323, 323, 323, 160,
+ 323, 323, 323, 323, 323, 323, 323, 160,
+
+ 726, 726, 727, 728, 727, 728, 726, 726,
+ 726, 727, 728, 726, 727, 728, 620, 620,
+ 620, 620, 620, 620, 620, 620, 619, 729,
+ 160, 160, 160, 160, 727, 728, 160, 160,
+
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 160, 730, 730, 730, 730, 730,
+
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 160, 160, 160, 160,
+
+ 731, 732, 733, 734, 735, 736, 737, 738,
+ 16, 17, 16, 17, 16, 17, 16, 17,
+ 16, 17, 735, 735, 16, 17, 16, 17,
+ 16, 17, 16, 17, 739, 16, 17, 740,
+
+ 735, 738, 738, 738, 738, 738, 738, 738,
+ 738, 738, 741, 742, 140, 743, 744, 744,
+ 745, 746, 746, 746, 746, 746, 735, 735,
+ 747, 747, 747, 748, 749, 750, 730, 735,
+
+ 160, 751, 737, 751, 737, 751, 737, 751,
+ 737, 751, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+
+ 737, 737, 737, 751, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+
+ 737, 737, 737, 751, 737, 751, 737, 751,
+ 737, 737, 737, 737, 737, 737, 751, 737,
+ 737, 737, 737, 737, 737, 752, 752, 160,
+ 160, 753, 753, 754, 754, 755, 755, 756,
+
+ 757, 758, 759, 758, 759, 758, 759, 758,
+ 759, 758, 759, 759, 759, 759, 759, 759,
+ 759, 759, 759, 759, 759, 759, 759, 759,
+ 759, 759, 759, 759, 759, 759, 759, 759,
+
+ 759, 759, 759, 758, 759, 759, 759, 759,
+ 759, 759, 759, 759, 759, 759, 759, 759,
+ 759, 759, 759, 759, 759, 759, 759, 759,
+ 759, 759, 759, 759, 759, 759, 759, 759,
+
+ 759, 759, 759, 758, 759, 758, 759, 758,
+ 759, 759, 759, 759, 759, 759, 758, 759,
+ 759, 759, 759, 759, 759, 758, 758, 759,
+ 759, 759, 759, 760, 761, 761, 761, 762,
+
+ 160, 160, 160, 160, 160, 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, 160, 160, 160,
+ 160, 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, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 160,
+ 764, 764, 765, 765, 765, 765, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 767, 767, 767, 767, 767, 767, 767, 767,
+ 767, 767, 767, 767, 767, 767, 767, 767,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 768, 768, 768, 768, 768, 768, 768, 768,
+ 768, 768, 768, 768, 768, 768, 768, 768,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 769, 769, 160,
+
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+
+ 764, 764, 764, 764, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 769, 770, 770, 770, 770, 770, 770, 770,
+ 770, 770, 770, 770, 770, 770, 770, 770,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 769, 769, 767, 764,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 770, 770, 770, 770, 770, 770, 770,
+ 770, 770, 770, 770, 770, 770, 770, 770,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 769, 769, 769, 769,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 160,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 769,
+ 769, 769, 769, 764, 764, 764, 764, 764,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 769, 769,
+
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 769,
+
+ 771, 771, 771, 771, 771, 771, 771, 771,
+ 771, 771, 771, 771, 771, 771, 771, 771,
+ 771, 771, 771, 771, 771, 771, 771, 771,
+ 771, 771, 771, 771, 771, 771, 771, 771,
+
+ 771, 771, 771, 771, 771, 771, 771, 771,
+ 771, 771, 771, 771, 771, 771, 771, 771,
+ 771, 771, 771, 771, 771, 771, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 737, 737,
+
+ 737, 737, 737, 737, 737, 737, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 160, 160, 160, 160,
+
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 773, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 766, 766, 766,
+
+ 766, 766, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 160, 160, 160,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+
+ 730, 730, 774, 774, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 774, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730,
+
+ 730, 774, 730, 730, 730, 774, 730, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 775, 775, 775, 775, 775, 775, 775, 775,
+ 775, 775, 775, 775, 775, 775, 775, 775,
+ 775, 775, 775, 775, 775, 775, 775, 776,
+ 776, 776, 776, 160, 160, 160, 160, 160,
+
+ 777, 777, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 323, 323, 778, 323, 323, 323, 779, 323,
+ 323, 323, 323, 780, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 464, 464, 780, 780, 464,
+ 418, 418, 418, 418, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 781, 781, 304, 304,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 782, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 782, 783, 783, 783,
+
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 782, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 782, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 782, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 782, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 782, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 782, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+ 783, 783, 783, 783, 783, 783, 783, 783,
+
+ 783, 783, 783, 783, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+
+ 785, 785, 785, 785, 785, 785, 785, 785,
+ 785, 785, 785, 785, 785, 785, 785, 785,
+ 785, 785, 785, 785, 785, 785, 785, 785,
+ 785, 785, 785, 785, 785, 785, 785, 785,
+
+ 737, 737, 737, 737, 737, 737, 737, 737,
+ 737, 737, 737, 737, 737, 737, 160, 160,
+ 786, 786, 786, 786, 786, 786, 786, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786,
+
+ 786, 786, 786, 786, 786, 786, 786, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786,
+
+ 786, 786, 786, 786, 786, 786, 786, 786,
+ 786, 786, 786, 160, 160, 160, 160, 160,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 160, 160, 160, 160, 160, 160,
+
+ 787, 788, 789, 790, 791, 792, 792, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 793, 794, 795, 796, 797,
+ 160, 160, 160, 160, 160, 798, 799, 231,
+
+ 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 633, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 205,
+ 231, 231, 231, 231, 231, 205, 231, 205,
+
+ 231, 231, 205, 231, 231, 205, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 598, 740,
+
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 235, 235, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 235, 235, 235, 235, 235, 235, 235, 235,
+ 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800,
+
+ 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 801, 239, 235, 235,
+
+ 423, 423, 423, 423, 423, 423, 423, 423,
+ 423, 423, 423, 423, 423, 423, 423, 423,
+ 802, 803, 803, 802, 802, 804, 804, 805,
+ 806, 807, 160, 160, 160, 160, 160, 160,
+
+ 139, 139, 139, 139, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 734, 745, 745, 808, 808, 598, 740, 598,
+ 740, 598, 740, 598, 740, 598, 740, 598,
+
+ 740, 598, 740, 598, 740, 750, 750, 809,
+ 810, 734, 734, 734, 734, 808, 808, 808,
+ 811, 734, 812, 160, 760, 813, 9, 9,
+ 745, 16, 17, 16, 17, 16, 17, 814,
+
+ 734, 734, 815, 816, 817, 818, 819, 160,
+ 734, 12, 13, 734, 160, 160, 160, 160,
+ 243, 243, 243, 286, 243, 235, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 243, 243, 243,
+ 243, 243, 243, 243, 243, 235, 235, 820,
+
+ 160, 9, 734, 814, 12, 13, 734, 734,
+ 16, 17, 734, 815, 811, 816, 812, 821,
+ 822, 823, 824, 825, 826, 827, 828, 829,
+ 830, 831, 813, 760, 832, 819, 833, 9,
+
+ 734, 834, 834, 834, 834, 834, 834, 834,
+ 834, 834, 834, 834, 834, 834, 834, 834,
+ 834, 834, 834, 834, 834, 834, 834, 834,
+ 834, 834, 834, 39, 734, 41, 835, 808,
+
+ 835, 836, 836, 836, 836, 836, 836, 836,
+ 836, 836, 836, 836, 836, 836, 836, 836,
+ 836, 836, 836, 836, 836, 836, 836, 836,
+ 836, 836, 836, 39, 819, 41, 819, 698,
+
+ 699, 733, 16, 17, 732, 760, 837, 758,
+ 758, 758, 758, 758, 758, 758, 758, 758,
+ 761, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 761, 761,
+
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 160,
+
+ 160, 160, 90, 90, 90, 90, 90, 90,
+ 160, 160, 90, 90, 90, 90, 90, 90,
+ 160, 160, 90, 90, 90, 90, 90, 90,
+ 160, 160, 90, 90, 90, 160, 160, 160,
+
+ 48, 12, 819, 835, 735, 12, 12, 160,
+ 49, 36, 36, 36, 36, 49, 49, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 838, 838, 838, 839, 49, 840, 840,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 160, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+
+ 308, 308, 308, 308, 308, 308, 308, 160,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 160, 308, 308, 160, 308,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 160, 160,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 160, 160,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 160, 160, 160, 160, 160,
+
+ 841, 842, 843, 160, 160, 160, 160, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844,
+
+ 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 160, 160, 160, 845,
+ 845, 845, 845, 845, 845, 845, 845, 845,
+
+ 846, 846, 846, 846, 846, 846, 846, 846,
+ 846, 846, 846, 846, 846, 846, 846, 846,
+ 846, 846, 846, 846, 846, 846, 846, 846,
+ 846, 846, 846, 846, 846, 846, 846, 846,
+
+ 846, 846, 846, 846, 846, 846, 846, 846,
+ 846, 846, 846, 846, 846, 846, 846, 846,
+ 846, 846, 846, 846, 846, 724, 724, 724,
+ 724, 418, 418, 418, 418, 418, 418, 418,
+
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 724, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 847, 847, 847, 847, 847, 847, 847, 847,
+ 847, 847, 847, 847, 847, 847, 847, 847,
+ 847, 847, 847, 847, 847, 847, 847, 847,
+ 847, 847, 847, 847, 847, 847, 847, 160,
+
+ 848, 848, 848, 848, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 847, 847, 847, 847, 847, 847, 847, 847,
+ 847, 847, 847, 847, 847, 847, 847, 847,
+
+ 847, 849, 847, 847, 847, 847, 847, 847,
+ 847, 847, 849, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 160, 841,
+
+ 323, 323, 323, 323, 160, 160, 160, 160,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 465, 850, 850, 850, 850, 850, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 851, 851, 851, 851, 851, 851, 851, 851,
+ 851, 851, 851, 851, 851, 851, 851, 851,
+ 851, 851, 851, 851, 851, 851, 851, 851,
+ 851, 851, 851, 851, 851, 851, 851, 851,
+
+ 851, 851, 851, 851, 851, 851, 852, 852,
+ 853, 853, 853, 853, 853, 853, 853, 853,
+ 853, 853, 853, 853, 853, 853, 853, 853,
+ 853, 853, 853, 853, 853, 853, 853, 853,
+
+ 853, 853, 853, 853, 853, 853, 853, 853,
+ 853, 853, 853, 853, 853, 853, 854, 854,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 160, 160,
+
+ 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 855, 855, 855, 855, 855, 855, 205, 205,
+ 855, 205, 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, 855, 855, 855, 855,
+ 855, 855, 855, 855, 855, 855, 205, 855,
+ 855, 205, 205, 205, 855, 205, 205, 855,
+
+ 856, 856, 856, 856, 856, 856, 856, 856,
+ 856, 856, 856, 856, 856, 856, 856, 856,
+ 856, 856, 856, 856, 856, 856, 857, 857,
+ 857, 857, 205, 205, 205, 205, 205, 858,
+
+ 859, 780, 780, 780, 205, 780, 780, 205,
+ 205, 205, 205, 205, 780, 152, 780, 153,
+ 859, 859, 859, 859, 205, 859, 859, 859,
+ 205, 859, 859, 859, 859, 859, 859, 859,
+
+ 859, 859, 859, 859, 859, 859, 859, 859,
+ 859, 859, 859, 859, 859, 859, 859, 859,
+ 859, 859, 859, 859, 205, 205, 205, 205,
+ 153, 641, 152, 205, 205, 205, 205, 779,
+
+ 860, 861, 862, 863, 864, 864, 864, 864,
+ 205, 205, 205, 205, 205, 205, 205, 205,
+ 865, 865, 865, 865, 865, 865, 865, 865,
+ 866, 205, 205, 205, 205, 205, 205, 205,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 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, 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, 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, 867, 867, 867, 867, 867, 867, 867,
+ 867, 867, 867, 867, 867, 867, 867, 867,
+ 867, 867, 867, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 481, 481, 481, 481, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 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, 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, 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, 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, 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, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 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, 160,
+ 160, 160, 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, 868, 868, 868, 868, 869, 870, 871,
+ 871, 871, 868, 868, 868, 872, 869, 869,
+ 869, 869, 869, 873, 873, 873, 873, 873,
+ 873, 873, 873, 874, 874, 874, 874, 874,
+ 874, 874, 874, 868, 868, 875, 875, 875,
+ 875, 875, 874, 874, 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, 875, 875, 875, 875, 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, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 153, 153, 153, 418, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 876, 876, 876, 876, 876, 876, 876, 876,
+ 876, 876, 876, 876, 876, 876, 876, 876,
+ 876, 876, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 878, 878,
+ 878, 878, 878, 878, 878, 160, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 877, 160, 877, 877,
+ 160, 160, 877, 160, 160, 877, 877, 160,
+ 160, 877, 877, 877, 877, 160, 877, 877,
+ 877, 877, 877, 877, 877, 877, 878, 878,
+ 878, 878, 160, 878, 160, 878, 878, 878,
+ 878, 102, 878, 878, 160, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+
+ 878, 878, 878, 878, 877, 877, 160, 877,
+ 877, 877, 877, 160, 160, 877, 877, 877,
+ 877, 877, 877, 877, 877, 160, 877, 877,
+ 877, 877, 877, 877, 877, 160, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 160, 877, 877, 877, 877, 160,
+ 877, 877, 877, 877, 877, 160, 877, 160,
+ 160, 160, 877, 877, 877, 877, 877, 877,
+ 877, 160, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 103, 103, 160, 160,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 879, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 879, 878, 878, 878, 878,
+ 878, 878, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 879, 878, 878, 878, 878,
+
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 879, 878, 878,
+ 878, 878, 878, 878, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 879, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 879,
+ 878, 878, 878, 878, 878, 878, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 879,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 879, 878, 878, 878, 878, 878, 878,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 877, 877, 877, 877, 877, 877, 877,
+ 877, 879, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878,
+ 878, 878, 878, 879, 878, 878, 878, 878,
+ 878, 878, 880, 723, 160, 160, 881, 882,
+ 883, 884, 885, 886, 887, 888, 889, 890,
+ 881, 882, 883, 884, 885, 886, 887, 888,
+ 889, 890, 881, 882, 883, 884, 885, 886,
+ 887, 888, 889, 890, 881, 882, 883, 884,
+ 885, 886, 887, 888, 889, 890, 881, 882,
+ 883, 884, 885, 886, 887, 888, 889, 890,
+
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 891, 891,
+
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 892, 892,
+ 892, 892, 892, 892, 892, 892, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 873, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 893, 893,
+ 893, 893, 893, 893, 893, 893, 891, 891,
+};
+
+#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 QUnicodeTables::Properties uc_properties[] = {
+ { 10, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+ { 10, 15, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3 },
+ { 10, 30, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1 },
+ { 10, 31, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3 },
+ { 10, 31, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3 },
+ { 10, 29, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
+ { 10, 19, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+ { 10, 19, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+ { 7, 28, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 26, 5, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 26, 11, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 8, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10 },
+ { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 27, 8, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 21, 14, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8 },
+ { 26, 6, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 10, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+ { 26, 7, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 32, 0, 0, 32, 0, 3, 5 },
+ { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 10 },
+ { 26, 8, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 10 },
+ { 29, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 20, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -32, -32, 0, 0, 3, 4 },
+ { 27, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 10, 11, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1 },
+ { 7, 3, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 28, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 10 },
+ { 11, 15, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 30, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 8, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 29, 16, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 743, 743, 775, 0, 3, 4 },
+ { 26, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+ { 6, 11, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, 0, 10 },
+ { 6, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 3, 0, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 121, 121, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 6, 0, 0, 0, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -232, -232, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 85, 85, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -121, 0, 0, -121, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -300, -300, -268, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 195, 195, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 210, 0, 0, 210, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 206, 0, 0, 206, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 205, 0, 0, 205, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 79, 0, 0, 79, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 202, 0, 0, 202, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 203, 0, 0, 203, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 207, 0, 0, 207, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 97, 97, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 211, 0, 0, 211, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 209, 0, 0, 209, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 163, 163, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 213, 0, 0, 213, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 130, 130, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 214, 0, 0, 214, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 218, 0, 0, 218, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 217, 0, 0, 217, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 219, 0, 0, 219, 0, 3, 5 },
+ { 19, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 56, 56, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -79, -79, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 96, 96, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, -97, 0, 0, -97, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, -56, 0, 0, -56, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, -130, 0, 0, -130, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 10795, 0, 0, 10795, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, -163, 0, 0, -163, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 10792, 0, 0, 10792, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -195, 0, 0, -195, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 69, 0, 0, 69, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 71, 0, 0, 71, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -210, -210, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -206, -206, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -205, -205, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -202, -202, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -203, -203, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -207, -207, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -209, -209, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -211, -211, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 10743, 10743, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -213, -213, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -214, -214, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 10727, 10727, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -218, -218, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -69, -69, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -217, -217, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -71, -71, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -219, -219, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 18, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 18, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 18, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 18, 16, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 29, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 29, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 230, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 232, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 216, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 202, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 1, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 240, 0, -1, 1, 0, 0, 0, 0, 0, 0, 84, 84, 116, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 232, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 233, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 234, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 233, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 234, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 3, 17, 233, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 14, 11, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 130, 130, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 38, 0, 0, 38, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 37, 0, 0, 37, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 64, 0, 0, 64, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 63, 0, 0, 63, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 88, 88, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -38, -38, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -37, -37, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 92, 92, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -31, -31, 1, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -64, -64, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -63, -63, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -62, -62, -30, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -57, -57, -25, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -47, -47, -15, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -54, -54, -22, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -86, -86, -54, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -80, -80, -48, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, -60, 0, 0, -60, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, -96, -96, -64, 0, 3, 4 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, -7, 0, 0, -7, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, -130, 0, 0, -130, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 80, 0, 0, 80, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 80, 0, 0, 80, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, -80, -80, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -80, -80, 0, 0, 3, 4 },
+ { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 3, 19, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 15, 0, 0, 15, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -15, -15, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 3, 5 },
+ { 26, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -48, -48, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 52, 49, 0, 0, 3, 4 },
+ { 26, 7, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 9 },
+ { 21, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 14, 11, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 220, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 222, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 228, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 10, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 11, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 12, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 13, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 14, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 15, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 16, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 17, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 18, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 19, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 19, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 20, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 21, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 22, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 15, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 23, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 24, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 25, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 5, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 18, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 19, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+ { 11, 11, 13, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 14, 11, 13, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 9, 13, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 7, 13, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 30, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 13, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 19, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 2, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 18, 11, 13, 0, 3, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 27, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 28, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 29, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 30, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 31, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 32, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 33, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 34, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 4, 10, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 5, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 5, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 10, 5, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 11, 13, 0, 1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 35, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 19, 11, 13, 0, 1, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 2, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 11, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 3, 19, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 18, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 2, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 11, 13, 0, 1, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 26, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 11, 11, 18, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 1, 19, 17, 36, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 19, 11, 13, 0, 1, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 2, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 19, 11, 13, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 4, 10, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 1, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 19, 11, 1, 0, 1, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 230, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 18, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 7, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 26, 5, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 18, 11, 1, 0, 3, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 7, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 9, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 15, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 4, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 19, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 2, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 6, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 28, 8, 4, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 10, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 1, 19, 17, 84, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 91, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 7, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 9, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 26, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 1, 26, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 26, 17, 103, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 26, 17, 9, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 18, 26, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 1, 26, 17, 107, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 15, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 26, 17, 118, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 26, 17, 122, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 19, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 16, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 16, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 3, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 5, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 10, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 6, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 216, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 22, 0, 10, 0, 0, -1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 2, 19, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 129, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 130, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 132, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 9, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 30, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 16, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 2, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 1, 26, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 26, 17, 7, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 26, 17, 9, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 4, 10, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 7264, 0, 0, 7264, 0, 3, 5 },
+ { 19, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 18, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 23, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 6 },
+ { 19, 24, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 6 },
+ { 19, 25, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 6 },
+ { 30, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 6, 11, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 7, 15, 9, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 22, 0, 10, 0, 0, -1, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 4, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 5, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 9, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 15, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 11, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 26, 4, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 28, 8, 4, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 26, 17, 230, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 6, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 21, 16, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 7, 3, 9, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 1, 19, 17, 228, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 17, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 222, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 5, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 4, 10, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 19, 26, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 19, 26, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 2, 26, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 4, 10, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 26, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 2, 19, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 26, 15, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 2, 19, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 7, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 9, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 10, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 26, 15, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 15, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 18, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 3814, 3814, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 99, 99, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 102, 102, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 105, 105, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 108, 108, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 111, 111, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, -59, -59, -58, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8, 0, 0, -8, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 114, 114, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 117, 117, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 121, 121, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 125, 125, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 74, 74, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 86, 86, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 112, 112, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 126, 126, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 163, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 166, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 169, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 172, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 175, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 178, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 181, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 184, 8, 0, 0, 3, 4 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 163, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 166, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 169, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 172, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 175, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 178, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 181, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 184, 0, -8, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 187, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 190, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 193, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 196, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 199, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 202, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 205, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 208, 8, 0, 0, 3, 4 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 187, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 190, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 193, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 196, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 199, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 202, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 205, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 208, 0, -8, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 211, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 214, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 217, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 220, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 223, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 226, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 229, 8, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 232, 8, 0, 0, 3, 4 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 211, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 214, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 217, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 220, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 223, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 226, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 229, 0, -8, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 232, 0, -8, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 247, 244, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 235, 9, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 253, 250, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 129, 129, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 284, 280, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -74, 0, 0, -74, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 235, 0, -9, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -7205, -7205, -7173, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 259, 256, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 238, 9, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 265, 262, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 132, 132, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 292, 288, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -86, 0, 0, -86, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 238, 0, -9, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 135, 135, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 139, 139, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 142, 142, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -100, 0, 0, -100, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 146, 146, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 150, 150, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 153, 153, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 156, 156, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -112, 0, 0, -112, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -7, 0, 0, -7, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 271, 268, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 241, 9, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 277, 274, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 160, 160, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 300, 296, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -128, 0, 0, -128, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -126, 0, 0, -126, 0, 3, 5 },
+ { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 241, 0, -9, 0, 3, 5 },
+ { 7, 15, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 7, 3, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 11, 18, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 11, 19, 18, 0, 3, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 11, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 21, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 21, 3, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 21, 17, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 21, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 4, 10 },
+ { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 26, 13, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+ { 8, 31, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1 },
+ { 9, 31, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1 },
+ { 11, 19, 11, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 14, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 16, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 12, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 15, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 7, 3, 6, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 26, 9, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 27, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 26, 4, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 4, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 20, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0 },
+ { 26, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 7, 15, 9, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 11, 20, 18, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 11, 18, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 11, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 6, 11, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 6, 11, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 8, 4, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 8, 4, 0, 0, -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 8, 4, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 8, 4, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 3, 19, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 1, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 220, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 1, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 30, 9, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 8, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -7517, 0, 0, -7517, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8383, 0, 0, -8383, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8262, 0, 0, -8262, 0, 3, 5 },
+ { 30, 11, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 28, 0, 0, 28, 0, 3, 5 },
+ { 30, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5 },
+ { 30, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -28, -28, 0, 0, 3, 4 },
+ { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 16, 0, 0, 16, 0, 3, 5 },
+ { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -16, -16, 0, 0, 3, 4 },
+ { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1824, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2104, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2108, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2106, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -138, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -8, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -7, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 2, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 26, 0, 0, 26, 0, 3, 5 },
+ { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -26, -26, 0, 0, 3, 4 },
+ { 6, 11, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 9, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 10, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 30, 5, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0 },
+ { 22, 0, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0 },
+ { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 10 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1824, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2016, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2104, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2106, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2108, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -48, -48, 0, 0, 3, 4 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -10743, 0, 0, -10743, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -3814, 0, 0, -3814, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -10727, 0, 0, -10727, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -10795, -10795, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -10792, -10792, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 6, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -7264, -7264, 0, 0, 3, 4 },
+ { 26, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 24, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10 },
+ { 25, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10 },
+ { 21, 15, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 12, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 7, 12, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+ { 26, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 5, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 21, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 1, 19, 17, 218, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 228, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 222, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 224, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 21, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 5, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 18, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 26, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 1, 19, 17, 8, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 29, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
+ { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 21, 4, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
+ { 19, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 26, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 12, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 30, 12, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 19, 12, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 18, 4, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 29, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 18, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 29, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 2, 19, 17, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 9, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 26, 16, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 21, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 6 },
+ { 19, 22, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 3, 6 },
+ { 12, 27, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 13, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 12, 9, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 18, 15, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 24, 21, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 31, 27, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 39, 35, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 46, 43, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 58, 55, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 64, 61, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 70, 67, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 76, 73, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 82, 79, 0, 0, 3, 4 },
+ { 19, 11, 1, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 1, 19, 17, 26, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 14, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 28, 9, 13, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 7, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+ { 26, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 5, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 22, 0, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 26, 13, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 20, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0 },
+ { 22, 0, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 23, 1, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 },
+ { 26, 1, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 1, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
+ { 26, 4, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 12, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 21, 12, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 11, 20, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 26, 12, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 4, 12, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 },
+ { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 32, 0, 0, 32, 0, 3, 5 },
+ { 29, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -32, -32, 0, 0, 3, 4 },
+ { 19, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6 },
+ { 11, 19, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 30, 11, 10, 0, 0, -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 14, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 15, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 30, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 6, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 5, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 40, 0, 0, 40, 0, 3, 5 },
+ { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 40, 0, 0, 40, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, -40, -40, 0, 0, 3, 4 },
+ { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, -40, -40, 0, 0, 3, 4 },
+ { 19, 11, 1, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 19, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 6, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 6, 11, 1, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 1, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 1, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 1, 0, 0, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 15, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 26, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6 },
+ { 30, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 2, 19, 0, 216, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 216, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 19, 17, 1, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 2, 19, 0, 226, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 11, 19, 18, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2 },
+ { 1, 19, 17, 220, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 1, 19, 17, 230, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 },
+ { 6, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5 },
+ { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4 },
+ { 27, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5 },
+ { 4, 10, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 7, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 8, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 4, 10, 2, 0, 0, 9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7 },
+ { 14, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 19, 12, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 13, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static inline const QUnicodeTables::Properties *qGetProp(uint ucs4)
+{
+ int index = GET_PROP_INDEX(ucs4);
+ return uc_properties + index;
+}
+
+static inline const QUnicodeTables::Properties *qGetProp(ushort ucs2)
+{
+ int index = GET_PROP_INDEX_UCS2(ucs2);
+ return uc_properties + index;
+}
+
+Q_CORE_EXPORT const QUnicodeTables::Properties * QT_FASTCALL QUnicodeTables::properties(uint ucs4)
+{
+ int index = GET_PROP_INDEX(ucs4);
+ return uc_properties + index;
+}
+
+Q_CORE_EXPORT const QUnicodeTables::Properties * QT_FASTCALL QUnicodeTables::properties(ushort ucs2)
+{
+ int index = GET_PROP_INDEX_UCS2(ucs2);
+ return uc_properties + index;
+}
+
+Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL QUnicodeTables::lineBreakClass(uint ucs4)
+{
+ return (QUnicodeTables::LineBreakClass)qGetProp(ucs4)->line_break_class;
+}
+
+static const ushort specialCaseMap[] = {
+ 0x53, 0x73, 0x0,
+ 0x53, 0x53, 0x0,
+ 0x69, 0x307, 0x0,
+ 0x46, 0x66, 0x0,
+ 0x46, 0x46, 0x0,
+ 0x46, 0x69, 0x0,
+ 0x46, 0x49, 0x0,
+ 0x46, 0x6c, 0x0,
+ 0x46, 0x4c, 0x0,
+ 0x46, 0x66, 0x69, 0x0,
+ 0x46, 0x46, 0x49, 0x0,
+ 0x46, 0x66, 0x6c, 0x0,
+ 0x46, 0x46, 0x4c, 0x0,
+ 0x53, 0x74, 0x0,
+ 0x53, 0x54, 0x0,
+ 0x535, 0x582, 0x0,
+ 0x535, 0x552, 0x0,
+ 0x544, 0x576, 0x0,
+ 0x544, 0x546, 0x0,
+ 0x544, 0x565, 0x0,
+ 0x544, 0x535, 0x0,
+ 0x544, 0x56b, 0x0,
+ 0x544, 0x53b, 0x0,
+ 0x54e, 0x576, 0x0,
+ 0x54e, 0x546, 0x0,
+ 0x544, 0x56d, 0x0,
+ 0x544, 0x53d, 0x0,
+ 0x2bc, 0x4e, 0x0,
+ 0x399, 0x308, 0x301, 0x0,
+ 0x3a5, 0x308, 0x301, 0x0,
+ 0x4a, 0x30c, 0x0,
+ 0x48, 0x331, 0x0,
+ 0x54, 0x308, 0x0,
+ 0x57, 0x30a, 0x0,
+ 0x59, 0x30a, 0x0,
+ 0x41, 0x2be, 0x0,
+ 0x3a5, 0x313, 0x0,
+ 0x3a5, 0x313, 0x300, 0x0,
+ 0x3a5, 0x313, 0x301, 0x0,
+ 0x3a5, 0x313, 0x342, 0x0,
+ 0x391, 0x342, 0x0,
+ 0x397, 0x342, 0x0,
+ 0x399, 0x308, 0x300, 0x0,
+ 0x399, 0x342, 0x0,
+ 0x399, 0x308, 0x342, 0x0,
+ 0x3a5, 0x308, 0x300, 0x0,
+ 0x3a1, 0x313, 0x0,
+ 0x3a5, 0x342, 0x0,
+ 0x3a5, 0x308, 0x342, 0x0,
+ 0x3a9, 0x342, 0x0,
+ 0x1f08, 0x399, 0x0,
+ 0x1f09, 0x399, 0x0,
+ 0x1f0a, 0x399, 0x0,
+ 0x1f0b, 0x399, 0x0,
+ 0x1f0c, 0x399, 0x0,
+ 0x1f0d, 0x399, 0x0,
+ 0x1f0e, 0x399, 0x0,
+ 0x1f0f, 0x399, 0x0,
+ 0x1f28, 0x399, 0x0,
+ 0x1f29, 0x399, 0x0,
+ 0x1f2a, 0x399, 0x0,
+ 0x1f2b, 0x399, 0x0,
+ 0x1f2c, 0x399, 0x0,
+ 0x1f2d, 0x399, 0x0,
+ 0x1f2e, 0x399, 0x0,
+ 0x1f2f, 0x399, 0x0,
+ 0x1f68, 0x399, 0x0,
+ 0x1f69, 0x399, 0x0,
+ 0x1f6a, 0x399, 0x0,
+ 0x1f6b, 0x399, 0x0,
+ 0x1f6c, 0x399, 0x0,
+ 0x1f6d, 0x399, 0x0,
+ 0x1f6e, 0x399, 0x0,
+ 0x1f6f, 0x399, 0x0,
+ 0x391, 0x399, 0x0,
+ 0x397, 0x399, 0x0,
+ 0x3a9, 0x399, 0x0,
+ 0x1fba, 0x345, 0x0,
+ 0x1fba, 0x399, 0x0,
+ 0x386, 0x345, 0x0,
+ 0x386, 0x399, 0x0,
+ 0x1fca, 0x345, 0x0,
+ 0x1fca, 0x399, 0x0,
+ 0x389, 0x345, 0x0,
+ 0x389, 0x399, 0x0,
+ 0x1ffa, 0x345, 0x0,
+ 0x1ffa, 0x399, 0x0,
+ 0x38f, 0x345, 0x0,
+ 0x38f, 0x399, 0x0,
+ 0x391, 0x342, 0x345, 0x0,
+ 0x391, 0x342, 0x399, 0x0,
+ 0x397, 0x342, 0x345, 0x0,
+ 0x397, 0x342, 0x399, 0x0,
+ 0x3a9, 0x342, 0x345, 0x0,
+ 0x3a9, 0x342, 0x399, 0x0
+
+};
+#define SPECIAL_CASE_MAX_LEN 3
+
+static const unsigned short uc_decomposition_trie[] = {
+ // 0 - 0x3400
+
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1564, 1580, 1596, 1612, 1628, 1644,
+ 1660, 1676, 1692, 1708, 1724, 1740, 1756, 1772,
+ 1548, 1548, 1788, 1804, 1820, 1836, 1852, 1868,
+ 1884, 1900, 1916, 1932, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1948, 1548, 1964, 1980, 1548,
+ 1548, 1548, 1548, 1548, 1996, 1548, 1548, 2012,
+ 2028, 2044, 2060, 2076, 2092, 2108, 1548, 2124,
+ 2140, 2156, 1548, 2172, 1548, 2188, 1548, 2204,
+ 1548, 1548, 1548, 1548, 2220, 2236, 2252, 2268,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 2284, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 2300, 1548, 1548, 1548, 1548, 2316,
+ 1548, 1548, 1548, 1548, 2332, 2348, 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, 2364, 2380, 1548, 2396, 1548, 1548,
+ 1548, 1548, 1548, 1548, 2412, 2428, 1548, 1548,
+ 1548, 1548, 1548, 2444, 1548, 2460, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 2476, 2492, 1548, 1548,
+ 1548, 2508, 1548, 1548, 2524, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 2540, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 2556, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 2572, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 2588, 1548, 1548,
+ 1548, 1548, 1548, 2604, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 2620, 1548, 2636, 1548, 1548,
+ 2652, 1548, 1548, 1548, 2668, 2684, 2700, 2716,
+ 2732, 2748, 2764, 2780, 1548, 1548, 1548, 1548,
+
+ 1548, 1548, 2796, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 2812,
+ 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, 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, 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, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 2828, 2844, 1548, 2860, 2876, 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, 2892, 2908, 2924, 2940, 2956, 2972,
+ 1548, 2988, 3004, 3020, 1548, 1548, 1548, 1548,
+ 3036, 3052, 3068, 3084, 3100, 3116, 3132, 3148,
+ 3164, 3180, 3196, 3212, 3228, 3244, 3260, 3276,
+ 3292, 3308, 3324, 3340, 3356, 3372, 3388, 3404,
+ 3420, 3436, 3452, 3468, 3484, 3500, 3516, 3532,
+
+ 3548, 3564, 3580, 3596, 3612, 3628, 1548, 3644,
+ 3660, 3676, 3692, 1548, 1548, 1548, 1548, 1548,
+ 3708, 3724, 3740, 3756, 3772, 3788, 3804, 3820,
+ 1548, 3836, 3852, 1548, 3868, 1548, 1548, 1548,
+ 3884, 1548, 3900, 3916, 3932, 1548, 3948, 3964,
+ 3980, 1548, 3996, 1548, 1548, 1548, 4012, 1548,
+ 1548, 1548, 4028, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 4044, 4060,
+ 4076, 4092, 4108, 4124, 4140, 4156, 4172, 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, 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,
+ 4188, 1548, 1548, 1548, 1548, 1548, 1548, 4204,
+ 1548, 1548, 1548, 1548, 1548, 4220, 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, 4236, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
+ 1548, 4252, 1548, 1548, 1548, 1548, 1548, 4268,
+ 4284, 4300, 4316, 4332, 4348, 4364, 4380, 4396,
+ 4412, 4428, 4444, 4460, 4476, 4492, 1548, 1548,
+
+ 4508, 1548, 1548, 4524, 4540, 4556, 4572, 4588,
+ 1548, 4604, 4620, 4636, 4652, 4668, 1548, 4684,
+ 1548, 1548, 1548, 4700, 4716, 4732, 4748, 4764,
+ 4780, 4796, 1548, 1548, 1548, 1548, 1548, 1548,
+ 4812, 4828, 4844, 4860, 4876, 4892, 4908, 4924,
+ 4940, 4956, 4972, 4988, 5004, 5020, 5036, 5052,
+ 5068, 5084, 5100, 5116, 5132, 5148, 5164, 5180,
+ 5196, 5212, 5228, 5244, 5260, 5276, 5292, 5308,
+
+ // 0x3400 - 0x30000
+
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+
+ 5324, 5324, 5324, 5324, 5324, 5580, 5836, 6092,
+ 6348, 6604, 6860, 7116, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 7372, 5324, 5324,
+ 7628, 7884, 8140, 8396, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+ 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324,
+
+ 5324, 5324, 5324, 5324, 8652, 8908, 9164, 5324,
+ 5324, 5324, 5324, 5324,
+
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2, 0xffff, 0x5, 0xffff, 0xffff, 0xffff, 0xffff, 0x7,
+
+ 0xffff, 0xffff, 0xa, 0xc, 0xe, 0x11, 0xffff, 0xffff,
+ 0x13, 0x16, 0x18, 0xffff, 0x1a, 0x1e, 0x22, 0xffff,
+
+ 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35, 0xffff, 0x38,
+ 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d, 0x50,
+
+ 0xffff, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0xffff,
+ 0xffff, 0x65, 0x68, 0x6b, 0x6e, 0x71, 0xffff, 0xffff,
+
+ 0x74, 0x77, 0x7a, 0x7d, 0x80, 0x83, 0xffff, 0x86,
+ 0x89, 0x8c, 0x8f, 0x92, 0x95, 0x98, 0x9b, 0x9e,
+
+ 0xffff, 0xa1, 0xa4, 0xa7, 0xaa, 0xad, 0xb0, 0xffff,
+ 0xffff, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xffff, 0xc2,
+
+ 0xc5, 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda,
+ 0xdd, 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2,
+
+ 0xffff, 0xffff, 0xf5, 0xf8, 0xfb, 0xfe, 0x101, 0x104,
+ 0x107, 0x10a, 0x10d, 0x110, 0x113, 0x116, 0x119, 0x11c,
+
+ 0x11f, 0x122, 0x125, 0x128, 0x12b, 0x12e, 0xffff, 0xffff,
+ 0x131, 0x134, 0x137, 0x13a, 0x13d, 0x140, 0x143, 0x146,
+
+ 0x149, 0xffff, 0x14c, 0x14f, 0x152, 0x155, 0x158, 0x15b,
+ 0xffff, 0x15e, 0x161, 0x164, 0x167, 0x16a, 0x16d, 0x170,
+
+ 0x173, 0xffff, 0xffff, 0x176, 0x179, 0x17c, 0x17f, 0x182,
+ 0x185, 0x188, 0xffff, 0xffff, 0x18b, 0x18e, 0x191, 0x194,
+
+ 0x197, 0x19a, 0xffff, 0xffff, 0x19d, 0x1a0, 0x1a3, 0x1a6,
+ 0x1a9, 0x1ac, 0x1af, 0x1b2, 0x1b5, 0x1b8, 0x1bb, 0x1be,
+
+ 0x1c1, 0x1c4, 0x1c7, 0x1ca, 0x1cd, 0x1d0, 0xffff, 0xffff,
+ 0x1d3, 0x1d6, 0x1d9, 0x1dc, 0x1df, 0x1e2, 0x1e5, 0x1e8,
+
+ 0x1eb, 0x1ee, 0x1f1, 0x1f4, 0x1f7, 0x1fa, 0x1fd, 0x200,
+ 0x203, 0x206, 0x209, 0x20c, 0x20f, 0x212, 0x215, 0x218,
+
+ 0x21a, 0x21d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x220,
+
+ 0x223, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x226, 0x229, 0x22c, 0x22f,
+ 0x232, 0x235, 0x238, 0x23b, 0x23e, 0x241, 0x244, 0x247,
+
+ 0x24a, 0x24d, 0x250, 0x253, 0x256, 0x259, 0x25c, 0x25f,
+ 0x262, 0x265, 0x268, 0x26b, 0x26e, 0xffff, 0x271, 0x274,
+
+ 0x277, 0x27a, 0x27d, 0x280, 0xffff, 0xffff, 0x283, 0x286,
+ 0x289, 0x28c, 0x28f, 0x292, 0x295, 0x298, 0x29b, 0x29e,
+
+ 0x2a1, 0x2a4, 0x2a7, 0x2aa, 0x2ad, 0x2b0, 0xffff, 0xffff,
+ 0x2b3, 0x2b6, 0x2b9, 0x2bc, 0x2bf, 0x2c2, 0x2c5, 0x2c8,
+
+ 0x2cb, 0x2ce, 0x2d1, 0x2d4, 0x2d7, 0x2da, 0x2dd, 0x2e0,
+ 0x2e3, 0x2e6, 0x2e9, 0x2ec, 0x2ef, 0x2f2, 0x2f5, 0x2f8,
+
+ 0x2fb, 0x2fe, 0x301, 0x304, 0x307, 0x30a, 0x30d, 0x310,
+ 0x313, 0x316, 0x319, 0x31c, 0xffff, 0xffff, 0x31f, 0x322,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x325, 0x328,
+ 0x32b, 0x32e, 0x331, 0x334, 0x337, 0x33a, 0x33d, 0x340,
+
+ 0x343, 0x346, 0x349, 0x34c, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x34f, 0x351, 0x353, 0x355, 0x357, 0x359, 0x35b, 0x35d,
+ 0x35f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x361, 0x364, 0x367, 0x36a, 0x36d, 0x370, 0xffff, 0xffff,
+
+ 0x373, 0x375, 0x377, 0x379, 0x37b, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x37d, 0x37f, 0xffff, 0x381, 0x383, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x386, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x388, 0xffff, 0xffff, 0xffff, 0x38b, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x38d, 0x390, 0x393, 0x396,
+ 0x398, 0x39b, 0x39e, 0xffff, 0x3a1, 0xffff, 0x3a4, 0x3a7,
+
+ 0x3aa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x3ad, 0x3b0, 0x3b3, 0x3b6, 0x3b9, 0x3bc,
+
+ 0x3bf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x3c2, 0x3c5, 0x3c8, 0x3cb, 0x3ce, 0xffff,
+
+ 0x3d1, 0x3d3, 0x3d5, 0x3d7, 0x3da, 0x3dd, 0x3df, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x3e1, 0x3e3, 0x3e5, 0xffff, 0x3e7, 0x3e9, 0xffff, 0xffff,
+ 0xffff, 0x3eb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x3ed, 0x3f0, 0xffff, 0x3f3, 0xffff, 0xffff, 0xffff, 0x3f6,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x3f9, 0x3fc, 0x3ff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x402, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x405, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x408, 0x40b, 0xffff, 0x40e, 0xffff, 0xffff, 0xffff, 0x411,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x414, 0x417, 0x41a, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x41d, 0x420,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0x423, 0x426, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x429, 0x42c, 0x42f, 0x432, 0xffff, 0xffff, 0x435, 0x438,
+ 0xffff, 0xffff, 0x43b, 0x43e, 0x441, 0x444, 0x447, 0x44a,
+
+ 0xffff, 0xffff, 0x44d, 0x450, 0x453, 0x456, 0x459, 0x45c,
+ 0xffff, 0xffff, 0x45f, 0x462, 0x465, 0x468, 0x46b, 0x46e,
+
+ 0x471, 0x474, 0x477, 0x47a, 0x47d, 0x480, 0xffff, 0xffff,
+ 0x483, 0x486, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x489,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0x48c, 0x48f, 0x492, 0x495, 0x498, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x49b, 0x49e, 0x4a1,
+ 0x4a4, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x4a7, 0xffff, 0x4aa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x4ad, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x4b0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0x4b3, 0xffff, 0xffff, 0x4b6, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x4b9, 0x4bc, 0x4bf, 0x4c2, 0x4c5, 0x4c8, 0x4cb, 0x4ce,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x4d1, 0x4d4, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x4d7, 0x4da, 0xffff, 0x4dd,
+
+ 0xffff, 0xffff, 0xffff, 0x4e0, 0xffff, 0xffff, 0x4e3, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x4e6, 0x4e9, 0x4ec, 0xffff, 0xffff, 0x4ef, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x4f2, 0xffff, 0xffff, 0x4f5, 0x4f8, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x4fb, 0x4fe, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x501, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x504, 0x507, 0x50a, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x50d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x510, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x513,
+ 0x516, 0xffff, 0x519, 0x51c, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x51f, 0x522, 0x525, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x528, 0xffff, 0x52b, 0x52e, 0x531, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x534, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x537, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x53a, 0x53d, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x540, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x542, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x545, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0x548, 0xffff, 0xffff, 0xffff, 0xffff, 0x54b,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x54e, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x551, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x554, 0xffff, 0x557, 0x55a, 0x55d,
+ 0x560, 0x563, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0x566, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x569, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x56c, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0x56f, 0xffff, 0xffff, 0xffff, 0xffff, 0x572,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x575, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x578, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x57b, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x57e, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x580, 0xffff,
+ 0x583, 0xffff, 0x586, 0xffff, 0x589, 0xffff, 0x58c, 0xffff,
+
+ 0xffff, 0xffff, 0x58f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x592, 0xffff, 0x595, 0xffff, 0xffff,
+
+ 0x598, 0x59b, 0xffff, 0x59e, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x5a1, 0x5a3, 0x5a5, 0xffff,
+
+ 0x5a7, 0x5a9, 0x5ab, 0x5ad, 0x5af, 0x5b1, 0x5b3, 0x5b5,
+ 0x5b7, 0x5b9, 0x5bb, 0xffff, 0x5bd, 0x5bf, 0x5c1, 0x5c3,
+
+ 0x5c5, 0x5c7, 0x5c9, 0x5cb, 0x5cd, 0x5cf, 0x5d1, 0x5d3,
+ 0x5d5, 0x5d7, 0x5d9, 0x5db, 0x5dd, 0x5df, 0xffff, 0x5e1,
+
+ 0x5e3, 0x5e5, 0x5e7, 0x5e9, 0x5eb, 0x5ed, 0x5ef, 0x5f1,
+ 0x5f3, 0x5f5, 0x5f7, 0x5f9, 0x5fb, 0x5fd, 0x5ff, 0x601,
+
+ 0x603, 0x605, 0x607, 0x609, 0x60b, 0x60d, 0x60f, 0x611,
+ 0x613, 0x615, 0x617, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x619, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x61b, 0x61d, 0x61f, 0x621, 0x623,
+
+ 0x625, 0x627, 0x629, 0x62b, 0x62d, 0x62f, 0x631, 0x633,
+ 0x635, 0x637, 0x639, 0x63b, 0x63d, 0x63f, 0x641, 0x643,
+
+ 0x645, 0x647, 0x649, 0x64b, 0x64d, 0x64f, 0x651, 0x653,
+ 0x655, 0x657, 0x659, 0x65b, 0x65d, 0x65f, 0x661, 0x663,
+
+ 0x665, 0x668, 0x66b, 0x66e, 0x671, 0x674, 0x677, 0x67a,
+ 0x67d, 0x680, 0x683, 0x686, 0x689, 0x68c, 0x68f, 0x692,
+
+ 0x695, 0x698, 0x69b, 0x69e, 0x6a1, 0x6a4, 0x6a7, 0x6aa,
+ 0x6ad, 0x6b0, 0x6b3, 0x6b6, 0x6b9, 0x6bc, 0x6bf, 0x6c2,
+
+ 0x6c5, 0x6c8, 0x6cb, 0x6ce, 0x6d1, 0x6d4, 0x6d7, 0x6da,
+ 0x6dd, 0x6e0, 0x6e3, 0x6e6, 0x6e9, 0x6ec, 0x6ef, 0x6f2,
+
+ 0x6f5, 0x6f8, 0x6fb, 0x6fe, 0x701, 0x704, 0x707, 0x70a,
+ 0x70d, 0x710, 0x713, 0x716, 0x719, 0x71c, 0x71f, 0x722,
+
+ 0x725, 0x728, 0x72b, 0x72e, 0x731, 0x734, 0x737, 0x73a,
+ 0x73d, 0x740, 0x743, 0x746, 0x749, 0x74c, 0x74f, 0x752,
+
+ 0x755, 0x758, 0x75b, 0x75e, 0x761, 0x764, 0x767, 0x76a,
+ 0x76d, 0x770, 0x773, 0x776, 0x779, 0x77c, 0x77f, 0x782,
+
+ 0x785, 0x788, 0x78b, 0x78e, 0x791, 0x794, 0x797, 0x79a,
+ 0x79d, 0x7a0, 0x7a3, 0x7a6, 0x7a9, 0x7ac, 0x7af, 0x7b2,
+
+ 0x7b5, 0x7b8, 0x7bb, 0x7be, 0x7c1, 0x7c4, 0x7c7, 0x7ca,
+ 0x7cd, 0x7d0, 0x7d3, 0x7d6, 0x7d9, 0x7dc, 0x7df, 0x7e2,
+
+ 0x7e5, 0x7e8, 0x7eb, 0x7ee, 0x7f1, 0x7f4, 0x7f7, 0x7fa,
+ 0x7fd, 0x800, 0x803, 0x806, 0x809, 0x80c, 0x80f, 0x812,
+
+ 0x815, 0x818, 0x81b, 0x81e, 0x821, 0x824, 0x827, 0x82a,
+ 0x82d, 0x830, 0x833, 0x836, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x839, 0x83c, 0x83f, 0x842, 0x845, 0x848, 0x84b, 0x84e,
+ 0x851, 0x854, 0x857, 0x85a, 0x85d, 0x860, 0x863, 0x866,
+
+ 0x869, 0x86c, 0x86f, 0x872, 0x875, 0x878, 0x87b, 0x87e,
+ 0x881, 0x884, 0x887, 0x88a, 0x88d, 0x890, 0x893, 0x896,
+
+ 0x899, 0x89c, 0x89f, 0x8a2, 0x8a5, 0x8a8, 0x8ab, 0x8ae,
+ 0x8b1, 0x8b4, 0x8b7, 0x8ba, 0x8bd, 0x8c0, 0x8c3, 0x8c6,
+
+ 0x8c9, 0x8cc, 0x8cf, 0x8d2, 0x8d5, 0x8d8, 0x8db, 0x8de,
+ 0x8e1, 0x8e4, 0x8e7, 0x8ea, 0x8ed, 0x8f0, 0x8f3, 0x8f6,
+
+ 0x8f9, 0x8fc, 0x8ff, 0x902, 0x905, 0x908, 0x90b, 0x90e,
+ 0x911, 0x914, 0x917, 0x91a, 0x91d, 0x920, 0x923, 0x926,
+
+ 0x929, 0x92c, 0x92f, 0x932, 0x935, 0x938, 0x93b, 0x93e,
+ 0x941, 0x944, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x947, 0x94a, 0x94d, 0x950, 0x953, 0x956, 0x959, 0x95c,
+ 0x95f, 0x962, 0x965, 0x968, 0x96b, 0x96e, 0x971, 0x974,
+
+ 0x977, 0x97a, 0x97d, 0x980, 0x983, 0x986, 0xffff, 0xffff,
+ 0x989, 0x98c, 0x98f, 0x992, 0x995, 0x998, 0xffff, 0xffff,
+
+ 0x99b, 0x99e, 0x9a1, 0x9a4, 0x9a7, 0x9aa, 0x9ad, 0x9b0,
+ 0x9b3, 0x9b6, 0x9b9, 0x9bc, 0x9bf, 0x9c2, 0x9c5, 0x9c8,
+
+ 0x9cb, 0x9ce, 0x9d1, 0x9d4, 0x9d7, 0x9da, 0x9dd, 0x9e0,
+ 0x9e3, 0x9e6, 0x9e9, 0x9ec, 0x9ef, 0x9f2, 0x9f5, 0x9f8,
+
+ 0x9fb, 0x9fe, 0xa01, 0xa04, 0xa07, 0xa0a, 0xffff, 0xffff,
+ 0xa0d, 0xa10, 0xa13, 0xa16, 0xa19, 0xa1c, 0xffff, 0xffff,
+
+ 0xa1f, 0xa22, 0xa25, 0xa28, 0xa2b, 0xa2e, 0xa31, 0xa34,
+ 0xffff, 0xa37, 0xffff, 0xa3a, 0xffff, 0xa3d, 0xffff, 0xa40,
+
+ 0xa43, 0xa46, 0xa49, 0xa4c, 0xa4f, 0xa52, 0xa55, 0xa58,
+ 0xa5b, 0xa5e, 0xa61, 0xa64, 0xa67, 0xa6a, 0xa6d, 0xa70,
+
+ 0xa73, 0xa76, 0xa78, 0xa7b, 0xa7d, 0xa80, 0xa82, 0xa85,
+ 0xa87, 0xa8a, 0xa8c, 0xa8f, 0xa91, 0xa94, 0xffff, 0xffff,
+
+ 0xa96, 0xa99, 0xa9c, 0xa9f, 0xaa2, 0xaa5, 0xaa8, 0xaab,
+ 0xaae, 0xab1, 0xab4, 0xab7, 0xaba, 0xabd, 0xac0, 0xac3,
+
+ 0xac6, 0xac9, 0xacc, 0xacf, 0xad2, 0xad5, 0xad8, 0xadb,
+ 0xade, 0xae1, 0xae4, 0xae7, 0xaea, 0xaed, 0xaf0, 0xaf3,
+
+ 0xaf6, 0xaf9, 0xafc, 0xaff, 0xb02, 0xb05, 0xb08, 0xb0b,
+ 0xb0e, 0xb11, 0xb14, 0xb17, 0xb1a, 0xb1d, 0xb20, 0xb23,
+
+ 0xb26, 0xb29, 0xb2c, 0xb2f, 0xb32, 0xffff, 0xb35, 0xb38,
+ 0xb3b, 0xb3e, 0xb41, 0xb44, 0xb46, 0xb49, 0xb4c, 0xb4e,
+
+ 0xb51, 0xb54, 0xb57, 0xb5a, 0xb5d, 0xffff, 0xb60, 0xb63,
+ 0xb66, 0xb69, 0xb6b, 0xb6e, 0xb70, 0xb73, 0xb76, 0xb79,
+
+ 0xb7c, 0xb7f, 0xb82, 0xb85, 0xffff, 0xffff, 0xb87, 0xb8a,
+ 0xb8d, 0xb90, 0xb93, 0xb96, 0xffff, 0xb98, 0xb9b, 0xb9e,
+
+ 0xba1, 0xba4, 0xba7, 0xbaa, 0xbac, 0xbaf, 0xbb2, 0xbb5,
+ 0xbb8, 0xbbb, 0xbbe, 0xbc1, 0xbc3, 0xbc6, 0xbc9, 0xbcb,
+
+ 0xffff, 0xffff, 0xbcd, 0xbd0, 0xbd3, 0xffff, 0xbd6, 0xbd9,
+ 0xbdc, 0xbdf, 0xbe1, 0xbe4, 0xbe6, 0xbe9, 0xbeb, 0xffff,
+
+ 0xbee, 0xbf0, 0xbf2, 0xbf4, 0xbf6, 0xbf8, 0xbfa, 0xbfc,
+ 0xbfe, 0xc00, 0xc02, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xc04, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc06,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xc09, 0xc0b, 0xc0e, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc12,
+
+ 0xffff, 0xffff, 0xffff, 0xc14, 0xc17, 0xffff, 0xc1b, 0xc1e,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xc22, 0xffff, 0xc25, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc28,
+ 0xc2b, 0xc2e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc31,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc36,
+
+ 0xc38, 0xc3a, 0xffff, 0xffff, 0xc3c, 0xc3e, 0xc40, 0xc42,
+ 0xc44, 0xc46, 0xc48, 0xc4a, 0xc4c, 0xc4e, 0xc50, 0xc52,
+
+ 0xc54, 0xc56, 0xc58, 0xc5a, 0xc5c, 0xc5e, 0xc60, 0xc62,
+ 0xc64, 0xc66, 0xc68, 0xc6a, 0xc6c, 0xc6e, 0xc70, 0xffff,
+
+ 0xc72, 0xc74, 0xc76, 0xc78, 0xc7a, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xc7c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xc7f, 0xc83, 0xc87, 0xc89, 0xffff, 0xc8c, 0xc90, 0xc94,
+ 0xffff, 0xc96, 0xc99, 0xc9b, 0xc9d, 0xc9f, 0xca1, 0xca3,
+
+ 0xca5, 0xca7, 0xca9, 0xcab, 0xffff, 0xcad, 0xcaf, 0xffff,
+ 0xffff, 0xcb2, 0xcb4, 0xcb6, 0xcb8, 0xcba, 0xffff, 0xffff,
+
+ 0xcbc, 0xcbf, 0xcc3, 0xffff, 0xcc6, 0xffff, 0xcc8, 0xffff,
+ 0xcca, 0xffff, 0xccc, 0xcce, 0xcd0, 0xcd2, 0xffff, 0xcd4,
+
+ 0xcd6, 0xcd8, 0xffff, 0xcda, 0xcdc, 0xcde, 0xce0, 0xce2,
+ 0xce4, 0xce6, 0xffff, 0xce8, 0xcec, 0xcee, 0xcf0, 0xcf2,
+
+ 0xcf4, 0xffff, 0xffff, 0xffff, 0xffff, 0xcf6, 0xcf8, 0xcfa,
+ 0xcfc, 0xcfe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10,
+ 0xd14, 0xd18, 0xd1c, 0xd20, 0xd24, 0xd28, 0xd2c, 0xd30,
+
+ 0xd33, 0xd35, 0xd38, 0xd3c, 0xd3f, 0xd41, 0xd44, 0xd48,
+ 0xd4d, 0xd50, 0xd52, 0xd55, 0xd59, 0xd5b, 0xd5d, 0xd5f,
+
+ 0xd61, 0xd63, 0xd66, 0xd6a, 0xd6d, 0xd6f, 0xd72, 0xd76,
+ 0xd7b, 0xd7e, 0xd80, 0xd83, 0xd87, 0xd89, 0xd8b, 0xd8d,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xd8f, 0xd92, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xd95, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xd98, 0xd9b, 0xd9e,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xda1, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xda4, 0xffff, 0xffff, 0xda7, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xdaa, 0xffff, 0xdad, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xdb0, 0xdb3, 0xffff, 0xdb7,
+
+ 0xdba, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xdbe, 0xffff, 0xffff, 0xdc1, 0xffff, 0xffff, 0xdc4,
+ 0xffff, 0xdc7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xdca, 0xffff, 0xdcd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xdd0, 0xdd3, 0xdd6,
+
+ 0xdd9, 0xddc, 0xffff, 0xffff, 0xddf, 0xde2, 0xffff, 0xffff,
+ 0xde5, 0xde8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xdeb, 0xdee, 0xffff, 0xffff, 0xdf1, 0xdf4, 0xffff, 0xffff,
+ 0xdf7, 0xdfa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xdfd, 0xe00, 0xe03, 0xe06,
+
+ 0xe09, 0xe0c, 0xe0f, 0xe12, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xe15, 0xe18, 0xe1b, 0xe1e, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xe21, 0xe23, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xe25, 0xe27, 0xe29, 0xe2b, 0xe2d, 0xe2f, 0xe31, 0xe33,
+ 0xe35, 0xe37, 0xe3a, 0xe3d, 0xe40, 0xe43, 0xe46, 0xe49,
+
+ 0xe4c, 0xe4f, 0xe52, 0xe55, 0xe58, 0xe5c, 0xe60, 0xe64,
+ 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe81, 0xe86,
+
+ 0xe8b, 0xe90, 0xe95, 0xe9a, 0xe9f, 0xea4, 0xea9, 0xeae,
+ 0xeb3, 0xeb6, 0xeb9, 0xebc, 0xebf, 0xec2, 0xec5, 0xec8,
+
+ 0xecb, 0xece, 0xed2, 0xed6, 0xeda, 0xede, 0xee2, 0xee6,
+ 0xeea, 0xeee, 0xef2, 0xef6, 0xefa, 0xefe, 0xf02, 0xf06,
+
+ 0xf0a, 0xf0e, 0xf12, 0xf16, 0xf1a, 0xf1e, 0xf22, 0xf26,
+ 0xf2a, 0xf2e, 0xf32, 0xf36, 0xf3a, 0xf3e, 0xf42, 0xf46,
+
+ 0xf4a, 0xf4e, 0xf52, 0xf56, 0xf5a, 0xf5e, 0xf62, 0xf64,
+ 0xf66, 0xf68, 0xf6a, 0xf6c, 0xf6e, 0xf70, 0xf72, 0xf74,
+
+ 0xf76, 0xf78, 0xf7a, 0xf7c, 0xf7e, 0xf80, 0xf82, 0xf84,
+ 0xf86, 0xf88, 0xf8a, 0xf8c, 0xf8e, 0xf90, 0xf92, 0xf94,
+
+ 0xf96, 0xf98, 0xf9a, 0xf9c, 0xf9e, 0xfa0, 0xfa2, 0xfa4,
+ 0xfa6, 0xfa8, 0xfaa, 0xfac, 0xfae, 0xfb0, 0xfb2, 0xfb4,
+
+ 0xfb6, 0xfb8, 0xfba, 0xfbc, 0xfbe, 0xfc0, 0xfc2, 0xfc4,
+ 0xfc6, 0xfc8, 0xfca, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xfcc, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xfd1, 0xfd5, 0xfd8, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xfdc, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfdf,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe1,
+
+ 0xffff, 0xffff, 0xffff, 0xfe3, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xfe5, 0xfe7, 0xfe9, 0xfeb, 0xfed, 0xfef, 0xff1, 0xff3,
+ 0xff5, 0xff7, 0xff9, 0xffb, 0xffd, 0xfff, 0x1001, 0x1003,
+
+ 0x1005, 0x1007, 0x1009, 0x100b, 0x100d, 0x100f, 0x1011, 0x1013,
+ 0x1015, 0x1017, 0x1019, 0x101b, 0x101d, 0x101f, 0x1021, 0x1023,
+
+ 0x1025, 0x1027, 0x1029, 0x102b, 0x102d, 0x102f, 0x1031, 0x1033,
+ 0x1035, 0x1037, 0x1039, 0x103b, 0x103d, 0x103f, 0x1041, 0x1043,
+
+ 0x1045, 0x1047, 0x1049, 0x104b, 0x104d, 0x104f, 0x1051, 0x1053,
+ 0x1055, 0x1057, 0x1059, 0x105b, 0x105d, 0x105f, 0x1061, 0x1063,
+
+ 0x1065, 0x1067, 0x1069, 0x106b, 0x106d, 0x106f, 0x1071, 0x1073,
+ 0x1075, 0x1077, 0x1079, 0x107b, 0x107d, 0x107f, 0x1081, 0x1083,
+
+ 0x1085, 0x1087, 0x1089, 0x108b, 0x108d, 0x108f, 0x1091, 0x1093,
+ 0x1095, 0x1097, 0x1099, 0x109b, 0x109d, 0x109f, 0x10a1, 0x10a3,
+
+ 0x10a5, 0x10a7, 0x10a9, 0x10ab, 0x10ad, 0x10af, 0x10b1, 0x10b3,
+ 0x10b5, 0x10b7, 0x10b9, 0x10bb, 0x10bd, 0x10bf, 0x10c1, 0x10c3,
+
+ 0x10c5, 0x10c7, 0x10c9, 0x10cb, 0x10cd, 0x10cf, 0x10d1, 0x10d3,
+ 0x10d5, 0x10d7, 0x10d9, 0x10db, 0x10dd, 0x10df, 0x10e1, 0x10e3,
+
+ 0x10e5, 0x10e7, 0x10e9, 0x10eb, 0x10ed, 0x10ef, 0x10f1, 0x10f3,
+ 0x10f5, 0x10f7, 0x10f9, 0x10fb, 0x10fd, 0x10ff, 0x1101, 0x1103,
+
+ 0x1105, 0x1107, 0x1109, 0x110b, 0x110d, 0x110f, 0x1111, 0x1113,
+ 0x1115, 0x1117, 0x1119, 0x111b, 0x111d, 0x111f, 0x1121, 0x1123,
+
+ 0x1125, 0x1127, 0x1129, 0x112b, 0x112d, 0x112f, 0x1131, 0x1133,
+ 0x1135, 0x1137, 0x1139, 0x113b, 0x113d, 0x113f, 0x1141, 0x1143,
+
+ 0x1145, 0x1147, 0x1149, 0x114b, 0x114d, 0x114f, 0x1151, 0x1153,
+ 0x1155, 0x1157, 0x1159, 0x115b, 0x115d, 0x115f, 0x1161, 0x1163,
+
+ 0x1165, 0x1167, 0x1169, 0x116b, 0x116d, 0x116f, 0x1171, 0x1173,
+ 0x1175, 0x1177, 0x1179, 0x117b, 0x117d, 0x117f, 0x1181, 0x1183,
+
+ 0x1185, 0x1187, 0x1189, 0x118b, 0x118d, 0x118f, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x1191, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1193, 0xffff,
+ 0x1195, 0x1197, 0x1199, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x119b, 0xffff, 0x119e, 0xffff,
+
+ 0x11a1, 0xffff, 0x11a4, 0xffff, 0x11a7, 0xffff, 0x11aa, 0xffff,
+ 0x11ad, 0xffff, 0x11b0, 0xffff, 0x11b3, 0xffff, 0x11b6, 0xffff,
+
+ 0x11b9, 0xffff, 0x11bc, 0xffff, 0xffff, 0x11bf, 0xffff, 0x11c2,
+ 0xffff, 0x11c5, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x11c8, 0x11cb, 0xffff, 0x11ce, 0x11d1, 0xffff, 0x11d4, 0x11d7,
+ 0xffff, 0x11da, 0x11dd, 0xffff, 0x11e0, 0x11e3, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x11e6, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x11e9, 0x11ec, 0xffff, 0x11ef, 0x11f2,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x11f5, 0xffff, 0x11f8, 0xffff,
+
+ 0x11fb, 0xffff, 0x11fe, 0xffff, 0x1201, 0xffff, 0x1204, 0xffff,
+ 0x1207, 0xffff, 0x120a, 0xffff, 0x120d, 0xffff, 0x1210, 0xffff,
+
+ 0x1213, 0xffff, 0x1216, 0xffff, 0xffff, 0x1219, 0xffff, 0x121c,
+ 0xffff, 0x121f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x1222, 0x1225, 0xffff, 0x1228, 0x122b, 0xffff, 0x122e, 0x1231,
+ 0xffff, 0x1234, 0x1237, 0xffff, 0x123a, 0x123d, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x1240, 0xffff, 0xffff, 0x1243,
+ 0x1246, 0x1249, 0x124c, 0xffff, 0xffff, 0xffff, 0x124f, 0x1252,
+
+ 0xffff, 0x1255, 0x1257, 0x1259, 0x125b, 0x125d, 0x125f, 0x1261,
+ 0x1263, 0x1265, 0x1267, 0x1269, 0x126b, 0x126d, 0x126f, 0x1271,
+
+ 0x1273, 0x1275, 0x1277, 0x1279, 0x127b, 0x127d, 0x127f, 0x1281,
+ 0x1283, 0x1285, 0x1287, 0x1289, 0x128b, 0x128d, 0x128f, 0x1291,
+
+ 0x1293, 0x1295, 0x1297, 0x1299, 0x129b, 0x129d, 0x129f, 0x12a1,
+ 0x12a3, 0x12a5, 0x12a7, 0x12a9, 0x12ab, 0x12ad, 0x12af, 0x12b1,
+
+ 0x12b3, 0x12b5, 0x12b7, 0x12b9, 0x12bb, 0x12bd, 0x12bf, 0x12c1,
+ 0x12c3, 0x12c5, 0x12c7, 0x12c9, 0x12cb, 0x12cd, 0x12cf, 0x12d1,
+
+ 0x12d3, 0x12d5, 0x12d7, 0x12d9, 0x12db, 0x12dd, 0x12df, 0x12e1,
+ 0x12e3, 0x12e5, 0x12e7, 0x12e9, 0x12eb, 0x12ed, 0x12ef, 0x12f1,
+
+ 0x12f3, 0x12f5, 0x12f7, 0x12f9, 0x12fb, 0x12fd, 0x12ff, 0x1301,
+ 0x1303, 0x1305, 0x1307, 0x1309, 0x130b, 0x130d, 0x130f, 0xffff,
+
+ 0xffff, 0xffff, 0x1311, 0x1313, 0x1315, 0x1317, 0x1319, 0x131b,
+ 0x131d, 0x131f, 0x1321, 0x1323, 0x1325, 0x1327, 0x1329, 0x132b,
+
+ 0x132d, 0x1331, 0x1335, 0x1339, 0x133d, 0x1341, 0x1345, 0x1349,
+ 0x134d, 0x1351, 0x1355, 0x1359, 0x135d, 0x1361, 0x1365, 0x136a,
+
+ 0x136f, 0x1374, 0x1379, 0x137e, 0x1383, 0x1388, 0x138d, 0x1392,
+ 0x1397, 0x139c, 0x13a1, 0x13a6, 0x13ab, 0x13b0, 0x13b8, 0xffff,
+
+ 0x13bf, 0x13c3, 0x13c7, 0x13cb, 0x13cf, 0x13d3, 0x13d7, 0x13db,
+ 0x13df, 0x13e3, 0x13e7, 0x13eb, 0x13ef, 0x13f3, 0x13f7, 0x13fb,
+
+ 0x13ff, 0x1403, 0x1407, 0x140b, 0x140f, 0x1413, 0x1417, 0x141b,
+ 0x141f, 0x1423, 0x1427, 0x142b, 0x142f, 0x1433, 0x1437, 0x143b,
+
+ 0x143f, 0x1443, 0x1447, 0x144b, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x144f, 0x1453, 0x1456, 0x1459, 0x145c, 0x145f, 0x1462, 0x1465,
+ 0x1468, 0x146b, 0x146e, 0x1471, 0x1474, 0x1477, 0x147a, 0x147d,
+
+ 0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148a, 0x148c, 0x148e,
+ 0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149a, 0x149c, 0x149f,
+
+ 0x14a2, 0x14a5, 0x14a8, 0x14ab, 0x14ae, 0x14b1, 0x14b4, 0x14b7,
+ 0x14ba, 0x14bd, 0x14c0, 0x14c3, 0x14c6, 0x14cc, 0x14d1, 0xffff,
+
+ 0x14d4, 0x14d6, 0x14d8, 0x14da, 0x14dc, 0x14de, 0x14e0, 0x14e2,
+ 0x14e4, 0x14e6, 0x14e8, 0x14ea, 0x14ec, 0x14ee, 0x14f0, 0x14f2,
+
+ 0x14f4, 0x14f6, 0x14f8, 0x14fa, 0x14fc, 0x14fe, 0x1500, 0x1502,
+ 0x1504, 0x1506, 0x1508, 0x150a, 0x150c, 0x150e, 0x1510, 0x1512,
+
+ 0x1514, 0x1516, 0x1518, 0x151a, 0x151c, 0x151e, 0x1520, 0x1522,
+ 0x1524, 0x1526, 0x1528, 0x152a, 0x152c, 0x152e, 0x1530, 0x1532,
+
+ 0x1534, 0x1536, 0x1539, 0x153c, 0x153f, 0x1542, 0x1545, 0x1548,
+ 0x154b, 0x154e, 0x1551, 0x1554, 0x1557, 0x155a, 0x155d, 0x1560,
+
+ 0x1563, 0x1566, 0x1569, 0x156c, 0x156f, 0x1572, 0x1575, 0x1578,
+ 0x157b, 0x157e, 0x1582, 0x1586, 0x158a, 0x158d, 0x1591, 0x1594,
+
+ 0x1598, 0x159a, 0x159c, 0x159e, 0x15a0, 0x15a2, 0x15a4, 0x15a6,
+ 0x15a8, 0x15aa, 0x15ac, 0x15ae, 0x15b0, 0x15b2, 0x15b4, 0x15b6,
+
+ 0x15b8, 0x15ba, 0x15bc, 0x15be, 0x15c0, 0x15c2, 0x15c4, 0x15c6,
+ 0x15c8, 0x15ca, 0x15cc, 0x15ce, 0x15d0, 0x15d2, 0x15d4, 0x15d6,
+
+ 0x15d8, 0x15da, 0x15dc, 0x15de, 0x15e0, 0x15e2, 0x15e4, 0x15e6,
+ 0x15e8, 0x15ea, 0x15ec, 0x15ee, 0x15f0, 0x15f2, 0x15f4, 0xffff,
+
+ 0x15f6, 0x15fb, 0x1600, 0x1605, 0x1609, 0x160e, 0x1612, 0x1616,
+ 0x161c, 0x1621, 0x1625, 0x1629, 0x162d, 0x1632, 0x1637, 0x163b,
+
+ 0x163f, 0x1642, 0x1646, 0x164b, 0x1650, 0x1653, 0x1659, 0x1660,
+ 0x1666, 0x166a, 0x1670, 0x1676, 0x167b, 0x167f, 0x1683, 0x1687,
+
+ 0x168c, 0x1692, 0x1697, 0x169b, 0x169f, 0x16a3, 0x16a6, 0x16a9,
+ 0x16ac, 0x16af, 0x16b3, 0x16b7, 0x16bd, 0x16c1, 0x16c6, 0x16cc,
+
+ 0x16d0, 0x16d3, 0x16d6, 0x16dc, 0x16e1, 0x16e7, 0x16eb, 0x16f1,
+ 0x16f4, 0x16f8, 0x16fc, 0x1700, 0x1704, 0x1708, 0x170d, 0x1711,
+
+ 0x1714, 0x1718, 0x171c, 0x1720, 0x1725, 0x1729, 0x172d, 0x1731,
+ 0x1737, 0x173c, 0x173f, 0x1745, 0x1748, 0x174d, 0x1752, 0x1756,
+
+ 0x175a, 0x175e, 0x1763, 0x1766, 0x176a, 0x176f, 0x1772, 0x1778,
+ 0x177c, 0x177f, 0x1782, 0x1785, 0x1788, 0x178b, 0x178e, 0x1791,
+
+ 0x1794, 0x1797, 0x179a, 0x179e, 0x17a2, 0x17a6, 0x17aa, 0x17ae,
+ 0x17b2, 0x17b6, 0x17ba, 0x17be, 0x17c2, 0x17c6, 0x17ca, 0x17ce,
+
+ 0x17d2, 0x17d6, 0x17da, 0x17dd, 0x17e0, 0x17e4, 0x17e7, 0x17ea,
+ 0x17ed, 0x17f1, 0x17f5, 0x17f8, 0x17fb, 0x17fe, 0x1801, 0x1804,
+
+ 0x1809, 0x180c, 0x180f, 0x1812, 0x1815, 0x1818, 0x181b, 0x181e,
+ 0x1821, 0x1825, 0x182a, 0x182d, 0x1830, 0x1833, 0x1836, 0x1839,
+
+ 0x183c, 0x183f, 0x1843, 0x1847, 0x184b, 0x184f, 0x1852, 0x1855,
+ 0x1858, 0x185b, 0x185e, 0x1861, 0x1864, 0x1867, 0x186a, 0x186d,
+
+ 0x1871, 0x1875, 0x1878, 0x187c, 0x1880, 0x1884, 0x1887, 0x188b,
+ 0x188f, 0x1894, 0x1897, 0x189b, 0x189f, 0x18a3, 0x18a7, 0x18ad,
+
+ 0x18b4, 0x18b7, 0x18ba, 0x18bd, 0x18c0, 0x18c3, 0x18c6, 0x18c9,
+ 0x18cc, 0x18cf, 0x18d2, 0x18d5, 0x18d8, 0x18db, 0x18de, 0x18e1,
+
+ 0x18e4, 0x18e7, 0x18ea, 0x18ef, 0x18f2, 0x18f5, 0x18f8, 0x18fd,
+ 0x1901, 0x1904, 0x1907, 0x190a, 0x190d, 0x1910, 0x1913, 0x1916,
+
+ 0x1919, 0x191c, 0x191f, 0x1923, 0x1926, 0x1929, 0x192d, 0x1931,
+ 0x1934, 0x1939, 0x193d, 0x1940, 0x1943, 0x1946, 0x1949, 0x194d,
+
+ 0x1951, 0x1954, 0x1957, 0x195a, 0x195d, 0x1960, 0x1963, 0x1966,
+ 0x1969, 0x196c, 0x1970, 0x1974, 0x1978, 0x197c, 0x1980, 0x1984,
+
+ 0x1988, 0x198c, 0x1990, 0x1994, 0x1998, 0x199c, 0x19a0, 0x19a4,
+ 0x19a8, 0x19ac, 0x19b0, 0x19b4, 0x19b8, 0x19bc, 0x19c0, 0x19c4,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x19c8, 0x19ca, 0x19cc, 0x19ce, 0x19d0, 0x19d2, 0x19d4, 0x19d6,
+ 0x19d8, 0x19da, 0x19dc, 0x19de, 0x19e0, 0x19e2, 0x19e4, 0x19e6,
+ 0x19e8, 0x19ea, 0x19ec, 0x19ee, 0x19f0, 0x19f2, 0x19f4, 0x19f6,
+ 0x19f8, 0x19fa, 0x19fc, 0x19fe, 0x1a00, 0x1a02, 0x1a04, 0x1a06,
+ 0x1a08, 0x1a0a, 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, 0xffff, 0xffff,
+ 0x1be4, 0xffff, 0x1be6, 0xffff, 0xffff, 0x1be8, 0x1bea, 0x1bec,
+ 0x1bee, 0x1bf0, 0x1bf2, 0x1bf4, 0x1bf6, 0x1bf8, 0x1bfa, 0xffff,
+ 0x1bfc, 0xffff, 0x1bfe, 0xffff, 0xffff, 0x1c00, 0x1c02, 0xffff,
+ 0xffff, 0xffff, 0x1c04, 0x1c06, 0x1c08, 0x1c0a, 0xffff, 0xffff,
+ 0x1c0c, 0x1c0e, 0x1c10, 0x1c12, 0x1c14, 0x1c16, 0x1c18, 0x1c1a,
+ 0x1c1c, 0x1c1e, 0x1c20, 0x1c22, 0x1c24, 0x1c26, 0x1c28, 0x1c2a,
+ 0x1c2c, 0x1c2e, 0x1c30, 0x1c32, 0x1c34, 0x1c36, 0x1c38, 0x1c3a,
+ 0x1c3c, 0x1c3e, 0x1c40, 0x1c42, 0x1c44, 0x1c46, 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, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 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, 0x1cd4, 0x1cd6, 0x1cd8, 0x1cda, 0x1cdc, 0x1cde, 0x1ce0,
+ 0x1ce2, 0x1ce4, 0x1ce6, 0x1ce8, 0x1cea, 0x1cec, 0x1cee, 0x1cf0,
+ 0x1cf2, 0x1cf4, 0x1cf6, 0x1cf8, 0x1cfa, 0x1cfc, 0x1cfe, 0x1d00,
+ 0x1d02, 0x1d04, 0x1d06, 0x1d08, 0x1d0a, 0x1d0c, 0x1d0e, 0x1d10,
+ 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e, 0x1d20,
+ 0x1d22, 0x1d24, 0x1d26, 0x1d28, 0x1d2a, 0x1d2c, 0x1d2e, 0x1d30,
+ 0x1d32, 0x1d34, 0x1d36, 0x1d38, 0x1d3a, 0x1d3c, 0x1d3e, 0x1d40,
+ 0x1d43, 0x1d46, 0x1d49, 0x1d4b, 0x1d4d, 0x1d4f, 0x1d52, 0x1d55,
+ 0x1d58, 0x1d5a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x1d5c, 0x1d5f, 0x1d62, 0x1d65, 0x1d69, 0x1d6d, 0x1d70, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x1d73, 0x1d76, 0x1d79, 0x1d7c, 0x1d7f,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1d82, 0xffff, 0x1d85,
+ 0x1d88, 0x1d8a, 0x1d8c, 0x1d8e, 0x1d90, 0x1d92, 0x1d94, 0x1d96,
+ 0x1d98, 0x1d9a, 0x1d9c, 0x1d9f, 0x1da2, 0x1da5, 0x1da8, 0x1dab,
+ 0x1dae, 0x1db1, 0x1db4, 0x1db7, 0x1dba, 0x1dbd, 0x1dc0, 0xffff,
+ 0x1dc3, 0x1dc6, 0x1dc9, 0x1dcc, 0x1dcf, 0xffff, 0x1dd2, 0xffff,
+ 0x1dd5, 0x1dd8, 0xffff, 0x1ddb, 0x1dde, 0xffff, 0x1de1, 0x1de4,
+ 0x1de7, 0x1dea, 0x1ded, 0x1df0, 0x1df3, 0x1df6, 0x1df9, 0x1dfc,
+ 0x1dff, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 0x1e0b, 0x1e0d,
+ 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 0x1e1d,
+ 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b, 0x1e2d,
+ 0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d,
+ 0x1e3f, 0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d,
+ 0x1e4f, 0x1e51, 0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d,
+ 0x1e5f, 0x1e61, 0x1e63, 0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d,
+ 0x1e6f, 0x1e71, 0x1e73, 0x1e75, 0x1e77, 0x1e79, 0x1e7b, 0x1e7d,
+ 0x1e7f, 0x1e81, 0x1e83, 0x1e85, 0x1e87, 0x1e89, 0x1e8b, 0x1e8d,
+ 0x1e8f, 0x1e91, 0x1e93, 0x1e95, 0x1e97, 0x1e99, 0x1e9b, 0x1e9d,
+ 0x1e9f, 0x1ea1, 0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9, 0x1eab, 0x1ead,
+ 0x1eaf, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb, 0x1ebd,
+ 0x1ebf, 0x1ec1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ec9, 0x1ecb,
+ 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed9, 0x1edb,
+ 0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9, 0x1eeb,
+ 0x1eed, 0x1eef, 0x1ef1, 0x1ef4, 0x1ef7, 0x1efa, 0x1efd, 0x1f00,
+ 0x1f03, 0x1f06, 0x1f09, 0x1f0c, 0x1f0f, 0x1f12, 0x1f15, 0x1f18,
+ 0x1f1b, 0x1f1e, 0x1f21, 0x1f24, 0x1f27, 0x1f29, 0x1f2b, 0x1f2d,
+
+ 0x1f2f, 0x1f32, 0x1f35, 0x1f38, 0x1f3b, 0x1f3e, 0x1f41, 0x1f44,
+ 0x1f47, 0x1f4a, 0x1f4d, 0x1f50, 0x1f53, 0x1f56, 0x1f59, 0x1f5c,
+ 0x1f5f, 0x1f62, 0x1f65, 0x1f68, 0x1f6b, 0x1f6e, 0x1f71, 0x1f74,
+ 0x1f77, 0x1f7a, 0x1f7d, 0x1f80, 0x1f83, 0x1f86, 0x1f89, 0x1f8c,
+ 0x1f8f, 0x1f92, 0x1f95, 0x1f98, 0x1f9b, 0x1f9e, 0x1fa1, 0x1fa4,
+ 0x1fa7, 0x1faa, 0x1fad, 0x1fb0, 0x1fb3, 0x1fb6, 0x1fb9, 0x1fbc,
+ 0x1fbf, 0x1fc2, 0x1fc5, 0x1fc8, 0x1fcb, 0x1fce, 0x1fd1, 0x1fd4,
+ 0x1fd7, 0x1fda, 0x1fdd, 0x1fe0, 0x1fe3, 0x1fe6, 0x1fe9, 0x1fec,
+ 0x1fef, 0x1ff2, 0x1ff5, 0x1ff8, 0x1ffb, 0x1ffe, 0x2001, 0x2004,
+ 0x2007, 0x200a, 0x200d, 0x2010, 0x2013, 0x2016, 0x2019, 0x201c,
+ 0x201f, 0x2022, 0x2025, 0x2028, 0x202b, 0x202e, 0x2031, 0x2034,
+ 0x2037, 0x203a, 0x203d, 0x2040, 0x2043, 0x2046, 0x2049, 0x204d,
+ 0x2051, 0x2055, 0x2059, 0x205d, 0x2061, 0x2064, 0x2067, 0x206a,
+ 0x206d, 0x2070, 0x2073, 0x2076, 0x2079, 0x207c, 0x207f, 0x2082,
+ 0x2085, 0x2088, 0x208b, 0x208e, 0x2091, 0x2094, 0x2097, 0x209a,
+ 0x209d, 0x20a0, 0x20a3, 0x20a6, 0x20a9, 0x20ac, 0x20af, 0x20b2,
+ 0x20b5, 0x20b8, 0x20bb, 0x20be, 0x20c1, 0x20c4, 0x20c7, 0x20ca,
+ 0x20cd, 0x20d0, 0x20d3, 0x20d6, 0x20d9, 0x20dc, 0x20df, 0x20e2,
+ 0x20e5, 0x20e8, 0x20eb, 0x20ee, 0x20f1, 0x20f4, 0x20f7, 0x20fa,
+ 0x20fd, 0x2100, 0x2103, 0x2106, 0x2109, 0x210c, 0x210f, 0x2112,
+ 0x2115, 0x2118, 0x211b, 0x211e, 0x2121, 0x2124, 0x2127, 0x212a,
+ 0x212d, 0x2130, 0x2133, 0x2136, 0x2139, 0x213c, 0x213f, 0x2142,
+ 0x2145, 0x2148, 0x214b, 0x214e, 0x2151, 0x2154, 0x2157, 0x215a,
+ 0x215d, 0x2160, 0x2163, 0x2166, 0x2169, 0x216c, 0x216f, 0x2172,
+ 0x2175, 0x2178, 0x217b, 0x217e, 0x2181, 0x2184, 0x2187, 0x218a,
+ 0x218d, 0x2190, 0x2193, 0x2196, 0x2199, 0x219c, 0x219f, 0x21a2,
+ 0x21a5, 0x21a8, 0x21ab, 0x21ae, 0x21b1, 0x21b4, 0x21b7, 0x21ba,
+ 0x21bd, 0x21c0, 0x21c3, 0x21c6, 0x21c9, 0x21cc, 0x21cf, 0x21d2,
+ 0x21d5, 0x21d8, 0x21db, 0x21de, 0x21e1, 0x21e4, 0x21e7, 0x21ea,
+ 0x21ed, 0x21f0, 0x21f3, 0x21f6, 0x21f9, 0x21fc, 0x21ff, 0x2202,
+ 0x2205, 0x2208, 0x220b, 0x220f, 0x2213, 0x2217, 0x221a, 0x221d,
+ 0x2220, 0x2223, 0x2226, 0x2229, 0x222c, 0x222f, 0x2232, 0x2235,
+
+ 0x2238, 0x223b, 0x223e, 0x2241, 0x2244, 0x2247, 0x224a, 0x224d,
+ 0x2250, 0x2253, 0x2256, 0x2259, 0x225c, 0x225f, 0x2262, 0x2265,
+ 0x2268, 0x226b, 0x226e, 0x2271, 0x2274, 0x2277, 0x227a, 0x227d,
+ 0x2280, 0x2283, 0x2286, 0x2289, 0x228c, 0x228f, 0x2292, 0x2295,
+ 0x2298, 0x229b, 0x229e, 0x22a1, 0x22a4, 0x22a7, 0x22aa, 0x22ad,
+ 0x22b0, 0x22b3, 0x22b6, 0x22b9, 0x22bc, 0x22bf, 0x22c2, 0x22c5,
+ 0x22c8, 0x22cb, 0x22ce, 0x22d1, 0x22d4, 0x22d7, 0x22da, 0x22dd,
+ 0x22e0, 0x22e3, 0x22e6, 0x22e9, 0x22ec, 0x22ef, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x22f2, 0x22f6, 0x22fa, 0x22fe, 0x2302, 0x2306, 0x230a, 0x230e,
+ 0x2312, 0x2316, 0x231a, 0x231e, 0x2322, 0x2326, 0x232a, 0x232e,
+ 0x2332, 0x2336, 0x233a, 0x233e, 0x2342, 0x2346, 0x234a, 0x234e,
+ 0x2352, 0x2356, 0x235a, 0x235e, 0x2362, 0x2366, 0x236a, 0x236e,
+ 0x2372, 0x2376, 0x237a, 0x237e, 0x2382, 0x2386, 0x238a, 0x238e,
+ 0x2392, 0x2396, 0x239a, 0x239e, 0x23a2, 0x23a6, 0x23aa, 0x23ae,
+ 0x23b2, 0x23b6, 0x23ba, 0x23be, 0x23c2, 0x23c6, 0x23ca, 0x23ce,
+ 0x23d2, 0x23d6, 0x23da, 0x23de, 0x23e2, 0x23e6, 0x23ea, 0x23ee,
+ 0xffff, 0xffff, 0x23f2, 0x23f6, 0x23fa, 0x23fe, 0x2402, 0x2406,
+ 0x240a, 0x240e, 0x2412, 0x2416, 0x241a, 0x241e, 0x2422, 0x2426,
+ 0x242a, 0x242e, 0x2432, 0x2436, 0x243a, 0x243e, 0x2442, 0x2446,
+ 0x244a, 0x244e, 0x2452, 0x2456, 0x245a, 0x245e, 0x2462, 0x2466,
+ 0x246a, 0x246e, 0x2472, 0x2476, 0x247a, 0x247e, 0x2482, 0x2486,
+ 0x248a, 0x248e, 0x2492, 0x2496, 0x249a, 0x249e, 0x24a2, 0x24a6,
+ 0x24aa, 0x24ae, 0x24b2, 0x24b6, 0x24ba, 0x24be, 0x24c2, 0x24c6,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x24ca, 0x24ce, 0x24d2, 0x24d7, 0x24dc, 0x24e1, 0x24e6, 0x24eb,
+ 0x24f0, 0x24f5, 0x24f9, 0x250c, 0x2515, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x251a, 0x251c, 0x251e, 0x2520, 0x2522, 0x2524, 0x2526, 0x2528,
+ 0x252a, 0x252c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x252e, 0x2530, 0x2532, 0x2534, 0x2536, 0x2538, 0x253a, 0x253c,
+ 0x253e, 0x2540, 0x2542, 0x2544, 0x2546, 0x2548, 0x254a, 0x254c,
+ 0x254e, 0x2550, 0x2552, 0x2554, 0x2556, 0xffff, 0xffff, 0x2558,
+ 0x255a, 0x255c, 0x255e, 0x2560, 0x2562, 0x2564, 0x2566, 0x2568,
+ 0x256a, 0x256c, 0x256e, 0xffff, 0x2570, 0x2572, 0x2574, 0x2576,
+ 0x2578, 0x257a, 0x257c, 0x257e, 0x2580, 0x2582, 0x2584, 0x2586,
+ 0x2588, 0x258a, 0x258c, 0x258e, 0x2590, 0x2592, 0x2594, 0xffff,
+ 0x2596, 0x2598, 0x259a, 0x259c, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x259e, 0x25a1, 0x25a4, 0xffff, 0x25a7, 0xffff, 0x25aa, 0x25ad,
+ 0x25b0, 0x25b3, 0x25b6, 0x25b9, 0x25bc, 0x25bf, 0x25c2, 0x25c5,
+ 0x25c8, 0x25ca, 0x25cc, 0x25ce, 0x25d0, 0x25d2, 0x25d4, 0x25d6,
+ 0x25d8, 0x25da, 0x25dc, 0x25de, 0x25e0, 0x25e2, 0x25e4, 0x25e6,
+ 0x25e8, 0x25ea, 0x25ec, 0x25ee, 0x25f0, 0x25f2, 0x25f4, 0x25f6,
+ 0x25f8, 0x25fa, 0x25fc, 0x25fe, 0x2600, 0x2602, 0x2604, 0x2606,
+ 0x2608, 0x260a, 0x260c, 0x260e, 0x2610, 0x2612, 0x2614, 0x2616,
+ 0x2618, 0x261a, 0x261c, 0x261e, 0x2620, 0x2622, 0x2624, 0x2626,
+ 0x2628, 0x262a, 0x262c, 0x262e, 0x2630, 0x2632, 0x2634, 0x2636,
+ 0x2638, 0x263a, 0x263c, 0x263e, 0x2640, 0x2642, 0x2644, 0x2646,
+ 0x2648, 0x264a, 0x264c, 0x264e, 0x2650, 0x2652, 0x2654, 0x2656,
+ 0x2658, 0x265a, 0x265c, 0x265e, 0x2660, 0x2662, 0x2664, 0x2666,
+ 0x2668, 0x266a, 0x266c, 0x266e, 0x2670, 0x2672, 0x2674, 0x2676,
+ 0x2678, 0x267a, 0x267c, 0x267e, 0x2680, 0x2682, 0x2684, 0x2686,
+ 0x2688, 0x268a, 0x268c, 0x268e, 0x2690, 0x2692, 0x2694, 0x2696,
+ 0x2698, 0x269a, 0x269c, 0x269e, 0x26a0, 0x26a2, 0x26a4, 0x26a6,
+ 0x26a8, 0x26aa, 0x26ac, 0x26ae, 0x26b0, 0x26b2, 0x26b5, 0x26b8,
+ 0x26bb, 0x26be, 0x26c1, 0x26c4, 0x26c7, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0x26ca, 0x26cc, 0x26ce, 0x26d0, 0x26d2, 0x26d4, 0x26d6,
+ 0x26d8, 0x26da, 0x26dc, 0x26de, 0x26e0, 0x26e2, 0x26e4, 0x26e6,
+ 0x26e8, 0x26ea, 0x26ec, 0x26ee, 0x26f0, 0x26f2, 0x26f4, 0x26f6,
+ 0x26f8, 0x26fa, 0x26fc, 0x26fe, 0x2700, 0x2702, 0x2704, 0x2706,
+ 0x2708, 0x270a, 0x270c, 0x270e, 0x2710, 0x2712, 0x2714, 0x2716,
+ 0x2718, 0x271a, 0x271c, 0x271e, 0x2720, 0x2722, 0x2724, 0x2726,
+ 0x2728, 0x272a, 0x272c, 0x272e, 0x2730, 0x2732, 0x2734, 0x2736,
+ 0x2738, 0x273a, 0x273c, 0x273e, 0x2740, 0x2742, 0x2744, 0x2746,
+ 0x2748, 0x274a, 0x274c, 0x274e, 0x2750, 0x2752, 0x2754, 0x2756,
+ 0x2758, 0x275a, 0x275c, 0x275e, 0x2760, 0x2762, 0x2764, 0x2766,
+ 0x2768, 0x276a, 0x276c, 0x276e, 0x2770, 0x2772, 0x2774, 0x2776,
+ 0x2778, 0x277a, 0x277c, 0x277e, 0x2780, 0x2782, 0x2784, 0x2786,
+ 0x2788, 0x278a, 0x278c, 0x278e, 0x2790, 0x2792, 0x2794, 0x2796,
+ 0x2798, 0x279a, 0x279c, 0x279e, 0x27a0, 0x27a2, 0x27a4, 0x27a6,
+ 0x27a8, 0x27aa, 0x27ac, 0x27ae, 0x27b0, 0x27b2, 0x27b4, 0x27b6,
+ 0x27b8, 0x27ba, 0x27bc, 0x27be, 0x27c0, 0x27c2, 0x27c4, 0x27c6,
+ 0x27c8, 0x27ca, 0x27cc, 0x27ce, 0x27d0, 0x27d2, 0x27d4, 0x27d6,
+ 0x27d8, 0x27da, 0x27dc, 0x27de, 0x27e0, 0x27e2, 0x27e4, 0x27e6,
+ 0x27e8, 0x27ea, 0x27ec, 0x27ee, 0x27f0, 0x27f2, 0x27f4, 0x27f6,
+ 0x27f8, 0x27fa, 0x27fc, 0x27fe, 0x2800, 0x2802, 0x2804, 0x2806,
+ 0x2808, 0x280a, 0x280c, 0x280e, 0x2810, 0x2812, 0x2814, 0x2816,
+ 0x2818, 0x281a, 0x281c, 0x281e, 0x2820, 0x2822, 0x2824, 0x2826,
+ 0x2828, 0x282a, 0x282c, 0x282e, 0x2830, 0x2832, 0x2834, 0x2836,
+ 0x2838, 0x283a, 0x283c, 0x283e, 0x2840, 0x2842, 0x2844, 0xffff,
+ 0xffff, 0xffff, 0x2846, 0x2848, 0x284a, 0x284c, 0x284e, 0x2850,
+ 0xffff, 0xffff, 0x2852, 0x2854, 0x2856, 0x2858, 0x285a, 0x285c,
+ 0xffff, 0xffff, 0x285e, 0x2860, 0x2862, 0x2864, 0x2866, 0x2868,
+ 0xffff, 0xffff, 0x286a, 0x286c, 0x286e, 0xffff, 0xffff, 0xffff,
+ 0x2870, 0x2872, 0x2874, 0x2876, 0x2878, 0x287a, 0x287c, 0xffff,
+ 0x287e, 0x2880, 0x2882, 0x2884, 0x2886, 0x2888, 0x288a, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x288c, 0x2891,
+ 0x2896, 0x289b, 0x28a0, 0x28a5, 0x28aa, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x28af, 0x28b4, 0x28b9, 0x28be, 0x28c3,
+ 0x28c8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x28cd, 0x28cf, 0x28d1, 0x28d3, 0x28d5, 0x28d7, 0x28d9, 0x28db,
+ 0x28dd, 0x28df, 0x28e1, 0x28e3, 0x28e5, 0x28e7, 0x28e9, 0x28eb,
+ 0x28ed, 0x28ef, 0x28f1, 0x28f3, 0x28f5, 0x28f7, 0x28f9, 0x28fb,
+ 0x28fd, 0x28ff, 0x2901, 0x2903, 0x2905, 0x2907, 0x2909, 0x290b,
+ 0x290d, 0x290f, 0x2911, 0x2913, 0x2915, 0x2917, 0x2919, 0x291b,
+ 0x291d, 0x291f, 0x2921, 0x2923, 0x2925, 0x2927, 0x2929, 0x292b,
+ 0x292d, 0x292f, 0x2931, 0x2933, 0x2935, 0x2937, 0x2939, 0x293b,
+ 0x293d, 0x293f, 0x2941, 0x2943, 0x2945, 0x2947, 0x2949, 0x294b,
+ 0x294d, 0x294f, 0x2951, 0x2953, 0x2955, 0x2957, 0x2959, 0x295b,
+ 0x295d, 0x295f, 0x2961, 0x2963, 0x2965, 0x2967, 0x2969, 0x296b,
+ 0x296d, 0x296f, 0x2971, 0x2973, 0x2975, 0xffff, 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, 0xffff, 0x2a05, 0x2a07,
+ 0xffff, 0xffff, 0x2a09, 0xffff, 0xffff, 0x2a0b, 0x2a0d, 0xffff,
+ 0xffff, 0x2a0f, 0x2a11, 0x2a13, 0x2a15, 0xffff, 0x2a17, 0x2a19,
+ 0x2a1b, 0x2a1d, 0x2a1f, 0x2a21, 0x2a23, 0x2a25, 0x2a27, 0x2a29,
+ 0x2a2b, 0x2a2d, 0xffff, 0x2a2f, 0xffff, 0x2a31, 0x2a33, 0x2a35,
+ 0x2a37, 0x2a39, 0x2a3b, 0x2a3d, 0xffff, 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,
+ 0x2a95, 0x2a97, 0x2a99, 0x2a9b, 0x2a9d, 0x2a9f, 0x2aa1, 0x2aa3,
+ 0x2aa5, 0x2aa7, 0x2aa9, 0x2aab, 0x2aad, 0x2aaf, 0x2ab1, 0x2ab3,
+
+ 0x2ab5, 0x2ab7, 0x2ab9, 0x2abb, 0x2abd, 0x2abf, 0xffff, 0x2ac1,
+ 0x2ac3, 0x2ac5, 0x2ac7, 0xffff, 0xffff, 0x2ac9, 0x2acb, 0x2acd,
+ 0x2acf, 0x2ad1, 0x2ad3, 0x2ad5, 0x2ad7, 0xffff, 0x2ad9, 0x2adb,
+ 0x2add, 0x2adf, 0x2ae1, 0x2ae3, 0x2ae5, 0xffff, 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, 0xffff, 0x2b1f, 0x2b21, 0x2b23, 0x2b25, 0xffff,
+ 0x2b27, 0x2b29, 0x2b2b, 0x2b2d, 0x2b2f, 0xffff, 0x2b31, 0xffff,
+ 0xffff, 0xffff, 0x2b33, 0x2b35, 0x2b37, 0x2b39, 0x2b3b, 0x2b3d,
+ 0x2b3f, 0xffff, 0x2b41, 0x2b43, 0x2b45, 0x2b47, 0x2b49, 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, 0x2bc1, 0x2bc3, 0x2bc5, 0x2bc7, 0x2bc9, 0x2bcb,
+ 0x2bcd, 0x2bcf, 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,
+ 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, 0xffff, 0xffff,
+ 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,
+ 0x2ea9, 0x2eab, 0x2ead, 0x2eaf, 0x2eb1, 0x2eb3, 0x2eb5, 0x2eb7,
+ 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, 0xffff, 0xffff, 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, 0x309e, 0x30a0, 0x30a2, 0x30a4,
+ 0x30a6, 0x30a8, 0x30aa, 0x30ac, 0x30ae, 0x30b0, 0x30b3, 0x30b5,
+ 0x30b7, 0x30b9, 0x30bb, 0x30be, 0x30c0, 0x30c2, 0x30c4, 0x30c7,
+ 0x30c9, 0x30cb, 0x30cd, 0x30cf, 0x30d1, 0x30d4, 0x30d6, 0x30d8,
+ 0x30da, 0x30dc, 0x30de, 0x30e0, 0x30e2, 0x30e4, 0x30e6, 0x30e8,
+ 0x30ea, 0x30ec, 0x30ee, 0x30f0, 0x30f2, 0x30f4, 0x30f6, 0x30f8,
+ 0x30fa, 0x30fc, 0x30fe, 0x3100, 0x3102, 0x3105, 0x3107, 0x3109,
+ 0x310b, 0x310e, 0x3110, 0x3112, 0x3114, 0x3116, 0x3118, 0x311a,
+ 0x311c, 0x311e, 0x3120, 0x3122, 0x3124, 0x3126, 0x3128, 0x312a,
+ 0x312c, 0x312e, 0x3130, 0x3132, 0x3134, 0x3136, 0x3138, 0x313a,
+ 0x313c, 0x313e, 0x3140, 0x3142, 0x3144, 0x3146, 0x3148, 0x314a,
+ 0x314c, 0x314e, 0x3151, 0x3153, 0x3155, 0x3157, 0x3159, 0x315b,
+ 0x315d, 0x3160, 0x3163, 0x3165, 0x3167, 0x3169, 0x316b, 0x316d,
+ 0x316f, 0x3171, 0x3173, 0x3175, 0x3177, 0x317a, 0x317c, 0x317e,
+ 0x3180, 0x3182, 0x3185, 0x3187, 0x3189, 0x318b, 0x318d, 0x318f,
+ 0x3191, 0x3193, 0x3195, 0x3197, 0x319a, 0x319c, 0x319f, 0x31a1,
+ 0x31a3, 0x31a5, 0x31a7, 0x31a9, 0x31ab, 0x31ad, 0x31af, 0x31b1,
+ 0x31b3, 0x31b5, 0x31b8, 0x31ba, 0x31bc, 0x31be, 0x31c0, 0x31c2,
+ 0x31c5, 0x31c7, 0x31ca, 0x31cd, 0x31cf, 0x31d1, 0x31d3, 0x31d5,
+ 0x31d8, 0x31db, 0x31dd, 0x31df, 0x31e1, 0x31e3, 0x31e5, 0x31e7,
+ 0x31e9, 0x31eb, 0x31ed, 0x31ef, 0x31f1, 0x31f4, 0x31f6, 0x31f8,
+ 0x31fa, 0x31fc, 0x31fe, 0x3200, 0x3202, 0x3204, 0x3206, 0x3208,
+ 0x320a, 0x320c, 0x320e, 0x3210, 0x3212, 0x3214, 0x3216, 0x3218,
+ 0x321a, 0x321d, 0x321f, 0x3221, 0x3223, 0x3225, 0x3227, 0x322a,
+ 0x322c, 0x322e, 0x3230, 0x3232, 0x3234, 0x3236, 0x3238, 0x323a,
+ 0x323c, 0x323e, 0x3240, 0x3243, 0x3245, 0x3247, 0x3249, 0x324b,
+ 0x324d, 0x324f, 0x3251, 0x3253, 0x3255, 0x3257, 0x3259, 0x325b,
+ 0x325d, 0x325f, 0x3261, 0x3263, 0x3265, 0x3267, 0x326a, 0x326c,
+ 0x326e, 0x3270, 0x3272, 0x3274, 0x3277, 0x3279, 0x327b, 0x327d,
+ 0x327f, 0x3281, 0x3283, 0x3285, 0x3287, 0x328a, 0x328c, 0x328e,
+ 0x3290, 0x3293, 0x3295, 0x3297, 0x3299, 0x329b, 0x329d, 0x329f,
+ 0x32a2, 0x32a5, 0x32a8, 0x32aa, 0x32ad, 0x32af, 0x32b1, 0x32b3,
+
+ 0x32b5, 0x32b7, 0x32b9, 0x32bb, 0x32bd, 0x32bf, 0x32c1, 0x32c4,
+ 0x32c6, 0x32c8, 0x32ca, 0x32cc, 0x32ce, 0x32d0, 0x32d3, 0x32d5,
+ 0x32d7, 0x32da, 0x32dd, 0x32df, 0x32e1, 0x32e3, 0x32e5, 0x32e7,
+ 0x32e9, 0x32eb, 0x32ed, 0x32ef, 0x32f2, 0x32f4, 0x32f7, 0x32f9,
+ 0x32fc, 0x32fe, 0x3300, 0x3302, 0x3305, 0x3307, 0x3309, 0x330c,
+ 0x330f, 0x3311, 0x3313, 0x3315, 0x3317, 0x3319, 0x331b, 0x331d,
+ 0x331f, 0x3321, 0x3323, 0x3325, 0x3327, 0x3329, 0x332c, 0x332e,
+ 0x3331, 0x3333, 0x3336, 0x3338, 0x333b, 0x333e, 0x3341, 0x3343,
+ 0x3345, 0x3347, 0x334a, 0x334d, 0x3350, 0x3353, 0x3355, 0x3357,
+ 0x3359, 0x335b, 0x335d, 0x335f, 0x3361, 0x3363, 0x3366, 0x3368,
+ 0x336a, 0x336c, 0x336e, 0x3371, 0x3373, 0x3376, 0x3379, 0x337b,
+ 0x337d, 0x337f, 0x3381, 0x3383, 0x3385, 0x3388, 0x338b, 0x338e,
+ 0x3390, 0x3392, 0x3395, 0x3397, 0x3399, 0x339b, 0x339e, 0x33a0,
+ 0x33a2, 0x33a4, 0x33a6, 0x33a8, 0x33ab, 0x33ad, 0x33af, 0x33b1,
+ 0x33b3, 0x33b5, 0x33b7, 0x33ba, 0x33bd, 0x33bf, 0x33c2, 0x33c4,
+ 0x33c7, 0x33c9, 0x33cb, 0x33cd, 0x33d0, 0x33d3, 0x33d5, 0x33d8,
+ 0x33da, 0x33dd, 0x33df, 0x33e1, 0x33e3, 0x33e5, 0x33e7, 0x33e9,
+ 0x33ec, 0x33ef, 0x33f2, 0x33f5, 0x33f7, 0x33f9, 0x33fb, 0x33fd,
+ 0x33ff, 0x3401, 0x3403, 0x3405, 0x3407, 0x3409, 0x340b, 0x340d,
+ 0x3410, 0x3412, 0x3414, 0x3416, 0x3418, 0x341a, 0x341c, 0x341e,
+ 0x3420, 0x3422, 0x3424, 0x3426, 0x3428, 0x342b, 0x342e, 0x3431,
+ 0x3433, 0x3435, 0x3437, 0x3439, 0x343c, 0x343e, 0x3441, 0x3443,
+ 0x3445, 0x3448, 0x344b, 0x344d, 0x344f, 0x3451, 0x3453, 0x3455,
+ 0x3457, 0x3459, 0x345b, 0x345d, 0x345f, 0x3461, 0x3463, 0x3465,
+ 0x3467, 0x3469, 0x346b, 0x346d, 0x346f, 0x3471, 0x3474, 0x3476,
+ 0x3478, 0x347a, 0x347c, 0x347e, 0x3481, 0x3484, 0x3486, 0x3488,
+ 0x348a, 0x348c, 0x348e, 0x3490, 0x3493, 0x3495, 0x3497, 0x3499,
+ 0x349b, 0x349e, 0x34a1, 0x34a3, 0x34a5, 0x34a7, 0x34aa, 0x34ac,
+ 0x34ae, 0x34b1, 0x34b4, 0x34b6, 0x34b8, 0x34ba, 0x34bd, 0x34bf,
+ 0x34c1, 0x34c3, 0x34c5, 0x34c7, 0x34c9, 0x34cb, 0x34ce, 0x34d0,
+ 0x34d2, 0x34d4, 0x34d7, 0x34d9, 0x34db, 0x34dd, 0x34df, 0x34e2,
+ 0x34e5, 0x34e7, 0x34e9, 0x34eb, 0x34ee, 0x34f0, 0x34f3, 0x34f5,
+
+ 0x34f7, 0x34f9, 0x34fc, 0x34fe, 0x3500, 0x3502, 0x3504, 0x3506,
+ 0x3508, 0x350a, 0x350d, 0x350f, 0x3511, 0x3513, 0x3515, 0x3517,
+ 0x3519, 0x351c, 0x351e, 0x3521, 0x3524, 0x3527, 0x3529, 0x352b,
+ 0x352d, 0x352f, 0x3531, 0x3533, 0x3535, 0x3537, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+};
+
+#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))
+
+static const 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,
+ 0x109, 0x6f, 0x311, 0x31, 0x2044, 0x34, 0x311, 0x31,
+ 0x2044, 0x32, 0x311, 0x33, 0x2044, 0x34, 0x201, 0x41,
+ 0x300, 0x201, 0x41, 0x301, 0x201, 0x41, 0x302, 0x201,
+ 0x41, 0x303, 0x201, 0x41, 0x308, 0x201, 0x41, 0x30a,
+ 0x201, 0x43, 0x327, 0x201, 0x45, 0x300, 0x201, 0x45,
+ 0x301, 0x201, 0x45, 0x302, 0x201, 0x45, 0x308, 0x201,
+ 0x49, 0x300, 0x201, 0x49, 0x301, 0x201, 0x49, 0x302,
+ 0x201, 0x49, 0x308, 0x201, 0x4e, 0x303, 0x201, 0x4f,
+ 0x300, 0x201, 0x4f, 0x301, 0x201, 0x4f, 0x302, 0x201,
+ 0x4f, 0x303, 0x201, 0x4f, 0x308, 0x201, 0x55, 0x300,
+ 0x201, 0x55, 0x301, 0x201, 0x55, 0x302, 0x201, 0x55,
+ 0x308, 0x201, 0x59, 0x301, 0x201, 0x61, 0x300, 0x201,
+ 0x61, 0x301, 0x201, 0x61, 0x302, 0x201, 0x61, 0x303,
+ 0x201, 0x61, 0x308, 0x201, 0x61, 0x30a, 0x201, 0x63,
+ 0x327, 0x201, 0x65, 0x300, 0x201, 0x65, 0x301, 0x201,
+ 0x65, 0x302, 0x201, 0x65, 0x308, 0x201, 0x69, 0x300,
+ 0x201, 0x69, 0x301, 0x201, 0x69, 0x302, 0x201, 0x69,
+ 0x308, 0x201, 0x6e, 0x303, 0x201, 0x6f, 0x300, 0x201,
+ 0x6f, 0x301, 0x201, 0x6f, 0x302, 0x201, 0x6f, 0x303,
+ 0x201, 0x6f, 0x308, 0x201, 0x75, 0x300, 0x201, 0x75,
+ 0x301, 0x201, 0x75, 0x302, 0x201, 0x75, 0x308, 0x201,
+ 0x79, 0x301, 0x201, 0x79, 0x308, 0x201, 0x41, 0x304,
+ 0x201, 0x61, 0x304, 0x201, 0x41, 0x306, 0x201, 0x61,
+ 0x306, 0x201, 0x41, 0x328, 0x201, 0x61, 0x328, 0x201,
+ 0x43, 0x301, 0x201, 0x63, 0x301, 0x201, 0x43, 0x302,
+ 0x201, 0x63, 0x302, 0x201, 0x43, 0x307, 0x201, 0x63,
+ 0x307, 0x201, 0x43, 0x30c, 0x201, 0x63, 0x30c, 0x201,
+ 0x44, 0x30c, 0x201, 0x64, 0x30c, 0x201, 0x45, 0x304,
+ 0x201, 0x65, 0x304, 0x201, 0x45, 0x306, 0x201, 0x65,
+ 0x306, 0x201, 0x45, 0x307, 0x201, 0x65, 0x307, 0x201,
+ 0x45, 0x328, 0x201, 0x65, 0x328, 0x201, 0x45, 0x30c,
+ 0x201, 0x65, 0x30c, 0x201, 0x47, 0x302, 0x201, 0x67,
+ 0x302, 0x201, 0x47, 0x306, 0x201, 0x67, 0x306, 0x201,
+ 0x47, 0x307, 0x201, 0x67, 0x307, 0x201, 0x47, 0x327,
+ 0x201, 0x67, 0x327, 0x201, 0x48, 0x302, 0x201, 0x68,
+ 0x302, 0x201, 0x49, 0x303, 0x201, 0x69, 0x303, 0x201,
+ 0x49, 0x304, 0x201, 0x69, 0x304, 0x201, 0x49, 0x306,
+ 0x201, 0x69, 0x306, 0x201, 0x49, 0x328, 0x201, 0x69,
+ 0x328, 0x201, 0x49, 0x307, 0x210, 0x49, 0x4a, 0x210,
+ 0x69, 0x6a, 0x201, 0x4a, 0x302, 0x201, 0x6a, 0x302,
+ 0x201, 0x4b, 0x327, 0x201, 0x6b, 0x327, 0x201, 0x4c,
+ 0x301, 0x201, 0x6c, 0x301, 0x201, 0x4c, 0x327, 0x201,
+ 0x6c, 0x327, 0x201, 0x4c, 0x30c, 0x201, 0x6c, 0x30c,
+ 0x210, 0x4c, 0xb7, 0x210, 0x6c, 0xb7, 0x201, 0x4e,
+ 0x301, 0x201, 0x6e, 0x301, 0x201, 0x4e, 0x327, 0x201,
+ 0x6e, 0x327, 0x201, 0x4e, 0x30c, 0x201, 0x6e, 0x30c,
+ 0x210, 0x2bc, 0x6e, 0x201, 0x4f, 0x304, 0x201, 0x6f,
+ 0x304, 0x201, 0x4f, 0x306, 0x201, 0x6f, 0x306, 0x201,
+ 0x4f, 0x30b, 0x201, 0x6f, 0x30b, 0x201, 0x52, 0x301,
+ 0x201, 0x72, 0x301, 0x201, 0x52, 0x327, 0x201, 0x72,
+ 0x327, 0x201, 0x52, 0x30c, 0x201, 0x72, 0x30c, 0x201,
+ 0x53, 0x301, 0x201, 0x73, 0x301, 0x201, 0x53, 0x302,
+ 0x201, 0x73, 0x302, 0x201, 0x53, 0x327, 0x201, 0x73,
+ 0x327, 0x201, 0x53, 0x30c, 0x201, 0x73, 0x30c, 0x201,
+ 0x54, 0x327, 0x201, 0x74, 0x327, 0x201, 0x54, 0x30c,
+ 0x201, 0x74, 0x30c, 0x201, 0x55, 0x303, 0x201, 0x75,
+ 0x303, 0x201, 0x55, 0x304, 0x201, 0x75, 0x304, 0x201,
+ 0x55, 0x306, 0x201, 0x75, 0x306, 0x201, 0x55, 0x30a,
+ 0x201, 0x75, 0x30a, 0x201, 0x55, 0x30b, 0x201, 0x75,
+ 0x30b, 0x201, 0x55, 0x328, 0x201, 0x75, 0x328, 0x201,
+ 0x57, 0x302, 0x201, 0x77, 0x302, 0x201, 0x59, 0x302,
+ 0x201, 0x79, 0x302, 0x201, 0x59, 0x308, 0x201, 0x5a,
+ 0x301, 0x201, 0x7a, 0x301, 0x201, 0x5a, 0x307, 0x201,
+ 0x7a, 0x307, 0x201, 0x5a, 0x30c, 0x201, 0x7a, 0x30c,
+ 0x110, 0x73, 0x201, 0x4f, 0x31b, 0x201, 0x6f, 0x31b,
+ 0x201, 0x55, 0x31b, 0x201, 0x75, 0x31b, 0x210, 0x44,
+ 0x17d, 0x210, 0x44, 0x17e, 0x210, 0x64, 0x17e, 0x210,
+ 0x4c, 0x4a, 0x210, 0x4c, 0x6a, 0x210, 0x6c, 0x6a,
+ 0x210, 0x4e, 0x4a, 0x210, 0x4e, 0x6a, 0x210, 0x6e,
+ 0x6a, 0x201, 0x41, 0x30c, 0x201, 0x61, 0x30c, 0x201,
+ 0x49, 0x30c, 0x201, 0x69, 0x30c, 0x201, 0x4f, 0x30c,
+ 0x201, 0x6f, 0x30c, 0x201, 0x55, 0x30c, 0x201, 0x75,
+ 0x30c, 0x201, 0xdc, 0x304, 0x201, 0xfc, 0x304, 0x201,
+ 0xdc, 0x301, 0x201, 0xfc, 0x301, 0x201, 0xdc, 0x30c,
+ 0x201, 0xfc, 0x30c, 0x201, 0xdc, 0x300, 0x201, 0xfc,
+ 0x300, 0x201, 0xc4, 0x304, 0x201, 0xe4, 0x304, 0x201,
+ 0x226, 0x304, 0x201, 0x227, 0x304, 0x201, 0xc6, 0x304,
+ 0x201, 0xe6, 0x304, 0x201, 0x47, 0x30c, 0x201, 0x67,
+ 0x30c, 0x201, 0x4b, 0x30c, 0x201, 0x6b, 0x30c, 0x201,
+ 0x4f, 0x328, 0x201, 0x6f, 0x328, 0x201, 0x1ea, 0x304,
+ 0x201, 0x1eb, 0x304, 0x201, 0x1b7, 0x30c, 0x201, 0x292,
+ 0x30c, 0x201, 0x6a, 0x30c, 0x210, 0x44, 0x5a, 0x210,
+ 0x44, 0x7a, 0x210, 0x64, 0x7a, 0x201, 0x47, 0x301,
+ 0x201, 0x67, 0x301, 0x201, 0x4e, 0x300, 0x201, 0x6e,
+ 0x300, 0x201, 0xc5, 0x301, 0x201, 0xe5, 0x301, 0x201,
+ 0xc6, 0x301, 0x201, 0xe6, 0x301, 0x201, 0xd8, 0x301,
+ 0x201, 0xf8, 0x301, 0x201, 0x41, 0x30f, 0x201, 0x61,
+ 0x30f, 0x201, 0x41, 0x311, 0x201, 0x61, 0x311, 0x201,
+ 0x45, 0x30f, 0x201, 0x65, 0x30f, 0x201, 0x45, 0x311,
+ 0x201, 0x65, 0x311, 0x201, 0x49, 0x30f, 0x201, 0x69,
+ 0x30f, 0x201, 0x49, 0x311, 0x201, 0x69, 0x311, 0x201,
+ 0x4f, 0x30f, 0x201, 0x6f, 0x30f, 0x201, 0x4f, 0x311,
+ 0x201, 0x6f, 0x311, 0x201, 0x52, 0x30f, 0x201, 0x72,
+ 0x30f, 0x201, 0x52, 0x311, 0x201, 0x72, 0x311, 0x201,
+ 0x55, 0x30f, 0x201, 0x75, 0x30f, 0x201, 0x55, 0x311,
+ 0x201, 0x75, 0x311, 0x201, 0x53, 0x326, 0x201, 0x73,
+ 0x326, 0x201, 0x54, 0x326, 0x201, 0x74, 0x326, 0x201,
+ 0x48, 0x30c, 0x201, 0x68, 0x30c, 0x201, 0x41, 0x307,
+ 0x201, 0x61, 0x307, 0x201, 0x45, 0x327, 0x201, 0x65,
+ 0x327, 0x201, 0xd6, 0x304, 0x201, 0xf6, 0x304, 0x201,
+ 0xd5, 0x304, 0x201, 0xf5, 0x304, 0x201, 0x4f, 0x307,
+ 0x201, 0x6f, 0x307, 0x201, 0x22e, 0x304, 0x201, 0x22f,
+ 0x304, 0x201, 0x59, 0x304, 0x201, 0x79, 0x304, 0x109,
+ 0x68, 0x109, 0x266, 0x109, 0x6a, 0x109, 0x72, 0x109,
+ 0x279, 0x109, 0x27b, 0x109, 0x281, 0x109, 0x77, 0x109,
+ 0x79, 0x210, 0x20, 0x306, 0x210, 0x20, 0x307, 0x210,
+ 0x20, 0x30a, 0x210, 0x20, 0x328, 0x210, 0x20, 0x303,
+ 0x210, 0x20, 0x30b, 0x109, 0x263, 0x109, 0x6c, 0x109,
+ 0x73, 0x109, 0x78, 0x109, 0x295, 0x101, 0x300, 0x101,
+ 0x301, 0x101, 0x313, 0x201, 0x308, 0x301, 0x101, 0x2b9,
+ 0x210, 0x20, 0x345, 0x101, 0x3b, 0x210, 0x20, 0x301,
+ 0x201, 0xa8, 0x301, 0x201, 0x391, 0x301, 0x101, 0xb7,
+ 0x201, 0x395, 0x301, 0x201, 0x397, 0x301, 0x201, 0x399,
+ 0x301, 0x201, 0x39f, 0x301, 0x201, 0x3a5, 0x301, 0x201,
+ 0x3a9, 0x301, 0x201, 0x3ca, 0x301, 0x201, 0x399, 0x308,
+ 0x201, 0x3a5, 0x308, 0x201, 0x3b1, 0x301, 0x201, 0x3b5,
+ 0x301, 0x201, 0x3b7, 0x301, 0x201, 0x3b9, 0x301, 0x201,
+ 0x3cb, 0x301, 0x201, 0x3b9, 0x308, 0x201, 0x3c5, 0x308,
+ 0x201, 0x3bf, 0x301, 0x201, 0x3c5, 0x301, 0x201, 0x3c9,
+ 0x301, 0x110, 0x3b2, 0x110, 0x3b8, 0x110, 0x3a5, 0x201,
+ 0x3d2, 0x301, 0x201, 0x3d2, 0x308, 0x110, 0x3c6, 0x110,
+ 0x3c0, 0x110, 0x3ba, 0x110, 0x3c1, 0x110, 0x3c2, 0x110,
+ 0x398, 0x110, 0x3b5, 0x110, 0x3a3, 0x201, 0x415, 0x300,
+ 0x201, 0x415, 0x308, 0x201, 0x413, 0x301, 0x201, 0x406,
+ 0x308, 0x201, 0x41a, 0x301, 0x201, 0x418, 0x300, 0x201,
+ 0x423, 0x306, 0x201, 0x418, 0x306, 0x201, 0x438, 0x306,
+ 0x201, 0x435, 0x300, 0x201, 0x435, 0x308, 0x201, 0x433,
+ 0x301, 0x201, 0x456, 0x308, 0x201, 0x43a, 0x301, 0x201,
+ 0x438, 0x300, 0x201, 0x443, 0x306, 0x201, 0x474, 0x30f,
+ 0x201, 0x475, 0x30f, 0x201, 0x416, 0x306, 0x201, 0x436,
+ 0x306, 0x201, 0x410, 0x306, 0x201, 0x430, 0x306, 0x201,
+ 0x410, 0x308, 0x201, 0x430, 0x308, 0x201, 0x415, 0x306,
+ 0x201, 0x435, 0x306, 0x201, 0x4d8, 0x308, 0x201, 0x4d9,
+ 0x308, 0x201, 0x416, 0x308, 0x201, 0x436, 0x308, 0x201,
+ 0x417, 0x308, 0x201, 0x437, 0x308, 0x201, 0x418, 0x304,
+ 0x201, 0x438, 0x304, 0x201, 0x418, 0x308, 0x201, 0x438,
+ 0x308, 0x201, 0x41e, 0x308, 0x201, 0x43e, 0x308, 0x201,
+ 0x4e8, 0x308, 0x201, 0x4e9, 0x308, 0x201, 0x42d, 0x308,
+ 0x201, 0x44d, 0x308, 0x201, 0x423, 0x304, 0x201, 0x443,
+ 0x304, 0x201, 0x423, 0x308, 0x201, 0x443, 0x308, 0x201,
+ 0x423, 0x30b, 0x201, 0x443, 0x30b, 0x201, 0x427, 0x308,
+ 0x201, 0x447, 0x308, 0x201, 0x42b, 0x308, 0x201, 0x44b,
+ 0x308, 0x210, 0x565, 0x582, 0x201, 0x627, 0x653, 0x201,
+ 0x627, 0x654, 0x201, 0x648, 0x654, 0x201, 0x627, 0x655,
+ 0x201, 0x64a, 0x654, 0x210, 0x627, 0x674, 0x210, 0x648,
+ 0x674, 0x210, 0x6c7, 0x674, 0x210, 0x64a, 0x674, 0x201,
+ 0x6d5, 0x654, 0x201, 0x6c1, 0x654, 0x201, 0x6d2, 0x654,
+ 0x201, 0x928, 0x93c, 0x201, 0x930, 0x93c, 0x201, 0x933,
+ 0x93c, 0x201, 0x915, 0x93c, 0x201, 0x916, 0x93c, 0x201,
+ 0x917, 0x93c, 0x201, 0x91c, 0x93c, 0x201, 0x921, 0x93c,
+ 0x201, 0x922, 0x93c, 0x201, 0x92b, 0x93c, 0x201, 0x92f,
+ 0x93c, 0x201, 0x9c7, 0x9be, 0x201, 0x9c7, 0x9d7, 0x201,
+ 0x9a1, 0x9bc, 0x201, 0x9a2, 0x9bc, 0x201, 0x9af, 0x9bc,
+ 0x201, 0xa32, 0xa3c, 0x201, 0xa38, 0xa3c, 0x201, 0xa16,
+ 0xa3c, 0x201, 0xa17, 0xa3c, 0x201, 0xa1c, 0xa3c, 0x201,
+ 0xa2b, 0xa3c, 0x201, 0xb47, 0xb56, 0x201, 0xb47, 0xb3e,
+ 0x201, 0xb47, 0xb57, 0x201, 0xb21, 0xb3c, 0x201, 0xb22,
+ 0xb3c, 0x201, 0xb92, 0xbd7, 0x201, 0xbc6, 0xbbe, 0x201,
+ 0xbc7, 0xbbe, 0x201, 0xbc6, 0xbd7, 0x201, 0xc46, 0xc56,
+ 0x201, 0xcbf, 0xcd5, 0x201, 0xcc6, 0xcd5, 0x201, 0xcc6,
+ 0xcd6, 0x201, 0xcc6, 0xcc2, 0x201, 0xcca, 0xcd5, 0x201,
+ 0xd46, 0xd3e, 0x201, 0xd47, 0xd3e, 0x201, 0xd46, 0xd57,
+ 0x201, 0xdd9, 0xdca, 0x201, 0xdd9, 0xdcf, 0x201, 0xddc,
+ 0xdca, 0x201, 0xdd9, 0xddf, 0x210, 0xe4d, 0xe32, 0x210,
+ 0xecd, 0xeb2, 0x210, 0xeab, 0xe99, 0x210, 0xeab, 0xea1,
+ 0x103, 0xf0b, 0x201, 0xf42, 0xfb7, 0x201, 0xf4c, 0xfb7,
+ 0x201, 0xf51, 0xfb7, 0x201, 0xf56, 0xfb7, 0x201, 0xf5b,
+ 0xfb7, 0x201, 0xf40, 0xfb5, 0x201, 0xf71, 0xf72, 0x201,
+ 0xf71, 0xf74, 0x201, 0xfb2, 0xf80, 0x210, 0xfb2, 0xf81,
+ 0x201, 0xfb3, 0xf80, 0x210, 0xfb3, 0xf81, 0x201, 0xf71,
+ 0xf80, 0x201, 0xf92, 0xfb7, 0x201, 0xf9c, 0xfb7, 0x201,
+ 0xfa1, 0xfb7, 0x201, 0xfa6, 0xfb7, 0x201, 0xfab, 0xfb7,
+ 0x201, 0xf90, 0xfb5, 0x201, 0x1025, 0x102e, 0x109, 0x10dc,
+ 0x201, 0x1b05, 0x1b35, 0x201, 0x1b07, 0x1b35, 0x201, 0x1b09,
+ 0x1b35, 0x201, 0x1b0b, 0x1b35, 0x201, 0x1b0d, 0x1b35, 0x201,
+ 0x1b11, 0x1b35, 0x201, 0x1b3a, 0x1b35, 0x201, 0x1b3c, 0x1b35,
+ 0x201, 0x1b3e, 0x1b35, 0x201, 0x1b3f, 0x1b35, 0x201, 0x1b42,
+ 0x1b35, 0x109, 0x41, 0x109, 0xc6, 0x109, 0x42, 0x109,
+ 0x44, 0x109, 0x45, 0x109, 0x18e, 0x109, 0x47, 0x109,
+ 0x48, 0x109, 0x49, 0x109, 0x4a, 0x109, 0x4b, 0x109,
+ 0x4c, 0x109, 0x4d, 0x109, 0x4e, 0x109, 0x4f, 0x109,
+ 0x222, 0x109, 0x50, 0x109, 0x52, 0x109, 0x54, 0x109,
+ 0x55, 0x109, 0x57, 0x109, 0x61, 0x109, 0x250, 0x109,
+ 0x251, 0x109, 0x1d02, 0x109, 0x62, 0x109, 0x64, 0x109,
+ 0x65, 0x109, 0x259, 0x109, 0x25b, 0x109, 0x25c, 0x109,
+ 0x67, 0x109, 0x6b, 0x109, 0x6d, 0x109, 0x14b, 0x109,
+ 0x6f, 0x109, 0x254, 0x109, 0x1d16, 0x109, 0x1d17, 0x109,
+ 0x70, 0x109, 0x74, 0x109, 0x75, 0x109, 0x1d1d, 0x109,
+ 0x26f, 0x109, 0x76, 0x109, 0x1d25, 0x109, 0x3b2, 0x109,
+ 0x3b3, 0x109, 0x3b4, 0x109, 0x3c6, 0x109, 0x3c7, 0x10a,
+ 0x69, 0x10a, 0x72, 0x10a, 0x75, 0x10a, 0x76, 0x10a,
+ 0x3b2, 0x10a, 0x3b3, 0x10a, 0x3c1, 0x10a, 0x3c6, 0x10a,
+ 0x3c7, 0x109, 0x43d, 0x109, 0x252, 0x109, 0x63, 0x109,
+ 0x255, 0x109, 0xf0, 0x109, 0x25c, 0x109, 0x66, 0x109,
+ 0x25f, 0x109, 0x261, 0x109, 0x265, 0x109, 0x268, 0x109,
+ 0x269, 0x109, 0x26a, 0x109, 0x1d7b, 0x109, 0x29d, 0x109,
+ 0x26d, 0x109, 0x1d85, 0x109, 0x29f, 0x109, 0x271, 0x109,
+ 0x270, 0x109, 0x272, 0x109, 0x273, 0x109, 0x274, 0x109,
+ 0x275, 0x109, 0x278, 0x109, 0x282, 0x109, 0x283, 0x109,
+ 0x1ab, 0x109, 0x289, 0x109, 0x28a, 0x109, 0x1d1c, 0x109,
+ 0x28b, 0x109, 0x28c, 0x109, 0x7a, 0x109, 0x290, 0x109,
+ 0x291, 0x109, 0x292, 0x109, 0x3b8, 0x201, 0x41, 0x325,
+ 0x201, 0x61, 0x325, 0x201, 0x42, 0x307, 0x201, 0x62,
+ 0x307, 0x201, 0x42, 0x323, 0x201, 0x62, 0x323, 0x201,
+ 0x42, 0x331, 0x201, 0x62, 0x331, 0x201, 0xc7, 0x301,
+ 0x201, 0xe7, 0x301, 0x201, 0x44, 0x307, 0x201, 0x64,
+ 0x307, 0x201, 0x44, 0x323, 0x201, 0x64, 0x323, 0x201,
+ 0x44, 0x331, 0x201, 0x64, 0x331, 0x201, 0x44, 0x327,
+ 0x201, 0x64, 0x327, 0x201, 0x44, 0x32d, 0x201, 0x64,
+ 0x32d, 0x201, 0x112, 0x300, 0x201, 0x113, 0x300, 0x201,
+ 0x112, 0x301, 0x201, 0x113, 0x301, 0x201, 0x45, 0x32d,
+ 0x201, 0x65, 0x32d, 0x201, 0x45, 0x330, 0x201, 0x65,
+ 0x330, 0x201, 0x228, 0x306, 0x201, 0x229, 0x306, 0x201,
+ 0x46, 0x307, 0x201, 0x66, 0x307, 0x201, 0x47, 0x304,
+ 0x201, 0x67, 0x304, 0x201, 0x48, 0x307, 0x201, 0x68,
+ 0x307, 0x201, 0x48, 0x323, 0x201, 0x68, 0x323, 0x201,
+ 0x48, 0x308, 0x201, 0x68, 0x308, 0x201, 0x48, 0x327,
+ 0x201, 0x68, 0x327, 0x201, 0x48, 0x32e, 0x201, 0x68,
+ 0x32e, 0x201, 0x49, 0x330, 0x201, 0x69, 0x330, 0x201,
+ 0xcf, 0x301, 0x201, 0xef, 0x301, 0x201, 0x4b, 0x301,
+ 0x201, 0x6b, 0x301, 0x201, 0x4b, 0x323, 0x201, 0x6b,
+ 0x323, 0x201, 0x4b, 0x331, 0x201, 0x6b, 0x331, 0x201,
+ 0x4c, 0x323, 0x201, 0x6c, 0x323, 0x201, 0x1e36, 0x304,
+ 0x201, 0x1e37, 0x304, 0x201, 0x4c, 0x331, 0x201, 0x6c,
+ 0x331, 0x201, 0x4c, 0x32d, 0x201, 0x6c, 0x32d, 0x201,
+ 0x4d, 0x301, 0x201, 0x6d, 0x301, 0x201, 0x4d, 0x307,
+ 0x201, 0x6d, 0x307, 0x201, 0x4d, 0x323, 0x201, 0x6d,
+ 0x323, 0x201, 0x4e, 0x307, 0x201, 0x6e, 0x307, 0x201,
+ 0x4e, 0x323, 0x201, 0x6e, 0x323, 0x201, 0x4e, 0x331,
+ 0x201, 0x6e, 0x331, 0x201, 0x4e, 0x32d, 0x201, 0x6e,
+ 0x32d, 0x201, 0xd5, 0x301, 0x201, 0xf5, 0x301, 0x201,
+ 0xd5, 0x308, 0x201, 0xf5, 0x308, 0x201, 0x14c, 0x300,
+ 0x201, 0x14d, 0x300, 0x201, 0x14c, 0x301, 0x201, 0x14d,
+ 0x301, 0x201, 0x50, 0x301, 0x201, 0x70, 0x301, 0x201,
+ 0x50, 0x307, 0x201, 0x70, 0x307, 0x201, 0x52, 0x307,
+ 0x201, 0x72, 0x307, 0x201, 0x52, 0x323, 0x201, 0x72,
+ 0x323, 0x201, 0x1e5a, 0x304, 0x201, 0x1e5b, 0x304, 0x201,
+ 0x52, 0x331, 0x201, 0x72, 0x331, 0x201, 0x53, 0x307,
+ 0x201, 0x73, 0x307, 0x201, 0x53, 0x323, 0x201, 0x73,
+ 0x323, 0x201, 0x15a, 0x307, 0x201, 0x15b, 0x307, 0x201,
+ 0x160, 0x307, 0x201, 0x161, 0x307, 0x201, 0x1e62, 0x307,
+ 0x201, 0x1e63, 0x307, 0x201, 0x54, 0x307, 0x201, 0x74,
+ 0x307, 0x201, 0x54, 0x323, 0x201, 0x74, 0x323, 0x201,
+ 0x54, 0x331, 0x201, 0x74, 0x331, 0x201, 0x54, 0x32d,
+ 0x201, 0x74, 0x32d, 0x201, 0x55, 0x324, 0x201, 0x75,
+ 0x324, 0x201, 0x55, 0x330, 0x201, 0x75, 0x330, 0x201,
+ 0x55, 0x32d, 0x201, 0x75, 0x32d, 0x201, 0x168, 0x301,
+ 0x201, 0x169, 0x301, 0x201, 0x16a, 0x308, 0x201, 0x16b,
+ 0x308, 0x201, 0x56, 0x303, 0x201, 0x76, 0x303, 0x201,
+ 0x56, 0x323, 0x201, 0x76, 0x323, 0x201, 0x57, 0x300,
+ 0x201, 0x77, 0x300, 0x201, 0x57, 0x301, 0x201, 0x77,
+ 0x301, 0x201, 0x57, 0x308, 0x201, 0x77, 0x308, 0x201,
+ 0x57, 0x307, 0x201, 0x77, 0x307, 0x201, 0x57, 0x323,
+ 0x201, 0x77, 0x323, 0x201, 0x58, 0x307, 0x201, 0x78,
+ 0x307, 0x201, 0x58, 0x308, 0x201, 0x78, 0x308, 0x201,
+ 0x59, 0x307, 0x201, 0x79, 0x307, 0x201, 0x5a, 0x302,
+ 0x201, 0x7a, 0x302, 0x201, 0x5a, 0x323, 0x201, 0x7a,
+ 0x323, 0x201, 0x5a, 0x331, 0x201, 0x7a, 0x331, 0x201,
+ 0x68, 0x331, 0x201, 0x74, 0x308, 0x201, 0x77, 0x30a,
+ 0x201, 0x79, 0x30a, 0x210, 0x61, 0x2be, 0x201, 0x17f,
+ 0x307, 0x201, 0x41, 0x323, 0x201, 0x61, 0x323, 0x201,
+ 0x41, 0x309, 0x201, 0x61, 0x309, 0x201, 0xc2, 0x301,
+ 0x201, 0xe2, 0x301, 0x201, 0xc2, 0x300, 0x201, 0xe2,
+ 0x300, 0x201, 0xc2, 0x309, 0x201, 0xe2, 0x309, 0x201,
+ 0xc2, 0x303, 0x201, 0xe2, 0x303, 0x201, 0x1ea0, 0x302,
+ 0x201, 0x1ea1, 0x302, 0x201, 0x102, 0x301, 0x201, 0x103,
+ 0x301, 0x201, 0x102, 0x300, 0x201, 0x103, 0x300, 0x201,
+ 0x102, 0x309, 0x201, 0x103, 0x309, 0x201, 0x102, 0x303,
+ 0x201, 0x103, 0x303, 0x201, 0x1ea0, 0x306, 0x201, 0x1ea1,
+ 0x306, 0x201, 0x45, 0x323, 0x201, 0x65, 0x323, 0x201,
+ 0x45, 0x309, 0x201, 0x65, 0x309, 0x201, 0x45, 0x303,
+ 0x201, 0x65, 0x303, 0x201, 0xca, 0x301, 0x201, 0xea,
+ 0x301, 0x201, 0xca, 0x300, 0x201, 0xea, 0x300, 0x201,
+ 0xca, 0x309, 0x201, 0xea, 0x309, 0x201, 0xca, 0x303,
+ 0x201, 0xea, 0x303, 0x201, 0x1eb8, 0x302, 0x201, 0x1eb9,
+ 0x302, 0x201, 0x49, 0x309, 0x201, 0x69, 0x309, 0x201,
+ 0x49, 0x323, 0x201, 0x69, 0x323, 0x201, 0x4f, 0x323,
+ 0x201, 0x6f, 0x323, 0x201, 0x4f, 0x309, 0x201, 0x6f,
+ 0x309, 0x201, 0xd4, 0x301, 0x201, 0xf4, 0x301, 0x201,
+ 0xd4, 0x300, 0x201, 0xf4, 0x300, 0x201, 0xd4, 0x309,
+ 0x201, 0xf4, 0x309, 0x201, 0xd4, 0x303, 0x201, 0xf4,
+ 0x303, 0x201, 0x1ecc, 0x302, 0x201, 0x1ecd, 0x302, 0x201,
+ 0x1a0, 0x301, 0x201, 0x1a1, 0x301, 0x201, 0x1a0, 0x300,
+ 0x201, 0x1a1, 0x300, 0x201, 0x1a0, 0x309, 0x201, 0x1a1,
+ 0x309, 0x201, 0x1a0, 0x303, 0x201, 0x1a1, 0x303, 0x201,
+ 0x1a0, 0x323, 0x201, 0x1a1, 0x323, 0x201, 0x55, 0x323,
+ 0x201, 0x75, 0x323, 0x201, 0x55, 0x309, 0x201, 0x75,
+ 0x309, 0x201, 0x1af, 0x301, 0x201, 0x1b0, 0x301, 0x201,
+ 0x1af, 0x300, 0x201, 0x1b0, 0x300, 0x201, 0x1af, 0x309,
+ 0x201, 0x1b0, 0x309, 0x201, 0x1af, 0x303, 0x201, 0x1b0,
+ 0x303, 0x201, 0x1af, 0x323, 0x201, 0x1b0, 0x323, 0x201,
+ 0x59, 0x300, 0x201, 0x79, 0x300, 0x201, 0x59, 0x323,
+ 0x201, 0x79, 0x323, 0x201, 0x59, 0x309, 0x201, 0x79,
+ 0x309, 0x201, 0x59, 0x303, 0x201, 0x79, 0x303, 0x201,
+ 0x3b1, 0x313, 0x201, 0x3b1, 0x314, 0x201, 0x1f00, 0x300,
+ 0x201, 0x1f01, 0x300, 0x201, 0x1f00, 0x301, 0x201, 0x1f01,
+ 0x301, 0x201, 0x1f00, 0x342, 0x201, 0x1f01, 0x342, 0x201,
+ 0x391, 0x313, 0x201, 0x391, 0x314, 0x201, 0x1f08, 0x300,
+ 0x201, 0x1f09, 0x300, 0x201, 0x1f08, 0x301, 0x201, 0x1f09,
+ 0x301, 0x201, 0x1f08, 0x342, 0x201, 0x1f09, 0x342, 0x201,
+ 0x3b5, 0x313, 0x201, 0x3b5, 0x314, 0x201, 0x1f10, 0x300,
+ 0x201, 0x1f11, 0x300, 0x201, 0x1f10, 0x301, 0x201, 0x1f11,
+ 0x301, 0x201, 0x395, 0x313, 0x201, 0x395, 0x314, 0x201,
+ 0x1f18, 0x300, 0x201, 0x1f19, 0x300, 0x201, 0x1f18, 0x301,
+ 0x201, 0x1f19, 0x301, 0x201, 0x3b7, 0x313, 0x201, 0x3b7,
+ 0x314, 0x201, 0x1f20, 0x300, 0x201, 0x1f21, 0x300, 0x201,
+ 0x1f20, 0x301, 0x201, 0x1f21, 0x301, 0x201, 0x1f20, 0x342,
+ 0x201, 0x1f21, 0x342, 0x201, 0x397, 0x313, 0x201, 0x397,
+ 0x314, 0x201, 0x1f28, 0x300, 0x201, 0x1f29, 0x300, 0x201,
+ 0x1f28, 0x301, 0x201, 0x1f29, 0x301, 0x201, 0x1f28, 0x342,
+ 0x201, 0x1f29, 0x342, 0x201, 0x3b9, 0x313, 0x201, 0x3b9,
+ 0x314, 0x201, 0x1f30, 0x300, 0x201, 0x1f31, 0x300, 0x201,
+ 0x1f30, 0x301, 0x201, 0x1f31, 0x301, 0x201, 0x1f30, 0x342,
+ 0x201, 0x1f31, 0x342, 0x201, 0x399, 0x313, 0x201, 0x399,
+ 0x314, 0x201, 0x1f38, 0x300, 0x201, 0x1f39, 0x300, 0x201,
+ 0x1f38, 0x301, 0x201, 0x1f39, 0x301, 0x201, 0x1f38, 0x342,
+ 0x201, 0x1f39, 0x342, 0x201, 0x3bf, 0x313, 0x201, 0x3bf,
+ 0x314, 0x201, 0x1f40, 0x300, 0x201, 0x1f41, 0x300, 0x201,
+ 0x1f40, 0x301, 0x201, 0x1f41, 0x301, 0x201, 0x39f, 0x313,
+ 0x201, 0x39f, 0x314, 0x201, 0x1f48, 0x300, 0x201, 0x1f49,
+ 0x300, 0x201, 0x1f48, 0x301, 0x201, 0x1f49, 0x301, 0x201,
+ 0x3c5, 0x313, 0x201, 0x3c5, 0x314, 0x201, 0x1f50, 0x300,
+ 0x201, 0x1f51, 0x300, 0x201, 0x1f50, 0x301, 0x201, 0x1f51,
+ 0x301, 0x201, 0x1f50, 0x342, 0x201, 0x1f51, 0x342, 0x201,
+ 0x3a5, 0x314, 0x201, 0x1f59, 0x300, 0x201, 0x1f59, 0x301,
+ 0x201, 0x1f59, 0x342, 0x201, 0x3c9, 0x313, 0x201, 0x3c9,
+ 0x314, 0x201, 0x1f60, 0x300, 0x201, 0x1f61, 0x300, 0x201,
+ 0x1f60, 0x301, 0x201, 0x1f61, 0x301, 0x201, 0x1f60, 0x342,
+ 0x201, 0x1f61, 0x342, 0x201, 0x3a9, 0x313, 0x201, 0x3a9,
+ 0x314, 0x201, 0x1f68, 0x300, 0x201, 0x1f69, 0x300, 0x201,
+ 0x1f68, 0x301, 0x201, 0x1f69, 0x301, 0x201, 0x1f68, 0x342,
+ 0x201, 0x1f69, 0x342, 0x201, 0x3b1, 0x300, 0x101, 0x3ac,
+ 0x201, 0x3b5, 0x300, 0x101, 0x3ad, 0x201, 0x3b7, 0x300,
+ 0x101, 0x3ae, 0x201, 0x3b9, 0x300, 0x101, 0x3af, 0x201,
+ 0x3bf, 0x300, 0x101, 0x3cc, 0x201, 0x3c5, 0x300, 0x101,
+ 0x3cd, 0x201, 0x3c9, 0x300, 0x101, 0x3ce, 0x201, 0x1f00,
+ 0x345, 0x201, 0x1f01, 0x345, 0x201, 0x1f02, 0x345, 0x201,
+ 0x1f03, 0x345, 0x201, 0x1f04, 0x345, 0x201, 0x1f05, 0x345,
+ 0x201, 0x1f06, 0x345, 0x201, 0x1f07, 0x345, 0x201, 0x1f08,
+ 0x345, 0x201, 0x1f09, 0x345, 0x201, 0x1f0a, 0x345, 0x201,
+ 0x1f0b, 0x345, 0x201, 0x1f0c, 0x345, 0x201, 0x1f0d, 0x345,
+ 0x201, 0x1f0e, 0x345, 0x201, 0x1f0f, 0x345, 0x201, 0x1f20,
+ 0x345, 0x201, 0x1f21, 0x345, 0x201, 0x1f22, 0x345, 0x201,
+ 0x1f23, 0x345, 0x201, 0x1f24, 0x345, 0x201, 0x1f25, 0x345,
+ 0x201, 0x1f26, 0x345, 0x201, 0x1f27, 0x345, 0x201, 0x1f28,
+ 0x345, 0x201, 0x1f29, 0x345, 0x201, 0x1f2a, 0x345, 0x201,
+ 0x1f2b, 0x345, 0x201, 0x1f2c, 0x345, 0x201, 0x1f2d, 0x345,
+ 0x201, 0x1f2e, 0x345, 0x201, 0x1f2f, 0x345, 0x201, 0x1f60,
+ 0x345, 0x201, 0x1f61, 0x345, 0x201, 0x1f62, 0x345, 0x201,
+ 0x1f63, 0x345, 0x201, 0x1f64, 0x345, 0x201, 0x1f65, 0x345,
+ 0x201, 0x1f66, 0x345, 0x201, 0x1f67, 0x345, 0x201, 0x1f68,
+ 0x345, 0x201, 0x1f69, 0x345, 0x201, 0x1f6a, 0x345, 0x201,
+ 0x1f6b, 0x345, 0x201, 0x1f6c, 0x345, 0x201, 0x1f6d, 0x345,
+ 0x201, 0x1f6e, 0x345, 0x201, 0x1f6f, 0x345, 0x201, 0x3b1,
+ 0x306, 0x201, 0x3b1, 0x304, 0x201, 0x1f70, 0x345, 0x201,
+ 0x3b1, 0x345, 0x201, 0x3ac, 0x345, 0x201, 0x3b1, 0x342,
+ 0x201, 0x1fb6, 0x345, 0x201, 0x391, 0x306, 0x201, 0x391,
+ 0x304, 0x201, 0x391, 0x300, 0x101, 0x386, 0x201, 0x391,
+ 0x345, 0x210, 0x20, 0x313, 0x101, 0x3b9, 0x210, 0x20,
+ 0x313, 0x210, 0x20, 0x342, 0x201, 0xa8, 0x342, 0x201,
+ 0x1f74, 0x345, 0x201, 0x3b7, 0x345, 0x201, 0x3ae, 0x345,
+ 0x201, 0x3b7, 0x342, 0x201, 0x1fc6, 0x345, 0x201, 0x395,
+ 0x300, 0x101, 0x388, 0x201, 0x397, 0x300, 0x101, 0x389,
+ 0x201, 0x397, 0x345, 0x201, 0x1fbf, 0x300, 0x201, 0x1fbf,
+ 0x301, 0x201, 0x1fbf, 0x342, 0x201, 0x3b9, 0x306, 0x201,
+ 0x3b9, 0x304, 0x201, 0x3ca, 0x300, 0x101, 0x390, 0x201,
+ 0x3b9, 0x342, 0x201, 0x3ca, 0x342, 0x201, 0x399, 0x306,
+ 0x201, 0x399, 0x304, 0x201, 0x399, 0x300, 0x101, 0x38a,
+ 0x201, 0x1ffe, 0x300, 0x201, 0x1ffe, 0x301, 0x201, 0x1ffe,
+ 0x342, 0x201, 0x3c5, 0x306, 0x201, 0x3c5, 0x304, 0x201,
+ 0x3cb, 0x300, 0x101, 0x3b0, 0x201, 0x3c1, 0x313, 0x201,
+ 0x3c1, 0x314, 0x201, 0x3c5, 0x342, 0x201, 0x3cb, 0x342,
+ 0x201, 0x3a5, 0x306, 0x201, 0x3a5, 0x304, 0x201, 0x3a5,
+ 0x300, 0x101, 0x38e, 0x201, 0x3a1, 0x314, 0x201, 0xa8,
+ 0x300, 0x101, 0x385, 0x101, 0x60, 0x201, 0x1f7c, 0x345,
+ 0x201, 0x3c9, 0x345, 0x201, 0x3ce, 0x345, 0x201, 0x3c9,
+ 0x342, 0x201, 0x1ff6, 0x345, 0x201, 0x39f, 0x300, 0x101,
+ 0x38c, 0x201, 0x3a9, 0x300, 0x101, 0x38f, 0x201, 0x3a9,
+ 0x345, 0x101, 0xb4, 0x210, 0x20, 0x314, 0x101, 0x2002,
+ 0x101, 0x2003, 0x110, 0x20, 0x110, 0x20, 0x110, 0x20,
+ 0x110, 0x20, 0x110, 0x20, 0x103, 0x20, 0x110, 0x20,
+ 0x110, 0x20, 0x110, 0x20, 0x103, 0x2010, 0x210, 0x20,
+ 0x333, 0x110, 0x2e, 0x210, 0x2e, 0x2e, 0x310, 0x2e,
+ 0x2e, 0x2e, 0x103, 0x20, 0x210, 0x2032, 0x2032, 0x310,
+ 0x2032, 0x2032, 0x2032, 0x210, 0x2035, 0x2035, 0x310, 0x2035,
+ 0x2035, 0x2035, 0x210, 0x21, 0x21, 0x210, 0x20, 0x305,
+ 0x210, 0x3f, 0x3f, 0x210, 0x3f, 0x21, 0x210, 0x21,
+ 0x3f, 0x410, 0x2032, 0x2032, 0x2032, 0x2032, 0x110, 0x20,
+ 0x109, 0x30, 0x109, 0x69, 0x109, 0x34, 0x109, 0x35,
+ 0x109, 0x36, 0x109, 0x37, 0x109, 0x38, 0x109, 0x39,
+ 0x109, 0x2b, 0x109, 0x2212, 0x109, 0x3d, 0x109, 0x28,
+ 0x109, 0x29, 0x109, 0x6e, 0x10a, 0x30, 0x10a, 0x31,
+ 0x10a, 0x32, 0x10a, 0x33, 0x10a, 0x34, 0x10a, 0x35,
+ 0x10a, 0x36, 0x10a, 0x37, 0x10a, 0x38, 0x10a, 0x39,
+ 0x10a, 0x2b, 0x10a, 0x2212, 0x10a, 0x3d, 0x10a, 0x28,
+ 0x10a, 0x29, 0x10a, 0x61, 0x10a, 0x65, 0x10a, 0x6f,
+ 0x10a, 0x78, 0x10a, 0x259, 0x210, 0x52, 0x73, 0x310,
+ 0x61, 0x2f, 0x63, 0x310, 0x61, 0x2f, 0x73, 0x102,
+ 0x43, 0x210, 0xb0, 0x43, 0x310, 0x63, 0x2f, 0x6f,
+ 0x310, 0x63, 0x2f, 0x75, 0x110, 0x190, 0x210, 0xb0,
+ 0x46, 0x102, 0x67, 0x102, 0x48, 0x102, 0x48, 0x102,
+ 0x48, 0x102, 0x68, 0x102, 0x127, 0x102, 0x49, 0x102,
+ 0x49, 0x102, 0x4c, 0x102, 0x6c, 0x102, 0x4e, 0x210,
+ 0x4e, 0x6f, 0x102, 0x50, 0x102, 0x51, 0x102, 0x52,
+ 0x102, 0x52, 0x102, 0x52, 0x209, 0x53, 0x4d, 0x310,
+ 0x54, 0x45, 0x4c, 0x209, 0x54, 0x4d, 0x102, 0x5a,
+ 0x101, 0x3a9, 0x102, 0x5a, 0x101, 0x4b, 0x101, 0xc5,
+ 0x102, 0x42, 0x102, 0x43, 0x102, 0x65, 0x102, 0x45,
+ 0x102, 0x46, 0x102, 0x4d, 0x102, 0x6f, 0x110, 0x5d0,
+ 0x110, 0x5d1, 0x110, 0x5d2, 0x110, 0x5d3, 0x102, 0x69,
+ 0x310, 0x46, 0x41, 0x58, 0x102, 0x3c0, 0x102, 0x3b3,
+ 0x102, 0x393, 0x102, 0x3a0, 0x102, 0x2211, 0x102, 0x44,
+ 0x102, 0x64, 0x102, 0x65, 0x102, 0x69, 0x102, 0x6a,
+ 0x311, 0x31, 0x2044, 0x33, 0x311, 0x32, 0x2044, 0x33,
+ 0x311, 0x31, 0x2044, 0x35, 0x311, 0x32, 0x2044, 0x35,
+ 0x311, 0x33, 0x2044, 0x35, 0x311, 0x34, 0x2044, 0x35,
+ 0x311, 0x31, 0x2044, 0x36, 0x311, 0x35, 0x2044, 0x36,
+ 0x311, 0x31, 0x2044, 0x38, 0x311, 0x33, 0x2044, 0x38,
+ 0x311, 0x35, 0x2044, 0x38, 0x311, 0x37, 0x2044, 0x38,
+ 0x211, 0x31, 0x2044, 0x110, 0x49, 0x210, 0x49, 0x49,
+ 0x310, 0x49, 0x49, 0x49, 0x210, 0x49, 0x56, 0x110,
+ 0x56, 0x210, 0x56, 0x49, 0x310, 0x56, 0x49, 0x49,
+ 0x410, 0x56, 0x49, 0x49, 0x49, 0x210, 0x49, 0x58,
+ 0x110, 0x58, 0x210, 0x58, 0x49, 0x310, 0x58, 0x49,
+ 0x49, 0x110, 0x4c, 0x110, 0x43, 0x110, 0x44, 0x110,
+ 0x4d, 0x110, 0x69, 0x210, 0x69, 0x69, 0x310, 0x69,
+ 0x69, 0x69, 0x210, 0x69, 0x76, 0x110, 0x76, 0x210,
+ 0x76, 0x69, 0x310, 0x76, 0x69, 0x69, 0x410, 0x76,
+ 0x69, 0x69, 0x69, 0x210, 0x69, 0x78, 0x110, 0x78,
+ 0x210, 0x78, 0x69, 0x310, 0x78, 0x69, 0x69, 0x110,
+ 0x6c, 0x110, 0x63, 0x110, 0x64, 0x110, 0x6d, 0x201,
+ 0x2190, 0x338, 0x201, 0x2192, 0x338, 0x201, 0x2194, 0x338,
+ 0x201, 0x21d0, 0x338, 0x201, 0x21d4, 0x338, 0x201, 0x21d2,
+ 0x338, 0x201, 0x2203, 0x338, 0x201, 0x2208, 0x338, 0x201,
+ 0x220b, 0x338, 0x201, 0x2223, 0x338, 0x201, 0x2225, 0x338,
+ 0x210, 0x222b, 0x222b, 0x310, 0x222b, 0x222b, 0x222b, 0x210,
+ 0x222e, 0x222e, 0x310, 0x222e, 0x222e, 0x222e, 0x201, 0x223c,
+ 0x338, 0x201, 0x2243, 0x338, 0x201, 0x2245, 0x338, 0x201,
+ 0x2248, 0x338, 0x201, 0x3d, 0x338, 0x201, 0x2261, 0x338,
+ 0x201, 0x224d, 0x338, 0x201, 0x3c, 0x338, 0x201, 0x3e,
+ 0x338, 0x201, 0x2264, 0x338, 0x201, 0x2265, 0x338, 0x201,
+ 0x2272, 0x338, 0x201, 0x2273, 0x338, 0x201, 0x2276, 0x338,
+ 0x201, 0x2277, 0x338, 0x201, 0x227a, 0x338, 0x201, 0x227b,
+ 0x338, 0x201, 0x2282, 0x338, 0x201, 0x2283, 0x338, 0x201,
+ 0x2286, 0x338, 0x201, 0x2287, 0x338, 0x201, 0x22a2, 0x338,
+ 0x201, 0x22a8, 0x338, 0x201, 0x22a9, 0x338, 0x201, 0x22ab,
+ 0x338, 0x201, 0x227c, 0x338, 0x201, 0x227d, 0x338, 0x201,
+ 0x2291, 0x338, 0x201, 0x2292, 0x338, 0x201, 0x22b2, 0x338,
+ 0x201, 0x22b3, 0x338, 0x201, 0x22b4, 0x338, 0x201, 0x22b5,
+ 0x338, 0x101, 0x3008, 0x101, 0x3009, 0x108, 0x31, 0x108,
+ 0x32, 0x108, 0x33, 0x108, 0x34, 0x108, 0x35, 0x108,
+ 0x36, 0x108, 0x37, 0x108, 0x38, 0x108, 0x39, 0x208,
+ 0x31, 0x30, 0x208, 0x31, 0x31, 0x208, 0x31, 0x32,
+ 0x208, 0x31, 0x33, 0x208, 0x31, 0x34, 0x208, 0x31,
+ 0x35, 0x208, 0x31, 0x36, 0x208, 0x31, 0x37, 0x208,
+ 0x31, 0x38, 0x208, 0x31, 0x39, 0x208, 0x32, 0x30,
+ 0x310, 0x28, 0x31, 0x29, 0x310, 0x28, 0x32, 0x29,
+ 0x310, 0x28, 0x33, 0x29, 0x310, 0x28, 0x34, 0x29,
+ 0x310, 0x28, 0x35, 0x29, 0x310, 0x28, 0x36, 0x29,
+ 0x310, 0x28, 0x37, 0x29, 0x310, 0x28, 0x38, 0x29,
+ 0x310, 0x28, 0x39, 0x29, 0x410, 0x28, 0x31, 0x30,
+ 0x29, 0x410, 0x28, 0x31, 0x31, 0x29, 0x410, 0x28,
+ 0x31, 0x32, 0x29, 0x410, 0x28, 0x31, 0x33, 0x29,
+ 0x410, 0x28, 0x31, 0x34, 0x29, 0x410, 0x28, 0x31,
+ 0x35, 0x29, 0x410, 0x28, 0x31, 0x36, 0x29, 0x410,
+ 0x28, 0x31, 0x37, 0x29, 0x410, 0x28, 0x31, 0x38,
+ 0x29, 0x410, 0x28, 0x31, 0x39, 0x29, 0x410, 0x28,
+ 0x32, 0x30, 0x29, 0x210, 0x31, 0x2e, 0x210, 0x32,
+ 0x2e, 0x210, 0x33, 0x2e, 0x210, 0x34, 0x2e, 0x210,
+ 0x35, 0x2e, 0x210, 0x36, 0x2e, 0x210, 0x37, 0x2e,
+ 0x210, 0x38, 0x2e, 0x210, 0x39, 0x2e, 0x310, 0x31,
+ 0x30, 0x2e, 0x310, 0x31, 0x31, 0x2e, 0x310, 0x31,
+ 0x32, 0x2e, 0x310, 0x31, 0x33, 0x2e, 0x310, 0x31,
+ 0x34, 0x2e, 0x310, 0x31, 0x35, 0x2e, 0x310, 0x31,
+ 0x36, 0x2e, 0x310, 0x31, 0x37, 0x2e, 0x310, 0x31,
+ 0x38, 0x2e, 0x310, 0x31, 0x39, 0x2e, 0x310, 0x32,
+ 0x30, 0x2e, 0x310, 0x28, 0x61, 0x29, 0x310, 0x28,
+ 0x62, 0x29, 0x310, 0x28, 0x63, 0x29, 0x310, 0x28,
+ 0x64, 0x29, 0x310, 0x28, 0x65, 0x29, 0x310, 0x28,
+ 0x66, 0x29, 0x310, 0x28, 0x67, 0x29, 0x310, 0x28,
+ 0x68, 0x29, 0x310, 0x28, 0x69, 0x29, 0x310, 0x28,
+ 0x6a, 0x29, 0x310, 0x28, 0x6b, 0x29, 0x310, 0x28,
+ 0x6c, 0x29, 0x310, 0x28, 0x6d, 0x29, 0x310, 0x28,
+ 0x6e, 0x29, 0x310, 0x28, 0x6f, 0x29, 0x310, 0x28,
+ 0x70, 0x29, 0x310, 0x28, 0x71, 0x29, 0x310, 0x28,
+ 0x72, 0x29, 0x310, 0x28, 0x73, 0x29, 0x310, 0x28,
+ 0x74, 0x29, 0x310, 0x28, 0x75, 0x29, 0x310, 0x28,
+ 0x76, 0x29, 0x310, 0x28, 0x77, 0x29, 0x310, 0x28,
+ 0x78, 0x29, 0x310, 0x28, 0x79, 0x29, 0x310, 0x28,
+ 0x7a, 0x29, 0x108, 0x41, 0x108, 0x42, 0x108, 0x43,
+ 0x108, 0x44, 0x108, 0x45, 0x108, 0x46, 0x108, 0x47,
+ 0x108, 0x48, 0x108, 0x49, 0x108, 0x4a, 0x108, 0x4b,
+ 0x108, 0x4c, 0x108, 0x4d, 0x108, 0x4e, 0x108, 0x4f,
+ 0x108, 0x50, 0x108, 0x51, 0x108, 0x52, 0x108, 0x53,
+ 0x108, 0x54, 0x108, 0x55, 0x108, 0x56, 0x108, 0x57,
+ 0x108, 0x58, 0x108, 0x59, 0x108, 0x5a, 0x108, 0x61,
+ 0x108, 0x62, 0x108, 0x63, 0x108, 0x64, 0x108, 0x65,
+ 0x108, 0x66, 0x108, 0x67, 0x108, 0x68, 0x108, 0x69,
+ 0x108, 0x6a, 0x108, 0x6b, 0x108, 0x6c, 0x108, 0x6d,
+ 0x108, 0x6e, 0x108, 0x6f, 0x108, 0x70, 0x108, 0x71,
+ 0x108, 0x72, 0x108, 0x73, 0x108, 0x74, 0x108, 0x75,
+ 0x108, 0x76, 0x108, 0x77, 0x108, 0x78, 0x108, 0x79,
+ 0x108, 0x7a, 0x108, 0x30, 0x410, 0x222b, 0x222b, 0x222b,
+ 0x222b, 0x310, 0x3a, 0x3a, 0x3d, 0x210, 0x3d, 0x3d,
+ 0x310, 0x3d, 0x3d, 0x3d, 0x201, 0x2add, 0x338, 0x109,
+ 0x2d61, 0x110, 0x6bcd, 0x110, 0x9f9f, 0x110, 0x4e00, 0x110,
+ 0x4e28, 0x110, 0x4e36, 0x110, 0x4e3f, 0x110, 0x4e59, 0x110,
+ 0x4e85, 0x110, 0x4e8c, 0x110, 0x4ea0, 0x110, 0x4eba, 0x110,
+ 0x513f, 0x110, 0x5165, 0x110, 0x516b, 0x110, 0x5182, 0x110,
+ 0x5196, 0x110, 0x51ab, 0x110, 0x51e0, 0x110, 0x51f5, 0x110,
+ 0x5200, 0x110, 0x529b, 0x110, 0x52f9, 0x110, 0x5315, 0x110,
+ 0x531a, 0x110, 0x5338, 0x110, 0x5341, 0x110, 0x535c, 0x110,
+ 0x5369, 0x110, 0x5382, 0x110, 0x53b6, 0x110, 0x53c8, 0x110,
+ 0x53e3, 0x110, 0x56d7, 0x110, 0x571f, 0x110, 0x58eb, 0x110,
+ 0x5902, 0x110, 0x590a, 0x110, 0x5915, 0x110, 0x5927, 0x110,
+ 0x5973, 0x110, 0x5b50, 0x110, 0x5b80, 0x110, 0x5bf8, 0x110,
+ 0x5c0f, 0x110, 0x5c22, 0x110, 0x5c38, 0x110, 0x5c6e, 0x110,
+ 0x5c71, 0x110, 0x5ddb, 0x110, 0x5de5, 0x110, 0x5df1, 0x110,
+ 0x5dfe, 0x110, 0x5e72, 0x110, 0x5e7a, 0x110, 0x5e7f, 0x110,
+ 0x5ef4, 0x110, 0x5efe, 0x110, 0x5f0b, 0x110, 0x5f13, 0x110,
+ 0x5f50, 0x110, 0x5f61, 0x110, 0x5f73, 0x110, 0x5fc3, 0x110,
+ 0x6208, 0x110, 0x6236, 0x110, 0x624b, 0x110, 0x652f, 0x110,
+ 0x6534, 0x110, 0x6587, 0x110, 0x6597, 0x110, 0x65a4, 0x110,
+ 0x65b9, 0x110, 0x65e0, 0x110, 0x65e5, 0x110, 0x66f0, 0x110,
+ 0x6708, 0x110, 0x6728, 0x110, 0x6b20, 0x110, 0x6b62, 0x110,
+ 0x6b79, 0x110, 0x6bb3, 0x110, 0x6bcb, 0x110, 0x6bd4, 0x110,
+ 0x6bdb, 0x110, 0x6c0f, 0x110, 0x6c14, 0x110, 0x6c34, 0x110,
+ 0x706b, 0x110, 0x722a, 0x110, 0x7236, 0x110, 0x723b, 0x110,
+ 0x723f, 0x110, 0x7247, 0x110, 0x7259, 0x110, 0x725b, 0x110,
+ 0x72ac, 0x110, 0x7384, 0x110, 0x7389, 0x110, 0x74dc, 0x110,
+ 0x74e6, 0x110, 0x7518, 0x110, 0x751f, 0x110, 0x7528, 0x110,
+ 0x7530, 0x110, 0x758b, 0x110, 0x7592, 0x110, 0x7676, 0x110,
+ 0x767d, 0x110, 0x76ae, 0x110, 0x76bf, 0x110, 0x76ee, 0x110,
+ 0x77db, 0x110, 0x77e2, 0x110, 0x77f3, 0x110, 0x793a, 0x110,
+ 0x79b8, 0x110, 0x79be, 0x110, 0x7a74, 0x110, 0x7acb, 0x110,
+ 0x7af9, 0x110, 0x7c73, 0x110, 0x7cf8, 0x110, 0x7f36, 0x110,
+ 0x7f51, 0x110, 0x7f8a, 0x110, 0x7fbd, 0x110, 0x8001, 0x110,
+ 0x800c, 0x110, 0x8012, 0x110, 0x8033, 0x110, 0x807f, 0x110,
+ 0x8089, 0x110, 0x81e3, 0x110, 0x81ea, 0x110, 0x81f3, 0x110,
+ 0x81fc, 0x110, 0x820c, 0x110, 0x821b, 0x110, 0x821f, 0x110,
+ 0x826e, 0x110, 0x8272, 0x110, 0x8278, 0x110, 0x864d, 0x110,
+ 0x866b, 0x110, 0x8840, 0x110, 0x884c, 0x110, 0x8863, 0x110,
+ 0x897e, 0x110, 0x898b, 0x110, 0x89d2, 0x110, 0x8a00, 0x110,
+ 0x8c37, 0x110, 0x8c46, 0x110, 0x8c55, 0x110, 0x8c78, 0x110,
+ 0x8c9d, 0x110, 0x8d64, 0x110, 0x8d70, 0x110, 0x8db3, 0x110,
+ 0x8eab, 0x110, 0x8eca, 0x110, 0x8f9b, 0x110, 0x8fb0, 0x110,
+ 0x8fb5, 0x110, 0x9091, 0x110, 0x9149, 0x110, 0x91c6, 0x110,
+ 0x91cc, 0x110, 0x91d1, 0x110, 0x9577, 0x110, 0x9580, 0x110,
+ 0x961c, 0x110, 0x96b6, 0x110, 0x96b9, 0x110, 0x96e8, 0x110,
+ 0x9751, 0x110, 0x975e, 0x110, 0x9762, 0x110, 0x9769, 0x110,
+ 0x97cb, 0x110, 0x97ed, 0x110, 0x97f3, 0x110, 0x9801, 0x110,
+ 0x98a8, 0x110, 0x98db, 0x110, 0x98df, 0x110, 0x9996, 0x110,
+ 0x9999, 0x110, 0x99ac, 0x110, 0x9aa8, 0x110, 0x9ad8, 0x110,
+ 0x9adf, 0x110, 0x9b25, 0x110, 0x9b2f, 0x110, 0x9b32, 0x110,
+ 0x9b3c, 0x110, 0x9b5a, 0x110, 0x9ce5, 0x110, 0x9e75, 0x110,
+ 0x9e7f, 0x110, 0x9ea5, 0x110, 0x9ebb, 0x110, 0x9ec3, 0x110,
+ 0x9ecd, 0x110, 0x9ed1, 0x110, 0x9ef9, 0x110, 0x9efd, 0x110,
+ 0x9f0e, 0x110, 0x9f13, 0x110, 0x9f20, 0x110, 0x9f3b, 0x110,
+ 0x9f4a, 0x110, 0x9f52, 0x110, 0x9f8d, 0x110, 0x9f9c, 0x110,
+ 0x9fa0, 0x10c, 0x20, 0x110, 0x3012, 0x110, 0x5341, 0x110,
+ 0x5344, 0x110, 0x5345, 0x201, 0x304b, 0x3099, 0x201, 0x304d,
+ 0x3099, 0x201, 0x304f, 0x3099, 0x201, 0x3051, 0x3099, 0x201,
+ 0x3053, 0x3099, 0x201, 0x3055, 0x3099, 0x201, 0x3057, 0x3099,
+ 0x201, 0x3059, 0x3099, 0x201, 0x305b, 0x3099, 0x201, 0x305d,
+ 0x3099, 0x201, 0x305f, 0x3099, 0x201, 0x3061, 0x3099, 0x201,
+ 0x3064, 0x3099, 0x201, 0x3066, 0x3099, 0x201, 0x3068, 0x3099,
+ 0x201, 0x306f, 0x3099, 0x201, 0x306f, 0x309a, 0x201, 0x3072,
+ 0x3099, 0x201, 0x3072, 0x309a, 0x201, 0x3075, 0x3099, 0x201,
+ 0x3075, 0x309a, 0x201, 0x3078, 0x3099, 0x201, 0x3078, 0x309a,
+ 0x201, 0x307b, 0x3099, 0x201, 0x307b, 0x309a, 0x201, 0x3046,
+ 0x3099, 0x210, 0x20, 0x3099, 0x210, 0x20, 0x309a, 0x201,
+ 0x309d, 0x3099, 0x20b, 0x3088, 0x308a, 0x201, 0x30ab, 0x3099,
+ 0x201, 0x30ad, 0x3099, 0x201, 0x30af, 0x3099, 0x201, 0x30b1,
+ 0x3099, 0x201, 0x30b3, 0x3099, 0x201, 0x30b5, 0x3099, 0x201,
+ 0x30b7, 0x3099, 0x201, 0x30b9, 0x3099, 0x201, 0x30bb, 0x3099,
+ 0x201, 0x30bd, 0x3099, 0x201, 0x30bf, 0x3099, 0x201, 0x30c1,
+ 0x3099, 0x201, 0x30c4, 0x3099, 0x201, 0x30c6, 0x3099, 0x201,
+ 0x30c8, 0x3099, 0x201, 0x30cf, 0x3099, 0x201, 0x30cf, 0x309a,
+ 0x201, 0x30d2, 0x3099, 0x201, 0x30d2, 0x309a, 0x201, 0x30d5,
+ 0x3099, 0x201, 0x30d5, 0x309a, 0x201, 0x30d8, 0x3099, 0x201,
+ 0x30d8, 0x309a, 0x201, 0x30db, 0x3099, 0x201, 0x30db, 0x309a,
+ 0x201, 0x30a6, 0x3099, 0x201, 0x30ef, 0x3099, 0x201, 0x30f0,
+ 0x3099, 0x201, 0x30f1, 0x3099, 0x201, 0x30f2, 0x3099, 0x201,
+ 0x30fd, 0x3099, 0x20b, 0x30b3, 0x30c8, 0x110, 0x1100, 0x110,
+ 0x1101, 0x110, 0x11aa, 0x110, 0x1102, 0x110, 0x11ac, 0x110,
+ 0x11ad, 0x110, 0x1103, 0x110, 0x1104, 0x110, 0x1105, 0x110,
+ 0x11b0, 0x110, 0x11b1, 0x110, 0x11b2, 0x110, 0x11b3, 0x110,
+ 0x11b4, 0x110, 0x11b5, 0x110, 0x111a, 0x110, 0x1106, 0x110,
+ 0x1107, 0x110, 0x1108, 0x110, 0x1121, 0x110, 0x1109, 0x110,
+ 0x110a, 0x110, 0x110b, 0x110, 0x110c, 0x110, 0x110d, 0x110,
+ 0x110e, 0x110, 0x110f, 0x110, 0x1110, 0x110, 0x1111, 0x110,
+ 0x1112, 0x110, 0x1161, 0x110, 0x1162, 0x110, 0x1163, 0x110,
+ 0x1164, 0x110, 0x1165, 0x110, 0x1166, 0x110, 0x1167, 0x110,
+ 0x1168, 0x110, 0x1169, 0x110, 0x116a, 0x110, 0x116b, 0x110,
+ 0x116c, 0x110, 0x116d, 0x110, 0x116e, 0x110, 0x116f, 0x110,
+ 0x1170, 0x110, 0x1171, 0x110, 0x1172, 0x110, 0x1173, 0x110,
+ 0x1174, 0x110, 0x1175, 0x110, 0x1160, 0x110, 0x1114, 0x110,
+ 0x1115, 0x110, 0x11c7, 0x110, 0x11c8, 0x110, 0x11cc, 0x110,
+ 0x11ce, 0x110, 0x11d3, 0x110, 0x11d7, 0x110, 0x11d9, 0x110,
+ 0x111c, 0x110, 0x11dd, 0x110, 0x11df, 0x110, 0x111d, 0x110,
+ 0x111e, 0x110, 0x1120, 0x110, 0x1122, 0x110, 0x1123, 0x110,
+ 0x1127, 0x110, 0x1129, 0x110, 0x112b, 0x110, 0x112c, 0x110,
+ 0x112d, 0x110, 0x112e, 0x110, 0x112f, 0x110, 0x1132, 0x110,
+ 0x1136, 0x110, 0x1140, 0x110, 0x1147, 0x110, 0x114c, 0x110,
+ 0x11f1, 0x110, 0x11f2, 0x110, 0x1157, 0x110, 0x1158, 0x110,
+ 0x1159, 0x110, 0x1184, 0x110, 0x1185, 0x110, 0x1188, 0x110,
+ 0x1191, 0x110, 0x1192, 0x110, 0x1194, 0x110, 0x119e, 0x110,
+ 0x11a1, 0x109, 0x4e00, 0x109, 0x4e8c, 0x109, 0x4e09, 0x109,
+ 0x56db, 0x109, 0x4e0a, 0x109, 0x4e2d, 0x109, 0x4e0b, 0x109,
+ 0x7532, 0x109, 0x4e59, 0x109, 0x4e19, 0x109, 0x4e01, 0x109,
+ 0x5929, 0x109, 0x5730, 0x109, 0x4eba, 0x310, 0x28, 0x1100,
+ 0x29, 0x310, 0x28, 0x1102, 0x29, 0x310, 0x28, 0x1103,
+ 0x29, 0x310, 0x28, 0x1105, 0x29, 0x310, 0x28, 0x1106,
+ 0x29, 0x310, 0x28, 0x1107, 0x29, 0x310, 0x28, 0x1109,
+ 0x29, 0x310, 0x28, 0x110b, 0x29, 0x310, 0x28, 0x110c,
+ 0x29, 0x310, 0x28, 0x110e, 0x29, 0x310, 0x28, 0x110f,
+ 0x29, 0x310, 0x28, 0x1110, 0x29, 0x310, 0x28, 0x1111,
+ 0x29, 0x310, 0x28, 0x1112, 0x29, 0x410, 0x28, 0x1100,
+ 0x1161, 0x29, 0x410, 0x28, 0x1102, 0x1161, 0x29, 0x410,
+ 0x28, 0x1103, 0x1161, 0x29, 0x410, 0x28, 0x1105, 0x1161,
+ 0x29, 0x410, 0x28, 0x1106, 0x1161, 0x29, 0x410, 0x28,
+ 0x1107, 0x1161, 0x29, 0x410, 0x28, 0x1109, 0x1161, 0x29,
+ 0x410, 0x28, 0x110b, 0x1161, 0x29, 0x410, 0x28, 0x110c,
+ 0x1161, 0x29, 0x410, 0x28, 0x110e, 0x1161, 0x29, 0x410,
+ 0x28, 0x110f, 0x1161, 0x29, 0x410, 0x28, 0x1110, 0x1161,
+ 0x29, 0x410, 0x28, 0x1111, 0x1161, 0x29, 0x410, 0x28,
+ 0x1112, 0x1161, 0x29, 0x410, 0x28, 0x110c, 0x116e, 0x29,
+ 0x710, 0x28, 0x110b, 0x1169, 0x110c, 0x1165, 0x11ab, 0x29,
+ 0x610, 0x28, 0x110b, 0x1169, 0x1112, 0x116e, 0x29, 0x310,
+ 0x28, 0x4e00, 0x29, 0x310, 0x28, 0x4e8c, 0x29, 0x310,
+ 0x28, 0x4e09, 0x29, 0x310, 0x28, 0x56db, 0x29, 0x310,
+ 0x28, 0x4e94, 0x29, 0x310, 0x28, 0x516d, 0x29, 0x310,
+ 0x28, 0x4e03, 0x29, 0x310, 0x28, 0x516b, 0x29, 0x310,
+ 0x28, 0x4e5d, 0x29, 0x310, 0x28, 0x5341, 0x29, 0x310,
+ 0x28, 0x6708, 0x29, 0x310, 0x28, 0x706b, 0x29, 0x310,
+ 0x28, 0x6c34, 0x29, 0x310, 0x28, 0x6728, 0x29, 0x310,
+ 0x28, 0x91d1, 0x29, 0x310, 0x28, 0x571f, 0x29, 0x310,
+ 0x28, 0x65e5, 0x29, 0x310, 0x28, 0x682a, 0x29, 0x310,
+ 0x28, 0x6709, 0x29, 0x310, 0x28, 0x793e, 0x29, 0x310,
+ 0x28, 0x540d, 0x29, 0x310, 0x28, 0x7279, 0x29, 0x310,
+ 0x28, 0x8ca1, 0x29, 0x310, 0x28, 0x795d, 0x29, 0x310,
+ 0x28, 0x52b4, 0x29, 0x310, 0x28, 0x4ee3, 0x29, 0x310,
+ 0x28, 0x547c, 0x29, 0x310, 0x28, 0x5b66, 0x29, 0x310,
+ 0x28, 0x76e3, 0x29, 0x310, 0x28, 0x4f01, 0x29, 0x310,
+ 0x28, 0x8cc7, 0x29, 0x310, 0x28, 0x5354, 0x29, 0x310,
+ 0x28, 0x796d, 0x29, 0x310, 0x28, 0x4f11, 0x29, 0x310,
+ 0x28, 0x81ea, 0x29, 0x310, 0x28, 0x81f3, 0x29, 0x30f,
+ 0x50, 0x54, 0x45, 0x208, 0x32, 0x31, 0x208, 0x32,
+ 0x32, 0x208, 0x32, 0x33, 0x208, 0x32, 0x34, 0x208,
+ 0x32, 0x35, 0x208, 0x32, 0x36, 0x208, 0x32, 0x37,
+ 0x208, 0x32, 0x38, 0x208, 0x32, 0x39, 0x208, 0x33,
+ 0x30, 0x208, 0x33, 0x31, 0x208, 0x33, 0x32, 0x208,
+ 0x33, 0x33, 0x208, 0x33, 0x34, 0x208, 0x33, 0x35,
+ 0x108, 0x1100, 0x108, 0x1102, 0x108, 0x1103, 0x108, 0x1105,
+ 0x108, 0x1106, 0x108, 0x1107, 0x108, 0x1109, 0x108, 0x110b,
+ 0x108, 0x110c, 0x108, 0x110e, 0x108, 0x110f, 0x108, 0x1110,
+ 0x108, 0x1111, 0x108, 0x1112, 0x208, 0x1100, 0x1161, 0x208,
+ 0x1102, 0x1161, 0x208, 0x1103, 0x1161, 0x208, 0x1105, 0x1161,
+ 0x208, 0x1106, 0x1161, 0x208, 0x1107, 0x1161, 0x208, 0x1109,
+ 0x1161, 0x208, 0x110b, 0x1161, 0x208, 0x110c, 0x1161, 0x208,
+ 0x110e, 0x1161, 0x208, 0x110f, 0x1161, 0x208, 0x1110, 0x1161,
+ 0x208, 0x1111, 0x1161, 0x208, 0x1112, 0x1161, 0x508, 0x110e,
+ 0x1161, 0x11b7, 0x1100, 0x1169, 0x408, 0x110c, 0x116e, 0x110b,
+ 0x1174, 0x208, 0x110b, 0x116e, 0x108, 0x4e00, 0x108, 0x4e8c,
+ 0x108, 0x4e09, 0x108, 0x56db, 0x108, 0x4e94, 0x108, 0x516d,
+ 0x108, 0x4e03, 0x108, 0x516b, 0x108, 0x4e5d, 0x108, 0x5341,
+ 0x108, 0x6708, 0x108, 0x706b, 0x108, 0x6c34, 0x108, 0x6728,
+ 0x108, 0x91d1, 0x108, 0x571f, 0x108, 0x65e5, 0x108, 0x682a,
+ 0x108, 0x6709, 0x108, 0x793e, 0x108, 0x540d, 0x108, 0x7279,
+ 0x108, 0x8ca1, 0x108, 0x795d, 0x108, 0x52b4, 0x108, 0x79d8,
+ 0x108, 0x7537, 0x108, 0x5973, 0x108, 0x9069, 0x108, 0x512a,
+ 0x108, 0x5370, 0x108, 0x6ce8, 0x108, 0x9805, 0x108, 0x4f11,
+ 0x108, 0x5199, 0x108, 0x6b63, 0x108, 0x4e0a, 0x108, 0x4e2d,
+ 0x108, 0x4e0b, 0x108, 0x5de6, 0x108, 0x53f3, 0x108, 0x533b,
+ 0x108, 0x5b97, 0x108, 0x5b66, 0x108, 0x76e3, 0x108, 0x4f01,
+ 0x108, 0x8cc7, 0x108, 0x5354, 0x108, 0x591c, 0x208, 0x33,
+ 0x36, 0x208, 0x33, 0x37, 0x208, 0x33, 0x38, 0x208,
+ 0x33, 0x39, 0x208, 0x34, 0x30, 0x208, 0x34, 0x31,
+ 0x208, 0x34, 0x32, 0x208, 0x34, 0x33, 0x208, 0x34,
+ 0x34, 0x208, 0x34, 0x35, 0x208, 0x34, 0x36, 0x208,
+ 0x34, 0x37, 0x208, 0x34, 0x38, 0x208, 0x34, 0x39,
+ 0x208, 0x35, 0x30, 0x210, 0x31, 0x6708, 0x210, 0x32,
+ 0x6708, 0x210, 0x33, 0x6708, 0x210, 0x34, 0x6708, 0x210,
+ 0x35, 0x6708, 0x210, 0x36, 0x6708, 0x210, 0x37, 0x6708,
+ 0x210, 0x38, 0x6708, 0x210, 0x39, 0x6708, 0x310, 0x31,
+ 0x30, 0x6708, 0x310, 0x31, 0x31, 0x6708, 0x310, 0x31,
+ 0x32, 0x6708, 0x20f, 0x48, 0x67, 0x30f, 0x65, 0x72,
+ 0x67, 0x20f, 0x65, 0x56, 0x30f, 0x4c, 0x54, 0x44,
+ 0x108, 0x30a2, 0x108, 0x30a4, 0x108, 0x30a6, 0x108, 0x30a8,
+ 0x108, 0x30aa, 0x108, 0x30ab, 0x108, 0x30ad, 0x108, 0x30af,
+ 0x108, 0x30b1, 0x108, 0x30b3, 0x108, 0x30b5, 0x108, 0x30b7,
+ 0x108, 0x30b9, 0x108, 0x30bb, 0x108, 0x30bd, 0x108, 0x30bf,
+ 0x108, 0x30c1, 0x108, 0x30c4, 0x108, 0x30c6, 0x108, 0x30c8,
+ 0x108, 0x30ca, 0x108, 0x30cb, 0x108, 0x30cc, 0x108, 0x30cd,
+ 0x108, 0x30ce, 0x108, 0x30cf, 0x108, 0x30d2, 0x108, 0x30d5,
+ 0x108, 0x30d8, 0x108, 0x30db, 0x108, 0x30de, 0x108, 0x30df,
+ 0x108, 0x30e0, 0x108, 0x30e1, 0x108, 0x30e2, 0x108, 0x30e4,
+ 0x108, 0x30e6, 0x108, 0x30e8, 0x108, 0x30e9, 0x108, 0x30ea,
+ 0x108, 0x30eb, 0x108, 0x30ec, 0x108, 0x30ed, 0x108, 0x30ef,
+ 0x108, 0x30f0, 0x108, 0x30f1, 0x108, 0x30f2, 0x40f, 0x30a2,
+ 0x30d1, 0x30fc, 0x30c8, 0x40f, 0x30a2, 0x30eb, 0x30d5, 0x30a1,
+ 0x40f, 0x30a2, 0x30f3, 0x30da, 0x30a2, 0x30f, 0x30a2, 0x30fc,
+ 0x30eb, 0x40f, 0x30a4, 0x30cb, 0x30f3, 0x30b0, 0x30f, 0x30a4,
+ 0x30f3, 0x30c1, 0x30f, 0x30a6, 0x30a9, 0x30f3, 0x50f, 0x30a8,
+ 0x30b9, 0x30af, 0x30fc, 0x30c9, 0x40f, 0x30a8, 0x30fc, 0x30ab,
+ 0x30fc, 0x30f, 0x30aa, 0x30f3, 0x30b9, 0x30f, 0x30aa, 0x30fc,
+ 0x30e0, 0x30f, 0x30ab, 0x30a4, 0x30ea, 0x40f, 0x30ab, 0x30e9,
+ 0x30c3, 0x30c8, 0x40f, 0x30ab, 0x30ed, 0x30ea, 0x30fc, 0x30f,
+ 0x30ac, 0x30ed, 0x30f3, 0x30f, 0x30ac, 0x30f3, 0x30de, 0x20f,
+ 0x30ae, 0x30ac, 0x30f, 0x30ae, 0x30cb, 0x30fc, 0x40f, 0x30ad,
+ 0x30e5, 0x30ea, 0x30fc, 0x40f, 0x30ae, 0x30eb, 0x30c0, 0x30fc,
+ 0x20f, 0x30ad, 0x30ed, 0x50f, 0x30ad, 0x30ed, 0x30b0, 0x30e9,
+ 0x30e0, 0x60f, 0x30ad, 0x30ed, 0x30e1, 0x30fc, 0x30c8, 0x30eb,
+ 0x50f, 0x30ad, 0x30ed, 0x30ef, 0x30c3, 0x30c8, 0x30f, 0x30b0,
+ 0x30e9, 0x30e0, 0x50f, 0x30b0, 0x30e9, 0x30e0, 0x30c8, 0x30f3,
+ 0x50f, 0x30af, 0x30eb, 0x30bc, 0x30a4, 0x30ed, 0x40f, 0x30af,
+ 0x30ed, 0x30fc, 0x30cd, 0x30f, 0x30b1, 0x30fc, 0x30b9, 0x30f,
+ 0x30b3, 0x30eb, 0x30ca, 0x30f, 0x30b3, 0x30fc, 0x30dd, 0x40f,
+ 0x30b5, 0x30a4, 0x30af, 0x30eb, 0x50f, 0x30b5, 0x30f3, 0x30c1,
+ 0x30fc, 0x30e0, 0x40f, 0x30b7, 0x30ea, 0x30f3, 0x30b0, 0x30f,
+ 0x30bb, 0x30f3, 0x30c1, 0x30f, 0x30bb, 0x30f3, 0x30c8, 0x30f,
+ 0x30c0, 0x30fc, 0x30b9, 0x20f, 0x30c7, 0x30b7, 0x20f, 0x30c9,
+ 0x30eb, 0x20f, 0x30c8, 0x30f3, 0x20f, 0x30ca, 0x30ce, 0x30f,
+ 0x30ce, 0x30c3, 0x30c8, 0x30f, 0x30cf, 0x30a4, 0x30c4, 0x50f,
+ 0x30d1, 0x30fc, 0x30bb, 0x30f3, 0x30c8, 0x30f, 0x30d1, 0x30fc,
+ 0x30c4, 0x40f, 0x30d0, 0x30fc, 0x30ec, 0x30eb, 0x50f, 0x30d4,
+ 0x30a2, 0x30b9, 0x30c8, 0x30eb, 0x30f, 0x30d4, 0x30af, 0x30eb,
+ 0x20f, 0x30d4, 0x30b3, 0x20f, 0x30d3, 0x30eb, 0x50f, 0x30d5,
+ 0x30a1, 0x30e9, 0x30c3, 0x30c9, 0x40f, 0x30d5, 0x30a3, 0x30fc,
+ 0x30c8, 0x50f, 0x30d6, 0x30c3, 0x30b7, 0x30a7, 0x30eb, 0x30f,
+ 0x30d5, 0x30e9, 0x30f3, 0x50f, 0x30d8, 0x30af, 0x30bf, 0x30fc,
+ 0x30eb, 0x20f, 0x30da, 0x30bd, 0x30f, 0x30da, 0x30cb, 0x30d2,
+ 0x30f, 0x30d8, 0x30eb, 0x30c4, 0x30f, 0x30da, 0x30f3, 0x30b9,
+ 0x30f, 0x30da, 0x30fc, 0x30b8, 0x30f, 0x30d9, 0x30fc, 0x30bf,
+ 0x40f, 0x30dd, 0x30a4, 0x30f3, 0x30c8, 0x30f, 0x30dc, 0x30eb,
+ 0x30c8, 0x20f, 0x30db, 0x30f3, 0x30f, 0x30dd, 0x30f3, 0x30c9,
+ 0x30f, 0x30db, 0x30fc, 0x30eb, 0x30f, 0x30db, 0x30fc, 0x30f3,
+ 0x40f, 0x30de, 0x30a4, 0x30af, 0x30ed, 0x30f, 0x30de, 0x30a4,
+ 0x30eb, 0x30f, 0x30de, 0x30c3, 0x30cf, 0x30f, 0x30de, 0x30eb,
+ 0x30af, 0x50f, 0x30de, 0x30f3, 0x30b7, 0x30e7, 0x30f3, 0x40f,
+ 0x30df, 0x30af, 0x30ed, 0x30f3, 0x20f, 0x30df, 0x30ea, 0x50f,
+ 0x30df, 0x30ea, 0x30d0, 0x30fc, 0x30eb, 0x20f, 0x30e1, 0x30ac,
+ 0x40f, 0x30e1, 0x30ac, 0x30c8, 0x30f3, 0x40f, 0x30e1, 0x30fc,
+ 0x30c8, 0x30eb, 0x30f, 0x30e4, 0x30fc, 0x30c9, 0x30f, 0x30e4,
+ 0x30fc, 0x30eb, 0x30f, 0x30e6, 0x30a2, 0x30f3, 0x40f, 0x30ea,
+ 0x30c3, 0x30c8, 0x30eb, 0x20f, 0x30ea, 0x30e9, 0x30f, 0x30eb,
+ 0x30d4, 0x30fc, 0x40f, 0x30eb, 0x30fc, 0x30d6, 0x30eb, 0x20f,
+ 0x30ec, 0x30e0, 0x50f, 0x30ec, 0x30f3, 0x30c8, 0x30b2, 0x30f3,
+ 0x30f, 0x30ef, 0x30c3, 0x30c8, 0x210, 0x30, 0x70b9, 0x210,
+ 0x31, 0x70b9, 0x210, 0x32, 0x70b9, 0x210, 0x33, 0x70b9,
+ 0x210, 0x34, 0x70b9, 0x210, 0x35, 0x70b9, 0x210, 0x36,
+ 0x70b9, 0x210, 0x37, 0x70b9, 0x210, 0x38, 0x70b9, 0x210,
+ 0x39, 0x70b9, 0x310, 0x31, 0x30, 0x70b9, 0x310, 0x31,
+ 0x31, 0x70b9, 0x310, 0x31, 0x32, 0x70b9, 0x310, 0x31,
+ 0x33, 0x70b9, 0x310, 0x31, 0x34, 0x70b9, 0x310, 0x31,
+ 0x35, 0x70b9, 0x310, 0x31, 0x36, 0x70b9, 0x310, 0x31,
+ 0x37, 0x70b9, 0x310, 0x31, 0x38, 0x70b9, 0x310, 0x31,
+ 0x39, 0x70b9, 0x310, 0x32, 0x30, 0x70b9, 0x310, 0x32,
+ 0x31, 0x70b9, 0x310, 0x32, 0x32, 0x70b9, 0x310, 0x32,
+ 0x33, 0x70b9, 0x310, 0x32, 0x34, 0x70b9, 0x30f, 0x68,
+ 0x50, 0x61, 0x20f, 0x64, 0x61, 0x20f, 0x41, 0x55,
+ 0x30f, 0x62, 0x61, 0x72, 0x20f, 0x6f, 0x56, 0x20f,
+ 0x70, 0x63, 0x20f, 0x64, 0x6d, 0x30f, 0x64, 0x6d,
+ 0xb2, 0x30f, 0x64, 0x6d, 0xb3, 0x20f, 0x49, 0x55,
+ 0x20f, 0x5e73, 0x6210, 0x20f, 0x662d, 0x548c, 0x20f, 0x5927,
+ 0x6b63, 0x20f, 0x660e, 0x6cbb, 0x40f, 0x682a, 0x5f0f, 0x4f1a,
+ 0x793e, 0x20f, 0x70, 0x41, 0x20f, 0x6e, 0x41, 0x20f,
+ 0x3bc, 0x41, 0x20f, 0x6d, 0x41, 0x20f, 0x6b, 0x41,
+ 0x20f, 0x4b, 0x42, 0x20f, 0x4d, 0x42, 0x20f, 0x47,
+ 0x42, 0x30f, 0x63, 0x61, 0x6c, 0x40f, 0x6b, 0x63,
+ 0x61, 0x6c, 0x20f, 0x70, 0x46, 0x20f, 0x6e, 0x46,
+ 0x20f, 0x3bc, 0x46, 0x20f, 0x3bc, 0x67, 0x20f, 0x6d,
+ 0x67, 0x20f, 0x6b, 0x67, 0x20f, 0x48, 0x7a, 0x30f,
+ 0x6b, 0x48, 0x7a, 0x30f, 0x4d, 0x48, 0x7a, 0x30f,
+ 0x47, 0x48, 0x7a, 0x30f, 0x54, 0x48, 0x7a, 0x20f,
+ 0x3bc, 0x2113, 0x20f, 0x6d, 0x2113, 0x20f, 0x64, 0x2113,
+ 0x20f, 0x6b, 0x2113, 0x20f, 0x66, 0x6d, 0x20f, 0x6e,
+ 0x6d, 0x20f, 0x3bc, 0x6d, 0x20f, 0x6d, 0x6d, 0x20f,
+ 0x63, 0x6d, 0x20f, 0x6b, 0x6d, 0x30f, 0x6d, 0x6d,
+ 0xb2, 0x30f, 0x63, 0x6d, 0xb2, 0x20f, 0x6d, 0xb2,
+ 0x30f, 0x6b, 0x6d, 0xb2, 0x30f, 0x6d, 0x6d, 0xb3,
+ 0x30f, 0x63, 0x6d, 0xb3, 0x20f, 0x6d, 0xb3, 0x30f,
+ 0x6b, 0x6d, 0xb3, 0x30f, 0x6d, 0x2215, 0x73, 0x40f,
+ 0x6d, 0x2215, 0x73, 0xb2, 0x20f, 0x50, 0x61, 0x30f,
+ 0x6b, 0x50, 0x61, 0x30f, 0x4d, 0x50, 0x61, 0x30f,
+ 0x47, 0x50, 0x61, 0x30f, 0x72, 0x61, 0x64, 0x50f,
+ 0x72, 0x61, 0x64, 0x2215, 0x73, 0x60f, 0x72, 0x61,
+ 0x64, 0x2215, 0x73, 0xb2, 0x20f, 0x70, 0x73, 0x20f,
+ 0x6e, 0x73, 0x20f, 0x3bc, 0x73, 0x20f, 0x6d, 0x73,
+ 0x20f, 0x70, 0x56, 0x20f, 0x6e, 0x56, 0x20f, 0x3bc,
+ 0x56, 0x20f, 0x6d, 0x56, 0x20f, 0x6b, 0x56, 0x20f,
+ 0x4d, 0x56, 0x20f, 0x70, 0x57, 0x20f, 0x6e, 0x57,
+ 0x20f, 0x3bc, 0x57, 0x20f, 0x6d, 0x57, 0x20f, 0x6b,
+ 0x57, 0x20f, 0x4d, 0x57, 0x20f, 0x6b, 0x3a9, 0x20f,
+ 0x4d, 0x3a9, 0x40f, 0x61, 0x2e, 0x6d, 0x2e, 0x20f,
+ 0x42, 0x71, 0x20f, 0x63, 0x63, 0x20f, 0x63, 0x64,
+ 0x40f, 0x43, 0x2215, 0x6b, 0x67, 0x30f, 0x43, 0x6f,
+ 0x2e, 0x20f, 0x64, 0x42, 0x20f, 0x47, 0x79, 0x20f,
+ 0x68, 0x61, 0x20f, 0x48, 0x50, 0x20f, 0x69, 0x6e,
+ 0x20f, 0x4b, 0x4b, 0x20f, 0x4b, 0x4d, 0x20f, 0x6b,
+ 0x74, 0x20f, 0x6c, 0x6d, 0x20f, 0x6c, 0x6e, 0x30f,
+ 0x6c, 0x6f, 0x67, 0x20f, 0x6c, 0x78, 0x20f, 0x6d,
+ 0x62, 0x30f, 0x6d, 0x69, 0x6c, 0x30f, 0x6d, 0x6f,
+ 0x6c, 0x20f, 0x50, 0x48, 0x40f, 0x70, 0x2e, 0x6d,
+ 0x2e, 0x30f, 0x50, 0x50, 0x4d, 0x20f, 0x50, 0x52,
+ 0x20f, 0x73, 0x72, 0x20f, 0x53, 0x76, 0x20f, 0x57,
+ 0x62, 0x30f, 0x56, 0x2215, 0x6d, 0x30f, 0x41, 0x2215,
+ 0x6d, 0x210, 0x31, 0x65e5, 0x210, 0x32, 0x65e5, 0x210,
+ 0x33, 0x65e5, 0x210, 0x34, 0x65e5, 0x210, 0x35, 0x65e5,
+ 0x210, 0x36, 0x65e5, 0x210, 0x37, 0x65e5, 0x210, 0x38,
+ 0x65e5, 0x210, 0x39, 0x65e5, 0x310, 0x31, 0x30, 0x65e5,
+ 0x310, 0x31, 0x31, 0x65e5, 0x310, 0x31, 0x32, 0x65e5,
+ 0x310, 0x31, 0x33, 0x65e5, 0x310, 0x31, 0x34, 0x65e5,
+ 0x310, 0x31, 0x35, 0x65e5, 0x310, 0x31, 0x36, 0x65e5,
+ 0x310, 0x31, 0x37, 0x65e5, 0x310, 0x31, 0x38, 0x65e5,
+ 0x310, 0x31, 0x39, 0x65e5, 0x310, 0x32, 0x30, 0x65e5,
+ 0x310, 0x32, 0x31, 0x65e5, 0x310, 0x32, 0x32, 0x65e5,
+ 0x310, 0x32, 0x33, 0x65e5, 0x310, 0x32, 0x34, 0x65e5,
+ 0x310, 0x32, 0x35, 0x65e5, 0x310, 0x32, 0x36, 0x65e5,
+ 0x310, 0x32, 0x37, 0x65e5, 0x310, 0x32, 0x38, 0x65e5,
+ 0x310, 0x32, 0x39, 0x65e5, 0x310, 0x33, 0x30, 0x65e5,
+ 0x310, 0x33, 0x31, 0x65e5, 0x30f, 0x67, 0x61, 0x6c,
+ 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, 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, 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, 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,
+ 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,
+ 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, 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,
+ 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, 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,
+ 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, 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, 0x33, 0x102, 0x34, 0x102,
+ 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, 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,
+ 0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102,
+ 0x37, 0x102, 0x38, 0x102, 0x39, 0x101, 0x4e3d, 0x101,
+ 0x4e38, 0x101, 0x4e41, 0x201, 0xd840, 0xdd22, 0x101, 0x4f60,
+ 0x101, 0x4fae, 0x101, 0x4fbb, 0x101, 0x5002, 0x101, 0x507a,
+ 0x101, 0x5099, 0x101, 0x50e7, 0x101, 0x50cf, 0x101, 0x349e,
+ 0x201, 0xd841, 0xde3a, 0x101, 0x514d, 0x101, 0x5154, 0x101,
+ 0x5164, 0x101, 0x5177, 0x201, 0xd841, 0xdd1c, 0x101, 0x34b9,
+ 0x101, 0x5167, 0x101, 0x518d, 0x201, 0xd841, 0xdd4b, 0x101,
+ 0x5197, 0x101, 0x51a4, 0x101, 0x4ecc, 0x101, 0x51ac, 0x101,
+ 0x51b5, 0x201, 0xd864, 0xdddf, 0x101, 0x51f5, 0x101, 0x5203,
+ 0x101, 0x34df, 0x101, 0x523b, 0x101, 0x5246, 0x101, 0x5272,
+ 0x101, 0x5277, 0x101, 0x3515, 0x101, 0x52c7, 0x101, 0x52c9,
+ 0x101, 0x52e4, 0x101, 0x52fa, 0x101, 0x5305, 0x101, 0x5306,
+ 0x101, 0x5317, 0x101, 0x5349, 0x101, 0x5351, 0x101, 0x535a,
+ 0x101, 0x5373, 0x101, 0x537d, 0x101, 0x537f, 0x101, 0x537f,
+ 0x101, 0x537f, 0x201, 0xd842, 0xde2c, 0x101, 0x7070, 0x101,
+ 0x53ca, 0x101, 0x53df, 0x201, 0xd842, 0xdf63, 0x101, 0x53eb,
+ 0x101, 0x53f1, 0x101, 0x5406, 0x101, 0x549e, 0x101, 0x5438,
+ 0x101, 0x5448, 0x101, 0x5468, 0x101, 0x54a2, 0x101, 0x54f6,
+ 0x101, 0x5510, 0x101, 0x5553, 0x101, 0x5563, 0x101, 0x5584,
+ 0x101, 0x5584, 0x101, 0x5599, 0x101, 0x55ab, 0x101, 0x55b3,
+ 0x101, 0x55c2, 0x101, 0x5716, 0x101, 0x5606, 0x101, 0x5717,
+ 0x101, 0x5651, 0x101, 0x5674, 0x101, 0x5207, 0x101, 0x58ee,
+ 0x101, 0x57ce, 0x101, 0x57f4, 0x101, 0x580d, 0x101, 0x578b,
+ 0x101, 0x5832, 0x101, 0x5831, 0x101, 0x58ac, 0x201, 0xd845,
+ 0xdce4, 0x101, 0x58f2, 0x101, 0x58f7, 0x101, 0x5906, 0x101,
+ 0x591a, 0x101, 0x5922, 0x101, 0x5962, 0x201, 0xd845, 0xdea8,
+ 0x201, 0xd845, 0xdeea, 0x101, 0x59ec, 0x101, 0x5a1b, 0x101,
+ 0x5a27, 0x101, 0x59d8, 0x101, 0x5a66, 0x101, 0x36ee, 0x101,
+ 0x36fc, 0x101, 0x5b08, 0x101, 0x5b3e, 0x101, 0x5b3e, 0x201,
+ 0xd846, 0xddc8, 0x101, 0x5bc3, 0x101, 0x5bd8, 0x101, 0x5be7,
+ 0x101, 0x5bf3, 0x201, 0xd846, 0xdf18, 0x101, 0x5bff, 0x101,
+ 0x5c06, 0x101, 0x5f53, 0x101, 0x5c22, 0x101, 0x3781, 0x101,
+ 0x5c60, 0x101, 0x5c6e, 0x101, 0x5cc0, 0x101, 0x5c8d, 0x201,
+ 0xd847, 0xdde4, 0x101, 0x5d43, 0x201, 0xd847, 0xdde6, 0x101,
+ 0x5d6e, 0x101, 0x5d6b, 0x101, 0x5d7c, 0x101, 0x5de1, 0x101,
+ 0x5de2, 0x101, 0x382f, 0x101, 0x5dfd, 0x101, 0x5e28, 0x101,
+ 0x5e3d, 0x101, 0x5e69, 0x101, 0x3862, 0x201, 0xd848, 0xdd83,
+ 0x101, 0x387c, 0x101, 0x5eb0, 0x101, 0x5eb3, 0x101, 0x5eb6,
+ 0x101, 0x5eca, 0x201, 0xd868, 0xdf92, 0x101, 0x5efe, 0x201,
+ 0xd848, 0xdf31, 0x201, 0xd848, 0xdf31, 0x101, 0x8201, 0x101,
+ 0x5f22, 0x101, 0x5f22, 0x101, 0x38c7, 0x201, 0xd84c, 0xdeb8,
+ 0x201, 0xd858, 0xddda, 0x101, 0x5f62, 0x101, 0x5f6b, 0x101,
+ 0x38e3, 0x101, 0x5f9a, 0x101, 0x5fcd, 0x101, 0x5fd7, 0x101,
+ 0x5ff9, 0x101, 0x6081, 0x101, 0x393a, 0x101, 0x391c, 0x101,
+ 0x6094, 0x201, 0xd849, 0xded4, 0x101, 0x60c7, 0x101, 0x6148,
+ 0x101, 0x614c, 0x101, 0x614e, 0x101, 0x614c, 0x101, 0x617a,
+ 0x101, 0x618e, 0x101, 0x61b2, 0x101, 0x61a4, 0x101, 0x61af,
+ 0x101, 0x61de, 0x101, 0x61f2, 0x101, 0x61f6, 0x101, 0x6210,
+ 0x101, 0x621b, 0x101, 0x625d, 0x101, 0x62b1, 0x101, 0x62d4,
+ 0x101, 0x6350, 0x201, 0xd84a, 0xdf0c, 0x101, 0x633d, 0x101,
+ 0x62fc, 0x101, 0x6368, 0x101, 0x6383, 0x101, 0x63e4, 0x201,
+ 0xd84a, 0xdff1, 0x101, 0x6422, 0x101, 0x63c5, 0x101, 0x63a9,
+ 0x101, 0x3a2e, 0x101, 0x6469, 0x101, 0x647e, 0x101, 0x649d,
+ 0x101, 0x6477, 0x101, 0x3a6c, 0x101, 0x654f, 0x101, 0x656c,
+ 0x201, 0xd84c, 0xdc0a, 0x101, 0x65e3, 0x101, 0x66f8, 0x101,
+ 0x6649, 0x101, 0x3b19, 0x101, 0x6691, 0x101, 0x3b08, 0x101,
+ 0x3ae4, 0x101, 0x5192, 0x101, 0x5195, 0x101, 0x6700, 0x101,
+ 0x669c, 0x101, 0x80ad, 0x101, 0x43d9, 0x101, 0x6717, 0x101,
+ 0x671b, 0x101, 0x6721, 0x101, 0x675e, 0x101, 0x6753, 0x201,
+ 0xd84c, 0xdfc3, 0x101, 0x3b49, 0x101, 0x67fa, 0x101, 0x6785,
+ 0x101, 0x6852, 0x101, 0x6885, 0x201, 0xd84d, 0xdc6d, 0x101,
+ 0x688e, 0x101, 0x681f, 0x101, 0x6914, 0x101, 0x3b9d, 0x101,
+ 0x6942, 0x101, 0x69a3, 0x101, 0x69ea, 0x101, 0x6aa8, 0x201,
+ 0xd84d, 0xdea3, 0x101, 0x6adb, 0x101, 0x3c18, 0x101, 0x6b21,
+ 0x201, 0xd84e, 0xdca7, 0x101, 0x6b54, 0x101, 0x3c4e, 0x101,
+ 0x6b72, 0x101, 0x6b9f, 0x101, 0x6bba, 0x101, 0x6bbb, 0x201,
+ 0xd84e, 0xde8d, 0x201, 0xd847, 0xdd0b, 0x201, 0xd84e, 0xdefa,
+ 0x101, 0x6c4e, 0x201, 0xd84f, 0xdcbc, 0x101, 0x6cbf, 0x101,
+ 0x6ccd, 0x101, 0x6c67, 0x101, 0x6d16, 0x101, 0x6d3e, 0x101,
+ 0x6d77, 0x101, 0x6d41, 0x101, 0x6d69, 0x101, 0x6d78, 0x101,
+ 0x6d85, 0x201, 0xd84f, 0xdd1e, 0x101, 0x6d34, 0x101, 0x6e2f,
+ 0x101, 0x6e6e, 0x101, 0x3d33, 0x101, 0x6ecb, 0x101, 0x6ec7,
+ 0x201, 0xd84f, 0xded1, 0x101, 0x6df9, 0x101, 0x6f6e, 0x201,
+ 0xd84f, 0xdf5e, 0x201, 0xd84f, 0xdf8e, 0x101, 0x6fc6, 0x101,
+ 0x7039, 0x101, 0x701e, 0x101, 0x701b, 0x101, 0x3d96, 0x101,
+ 0x704a, 0x101, 0x707d, 0x101, 0x7077, 0x101, 0x70ad, 0x201,
+ 0xd841, 0xdd25, 0x101, 0x7145, 0x201, 0xd850, 0xde63, 0x101,
+ 0x719c, 0x201, 0xd850, 0xdfab, 0x101, 0x7228, 0x101, 0x7235,
+ 0x101, 0x7250, 0x201, 0xd851, 0xde08, 0x101, 0x7280, 0x101,
+ 0x7295, 0x201, 0xd851, 0xdf35, 0x201, 0xd852, 0xdc14, 0x101,
+ 0x737a, 0x101, 0x738b, 0x101, 0x3eac, 0x101, 0x73a5, 0x101,
+ 0x3eb8, 0x101, 0x3eb8, 0x101, 0x7447, 0x101, 0x745c, 0x101,
+ 0x7471, 0x101, 0x7485, 0x101, 0x74ca, 0x101, 0x3f1b, 0x101,
+ 0x7524, 0x201, 0xd853, 0xdc36, 0x101, 0x753e, 0x201, 0xd853,
+ 0xdc92, 0x101, 0x7570, 0x201, 0xd848, 0xdd9f, 0x101, 0x7610,
+ 0x201, 0xd853, 0xdfa1, 0x201, 0xd853, 0xdfb8, 0x201, 0xd854,
+ 0xdc44, 0x101, 0x3ffc, 0x101, 0x4008, 0x101, 0x76f4, 0x201,
+ 0xd854, 0xdcf3, 0x201, 0xd854, 0xdcf2, 0x201, 0xd854, 0xdd19,
+ 0x201, 0xd854, 0xdd33, 0x101, 0x771e, 0x101, 0x771f, 0x101,
+ 0x771f, 0x101, 0x774a, 0x101, 0x4039, 0x101, 0x778b, 0x101,
+ 0x4046, 0x101, 0x4096, 0x201, 0xd855, 0xdc1d, 0x101, 0x784e,
+ 0x101, 0x788c, 0x101, 0x78cc, 0x101, 0x40e3, 0x201, 0xd855,
+ 0xde26, 0x101, 0x7956, 0x201, 0xd855, 0xde9a, 0x201, 0xd855,
+ 0xdec5, 0x101, 0x798f, 0x101, 0x79eb, 0x101, 0x412f, 0x101,
+ 0x7a40, 0x101, 0x7a4a, 0x101, 0x7a4f, 0x201, 0xd856, 0xdd7c,
+ 0x201, 0xd856, 0xdea7, 0x201, 0xd856, 0xdea7, 0x101, 0x7aee,
+ 0x101, 0x4202, 0x201, 0xd856, 0xdfab, 0x101, 0x7bc6, 0x101,
+ 0x7bc9, 0x101, 0x4227, 0x201, 0xd857, 0xdc80, 0x101, 0x7cd2,
+ 0x101, 0x42a0, 0x101, 0x7ce8, 0x101, 0x7ce3, 0x101, 0x7d00,
+ 0x201, 0xd857, 0xdf86, 0x101, 0x7d63, 0x101, 0x4301, 0x101,
+ 0x7dc7, 0x101, 0x7e02, 0x101, 0x7e45, 0x101, 0x4334, 0x201,
+ 0xd858, 0xde28, 0x201, 0xd858, 0xde47, 0x101, 0x4359, 0x201,
+ 0xd858, 0xded9, 0x101, 0x7f7a, 0x201, 0xd858, 0xdf3e, 0x101,
+ 0x7f95, 0x101, 0x7ffa, 0x101, 0x8005, 0x201, 0xd859, 0xdcda,
+ 0x201, 0xd859, 0xdd23, 0x101, 0x8060, 0x201, 0xd859, 0xdda8,
+ 0x101, 0x8070, 0x201, 0xd84c, 0xdf5f, 0x101, 0x43d5, 0x101,
+ 0x80b2, 0x101, 0x8103, 0x101, 0x440b, 0x101, 0x813e, 0x101,
+ 0x5ab5, 0x201, 0xd859, 0xdfa7, 0x201, 0xd859, 0xdfb5, 0x201,
+ 0xd84c, 0xdf93, 0x201, 0xd84c, 0xdf9c, 0x101, 0x8201, 0x101,
+ 0x8204, 0x101, 0x8f9e, 0x101, 0x446b, 0x101, 0x8291, 0x101,
+ 0x828b, 0x101, 0x829d, 0x101, 0x52b3, 0x101, 0x82b1, 0x101,
+ 0x82b3, 0x101, 0x82bd, 0x101, 0x82e6, 0x201, 0xd85a, 0xdf3c,
+ 0x101, 0x82e5, 0x101, 0x831d, 0x101, 0x8363, 0x101, 0x83ad,
+ 0x101, 0x8323, 0x101, 0x83bd, 0x101, 0x83e7, 0x101, 0x8457,
+ 0x101, 0x8353, 0x101, 0x83ca, 0x101, 0x83cc, 0x101, 0x83dc,
+ 0x201, 0xd85b, 0xdc36, 0x201, 0xd85b, 0xdd6b, 0x201, 0xd85b,
+ 0xdcd5, 0x101, 0x452b, 0x101, 0x84f1, 0x101, 0x84f3, 0x101,
+ 0x8516, 0x201, 0xd85c, 0xdfca, 0x101, 0x8564, 0x201, 0xd85b,
+ 0xdf2c, 0x101, 0x455d, 0x101, 0x4561, 0x201, 0xd85b, 0xdfb1,
+ 0x201, 0xd85c, 0xdcd2, 0x101, 0x456b, 0x101, 0x8650, 0x101,
+ 0x865c, 0x101, 0x8667, 0x101, 0x8669, 0x101, 0x86a9, 0x101,
+ 0x8688, 0x101, 0x870e, 0x101, 0x86e2, 0x101, 0x8779, 0x101,
+ 0x8728, 0x101, 0x876b, 0x101, 0x8786, 0x101, 0x45d7, 0x101,
+ 0x87e1, 0x101, 0x8801, 0x101, 0x45f9, 0x101, 0x8860, 0x101,
+ 0x8863, 0x201, 0xd85d, 0xde67, 0x101, 0x88d7, 0x101, 0x88de,
+ 0x101, 0x4635, 0x101, 0x88fa, 0x101, 0x34bb, 0x201, 0xd85e,
+ 0xdcae, 0x201, 0xd85e, 0xdd66, 0x101, 0x46be, 0x101, 0x46c7,
+ 0x101, 0x8aa0, 0x101, 0x8aed, 0x101, 0x8b8a, 0x101, 0x8c55,
+ 0x201, 0xd85f, 0xdca8, 0x101, 0x8cab, 0x101, 0x8cc1, 0x101,
+ 0x8d1b, 0x101, 0x8d77, 0x201, 0xd85f, 0xdf2f, 0x201, 0xd842,
+ 0xdc04, 0x101, 0x8dcb, 0x101, 0x8dbc, 0x101, 0x8df0, 0x201,
+ 0xd842, 0xdcde, 0x101, 0x8ed4, 0x101, 0x8f38, 0x201, 0xd861,
+ 0xddd2, 0x201, 0xd861, 0xdded, 0x101, 0x9094, 0x101, 0x90f1,
+ 0x101, 0x9111, 0x201, 0xd861, 0xdf2e, 0x101, 0x911b, 0x101,
+ 0x9238, 0x101, 0x92d7, 0x101, 0x92d8, 0x101, 0x927c, 0x101,
+ 0x93f9, 0x101, 0x9415, 0x201, 0xd862, 0xdffa, 0x101, 0x958b,
+ 0x101, 0x4995, 0x101, 0x95b7, 0x201, 0xd863, 0xdd77, 0x101,
+ 0x49e6, 0x101, 0x96c3, 0x101, 0x5db2, 0x101, 0x9723, 0x201,
+ 0xd864, 0xdd45, 0x201, 0xd864, 0xde1a, 0x101, 0x4a6e, 0x101,
+ 0x4a76, 0x101, 0x97e0, 0x201, 0xd865, 0xdc0a, 0x101, 0x4ab2,
+ 0x201, 0xd865, 0xdc96, 0x101, 0x980b, 0x101, 0x980b, 0x101,
+ 0x9829, 0x201, 0xd865, 0xddb6, 0x101, 0x98e2, 0x101, 0x4b33,
+ 0x101, 0x9929, 0x101, 0x99a7, 0x101, 0x99c2, 0x101, 0x99fe,
+ 0x101, 0x4bce, 0x201, 0xd866, 0xdf30, 0x101, 0x9b12, 0x101,
+ 0x9c40, 0x101, 0x9cfd, 0x101, 0x4cce, 0x101, 0x4ced, 0x101,
+ 0x9d67, 0x201, 0xd868, 0xdcce, 0x101, 0x4cf8, 0x201, 0xd868,
+ 0xdd05, 0x201, 0xd868, 0xde0e, 0x201, 0xd868, 0xde91, 0x101,
+ 0x9ebb, 0x101, 0x4d56, 0x101, 0x9ef9, 0x101, 0x9efe, 0x101,
+ 0x9f05, 0x101, 0x9f0f, 0x101, 0x9f16, 0x101, 0x9f3b, 0x201,
+ 0xd869, 0xde00,
+};
+
+static const unsigned short uc_ligature_trie[] = {
+ // 0 - 0x3100
+
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 424, 456, 488, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 520, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 552, 392, 392, 392, 584, 616, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 648, 680, 392, 392, 712, 744, 392,
+ 392, 392, 776, 392, 392, 392, 808, 392,
+ 392, 840, 872, 392, 392, 392, 904, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+
+ 392, 936, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 968, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392,
+
+ 392, 392, 392, 392, 1000, 392, 392, 392,
+
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x0, 0xa9, 0x194, 0x1d5, 0x20e, 0xffff, 0x267, 0x2a8,
+ 0x305, 0x372, 0x3a3, 0x3b0, 0x3bd, 0xffff, 0xffff, 0x408,
+ 0xffff, 0x425, 0xffff, 0x43e, 0x45b, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x47c, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0x485, 0x4da, 0x4df, 0x4e4, 0x4ed,
+ 0x51a, 0xffff, 0xffff, 0xffff, 0xffff, 0x52f, 0x548, 0xffff,
+ 0x54d, 0x55a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x57d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0x5d6, 0xffff, 0xffff, 0x611, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x690, 0x693, 0x6a0, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x6a3, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6aa, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6ad,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b0, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b3, 0x6b6,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b9, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6be,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6c3, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0x6c6, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6c9, 0x6d0, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6d3, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6d8,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x6db, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e0,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e3,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e6, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e9, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x700, 0x761, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+};
+
+#define GET_LIGATURE_INDEX(u2) (u2 < 0x3100 ? uc_ligature_trie[uc_ligature_trie[u2>>5] + (u2 & 0x1f)] : 0xffff);
+
+static const 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,
+ 0x1f9, 0x6f, 0xf2, 0x75, 0xf9, 0x77, 0x1e81, 0x79,
+ 0x1ef3, 0xa8, 0x1fed, 0xc2, 0x1ea6, 0xca, 0x1ec0, 0xd4,
+ 0x1ed2, 0xdc, 0x1db, 0xe2, 0x1ea7, 0xea, 0x1ec1, 0xf4,
+ 0x1ed3, 0xfc, 0x1dc, 0x102, 0x1eb0, 0x103, 0x1eb1, 0x112,
+ 0x1e14, 0x113, 0x1e15, 0x14c, 0x1e50, 0x14d, 0x1e51, 0x1a0,
+ 0x1edc, 0x1a1, 0x1edd, 0x1af, 0x1eea, 0x1b0, 0x1eeb, 0x391,
+ 0x1fba, 0x395, 0x1fc8, 0x397, 0x1fca, 0x399, 0x1fda, 0x39f,
+ 0x1ff8, 0x3a5, 0x1fea, 0x3a9, 0x1ffa, 0x3b1, 0x1f70, 0x3b5,
+ 0x1f72, 0x3b7, 0x1f74, 0x3b9, 0x1f76, 0x3bf, 0x1f78, 0x3c5,
+ 0x1f7a, 0x3c9, 0x1f7c, 0x3ca, 0x1fd2, 0x3cb, 0x1fe2, 0x415,
+ 0x400, 0x418, 0x40d, 0x435, 0x450, 0x438, 0x45d, 0x1f00,
+ 0x1f02, 0x1f01, 0x1f03, 0x1f08, 0x1f0a, 0x1f09, 0x1f0b, 0x1f10,
+ 0x1f12, 0x1f11, 0x1f13, 0x1f18, 0x1f1a, 0x1f19, 0x1f1b, 0x1f20,
+ 0x1f22, 0x1f21, 0x1f23, 0x1f28, 0x1f2a, 0x1f29, 0x1f2b, 0x1f30,
+ 0x1f32, 0x1f31, 0x1f33, 0x1f38, 0x1f3a, 0x1f39, 0x1f3b, 0x1f40,
+ 0x1f42, 0x1f41, 0x1f43, 0x1f48, 0x1f4a, 0x1f49, 0x1f4b, 0x1f50,
+ 0x1f52, 0x1f51, 0x1f53, 0x1f59, 0x1f5b, 0x1f60, 0x1f62, 0x1f61,
+ 0x1f63, 0x1f68, 0x1f6a, 0x1f69, 0x1f6b, 0x1fbf, 0x1fcd, 0x1ffe,
+ 0x1fdd, 0x75, 0x41, 0xc1, 0x43, 0x106, 0x45, 0xc9,
+ 0x47, 0x1f4, 0x49, 0xcd, 0x4b, 0x1e30, 0x4c, 0x139,
+ 0x4d, 0x1e3e, 0x4e, 0x143, 0x4f, 0xd3, 0x50, 0x1e54,
+ 0x52, 0x154, 0x53, 0x15a, 0x55, 0xda, 0x57, 0x1e82,
+ 0x59, 0xdd, 0x5a, 0x179, 0x61, 0xe1, 0x63, 0x107,
+ 0x65, 0xe9, 0x67, 0x1f5, 0x69, 0xed, 0x6b, 0x1e31,
+ 0x6c, 0x13a, 0x6d, 0x1e3f, 0x6e, 0x144, 0x6f, 0xf3,
+ 0x70, 0x1e55, 0x72, 0x155, 0x73, 0x15b, 0x75, 0xfa,
+ 0x77, 0x1e83, 0x79, 0xfd, 0x7a, 0x17a, 0xa8, 0x385,
+ 0xc2, 0x1ea4, 0xc5, 0x1fa, 0xc6, 0x1fc, 0xc7, 0x1e08,
+ 0xca, 0x1ebe, 0xcf, 0x1e2e, 0xd4, 0x1ed0, 0xd5, 0x1e4c,
+ 0xd8, 0x1fe, 0xdc, 0x1d7, 0xe2, 0x1ea5, 0xe5, 0x1fb,
+ 0xe6, 0x1fd, 0xe7, 0x1e09, 0xea, 0x1ebf, 0xef, 0x1e2f,
+ 0xf4, 0x1ed1, 0xf5, 0x1e4d, 0xf8, 0x1ff, 0xfc, 0x1d8,
+ 0x102, 0x1eae, 0x103, 0x1eaf, 0x112, 0x1e16, 0x113, 0x1e17,
+ 0x14c, 0x1e52, 0x14d, 0x1e53, 0x168, 0x1e78, 0x169, 0x1e79,
+ 0x1a0, 0x1eda, 0x1a1, 0x1edb, 0x1af, 0x1ee8, 0x1b0, 0x1ee9,
+ 0x391, 0x386, 0x395, 0x388, 0x397, 0x389, 0x399, 0x38a,
+ 0x39f, 0x38c, 0x3a5, 0x38e, 0x3a9, 0x38f, 0x3b1, 0x3ac,
+ 0x3b5, 0x3ad, 0x3b7, 0x3ae, 0x3b9, 0x3af, 0x3bf, 0x3cc,
+ 0x3c5, 0x3cd, 0x3c9, 0x3ce, 0x3ca, 0x390, 0x3cb, 0x3b0,
+ 0x3d2, 0x3d3, 0x413, 0x403, 0x41a, 0x40c, 0x433, 0x453,
+ 0x43a, 0x45c, 0x1f00, 0x1f04, 0x1f01, 0x1f05, 0x1f08, 0x1f0c,
+ 0x1f09, 0x1f0d, 0x1f10, 0x1f14, 0x1f11, 0x1f15, 0x1f18, 0x1f1c,
+ 0x1f19, 0x1f1d, 0x1f20, 0x1f24, 0x1f21, 0x1f25, 0x1f28, 0x1f2c,
+ 0x1f29, 0x1f2d, 0x1f30, 0x1f34, 0x1f31, 0x1f35, 0x1f38, 0x1f3c,
+ 0x1f39, 0x1f3d, 0x1f40, 0x1f44, 0x1f41, 0x1f45, 0x1f48, 0x1f4c,
+ 0x1f49, 0x1f4d, 0x1f50, 0x1f54, 0x1f51, 0x1f55, 0x1f59, 0x1f5d,
+ 0x1f60, 0x1f64, 0x1f61, 0x1f65, 0x1f68, 0x1f6c, 0x1f69, 0x1f6d,
+ 0x1fbf, 0x1fce, 0x1ffe, 0x1fde, 0x20, 0x41, 0xc2, 0x43,
+ 0x108, 0x45, 0xca, 0x47, 0x11c, 0x48, 0x124, 0x49,
+ 0xce, 0x4a, 0x134, 0x4f, 0xd4, 0x53, 0x15c, 0x55,
+ 0xdb, 0x57, 0x174, 0x59, 0x176, 0x5a, 0x1e90, 0x61,
+ 0xe2, 0x63, 0x109, 0x65, 0xea, 0x67, 0x11d, 0x68,
+ 0x125, 0x69, 0xee, 0x6a, 0x135, 0x6f, 0xf4, 0x73,
+ 0x15d, 0x75, 0xfb, 0x77, 0x175, 0x79, 0x177, 0x7a,
+ 0x1e91, 0x1ea0, 0x1eac, 0x1ea1, 0x1ead, 0x1eb8, 0x1ec6, 0x1eb9,
+ 0x1ec7, 0x1ecc, 0x1ed8, 0x1ecd, 0x1ed9, 0x1c, 0x41, 0xc3,
+ 0x45, 0x1ebc, 0x49, 0x128, 0x4e, 0xd1, 0x4f, 0xd5,
+ 0x55, 0x168, 0x56, 0x1e7c, 0x59, 0x1ef8, 0x61, 0xe3,
+ 0x65, 0x1ebd, 0x69, 0x129, 0x6e, 0xf1, 0x6f, 0xf5,
+ 0x75, 0x169, 0x76, 0x1e7d, 0x79, 0x1ef9, 0xc2, 0x1eaa,
+ 0xca, 0x1ec4, 0xd4, 0x1ed6, 0xe2, 0x1eab, 0xea, 0x1ec5,
+ 0xf4, 0x1ed7, 0x102, 0x1eb4, 0x103, 0x1eb5, 0x1a0, 0x1ee0,
+ 0x1a1, 0x1ee1, 0x1af, 0x1eee, 0x1b0, 0x1eef, 0x2c, 0x41,
+ 0x100, 0x45, 0x112, 0x47, 0x1e20, 0x49, 0x12a, 0x4f,
+ 0x14c, 0x55, 0x16a, 0x59, 0x232, 0x61, 0x101, 0x65,
+ 0x113, 0x67, 0x1e21, 0x69, 0x12b, 0x6f, 0x14d, 0x75,
+ 0x16b, 0x79, 0x233, 0xc4, 0x1de, 0xc6, 0x1e2, 0xd5,
+ 0x22c, 0xd6, 0x22a, 0xdc, 0x1d5, 0xe4, 0x1df, 0xe6,
+ 0x1e3, 0xf5, 0x22d, 0xf6, 0x22b, 0xfc, 0x1d6, 0x1ea,
+ 0x1ec, 0x1eb, 0x1ed, 0x226, 0x1e0, 0x227, 0x1e1, 0x22e,
+ 0x230, 0x22f, 0x231, 0x391, 0x1fb9, 0x399, 0x1fd9, 0x3a5,
+ 0x1fe9, 0x3b1, 0x1fb1, 0x3b9, 0x1fd1, 0x3c5, 0x1fe1, 0x418,
+ 0x4e2, 0x423, 0x4ee, 0x438, 0x4e3, 0x443, 0x4ef, 0x1e36,
+ 0x1e38, 0x1e37, 0x1e39, 0x1e5a, 0x1e5c, 0x1e5b, 0x1e5d, 0x20,
+ 0x41, 0x102, 0x45, 0x114, 0x47, 0x11e, 0x49, 0x12c,
+ 0x4f, 0x14e, 0x55, 0x16c, 0x61, 0x103, 0x65, 0x115,
+ 0x67, 0x11f, 0x69, 0x12d, 0x6f, 0x14f, 0x75, 0x16d,
+ 0x228, 0x1e1c, 0x229, 0x1e1d, 0x391, 0x1fb8, 0x399, 0x1fd8,
+ 0x3a5, 0x1fe8, 0x3b1, 0x1fb0, 0x3b9, 0x1fd0, 0x3c5, 0x1fe0,
+ 0x410, 0x4d0, 0x415, 0x4d6, 0x416, 0x4c1, 0x418, 0x419,
+ 0x423, 0x40e, 0x430, 0x4d1, 0x435, 0x4d7, 0x436, 0x4c2,
+ 0x438, 0x439, 0x443, 0x45e, 0x1ea0, 0x1eb6, 0x1ea1, 0x1eb7,
+ 0x2e, 0x41, 0x226, 0x42, 0x1e02, 0x43, 0x10a, 0x44,
+ 0x1e0a, 0x45, 0x116, 0x46, 0x1e1e, 0x47, 0x120, 0x48,
+ 0x1e22, 0x49, 0x130, 0x4d, 0x1e40, 0x4e, 0x1e44, 0x4f,
+ 0x22e, 0x50, 0x1e56, 0x52, 0x1e58, 0x53, 0x1e60, 0x54,
+ 0x1e6a, 0x57, 0x1e86, 0x58, 0x1e8a, 0x59, 0x1e8e, 0x5a,
+ 0x17b, 0x61, 0x227, 0x62, 0x1e03, 0x63, 0x10b, 0x64,
+ 0x1e0b, 0x65, 0x117, 0x66, 0x1e1f, 0x67, 0x121, 0x68,
+ 0x1e23, 0x6d, 0x1e41, 0x6e, 0x1e45, 0x6f, 0x22f, 0x70,
+ 0x1e57, 0x72, 0x1e59, 0x73, 0x1e61, 0x74, 0x1e6b, 0x77,
+ 0x1e87, 0x78, 0x1e8b, 0x79, 0x1e8f, 0x7a, 0x17c, 0x15a,
+ 0x1e64, 0x15b, 0x1e65, 0x160, 0x1e66, 0x161, 0x1e67, 0x17f,
+ 0x1e9b, 0x1e62, 0x1e68, 0x1e63, 0x1e69, 0x36, 0x41, 0xc4,
+ 0x45, 0xcb, 0x48, 0x1e26, 0x49, 0xcf, 0x4f, 0xd6,
+ 0x55, 0xdc, 0x57, 0x1e84, 0x58, 0x1e8c, 0x59, 0x178,
+ 0x61, 0xe4, 0x65, 0xeb, 0x68, 0x1e27, 0x69, 0xef,
+ 0x6f, 0xf6, 0x74, 0x1e97, 0x75, 0xfc, 0x77, 0x1e85,
+ 0x78, 0x1e8d, 0x79, 0xff, 0xd5, 0x1e4e, 0xf5, 0x1e4f,
+ 0x16a, 0x1e7a, 0x16b, 0x1e7b, 0x399, 0x3aa, 0x3a5, 0x3ab,
+ 0x3b9, 0x3ca, 0x3c5, 0x3cb, 0x3d2, 0x3d4, 0x406, 0x407,
+ 0x410, 0x4d2, 0x415, 0x401, 0x416, 0x4dc, 0x417, 0x4de,
+ 0x418, 0x4e4, 0x41e, 0x4e6, 0x423, 0x4f0, 0x427, 0x4f4,
+ 0x42b, 0x4f8, 0x42d, 0x4ec, 0x430, 0x4d3, 0x435, 0x451,
+ 0x436, 0x4dd, 0x437, 0x4df, 0x438, 0x4e5, 0x43e, 0x4e7,
+ 0x443, 0x4f1, 0x447, 0x4f5, 0x44b, 0x4f9, 0x44d, 0x4ed,
+ 0x456, 0x457, 0x4d8, 0x4da, 0x4d9, 0x4db, 0x4e8, 0x4ea,
+ 0x4e9, 0x4eb, 0x18, 0x41, 0x1ea2, 0x45, 0x1eba, 0x49,
+ 0x1ec8, 0x4f, 0x1ece, 0x55, 0x1ee6, 0x59, 0x1ef6, 0x61,
+ 0x1ea3, 0x65, 0x1ebb, 0x69, 0x1ec9, 0x6f, 0x1ecf, 0x75,
+ 0x1ee7, 0x79, 0x1ef7, 0xc2, 0x1ea8, 0xca, 0x1ec2, 0xd4,
+ 0x1ed4, 0xe2, 0x1ea9, 0xea, 0x1ec3, 0xf4, 0x1ed5, 0x102,
+ 0x1eb2, 0x103, 0x1eb3, 0x1a0, 0x1ede, 0x1a1, 0x1edf, 0x1af,
+ 0x1eec, 0x1b0, 0x1eed, 0x6, 0x41, 0xc5, 0x55, 0x16e,
+ 0x61, 0xe5, 0x75, 0x16f, 0x77, 0x1e98, 0x79, 0x1e99,
+ 0x6, 0x4f, 0x150, 0x55, 0x170, 0x6f, 0x151, 0x75,
+ 0x171, 0x423, 0x4f2, 0x443, 0x4f3, 0x25, 0x41, 0x1cd,
+ 0x43, 0x10c, 0x44, 0x10e, 0x45, 0x11a, 0x47, 0x1e6,
+ 0x48, 0x21e, 0x49, 0x1cf, 0x4b, 0x1e8, 0x4c, 0x13d,
+ 0x4e, 0x147, 0x4f, 0x1d1, 0x52, 0x158, 0x53, 0x160,
+ 0x54, 0x164, 0x55, 0x1d3, 0x5a, 0x17d, 0x61, 0x1ce,
+ 0x63, 0x10d, 0x64, 0x10f, 0x65, 0x11b, 0x67, 0x1e7,
+ 0x68, 0x21f, 0x69, 0x1d0, 0x6a, 0x1f0, 0x6b, 0x1e9,
+ 0x6c, 0x13e, 0x6e, 0x148, 0x6f, 0x1d2, 0x72, 0x159,
+ 0x73, 0x161, 0x74, 0x165, 0x75, 0x1d4, 0x7a, 0x17e,
+ 0xdc, 0x1d9, 0xfc, 0x1da, 0x1b7, 0x1ee, 0x292, 0x1ef,
+ 0xe, 0x41, 0x200, 0x45, 0x204, 0x49, 0x208, 0x4f,
+ 0x20c, 0x52, 0x210, 0x55, 0x214, 0x61, 0x201, 0x65,
+ 0x205, 0x69, 0x209, 0x6f, 0x20d, 0x72, 0x211, 0x75,
+ 0x215, 0x474, 0x476, 0x475, 0x477, 0xc, 0x41, 0x202,
+ 0x45, 0x206, 0x49, 0x20a, 0x4f, 0x20e, 0x52, 0x212,
+ 0x55, 0x216, 0x61, 0x203, 0x65, 0x207, 0x69, 0x20b,
+ 0x6f, 0x20f, 0x72, 0x213, 0x75, 0x217, 0xe, 0x391,
+ 0x1f08, 0x395, 0x1f18, 0x397, 0x1f28, 0x399, 0x1f38, 0x39f,
+ 0x1f48, 0x3a9, 0x1f68, 0x3b1, 0x1f00, 0x3b5, 0x1f10, 0x3b7,
+ 0x1f20, 0x3b9, 0x1f30, 0x3bf, 0x1f40, 0x3c1, 0x1fe4, 0x3c5,
+ 0x1f50, 0x3c9, 0x1f60, 0x10, 0x391, 0x1f09, 0x395, 0x1f19,
+ 0x397, 0x1f29, 0x399, 0x1f39, 0x39f, 0x1f49, 0x3a1, 0x1fec,
+ 0x3a5, 0x1f59, 0x3a9, 0x1f69, 0x3b1, 0x1f01, 0x3b5, 0x1f11,
+ 0x3b7, 0x1f21, 0x3b9, 0x1f31, 0x3bf, 0x1f41, 0x3c1, 0x1fe5,
+ 0x3c5, 0x1f51, 0x3c9, 0x1f61, 0x4, 0x4f, 0x1a0, 0x55,
+ 0x1af, 0x6f, 0x1a1, 0x75, 0x1b0, 0x2a, 0x41, 0x1ea0,
+ 0x42, 0x1e04, 0x44, 0x1e0c, 0x45, 0x1eb8, 0x48, 0x1e24,
+ 0x49, 0x1eca, 0x4b, 0x1e32, 0x4c, 0x1e36, 0x4d, 0x1e42,
+ 0x4e, 0x1e46, 0x4f, 0x1ecc, 0x52, 0x1e5a, 0x53, 0x1e62,
+ 0x54, 0x1e6c, 0x55, 0x1ee4, 0x56, 0x1e7e, 0x57, 0x1e88,
+ 0x59, 0x1ef4, 0x5a, 0x1e92, 0x61, 0x1ea1, 0x62, 0x1e05,
+ 0x64, 0x1e0d, 0x65, 0x1eb9, 0x68, 0x1e25, 0x69, 0x1ecb,
+ 0x6b, 0x1e33, 0x6c, 0x1e37, 0x6d, 0x1e43, 0x6e, 0x1e47,
+ 0x6f, 0x1ecd, 0x72, 0x1e5b, 0x73, 0x1e63, 0x74, 0x1e6d,
+ 0x75, 0x1ee5, 0x76, 0x1e7f, 0x77, 0x1e89, 0x79, 0x1ef5,
+ 0x7a, 0x1e93, 0x1a0, 0x1ee2, 0x1a1, 0x1ee3, 0x1af, 0x1ef0,
+ 0x1b0, 0x1ef1, 0x2, 0x55, 0x1e72, 0x75, 0x1e73, 0x2,
+ 0x41, 0x1e00, 0x61, 0x1e01, 0x4, 0x53, 0x218, 0x54,
+ 0x21a, 0x73, 0x219, 0x74, 0x21b, 0x16, 0x43, 0xc7,
+ 0x44, 0x1e10, 0x45, 0x228, 0x47, 0x122, 0x48, 0x1e28,
+ 0x4b, 0x136, 0x4c, 0x13b, 0x4e, 0x145, 0x52, 0x156,
+ 0x53, 0x15e, 0x54, 0x162, 0x63, 0xe7, 0x64, 0x1e11,
+ 0x65, 0x229, 0x67, 0x123, 0x68, 0x1e29, 0x6b, 0x137,
+ 0x6c, 0x13c, 0x6e, 0x146, 0x72, 0x157, 0x73, 0x15f,
+ 0x74, 0x163, 0xa, 0x41, 0x104, 0x45, 0x118, 0x49,
+ 0x12e, 0x4f, 0x1ea, 0x55, 0x172, 0x61, 0x105, 0x65,
+ 0x119, 0x69, 0x12f, 0x6f, 0x1eb, 0x75, 0x173, 0xc,
+ 0x44, 0x1e12, 0x45, 0x1e18, 0x4c, 0x1e3c, 0x4e, 0x1e4a,
+ 0x54, 0x1e70, 0x55, 0x1e76, 0x64, 0x1e13, 0x65, 0x1e19,
+ 0x6c, 0x1e3d, 0x6e, 0x1e4b, 0x74, 0x1e71, 0x75, 0x1e77,
+ 0x2, 0x48, 0x1e2a, 0x68, 0x1e2b, 0x6, 0x45, 0x1e1a,
+ 0x49, 0x1e2c, 0x55, 0x1e74, 0x65, 0x1e1b, 0x69, 0x1e2d,
+ 0x75, 0x1e75, 0x11, 0x42, 0x1e06, 0x44, 0x1e0e, 0x4b,
+ 0x1e34, 0x4c, 0x1e3a, 0x4e, 0x1e48, 0x52, 0x1e5e, 0x54,
+ 0x1e6e, 0x5a, 0x1e94, 0x62, 0x1e07, 0x64, 0x1e0f, 0x68,
+ 0x1e96, 0x6b, 0x1e35, 0x6c, 0x1e3b, 0x6e, 0x1e49, 0x72,
+ 0x1e5f, 0x74, 0x1e6f, 0x7a, 0x1e95, 0x2c, 0x3c, 0x226e,
+ 0x3d, 0x2260, 0x3e, 0x226f, 0x2190, 0x219a, 0x2192, 0x219b,
+ 0x2194, 0x21ae, 0x21d0, 0x21cd, 0x21d2, 0x21cf, 0x21d4, 0x21ce,
+ 0x2203, 0x2204, 0x2208, 0x2209, 0x220b, 0x220c, 0x2223, 0x2224,
+ 0x2225, 0x2226, 0x223c, 0x2241, 0x2243, 0x2244, 0x2245, 0x2247,
+ 0x2248, 0x2249, 0x224d, 0x226d, 0x2261, 0x2262, 0x2264, 0x2270,
+ 0x2265, 0x2271, 0x2272, 0x2274, 0x2273, 0x2275, 0x2276, 0x2278,
+ 0x2277, 0x2279, 0x227a, 0x2280, 0x227b, 0x2281, 0x227c, 0x22e0,
+ 0x227d, 0x22e1, 0x2282, 0x2284, 0x2283, 0x2285, 0x2286, 0x2288,
+ 0x2287, 0x2289, 0x2291, 0x22e2, 0x2292, 0x22e3, 0x22a2, 0x22ac,
+ 0x22a8, 0x22ad, 0x22a9, 0x22ae, 0x22ab, 0x22af, 0x22b2, 0x22ea,
+ 0x22b3, 0x22eb, 0x22b4, 0x22ec, 0x22b5, 0x22ed, 0x1d, 0xa8,
+ 0x1fc1, 0x3b1, 0x1fb6, 0x3b7, 0x1fc6, 0x3b9, 0x1fd6, 0x3c5,
+ 0x1fe6, 0x3c9, 0x1ff6, 0x3ca, 0x1fd7, 0x3cb, 0x1fe7, 0x1f00,
+ 0x1f06, 0x1f01, 0x1f07, 0x1f08, 0x1f0e, 0x1f09, 0x1f0f, 0x1f20,
+ 0x1f26, 0x1f21, 0x1f27, 0x1f28, 0x1f2e, 0x1f29, 0x1f2f, 0x1f30,
+ 0x1f36, 0x1f31, 0x1f37, 0x1f38, 0x1f3e, 0x1f39, 0x1f3f, 0x1f50,
+ 0x1f56, 0x1f51, 0x1f57, 0x1f59, 0x1f5f, 0x1f60, 0x1f66, 0x1f61,
+ 0x1f67, 0x1f68, 0x1f6e, 0x1f69, 0x1f6f, 0x1fbf, 0x1fcf, 0x1ffe,
+ 0x1fdf, 0x3f, 0x391, 0x1fbc, 0x397, 0x1fcc, 0x3a9, 0x1ffc,
+ 0x3ac, 0x1fb4, 0x3ae, 0x1fc4, 0x3b1, 0x1fb3, 0x3b7, 0x1fc3,
+ 0x3c9, 0x1ff3, 0x3ce, 0x1ff4, 0x1f00, 0x1f80, 0x1f01, 0x1f81,
+ 0x1f02, 0x1f82, 0x1f03, 0x1f83, 0x1f04, 0x1f84, 0x1f05, 0x1f85,
+ 0x1f06, 0x1f86, 0x1f07, 0x1f87, 0x1f08, 0x1f88, 0x1f09, 0x1f89,
+ 0x1f0a, 0x1f8a, 0x1f0b, 0x1f8b, 0x1f0c, 0x1f8c, 0x1f0d, 0x1f8d,
+ 0x1f0e, 0x1f8e, 0x1f0f, 0x1f8f, 0x1f20, 0x1f90, 0x1f21, 0x1f91,
+ 0x1f22, 0x1f92, 0x1f23, 0x1f93, 0x1f24, 0x1f94, 0x1f25, 0x1f95,
+ 0x1f26, 0x1f96, 0x1f27, 0x1f97, 0x1f28, 0x1f98, 0x1f29, 0x1f99,
+ 0x1f2a, 0x1f9a, 0x1f2b, 0x1f9b, 0x1f2c, 0x1f9c, 0x1f2d, 0x1f9d,
+ 0x1f2e, 0x1f9e, 0x1f2f, 0x1f9f, 0x1f60, 0x1fa0, 0x1f61, 0x1fa1,
+ 0x1f62, 0x1fa2, 0x1f63, 0x1fa3, 0x1f64, 0x1fa4, 0x1f65, 0x1fa5,
+ 0x1f66, 0x1fa6, 0x1f67, 0x1fa7, 0x1f68, 0x1fa8, 0x1f69, 0x1fa9,
+ 0x1f6a, 0x1faa, 0x1f6b, 0x1fab, 0x1f6c, 0x1fac, 0x1f6d, 0x1fad,
+ 0x1f6e, 0x1fae, 0x1f6f, 0x1faf, 0x1f70, 0x1fb2, 0x1f74, 0x1fc2,
+ 0x1f7c, 0x1ff2, 0x1fb6, 0x1fb7, 0x1fc6, 0x1fc7, 0x1ff6, 0x1ff7,
+ 0x1, 0x627, 0x622, 0x6, 0x627, 0x623, 0x648, 0x624,
+ 0x64a, 0x626, 0x6c1, 0x6c2, 0x6d2, 0x6d3, 0x6d5, 0x6c0,
+ 0x1, 0x627, 0x625, 0x3, 0x928, 0x929, 0x930, 0x931,
+ 0x933, 0x934, 0x1, 0x9c7, 0x9cb, 0x1, 0x9c7, 0x9cc,
+ 0x1, 0xb47, 0xb4b, 0x1, 0xb47, 0xb48, 0x1, 0xb47,
+ 0xb4c, 0x2, 0xbc6, 0xbca, 0xbc7, 0xbcb, 0x2, 0xb92,
+ 0xb94, 0xbc6, 0xbcc, 0x1, 0xc46, 0xc48, 0x1, 0xcc6,
+ 0xcca, 0x3, 0xcbf, 0xcc0, 0xcc6, 0xcc7, 0xcca, 0xccb,
+ 0x1, 0xcc6, 0xcc8, 0x2, 0xd46, 0xd4a, 0xd47, 0xd4b,
+ 0x1, 0xd46, 0xd4c, 0x2, 0xdd9, 0xdda, 0xddc, 0xddd,
+ 0x1, 0xdd9, 0xddc, 0x1, 0xdd9, 0xdde, 0x1, 0x1025,
+ 0x1026, 0xb, 0x1b05, 0x1b06, 0x1b07, 0x1b08, 0x1b09, 0x1b0a,
+ 0x1b0b, 0x1b0c, 0x1b0d, 0x1b0e, 0x1b11, 0x1b12, 0x1b3a, 0x1b3b,
+ 0x1b3c, 0x1b3d, 0x1b3e, 0x1b40, 0x1b3f, 0x1b41, 0x1b42, 0x1b43,
+ 0x30, 0x3046, 0x3094, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f,
+ 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
+ 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f,
+ 0x3060, 0x3061, 0x3062, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068,
+ 0x3069, 0x306f, 0x3070, 0x3072, 0x3073, 0x3075, 0x3076, 0x3078,
+ 0x3079, 0x307b, 0x307c, 0x309d, 0x309e, 0x30a6, 0x30f4, 0x30ab,
+ 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3,
+ 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb,
+ 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c4,
+ 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30cf, 0x30d0, 0x30d2,
+ 0x30d3, 0x30d5, 0x30d6, 0x30d8, 0x30d9, 0x30db, 0x30dc, 0x30ef,
+ 0x30f7, 0x30f0, 0x30f8, 0x30f1, 0x30f9, 0x30f2, 0x30fa, 0x30fd,
+ 0x30fe, 0xa, 0x306f, 0x3071, 0x3072, 0x3074, 0x3075, 0x3077,
+ 0x3078, 0x307a, 0x307b, 0x307d, 0x30cf, 0x30d1, 0x30d2, 0x30d4,
+ 0x30d5, 0x30d7, 0x30d8, 0x30da, 0x30db, 0x30dd,
+};
+
+struct NormalizationCorrection {
+ uint ucs4;
+ uint old_mapping;
+ int version;
+};
+
+static const NormalizationCorrection uc_normalization_corrections[] = {
+ { 0xf951, 0x96fb, 6 },
+ { 0x2f868, 0x2136a, 7 },
+ { 0x2f874, 0x5f33, 7 },
+ { 0x2f91f, 0x43ab, 7 },
+ { 0x2f95f, 0x7aae, 7 },
+ { 0x2f9bf, 0x4d57, 7 },
+};
+
+enum { NumNormalizationCorrections = 6 };
+
+enum { UnicodeBlockCount = 512 }; // number of unicode blocks
+enum { UnicodeBlockSize = 128 }; // size of each block
+
+namespace QUnicodeTables {
+
+static const unsigned char uc_scripts[] = {
+ Common, /* U+0000-007f */
+ Common, /* U+0080-00ff */
+ Latin, /* U+0100-017f */
+ Latin, /* U+0180-01ff */
+ Latin, /* U+0200-027f */
+ Latin, /* U+0280-02ff */
+ 32, /* U+0300-037f at offset 512 */
+ 33, /* U+0380-03ff at offset 640 */
+ Cyrillic, /* U+0400-047f */
+ 34, /* U+0480-04ff at offset 768 */
+ 35, /* U+0500-057f at offset 896 */
+ 36, /* U+0580-05ff at offset 1024 */
+ 37, /* U+0600-067f at offset 1152 */
+ 38, /* U+0680-06ff at offset 1280 */
+ 39, /* U+0700-077f at offset 1408 */
+ 40, /* U+0780-07ff at offset 1536 */
+ Common, /* U+0800-087f */
+ Common, /* U+0880-08ff */
+ 41, /* U+0900-097f at offset 1664 */
+ 42, /* U+0980-09ff at offset 1792 */
+ 43, /* U+0a00-0a7f at offset 1920 */
+ 44, /* U+0a80-0aff at offset 2048 */
+ 45, /* U+0b00-0b7f at offset 2176 */
+ 46, /* U+0b80-0bff at offset 2304 */
+ 47, /* U+0c00-0c7f at offset 2432 */
+ 48, /* U+0c80-0cff at offset 2560 */
+ 49, /* U+0d00-0d7f at offset 2688 */
+ 50, /* U+0d80-0dff at offset 2816 */
+ 51, /* U+0e00-0e7f at offset 2944 */
+ 52, /* U+0e80-0eff at offset 3072 */
+ 53, /* U+0f00-0f7f at offset 3200 */
+ 54, /* U+0f80-0fff at offset 3328 */
+ 55, /* U+1000-107f at offset 3456 */
+ 56, /* U+1080-10ff at offset 3584 */
+ 57, /* U+1100-117f at offset 3712 */
+ 58, /* U+1180-11ff at offset 3840 */
+ Ethiopic, /* U+1200-127f */
+ Ethiopic, /* U+1280-12ff */
+ Ethiopic, /* U+1300-137f */
+ Ethiopic, /* U+1380-13ff */
+ Common, /* U+1400-147f */
+ CanadianAboriginal, /* U+1480-14ff */
+ CanadianAboriginal, /* U+1500-157f */
+ CanadianAboriginal, /* U+1580-15ff */
+ CanadianAboriginal, /* U+1600-167f */
+ 59, /* U+1680-16ff at offset 3968 */
+ Tagalog, /* U+1700-177f */
+ 60, /* U+1780-17ff at offset 4096 */
+ Mongolian, /* U+1800-187f */
+ Mongolian, /* U+1880-18ff */
+ Limbu, /* U+1900-197f */
+ 61, /* U+1980-19ff at offset 4224 */
+ Buginese, /* U+1a00-1a7f */
+ Common, /* U+1a80-1aff */
+ Balinese, /* U+1b00-1b7f */
+ Common, /* U+1b80-1bff */
+ Common, /* U+1c00-1c7f */
+ Common, /* U+1c80-1cff */
+ 62, /* U+1d00-1d7f at offset 4352 */
+ 63, /* U+1d80-1dff at offset 4480 */
+ Latin, /* U+1e00-1e7f */
+ Latin, /* U+1e80-1eff */
+ 64, /* U+1f00-1f7f at offset 4608 */
+ 65, /* U+1f80-1fff at offset 4736 */
+ 66, /* U+2000-207f at offset 4864 */
+ 67, /* U+2080-20ff at offset 4992 */
+ 68, /* U+2100-217f at offset 5120 */
+ Common, /* U+2180-21ff */
+ Common, /* U+2200-227f */
+ Common, /* U+2280-22ff */
+ Common, /* U+2300-237f */
+ Common, /* U+2380-23ff */
+ Common, /* U+2400-247f */
+ Common, /* U+2480-24ff */
+ Common, /* U+2500-257f */
+ Common, /* U+2580-25ff */
+ Common, /* U+2600-267f */
+ Common, /* U+2680-26ff */
+ Common, /* U+2700-277f */
+ Common, /* U+2780-27ff */
+ Braille, /* U+2800-287f */
+ Braille, /* U+2880-28ff */
+ Common, /* U+2900-297f */
+ Common, /* U+2980-29ff */
+ Common, /* U+2a00-2a7f */
+ Common, /* U+2a80-2aff */
+ Common, /* U+2b00-2b7f */
+ Common, /* U+2b80-2bff */
+ Glagolitic, /* U+2c00-2c7f */
+ Coptic, /* U+2c80-2cff */
+ 69, /* U+2d00-2d7f at offset 5248 */
+ Ethiopic, /* U+2d80-2dff */
+ Common, /* U+2e00-2e7f */
+ Han, /* U+2e80-2eff */
+ Han, /* U+2f00-2f7f */
+ Han, /* U+2f80-2fff */
+ 70, /* U+3000-307f at offset 5376 */
+ 71, /* U+3080-30ff at offset 5504 */
+ 72, /* U+3100-317f at offset 5632 */
+ 73, /* U+3180-31ff at offset 5760 */
+ 74, /* U+3200-327f at offset 5888 */
+ Common, /* U+3280-32ff */
+ Common, /* U+3300-337f */
+ Common, /* U+3380-33ff */
+ Han, /* U+3400-347f */
+ Han, /* U+3480-34ff */
+ Han, /* U+3500-357f */
+ Han, /* U+3580-35ff */
+ Han, /* U+3600-367f */
+ Han, /* U+3680-36ff */
+ Han, /* U+3700-377f */
+ Han, /* U+3780-37ff */
+ Han, /* U+3800-387f */
+ Han, /* U+3880-38ff */
+ Han, /* U+3900-397f */
+ Han, /* U+3980-39ff */
+ Han, /* U+3a00-3a7f */
+ Han, /* U+3a80-3aff */
+ Han, /* U+3b00-3b7f */
+ Han, /* U+3b80-3bff */
+ Han, /* U+3c00-3c7f */
+ Han, /* U+3c80-3cff */
+ Han, /* U+3d00-3d7f */
+ Han, /* U+3d80-3dff */
+ Han, /* U+3e00-3e7f */
+ Han, /* U+3e80-3eff */
+ Han, /* U+3f00-3f7f */
+ Han, /* U+3f80-3fff */
+ Han, /* U+4000-407f */
+ Han, /* U+4080-40ff */
+ Han, /* U+4100-417f */
+ Han, /* U+4180-41ff */
+ Han, /* U+4200-427f */
+ Han, /* U+4280-42ff */
+ Han, /* U+4300-437f */
+ Han, /* U+4380-43ff */
+ Han, /* U+4400-447f */
+ Han, /* U+4480-44ff */
+ Han, /* U+4500-457f */
+ Han, /* U+4580-45ff */
+ Han, /* U+4600-467f */
+ Han, /* U+4680-46ff */
+ Han, /* U+4700-477f */
+ Han, /* U+4780-47ff */
+ Han, /* U+4800-487f */
+ Han, /* U+4880-48ff */
+ Han, /* U+4900-497f */
+ Han, /* U+4980-49ff */
+ Han, /* U+4a00-4a7f */
+ Han, /* U+4a80-4aff */
+ Han, /* U+4b00-4b7f */
+ Han, /* U+4b80-4bff */
+ Han, /* U+4c00-4c7f */
+ Han, /* U+4c80-4cff */
+ Han, /* U+4d00-4d7f */
+ Han, /* U+4d80-4dff */
+ Han, /* U+4e00-4e7f */
+ Han, /* U+4e80-4eff */
+ Han, /* U+4f00-4f7f */
+ Han, /* U+4f80-4fff */
+ Han, /* U+5000-507f */
+ Han, /* U+5080-50ff */
+ Han, /* U+5100-517f */
+ Han, /* U+5180-51ff */
+ Han, /* U+5200-527f */
+ Han, /* U+5280-52ff */
+ Han, /* U+5300-537f */
+ Han, /* U+5380-53ff */
+ Han, /* U+5400-547f */
+ Han, /* U+5480-54ff */
+ Han, /* U+5500-557f */
+ Han, /* U+5580-55ff */
+ Han, /* U+5600-567f */
+ Han, /* U+5680-56ff */
+ Han, /* U+5700-577f */
+ Han, /* U+5780-57ff */
+ Han, /* U+5800-587f */
+ Han, /* U+5880-58ff */
+ Han, /* U+5900-597f */
+ Han, /* U+5980-59ff */
+ Han, /* U+5a00-5a7f */
+ Han, /* U+5a80-5aff */
+ Han, /* U+5b00-5b7f */
+ Han, /* U+5b80-5bff */
+ Han, /* U+5c00-5c7f */
+ Han, /* U+5c80-5cff */
+ Han, /* U+5d00-5d7f */
+ Han, /* U+5d80-5dff */
+ Han, /* U+5e00-5e7f */
+ Han, /* U+5e80-5eff */
+ Han, /* U+5f00-5f7f */
+ Han, /* U+5f80-5fff */
+ Han, /* U+6000-607f */
+ Han, /* U+6080-60ff */
+ Han, /* U+6100-617f */
+ Han, /* U+6180-61ff */
+ Han, /* U+6200-627f */
+ Han, /* U+6280-62ff */
+ Han, /* U+6300-637f */
+ Han, /* U+6380-63ff */
+ Han, /* U+6400-647f */
+ Han, /* U+6480-64ff */
+ Han, /* U+6500-657f */
+ Han, /* U+6580-65ff */
+ Han, /* U+6600-667f */
+ Han, /* U+6680-66ff */
+ Han, /* U+6700-677f */
+ Han, /* U+6780-67ff */
+ Han, /* U+6800-687f */
+ Han, /* U+6880-68ff */
+ Han, /* U+6900-697f */
+ Han, /* U+6980-69ff */
+ Han, /* U+6a00-6a7f */
+ Han, /* U+6a80-6aff */
+ Han, /* U+6b00-6b7f */
+ Han, /* U+6b80-6bff */
+ Han, /* U+6c00-6c7f */
+ Han, /* U+6c80-6cff */
+ Han, /* U+6d00-6d7f */
+ Han, /* U+6d80-6dff */
+ Han, /* U+6e00-6e7f */
+ Han, /* U+6e80-6eff */
+ Han, /* U+6f00-6f7f */
+ Han, /* U+6f80-6fff */
+ Han, /* U+7000-707f */
+ Han, /* U+7080-70ff */
+ Han, /* U+7100-717f */
+ Han, /* U+7180-71ff */
+ Han, /* U+7200-727f */
+ Han, /* U+7280-72ff */
+ Han, /* U+7300-737f */
+ Han, /* U+7380-73ff */
+ Han, /* U+7400-747f */
+ Han, /* U+7480-74ff */
+ Han, /* U+7500-757f */
+ Han, /* U+7580-75ff */
+ Han, /* U+7600-767f */
+ Han, /* U+7680-76ff */
+ Han, /* U+7700-777f */
+ Han, /* U+7780-77ff */
+ Han, /* U+7800-787f */
+ Han, /* U+7880-78ff */
+ Han, /* U+7900-797f */
+ Han, /* U+7980-79ff */
+ Han, /* U+7a00-7a7f */
+ Han, /* U+7a80-7aff */
+ Han, /* U+7b00-7b7f */
+ Han, /* U+7b80-7bff */
+ Han, /* U+7c00-7c7f */
+ Han, /* U+7c80-7cff */
+ Han, /* U+7d00-7d7f */
+ Han, /* U+7d80-7dff */
+ Han, /* U+7e00-7e7f */
+ Han, /* U+7e80-7eff */
+ Han, /* U+7f00-7f7f */
+ Han, /* U+7f80-7fff */
+ Han, /* U+8000-807f */
+ Han, /* U+8080-80ff */
+ Han, /* U+8100-817f */
+ Han, /* U+8180-81ff */
+ Han, /* U+8200-827f */
+ Han, /* U+8280-82ff */
+ Han, /* U+8300-837f */
+ Han, /* U+8380-83ff */
+ Han, /* U+8400-847f */
+ Han, /* U+8480-84ff */
+ Han, /* U+8500-857f */
+ Han, /* U+8580-85ff */
+ Han, /* U+8600-867f */
+ Han, /* U+8680-86ff */
+ Han, /* U+8700-877f */
+ Han, /* U+8780-87ff */
+ Han, /* U+8800-887f */
+ Han, /* U+8880-88ff */
+ Han, /* U+8900-897f */
+ Han, /* U+8980-89ff */
+ Han, /* U+8a00-8a7f */
+ Han, /* U+8a80-8aff */
+ Han, /* U+8b00-8b7f */
+ Han, /* U+8b80-8bff */
+ Han, /* U+8c00-8c7f */
+ Han, /* U+8c80-8cff */
+ Han, /* U+8d00-8d7f */
+ Han, /* U+8d80-8dff */
+ Han, /* U+8e00-8e7f */
+ Han, /* U+8e80-8eff */
+ Han, /* U+8f00-8f7f */
+ Han, /* U+8f80-8fff */
+ Han, /* U+9000-907f */
+ Han, /* U+9080-90ff */
+ Han, /* U+9100-917f */
+ Han, /* U+9180-91ff */
+ Han, /* U+9200-927f */
+ Han, /* U+9280-92ff */
+ Han, /* U+9300-937f */
+ Han, /* U+9380-93ff */
+ Han, /* U+9400-947f */
+ Han, /* U+9480-94ff */
+ Han, /* U+9500-957f */
+ Han, /* U+9580-95ff */
+ Han, /* U+9600-967f */
+ Han, /* U+9680-96ff */
+ Han, /* U+9700-977f */
+ Han, /* U+9780-97ff */
+ Han, /* U+9800-987f */
+ Han, /* U+9880-98ff */
+ Han, /* U+9900-997f */
+ Han, /* U+9980-99ff */
+ Han, /* U+9a00-9a7f */
+ Han, /* U+9a80-9aff */
+ Han, /* U+9b00-9b7f */
+ Han, /* U+9b80-9bff */
+ Han, /* U+9c00-9c7f */
+ Han, /* U+9c80-9cff */
+ Han, /* U+9d00-9d7f */
+ Han, /* U+9d80-9dff */
+ Han, /* U+9e00-9e7f */
+ Han, /* U+9e80-9eff */
+ Han, /* U+9f00-9f7f */
+ Han, /* U+9f80-9fff */
+ Yi, /* U+a000-a07f */
+ Yi, /* U+a080-a0ff */
+ Yi, /* U+a100-a17f */
+ Yi, /* U+a180-a1ff */
+ Yi, /* U+a200-a27f */
+ Yi, /* U+a280-a2ff */
+ Yi, /* U+a300-a37f */
+ Yi, /* U+a380-a3ff */
+ Yi, /* U+a400-a47f */
+ Yi, /* U+a480-a4ff */
+ Common, /* U+a500-a57f */
+ Common, /* U+a580-a5ff */
+ Common, /* U+a600-a67f */
+ Common, /* U+a680-a6ff */
+ Common, /* U+a700-a77f */
+ Common, /* U+a780-a7ff */
+ SylotiNagri, /* U+a800-a87f */
+ Common, /* U+a880-a8ff */
+ Common, /* U+a900-a97f */
+ Common, /* U+a980-a9ff */
+ Common, /* U+aa00-aa7f */
+ Common, /* U+aa80-aaff */
+ Common, /* U+ab00-ab7f */
+ Common, /* U+ab80-abff */
+ Hangul, /* U+ac00-ac7f */
+ Hangul, /* U+ac80-acff */
+ Hangul, /* U+ad00-ad7f */
+ Hangul, /* U+ad80-adff */
+ Hangul, /* U+ae00-ae7f */
+ Hangul, /* U+ae80-aeff */
+ Hangul, /* U+af00-af7f */
+ Hangul, /* U+af80-afff */
+ Hangul, /* U+b000-b07f */
+ Hangul, /* U+b080-b0ff */
+ Hangul, /* U+b100-b17f */
+ Hangul, /* U+b180-b1ff */
+ Hangul, /* U+b200-b27f */
+ Hangul, /* U+b280-b2ff */
+ Hangul, /* U+b300-b37f */
+ Hangul, /* U+b380-b3ff */
+ Hangul, /* U+b400-b47f */
+ Hangul, /* U+b480-b4ff */
+ Hangul, /* U+b500-b57f */
+ Hangul, /* U+b580-b5ff */
+ Hangul, /* U+b600-b67f */
+ Hangul, /* U+b680-b6ff */
+ Hangul, /* U+b700-b77f */
+ Hangul, /* U+b780-b7ff */
+ Hangul, /* U+b800-b87f */
+ Hangul, /* U+b880-b8ff */
+ Hangul, /* U+b900-b97f */
+ Hangul, /* U+b980-b9ff */
+ Hangul, /* U+ba00-ba7f */
+ Hangul, /* U+ba80-baff */
+ Hangul, /* U+bb00-bb7f */
+ Hangul, /* U+bb80-bbff */
+ Hangul, /* U+bc00-bc7f */
+ Hangul, /* U+bc80-bcff */
+ Hangul, /* U+bd00-bd7f */
+ Hangul, /* U+bd80-bdff */
+ Hangul, /* U+be00-be7f */
+ Hangul, /* U+be80-beff */
+ Hangul, /* U+bf00-bf7f */
+ Hangul, /* U+bf80-bfff */
+ Hangul, /* U+c000-c07f */
+ Hangul, /* U+c080-c0ff */
+ Hangul, /* U+c100-c17f */
+ Hangul, /* U+c180-c1ff */
+ Hangul, /* U+c200-c27f */
+ Hangul, /* U+c280-c2ff */
+ Hangul, /* U+c300-c37f */
+ Hangul, /* U+c380-c3ff */
+ Hangul, /* U+c400-c47f */
+ Hangul, /* U+c480-c4ff */
+ Hangul, /* U+c500-c57f */
+ Hangul, /* U+c580-c5ff */
+ Hangul, /* U+c600-c67f */
+ Hangul, /* U+c680-c6ff */
+ Hangul, /* U+c700-c77f */
+ Hangul, /* U+c780-c7ff */
+ Hangul, /* U+c800-c87f */
+ Hangul, /* U+c880-c8ff */
+ Hangul, /* U+c900-c97f */
+ Hangul, /* U+c980-c9ff */
+ Hangul, /* U+ca00-ca7f */
+ Hangul, /* U+ca80-caff */
+ Hangul, /* U+cb00-cb7f */
+ Hangul, /* U+cb80-cbff */
+ Hangul, /* U+cc00-cc7f */
+ Hangul, /* U+cc80-ccff */
+ Hangul, /* U+cd00-cd7f */
+ Hangul, /* U+cd80-cdff */
+ Hangul, /* U+ce00-ce7f */
+ Hangul, /* U+ce80-ceff */
+ Hangul, /* U+cf00-cf7f */
+ Hangul, /* U+cf80-cfff */
+ Hangul, /* U+d000-d07f */
+ Hangul, /* U+d080-d0ff */
+ Hangul, /* U+d100-d17f */
+ Hangul, /* U+d180-d1ff */
+ Hangul, /* U+d200-d27f */
+ Hangul, /* U+d280-d2ff */
+ Hangul, /* U+d300-d37f */
+ Hangul, /* U+d380-d3ff */
+ Hangul, /* U+d400-d47f */
+ Hangul, /* U+d480-d4ff */
+ Hangul, /* U+d500-d57f */
+ Hangul, /* U+d580-d5ff */
+ Hangul, /* U+d600-d67f */
+ Hangul, /* U+d680-d6ff */
+ Hangul, /* U+d700-d77f */
+ 75, /* U+d780-d7ff at offset 6016 */
+ Common, /* U+d800-d87f */
+ Common, /* U+d880-d8ff */
+ Common, /* U+d900-d97f */
+ Common, /* U+d980-d9ff */
+ Common, /* U+da00-da7f */
+ Common, /* U+da80-daff */
+ Common, /* U+db00-db7f */
+ Common, /* U+db80-dbff */
+ Common, /* U+dc00-dc7f */
+ Common, /* U+dc80-dcff */
+ Common, /* U+dd00-dd7f */
+ Common, /* U+dd80-ddff */
+ Common, /* U+de00-de7f */
+ Common, /* U+de80-deff */
+ Common, /* U+df00-df7f */
+ Common, /* U+df80-dfff */
+ Common, /* U+e000-e07f */
+ Common, /* U+e080-e0ff */
+ Common, /* U+e100-e17f */
+ Common, /* U+e180-e1ff */
+ Common, /* U+e200-e27f */
+ Common, /* U+e280-e2ff */
+ Common, /* U+e300-e37f */
+ Common, /* U+e380-e3ff */
+ Common, /* U+e400-e47f */
+ Common, /* U+e480-e4ff */
+ Common, /* U+e500-e57f */
+ Common, /* U+e580-e5ff */
+ Common, /* U+e600-e67f */
+ Common, /* U+e680-e6ff */
+ Common, /* U+e700-e77f */
+ Common, /* U+e780-e7ff */
+ Common, /* U+e800-e87f */
+ Common, /* U+e880-e8ff */
+ Common, /* U+e900-e97f */
+ Common, /* U+e980-e9ff */
+ Common, /* U+ea00-ea7f */
+ Common, /* U+ea80-eaff */
+ Common, /* U+eb00-eb7f */
+ Common, /* U+eb80-ebff */
+ Common, /* U+ec00-ec7f */
+ Common, /* U+ec80-ecff */
+ Common, /* U+ed00-ed7f */
+ Common, /* U+ed80-edff */
+ Common, /* U+ee00-ee7f */
+ Common, /* U+ee80-eeff */
+ Common, /* U+ef00-ef7f */
+ Common, /* U+ef80-efff */
+ Common, /* U+f000-f07f */
+ Common, /* U+f080-f0ff */
+ Common, /* U+f100-f17f */
+ Common, /* U+f180-f1ff */
+ Common, /* U+f200-f27f */
+ Common, /* U+f280-f2ff */
+ Common, /* U+f300-f37f */
+ Common, /* U+f380-f3ff */
+ Common, /* U+f400-f47f */
+ Common, /* U+f480-f4ff */
+ Common, /* U+f500-f57f */
+ Common, /* U+f580-f5ff */
+ Common, /* U+f600-f67f */
+ Common, /* U+f680-f6ff */
+ Common, /* U+f700-f77f */
+ Common, /* U+f780-f7ff */
+ Common, /* U+f800-f87f */
+ Common, /* U+f880-f8ff */
+ Han, /* U+f900-f97f */
+ Han, /* U+f980-f9ff */
+ Han, /* U+fa00-fa7f */
+ Han, /* U+fa80-faff */
+ 76, /* U+fb00-fb7f at offset 6144 */
+ 77, /* U+fb80-fbff at offset 6272 */
+ Arabic, /* U+fc00-fc7f */
+ Arabic, /* U+fc80-fcff */
+ 78, /* U+fd00-fd7f at offset 6400 */
+ 79, /* U+fd80-fdff at offset 6528 */
+ 80, /* U+fe00-fe7f at offset 6656 */
+ 81, /* U+fe80-feff at offset 6784 */
+ Common, /* U+ff00-ff7f */
+ 82, /* U+ff80-ffff at offset 6912 */
+
+
+ /* U+0300-037f at offset 512 */
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Common, Common, Common, Common, Greek, Greek, Common, Common,
+ Common, Common, Greek, Greek, Greek, Greek, Common, Common,
+
+ /* U+0380-03ff at offset 640 */
+ Common, Common, Common, Common, Greek, Greek, Greek, Common,
+ Greek, Greek, Greek, Common, Greek, Common, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Common, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic,
+ Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+
+ /* U+0480-04ff at offset 768 */
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Common,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+
+ /* U+0500-057f at offset 896 */
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic,
+ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Common,
+ Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+
+ /* U+0580-05ff at offset 1024 */
+ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Common, Common, Armenian, Common, Common, Common, Common, Common,
+ Common, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Common, Common, Common, Common, Common,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0600-067f at offset 1152 */
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Arabic, Common, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common,
+ Common, Common, Common, Common, Common, Common, Arabic, Common,
+ Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Common, Common, Common, Common, Common,
+ Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Inherited, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+0680-06ff at offset 1280 */
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Common, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+0700-077f at offset 1408 */
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Common, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac,
+ Syriac, Syriac, Syriac, Common, Common, Syriac, Syriac, Syriac,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0780-07ff at offset 1536 */
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana,
+ Thaana, Thaana, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko,
+ Nko, Nko, Nko, Common, Common, Common, Common, Common,
+
+ /* U+0900-097f at offset 1664 */
+ Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Common, Common,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Common,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Devanagari, Devanagari,
+ Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari,
+
+ /* U+0980-09ff at offset 1792 */
+ Common, Bengali, Bengali, Bengali, Common, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali,
+ Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Common, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Common, Bengali, Common, Common, Common, Bengali, Bengali,
+ Bengali, Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali,
+ Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, Common,
+ Common, Common, Common, Common, Common, Common, Common, Bengali,
+ Common, Common, Common, Common, Bengali, Bengali, Common, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali,
+ Bengali, Bengali, Bengali, Common, Common, Common, Common, Common,
+
+ /* U+0a00-0a7f at offset 1920 */
+ Common, Gurmukhi, Gurmukhi, Gurmukhi, Common, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, Common, Gurmukhi,
+ Gurmukhi, Common, Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Common, Gurmukhi, Gurmukhi, Common, Gurmukhi, Gurmukhi, Common,
+ Gurmukhi, Gurmukhi, Common, Common, Gurmukhi, Common, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, Common, Gurmukhi,
+ Gurmukhi, Common, Common, Gurmukhi, Gurmukhi, Gurmukhi, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Common, Gurmukhi, Common,
+ Common, Common, Common, Common, Common, Common, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi,
+ Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0a80-0aff at offset 2048 */
+ Common, Gujarati, Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati,
+ Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Common, Gujarati,
+ Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati,
+ Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati,
+ Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati,
+ Gujarati, Common, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati,
+ Gujarati, Common, Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati,
+ Gujarati, Gujarati, Common, Common, Gujarati, Gujarati, Gujarati, Gujarati,
+ Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Common, Gujarati,
+ Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, Common, Common,
+ Gujarati, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Gujarati, Gujarati, Gujarati, Gujarati, Common, Common, Gujarati, Gujarati,
+ Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati,
+ Common, Gujarati, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0b00-0b7f at offset 2176 */
+ Common, Oriya, Oriya, Oriya, Common, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Oriya, Oriya, Oriya, Common, Common, Oriya,
+ Oriya, Common, Common, Oriya, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Common, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Common, Oriya, Oriya, Common, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Common, Common, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Oriya, Oriya, Common, Common, Common, Oriya,
+ Oriya, Common, Common, Oriya, Oriya, Oriya, Common, Common,
+ Common, Common, Common, Common, Common, Common, Oriya, Oriya,
+ Common, Common, Common, Common, Oriya, Oriya, Common, Oriya,
+ Oriya, Oriya, Common, Common, Common, Common, Oriya, Oriya,
+ Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya,
+ Oriya, Oriya, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0b80-0bff at offset 2304 */
+ Common, Common, Tamil, Tamil, Common, Tamil, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil,
+ Tamil, Common, Tamil, Tamil, Tamil, Tamil, Common, Common,
+ Common, Tamil, Tamil, Common, Tamil, Common, Tamil, Tamil,
+ Common, Common, Common, Tamil, Tamil, Common, Common, Common,
+ Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil,
+ Tamil, Tamil, Common, Common, Common, Common, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil,
+ Tamil, Common, Tamil, Tamil, Tamil, Tamil, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Tamil,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil,
+ Tamil, Tamil, Tamil, Common, Common, Common, Common, Common,
+
+ /* U+0c00-0c7f at offset 2432 */
+ Common, Telugu, Telugu, Telugu, Common, Telugu, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu,
+ Telugu, Common, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu,
+ Telugu, Common, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu, Telugu,
+ Telugu, Telugu, Common, Common, Common, Common, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu,
+ Telugu, Common, Telugu, Telugu, Telugu, Telugu, Common, Common,
+ Common, Common, Common, Common, Common, Telugu, Telugu, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Telugu, Telugu, Common, Common, Common, Common, Telugu, Telugu,
+ Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0c80-0cff at offset 2560 */
+ Common, Common, Kannada, Kannada, Common, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada,
+ Kannada, Common, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada,
+ Kannada, Common, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Common, Common, Kannada, Kannada, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada,
+ Kannada, Common, Kannada, Kannada, Kannada, Kannada, Common, Common,
+ Common, Common, Common, Common, Common, Kannada, Kannada, Common,
+ Common, Common, Common, Common, Common, Common, Kannada, Common,
+ Kannada, Kannada, Kannada, Kannada, Common, Common, Kannada, Kannada,
+ Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada,
+ Common, Kannada, Kannada, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0d00-0d7f at offset 2688 */
+ Common, Common, Malayalam, Malayalam, Common, Malayalam, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Common, Malayalam, Malayalam,
+ Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Malayalam, Malayalam, Common, Common, Common, Common, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Common, Common, Malayalam, Malayalam,
+ Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Malayalam,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Malayalam, Malayalam, Common, Common, Common, Common, Malayalam, Malayalam,
+ Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0d80-0dff at offset 2816 */
+ Common, Common, Sinhala, Sinhala, Common, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common,
+ Common, Common, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Common, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Common, Sinhala, Common, Common,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common,
+ Common, Common, Sinhala, Common, Common, Common, Common, Sinhala,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common, Sinhala, Common,
+ Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Sinhala, Sinhala, Sinhala, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0e00-0e7f at offset 2944 */
+ Common, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Common, Common, Common, Common, Common,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,
+ Thai, Thai, Thai, Thai, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0e80-0eff at offset 3072 */
+ Common, Lao, Lao, Common, Lao, Common, Common, Lao,
+ Lao, Common, Lao, Common, Common, Lao, Common, Common,
+ Common, Common, Common, Common, Lao, Lao, Lao, Lao,
+ Common, Lao, Lao, Lao, Lao, Lao, Lao, Lao,
+ Common, Lao, Lao, Lao, Common, Lao, Common, Lao,
+ Common, Common, Lao, Lao, Common, Lao, Lao, Lao,
+ Lao, Lao, Lao, Lao, Lao, Lao, Lao, Lao,
+ Lao, Lao, Common, Lao, Lao, Lao, Common, Common,
+ Lao, Lao, Lao, Lao, Lao, Common, Lao, Common,
+ Lao, Lao, Lao, Lao, Lao, Lao, Common, Common,
+ Lao, Lao, Lao, Lao, Lao, Lao, Lao, Lao,
+ Lao, Lao, Common, Common, Lao, Lao, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+0f00-0f7f at offset 3200 */
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Common, Common, Common, Common, Common,
+ Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+
+ /* U+0f80-0fff at offset 3328 */
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Common, Common, Common, Common,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Common, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan,
+ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Common, Common, Tibetan,
+ Tibetan, Tibetan, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+1000-107f at offset 3456 */
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Common, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Common, Myanmar, Myanmar, Common, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Common, Common, Common, Myanmar, Myanmar,
+ Myanmar, Myanmar, Common, Common, Common, Common, Common, Common,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar,
+ Myanmar, Myanmar, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+1080-10ff at offset 3584 */
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Common, Georgian, Common, Common, Common,
+
+ /* U+1100-117f at offset 3712 */
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Common, Common, Common, Common, Common, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+
+ /* U+1180-11ff at offset 3840 */
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Common, Common, Common, Common, Common,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Common, Common, Common, Common, Common, Common,
+
+ /* U+1680-16ff at offset 3968 */
+ Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham,
+ Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham,
+ Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham,
+ Ogham, Ogham, Ogham, Ogham, Ogham, Common, Common, Common,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic,
+ Runic, Runic, Runic, Common, Common, Common, Runic, Runic,
+ Runic, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+1780-17ff at offset 4096 */
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Common, Common,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Common, Common, Common, Common, Common, Common,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Common, Common, Common, Common, Common, Common,
+
+ /* U+1980-19ff at offset 4224 */
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, Common, Common, Common, Common, Common, Common,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, Common, Common, Common, Common, Common, Common,
+ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue,
+ NewTaiLue, NewTaiLue, Common, Common, Common, Common, NewTaiLue, NewTaiLue,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer,
+
+ /* U+1d00-1d7f at offset 4352 */
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Greek, Greek,
+ Greek, Greek, Greek, Cyrillic, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Greek, Greek, Greek,
+ Greek, Greek, Latin, Latin, Latin, Latin, Greek, Greek,
+ Greek, Greek, Greek, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Cyrillic, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+
+ /* U+1d80-1dff at offset 4480 */
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin,
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Greek,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Inherited, Inherited,
+
+ /* U+1f00-1f7f at offset 4608 */
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Common, Common,
+ Greek, Greek, Greek, Greek, Greek, Greek, Common, Common,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Common, Common,
+ Greek, Greek, Greek, Greek, Greek, Greek, Common, Common,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Common, Greek, Common, Greek, Common, Greek, Common, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Common, Common,
+
+ /* U+1f80-1fff at offset 4736 */
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Common, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Common, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Common, Common, Greek, Greek,
+ Greek, Greek, Greek, Greek, Common, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek,
+ Common, Common, Greek, Greek, Greek, Common, Greek, Greek,
+ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common,
+
+ /* U+2000-207f at offset 4864 */
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Inherited, Inherited, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Latin, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Latin,
+
+ /* U+2080-20ff at offset 4992 */
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Latin, Latin, Latin, Latin, Latin, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+2100-217f at offset 5120 */
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Greek, Common,
+ Common, Common, Latin, Latin, Common, Common, Common, Common,
+ Common, Common, Latin, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Latin, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+2d00-2d7f at offset 5248 */
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian,
+ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh,
+ Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Tifinagh,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+3000-307f at offset 5376 */
+ Common, Common, Common, Common, Common, Han, Common, Han,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Han, Han, Han, Han, Common, Common, Common, Common,
+ Common, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+
+ /* U+3080-30ff at offset 5504 */
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana,
+ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Common,
+ Common, Inherited, Inherited, Common, Common, Hiragana, Hiragana, Hiragana,
+ Common, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Common, Common, Katakana, Katakana, Katakana,
+
+ /* U+3100-317f at offset 5632 */
+ Common, Common, Common, Common, Common, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Common, Common, Common,
+ Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+
+ /* U+3180-31ff at offset 5760 */
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+
+ /* U+3200-327f at offset 5888 */
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, Common,
+
+ /* U+d780-d7ff at offset 6016 */
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+
+ /* U+fb00-fb7f at offset 6144 */
+ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Armenian, Armenian, Armenian, Armenian, Armenian,
+ Common, Common, Common, Common, Common, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Hebrew, Common,
+ Hebrew, Hebrew, Common, Hebrew, Hebrew, Common, Hebrew, Hebrew,
+ Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+fb80-fbff at offset 6272 */
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+fd00-fd7f at offset 6400 */
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+fd80-fdff at offset 6528 */
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common,
+
+ /* U+fe00-fe7f at offset 6656 */
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Inherited, Inherited, Inherited, Inherited, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Common, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+
+ /* U+fe80-feff at offset 6784 */
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic,
+ Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common,
+
+ /* U+ff80-ffff at offset 6912 */
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana,
+ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Common, Common,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common,
+ Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Common, Common, Hangul, Hangul, Hangul, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common,
+ Common, Common, Common, Common, Common, Common, Common, Common
+};
+
+} // namespace QUnicodeTables
+
+Q_CORE_EXPORT int QT_FASTCALL QUnicodeTables::script(uint ucs4)
+{
+ if (ucs4 > 0xffff)
+ return Common;
+ int script = uc_scripts[ucs4 >> 7];
+ if (script < ScriptSentinel)
+ return script;
+ script = (((script - ScriptSentinel) * UnicodeBlockSize) + UnicodeBlockCount);
+ script = uc_scripts[script + (ucs4 & 0x7f)];
+ return script;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h
new file mode 100644
index 0000000000..4833a59a1b
--- /dev/null
+++ b/src/corelib/tools/qunicodetables_p.h
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* This file is autogenerated from the Unicode 5.0 database. Do not edit */
+
+//
+// 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.
+//
+
+#ifndef QUNICODETABLES_P_H
+#define QUNICODETABLES_P_H
+
+#include <QtCore/qchar.h>
+
+QT_BEGIN_NAMESPACE
+
+#define UNICODE_DATA_VERSION QChar::Unicode_5_0
+
+#define UNICODE_LAST_CODEPOINT 0x10ffff
+
+namespace QUnicodeTables {
+
+ struct Properties {
+ ushort category : 8; /* 5 needed */
+ ushort line_break_class : 8; /* 6 needed */
+ ushort direction : 8; /* 5 needed */
+ ushort combiningClass : 8;
+ ushort joining : 2;
+ signed short digitValue : 6; /* 5 needed */
+ ushort unicodeVersion : 4;
+ ushort lowerCaseSpecial : 1;
+ ushort upperCaseSpecial : 1;
+ ushort titleCaseSpecial : 1;
+ ushort caseFoldSpecial : 1; /* currently unused */
+ signed short mirrorDiff : 16;
+ signed short lowerCaseDiff : 16;
+ signed short upperCaseDiff : 16;
+ signed short titleCaseDiff : 16;
+ signed short caseFoldDiff : 16;
+ ushort graphemeBreak : 8; /* 4 needed */
+ ushort wordBreak : 8; /* 4 needed */
+ ushort sentenceBreak : 8; /* 4 needed */
+ };
+ Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
+ Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
+
+ // See http://www.unicode.org/reports/tr24/tr24-5.html
+ enum Script {
+ Common,
+ Greek,
+ Cyrillic,
+ Armenian,
+ Hebrew,
+ Arabic,
+ Syriac,
+ Thaana,
+ Devanagari,
+ Bengali,
+ Gurmukhi,
+ Gujarati,
+ Oriya,
+ Tamil,
+ Telugu,
+ Kannada,
+ Malayalam,
+ Sinhala,
+ Thai,
+ Lao,
+ Tibetan,
+ Myanmar,
+ Georgian,
+ Hangul,
+ Ogham,
+ Runic,
+ Khmer,
+ Nko,
+ Inherited,
+ ScriptCount = Inherited,
+ Latin = Common,
+ Ethiopic = Common,
+ Cherokee = Common,
+ CanadianAboriginal = Common,
+ Mongolian = Common,
+ Hiragana = Common,
+ Katakana = Common,
+ Bopomofo = Common,
+ Han = Common,
+ Yi = Common,
+ OldItalic = Common,
+ Gothic = Common,
+ Deseret = Common,
+ Tagalog = Common,
+ Hanunoo = Common,
+ Buhid = Common,
+ Tagbanwa = Common,
+ Limbu = Common,
+ TaiLe = Common,
+ LinearB = Common,
+ Ugaritic = Common,
+ Shavian = Common,
+ Osmanya = Common,
+ Cypriot = Common,
+ Braille = Common,
+ Buginese = Common,
+ Coptic = Common,
+ NewTaiLue = Common,
+ Glagolitic = Common,
+ Tifinagh = Common,
+ SylotiNagri = Common,
+ OldPersian = Common,
+ Kharoshthi = Common,
+ Balinese = Common,
+ Cuneiform = Common,
+ Phoenician = Common,
+ PhagsPa = Common
+ };
+ enum { ScriptSentinel = 32 };
+
+
+ enum GraphemeBreak {
+ GraphemeBreakOther,
+ GraphemeBreakCR,
+ GraphemeBreakLF,
+ GraphemeBreakControl,
+ GraphemeBreakExtend,
+ GraphemeBreakL,
+ GraphemeBreakV,
+ GraphemeBreakT,
+ GraphemeBreakLV,
+ GraphemeBreakLVT
+ };
+
+
+ enum WordBreak {
+ WordBreakOther,
+ WordBreakFormat,
+ WordBreakKatakana,
+ WordBreakALetter,
+ WordBreakMidLetter,
+ WordBreakMidNum,
+ WordBreakNumeric,
+ WordBreakExtendNumLet
+ };
+
+
+ enum SentenceBreak {
+ SentenceBreakOther,
+ SentenceBreakSep,
+ SentenceBreakFormat,
+ SentenceBreakSp,
+ SentenceBreakLower,
+ SentenceBreakUpper,
+ SentenceBreakOLetter,
+ SentenceBreakNumeric,
+ SentenceBreakATerm,
+ SentenceBreakSTerm,
+ SentenceBreakClose
+ };
+
+
+ // see http://www.unicode.org/reports/tr14/tr14-19.html
+ // we don't use the XX, AI and CB properties and map them to AL instead.
+ // as we don't support any EBDIC based OS'es, NL is ignored and mapped to AL as well.
+ enum LineBreakClass {
+ LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS,
+ LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO,
+ LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY,
+ LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM,
+ LineBreak_WJ, LineBreak_H2, LineBreak_H3, LineBreak_JL, LineBreak_JV,
+ LineBreak_JT, LineBreak_SA, LineBreak_SG,
+ LineBreak_SP, LineBreak_CR, LineBreak_LF, LineBreak_BK
+ };
+
+
+ Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4);
+ inline int lineBreakClass(const QChar &ch)
+ { return lineBreakClass(ch.unicode()); }
+
+ Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4);
+ inline int script(const QChar &ch)
+ { return script(ch.unicode()); }
+
+} // namespace QUnicodeTables
+
+QT_END_NAMESPACE
+
+#endif // QUNICODETABLES_P_H
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
new file mode 100644
index 0000000000..6a9875543b
--- /dev/null
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVARLENGTHARRAY_H
+#define QVARLENGTHARRAY_H
+
+#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qalgorithms.h>
+
+#include <new>
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template<class T, int Prealloc>
+class QPodList;
+
+// Prealloc = 256 by default, specified in qcontainerfwd.h
+template<class T, int Prealloc>
+class QVarLengthArray
+{
+public:
+ inline explicit QVarLengthArray(int size = 0);
+
+ inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
+ : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
+ {
+ append(other.constData(), other.size());
+ }
+
+ inline ~QVarLengthArray() {
+ if (QTypeInfo<T>::isComplex) {
+ T *i = ptr + s;
+ while (i-- != ptr)
+ i->~T();
+ }
+ if (ptr != reinterpret_cast<T *>(array))
+ qFree(ptr);
+ }
+ inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
+ {
+ if (this != &other) {
+ clear();
+ append(other.constData(), other.size());
+ }
+ return *this;
+ }
+
+ inline void removeLast() {
+ Q_ASSERT(s > 0);
+ realloc(s - 1, a);
+ }
+ inline int size() const { return s; }
+ inline int count() const { return s; }
+ inline bool isEmpty() const { return (s == 0); }
+ inline void resize(int size);
+ inline void clear() { resize(0); }
+
+ inline int capacity() const { return a; }
+ inline void reserve(int size);
+
+ inline T &operator[](int idx) {
+ Q_ASSERT(idx >= 0 && idx < s);
+ return ptr[idx];
+ }
+ inline const T &operator[](int idx) const {
+ Q_ASSERT(idx >= 0 && idx < s);
+ return ptr[idx];
+ }
+ inline const T &at(int idx) const { return operator[](idx); }
+
+ T value(int i) const;
+ T value(int i, const T &defaultValue) const;
+
+ inline void append(const T &t) {
+ if (s == a) // i.e. s != 0
+ realloc(s, s<<1);
+ const int idx = s++;
+ if (QTypeInfo<T>::isComplex) {
+ new (ptr + idx) T(t);
+ } else {
+ ptr[idx] = t;
+ }
+ }
+ void append(const T *buf, int size);
+ inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
+ { append(t); return *this; }
+ inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
+ { append(t); return *this; }
+
+ void prepend(const T &t);
+ void insert(int i, const T &t);
+ void insert(int i, int n, const T &t);
+ void replace(int i, const T &t);
+ void remove(int i);
+ void remove(int i, int n);
+
+
+ inline T *data() { return ptr; }
+ inline const T *data() const { return ptr; }
+ inline const T * constData() const { return ptr; }
+ typedef int 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;
+
+ inline iterator begin() { return ptr; }
+ inline const_iterator begin() 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 constEnd() const { return ptr + s; }
+ iterator insert(iterator before, int n, const T &x);
+ inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
+ iterator erase(iterator begin, iterator end);
+ inline iterator erase(iterator pos) { return erase(pos, pos+1); }
+
+private:
+ friend class QPodList<T, Prealloc>;
+ void realloc(int size, int alloc);
+
+ int a; // capacity
+ int s; // size
+ T *ptr; // data
+ union {
+ // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
+ char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
+ qint64 q_for_alignment_1;
+ double q_for_alignment_2;
+ };
+};
+
+template <class T, int Prealloc>
+Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
+ : s(asize) {
+ if (s > Prealloc) {
+ ptr = reinterpret_cast<T *>(qMalloc(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;
+ }
+}
+
+template <class T, int Prealloc>
+Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(int asize)
+{ realloc(asize, qMax(asize, a)); }
+
+template <class T, int Prealloc>
+Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
+{ if (asize > a) realloc(s, asize); }
+
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
+{
+ Q_ASSERT(abuf);
+ if (increment <= 0)
+ return;
+
+ const int asize = s + increment;
+
+ if (asize >= a)
+ realloc(s, qMax(s*2, asize));
+
+ if (QTypeInfo<T>::isComplex) {
+ // call constructor for new objects (which can throw)
+ while (s < asize)
+ new (ptr+(s++)) T(*abuf++);
+ } else {
+ qMemCopy(&ptr[s], abuf, increment * sizeof(T));
+ s = asize;
+ }
+}
+
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
+{
+ Q_ASSERT(aalloc >= asize);
+ T *oldPtr = ptr;
+ int osize = s;
+
+ const int copySize = qMin(asize, osize);
+ if (aalloc != a) {
+ ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
+ Q_CHECK_PTR(ptr);
+ if (ptr) {
+ s = 0;
+ a = aalloc;
+
+ if (QTypeInfo<T>::isStatic) {
+ QT_TRY {
+ // copy all the old elements
+ while (s < copySize) {
+ new (ptr+s) T(*(oldPtr+s));
+ (oldPtr+s)->~T();
+ s++;
+ }
+ } QT_CATCH(...) {
+ // clean up all the old objects and then free the old ptr
+ int sClean = s;
+ while (sClean < osize)
+ (oldPtr+(sClean++))->~T();
+ if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
+ qFree(oldPtr);
+ QT_RETHROW;
+ }
+ } else {
+ qMemCopy(ptr, oldPtr, copySize * sizeof(T));
+ }
+ } else {
+ ptr = oldPtr;
+ return;
+ }
+ }
+ s = copySize;
+
+ if (QTypeInfo<T>::isComplex) {
+ // destroy remaining old objects
+ while (osize > asize)
+ (oldPtr+(--osize))->~T();
+ }
+
+ if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
+ qFree(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, int Prealloc>
+Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i) const
+{
+ if (i < 0 || i >= size()) {
+ return T();
+ }
+ return at(i);
+}
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i, const T &defaultValue) const
+{
+ return (i < 0 || i >= size()) ? defaultValue : at(i);
+}
+
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::insert(int i, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
+ insert(begin() + i, 1, t); }
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::insert(int i, int n, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
+ insert(begin() + i, n, t); }
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::remove(int i, int n)
+{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= s, "QVarLengthArray::remove", "index out of range");
+ erase(begin() + i, begin() + i + n); }
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::remove(int i)
+{ Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::remove", "index out of range");
+ erase(begin() + i, begin() + i + 1); }
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::prepend(const T &t)
+{ insert(begin(), 1, t); }
+
+template <class T, int Prealloc>
+inline void QVarLengthArray<T, Prealloc>::replace(int i, const T &t)
+{
+ Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::replace", "index out of range");
+ const T copy(t);
+ data()[i] = copy;
+}
+
+
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(iterator before, size_type n, const T &t)
+{
+ int offset = int(before - ptr);
+ if (n != 0) {
+ resize(s + n);
+ const T copy(t);
+ if (QTypeInfo<T>::isStatic) {
+ 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(i, b, (s - offset - n) * sizeof(T));
+ while (i != b)
+ new (--i) T(copy);
+ }
+ }
+ return ptr + offset;
+}
+
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::erase(iterator abegin, iterator aend)
+{
+ int f = int(abegin - ptr);
+ int l = int(aend - ptr);
+ int n = l - f;
+ if (QTypeInfo<T>::isComplex) {
+ qCopy(ptr + l, ptr + s, ptr + f);
+ T *i = ptr + s;
+ T *b = ptr + s - n;
+ while (i != b) {
+ --i;
+ i->~T();
+ }
+ } else {
+ memmove(ptr + f, ptr + l, (s - l) * sizeof(T));
+ }
+ s -= n;
+ return ptr + f;
+}
+
+template <typename T, int Prealloc1, int Prealloc2>
+bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{
+ if (l.size() != r.size())
+ return false;
+ for (int i = 0; i < l.size(); i++) {
+ if (l.at(i) != r.at(i))
+ return false;
+ }
+ return true;
+}
+
+template <typename T, int Prealloc1, int Prealloc2>
+bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{
+ return !(l == r);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QVARLENGTHARRAY_H
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
new file mode 100644
index 0000000000..3c80c1cbbd
--- /dev/null
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QVarLengthArray
+ \brief The QVarLengthArray class provides a low-level variable-length array.
+
+ \ingroup tools
+ \reentrant
+
+ The C++ language doesn't support variable-length arrays on the stack.
+ For example, the following code won't compile:
+
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.cpp 0
+
+ The alternative is to allocate the array on the heap (with
+ \c{new}):
+
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.cpp 1
+
+ However, if myfunc() is called very frequently from the
+ application's inner loop, heap allocation can be a major source
+ of slowdown.
+
+ QVarLengthArray is an attempt to work around this gap in the C++
+ language. It allocates a certain number of elements on the stack,
+ and if you resize the array to a larger size, it automatically
+ uses the heap instead. Stack allocation has the advantage that
+ it is much faster than heap allocation.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.cpp 2
+
+ In the example above, QVarLengthArray will preallocate 1024
+ elements on the stack and use them unless \c{n + 1} is greater
+ than 1024. If you omit the second template argument,
+ QVarLengthArray's default of 256 is used.
+
+ QVarLengthArray's value type must be an \l{assignable data type}.
+ This covers most data types that are commonly used, but the
+ compiler won't let you, for example, store a QWidget as a value;
+ instead, store a QWidget *.
+
+ QVarLengthArray, like QVector, provides a resizable array data
+ structure. The main differences between the two classes are:
+
+ \list
+ \o QVarLengthArray's API is much more low-level. It provides no
+ iterators and lacks much of QVector's functionality.
+
+ \o QVarLengthArray doesn't initialize the memory if the value is
+ a basic type. (QVector always does.)
+
+ \o QVector uses \l{implicit sharing} as a memory optimization.
+ QVarLengthArray doesn't provide that feature; however, it
+ usually produces slightly better performance due to reduced
+ overhead, especially in tight loops.
+ \endlist
+
+ In summary, QVarLengthArray is a low-level optimization class
+ that only makes sense in very specific cases. It is used a few
+ places inside Qt and was added to Qt's public API for the
+ convenience of advanced users.
+
+ \sa QVector, QList, QLinkedList
+*/
+
+/*! \fn QVarLengthArray::QVarLengthArray(int size)
+
+ Constructs an array with an initial size of \a size elements.
+
+ If the value type is a primitive type (e.g., char, int, float) or
+ a pointer type (e.g., QWidget *), the elements are not
+ initialized. For other types, the elements are initialized with a
+ \l{default-constructed value}.
+*/
+
+/*! \fn QVarLengthArray::~QVarLengthArray()
+
+ Destroys the array.
+*/
+
+/*! \fn int QVarLengthArray::size() const
+
+ Returns the number of elements in the array.
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn int QVarLengthArray::count() const
+
+ Same as size().
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QVarLengthArray::isEmpty() const
+
+ Returns true if the array has size 0; otherwise returns false.
+
+ \sa size(), resize()
+*/
+
+/*! \fn void QVarLengthArray::clear()
+
+ Removes all the elements from the array.
+
+ Same as resize(0).
+*/
+
+/*! \fn void QVarLengthArray::resize(int size)
+
+ Sets the size of the array to \a size. If \a size is greater than
+ the current size, elements are added to the end. If \a size is
+ less than the current size, elements are removed from the end.
+
+ If the value type is a primitive type (e.g., char, int, float) or
+ a pointer type (e.g., QWidget *), new elements are not
+ initialized. For other types, the elements are initialized with a
+ \l{default-constructed value}.
+
+ \sa size()
+*/
+
+/*! \fn int QVarLengthArray::capacity() const
+
+ Returns the maximum number of elements that can be stored in the
+ array without forcing a reallocation.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVarLengthArray's memory usage. In general, you will rarely ever
+ need to call this function. If you want to know how many items are
+ in the array, call size().
+
+ \sa reserve()
+*/
+
+/*! \fn void QVarLengthArray::reserve(int size)
+
+ Attempts to allocate memory for at least \a size elements. If you
+ know in advance how large the array can get, 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 QVarLengthArray will be a bit
+ slower.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVarLengthArray's memory usage. In general, you will
+ rarely ever need to call this function. If you want to change the
+ size of the array, call resize().
+
+ \sa capacity()
+*/
+
+/*! \fn T &QVarLengthArray::operator[](int i)
+
+ Returns a reference to the item at index position \a i.
+
+ \a i must be a valid index position in the array (i.e., 0 <= \a i
+ < size()).
+
+ \sa data(), at()
+*/
+
+/*! \fn const T &QVarLengthArray::operator[](int i) const
+
+ \overload
+*/
+
+
+/*!
+ \fn void QVarLengthArray::append(const T &t)
+
+ Appends item \a t to the array, extending the array if necessary.
+
+ \sa removeLast()
+*/
+
+
+/*!
+ \fn inline void QVarLengthArray::removeLast()
+ \since 4.5
+
+ Decreases the size of the array by one. The allocated size is not changed.
+
+ \sa append()
+*/
+
+/*!
+ \fn void QVarLengthArray::append(const T *buf, int size)
+
+ Appends \a size amount of items referenced by \a buf to this array.
+*/
+
+
+/*! \fn T *QVarLengthArray::data()
+
+ Returns a pointer to the data stored in the array. The pointer can
+ be used to access and modify the items in the array.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.cpp 3
+
+ The pointer remains valid as long as the array isn't reallocated.
+
+ This function is mostly useful to pass an array to a function
+ that accepts a plain C++ array.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const T *QVarLengthArray::data() const
+
+ \overload
+*/
+
+/*! \fn const T *QVarLengthArray::constData() const
+
+ Returns a const pointer to the data stored in the array. The
+ pointer can be used to access the items in the array. The
+ pointer remains valid as long as the array isn't reallocated.
+
+ This function is mostly useful to pass an array to a function
+ that accepts a plain C++ array.
+
+ \sa data(), operator[]()
+*/
+
+/*! \fn QVarLengthArray<T, Prealloc> &QVarLengthArray::operator=(const QVarLengthArray<T, Prealloc> &other)
+ Assigns \a other to this array and returns a reference to this array.
+ */
+
+/*! \fn QVarLengthArray::QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
+ Constructs a copy of \a other.
+ */
+
+/*! \fn const T &QVarLengthArray::at(int i) const
+
+ Returns a reference to the item at index position \a i.
+
+ \a i must be a valid index position in the array (i.e., 0 <= \a i
+ < size()).
+
+ \sa value(), operator[]()
+*/
+
+/*! \fn T QVarLengthArray::value(int i) const
+
+ Returns the value at index position \a i.
+
+ 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 T QVarLengthArray::value(int i, const T &defaultValue) const
+
+ \overload
+
+ If the index \a i is out of bounds, the function returns
+ \a defaultValue.
+*/
+
+/*!
+ \typedef QVarLengthArray::size_type
+ \since 4.7
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::value_type
+ \since 4.7
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::difference_type
+ \since 4.7
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::pointer
+ \since 4.7
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::const_pointer
+ \since 4.7
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::reference
+ \since 4.7
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QVarLengthArray::const_reference
+ \since 4.7
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*! \fn void QVarLengthArray::prepend(const T &value)
+
+ \since 4.8
+ Inserts \a value at the beginning of the array.
+
+
+ This is the same as vector.insert(0, \a value).
+
+ For large arrays, this operation can be slow (\l{linear time}),
+ because it requires moving all the items in the vector by one
+ position further in memory. If you want a container class that
+ provides a fast prepend() function, use QList or QLinkedList
+ instead.
+
+ \sa append(), insert()
+*/
+
+/*! \fn void QVarLengthArray::replace(int i, const T &value)
+
+ \since 4.8
+ Replaces the item at index position \a i with \a value.
+
+ \a i must be a valid index position in the array (i.e., 0 <= \a
+ i < size()).
+
+ \sa operator[](), remove()
+*/
+
+/*! \fn void QVarLengthArray::remove(int i)
+
+ \overload
+ \since 4.8
+
+ Removes the element at index position \a i.
+
+ \sa insert(), replace()
+*/
+
+/*! \fn void QVarLengthArray::remove(int i, int count)
+
+ \overload
+ \since 4.8
+
+ Removes \a count elements from the middle of the array, starting at
+ index position \a i.
+
+ \sa insert(), replace()
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::begin()
+ \since 4.8
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the array.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QVarLengthArray::const_iterator QVarLengthArray::begin() const
+ \since 4.8
+ \overload
+*/
+
+/*! \fn QVarLengthArray::const_iterator QVarLengthArray::constBegin() const
+ \since 4.8
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the array.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::end()
+ \since 4.8
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the array.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QVarLengthArray::const_iterator QVarLengthArray::end() const
+ \since 4.8
+
+ \overload
+*/
+
+/*! \fn QVarLengthArray::const_iterator QVarLengthArray::constEnd() const
+ \since 4.8
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the array.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::erase(iterator pos)
+ \since 4.8
+
+ Removes the item pointed to by the iterator \a pos from the
+ vector, and returns an iterator to the next item in the vector
+ (which may be end()).
+
+ \sa insert(), remove()
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::erase(iterator begin, iterator end)
+
+ \overload
+ \since 4.8
+
+ 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.
+*/
+
+/*! \fn void QVarLengthArray::insert(int i, const T &value)
+ \since 4.8
+
+ Inserts \a value at index position \a i in the array. If \a i is
+ 0, the value is prepended to the vector. If \a i is size(), the
+ value is appended to the vector.
+
+ For large arrays, this operation can be slow (\l{linear time}),
+ because it requires moving all the items at indexes \a i and
+ above by one position further in memory. If you want a container
+ class that provides a fast insert() function, use QLinkedList
+ instead.
+
+ \sa remove()
+*/
+
+/*! \fn void QVarLengthArray::insert(int i, int count, const T &value)
+
+ \overload
+ \since 4.8
+
+ Inserts \a count copies of \a value at index position \a i in the
+ vector.
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::insert(iterator before, const T &value)
+
+ \overload
+ \since 4.8
+
+ Inserts \a value in front of the item pointed to by the iterator
+ \a before. Returns an iterator pointing at the inserted item.
+*/
+
+/*! \fn QVarLengthArray::iterator QVarLengthArray::insert(iterator before, int count, const T &value)
+
+ \since 4.8
+ 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
+ first of the inserted items.
+*/
+
+
+
+/*! \fn bool operator==(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right)
+
+ \relates QVarLengthArray
+ \since 4.8
+ Returns true if the two array are equal;
+
+ Two arrays are considered equal if they contain the same values
+ in the same order.
+
+ This function requires the value type to have an implementation
+ of \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool operator!=(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right)
+
+ \relates QVarLengthArray
+ \since 4.8
+ Returns true if the two array are different;
+
+ Two arrays are considered equal if they contain the same values
+ in the same order.
+
+ This function requires the value type to have an implementation
+ of \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn QVarLengthArray &QVarLengthArray::operator<<(const T &value)
+
+ \since 4.8
+ Appends \a value to the array and returns a reference to this
+ vector.
+
+ \sa append(), operator+=()
+*/
+
+/*! \fn QVarLengthArray &QVarLengthArray::operator+=(const T &value)
+
+ \since 4.8
+ Appends \a value to the array and returns a reference to this
+ vector.
+
+ \sa append(), operator<<()
+*/
+
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
new file mode 100644
index 0000000000..06ed6bb1a5
--- /dev/null
+++ b/src/corelib/tools/qvector.cpp
@@ -0,0 +1,1017 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector.h"
+#include "qtools_p.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline int alignmentThreshold()
+{
+ // 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*);
+}
+
+QVectorData QVectorData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, true, false, 0 };
+
+QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
+{
+ QVectorData* p = (QVectorData *)qMalloc(sizeofTypedData + (size - 1) * sizeofT);
+ Q_CHECK_PTR(p);
+ ::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT);
+ return p;
+}
+
+QVectorData *QVectorData::allocate(int size, int alignment)
+{
+ return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : qMalloc(size));
+}
+
+QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment)
+{
+ if (alignment > alignmentThreshold())
+ return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment));
+ return static_cast<QVectorData *>(qRealloc(x, newsize));
+}
+
+void QVectorData::free(QVectorData *x, int alignment)
+{
+ if (alignment > alignmentThreshold())
+ qFreeAligned(x);
+ else
+ qFree(x);
+}
+
+int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive)
+{
+ if (excessive)
+ return size + size / 2;
+ return qAllocMore(size * sizeofT, sizeofTypedData - sizeofT) / sizeofT;
+}
+
+/*!
+ \class QVector
+ \brief The QVector class is a template class that provides a dynamic array.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QVector\<T\> is one of Qt's generic \l{container classes}. It
+ stores its items in adjacent memory locations and provides fast
+ index-based access.
+
+ QList\<T\>, QLinkedList\<T\>, and QVarLengthArray\<T\> provide
+ similar functionality. Here's an overview:
+
+ \list
+ \i For most purposes, QList is the right class to use. Operations
+ like prepend() and insert() are usually faster than with
+ QVector because of the way QList stores its items in memory
+ (see \l{Algorithmic Complexity} for details),
+ and its index-based API is more convenient than QLinkedList's
+ iterator-based API. It also expands to less code in your
+ executable.
+ \i If you need a real linked list, with guarantees of \l{constant
+ time} insertions in the middle of the list and iterators to
+ items rather than indexes, use QLinkedList.
+ \i If you want the items to occupy adjacent memory positions, or
+ if your items are larger than a pointer and you want to avoid
+ the overhead of allocating them on the heap individually at
+ insertion time, then use QVector.
+ \i If you want a low-level variable-size array, QVarLengthArray
+ may be sufficient.
+ \endlist
+
+ Here's an example of a QVector that stores integers and a QVector
+ that stores QString values:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 0
+
+ QVector stores a vector (or array) of items. Typically, vectors
+ are created with an initial size. For example, the following code
+ constructs a QVector with 200 elements:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 1
+
+ The elements are automatically initialized with a
+ \l{default-constructed value}. If you want to initialize the
+ vector with a different value, pass that value as the second
+ argument to the constructor:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 2
+
+ You can also call fill() at any time to fill the vector with a
+ value.
+
+ QVector uses 0-based indexes, just like C++ arrays. To access the
+ item at a particular index position, you can use operator[](). On
+ non-const vectors, operator[]() returns a reference to the item
+ that can be used on the left side of an assignment:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 3
+
+ For read-only access, an alternative syntax is to use at():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 4
+
+ at() can be faster than operator[](), because it never causes a
+ \l{deep copy} to occur.
+
+ Another way to access the data stored in a QVector is to call
+ data(). The function returns a pointer to the first item in the
+ vector. You can use the pointer to directly access and modify the
+ elements stored in the vector. The pointer is also useful if you
+ need to pass a QVector to a function that accepts a plain C++
+ array.
+
+ If you want to find all occurrences of a particular value in a
+ vector, use indexOf() or lastIndexOf(). The former searches
+ forward starting from a given index position, the latter searches
+ backward. Both return the index of the matching item if they found
+ one; otherwise, they return -1. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 5
+
+ If you simply want to check whether a vector contains a
+ particular value, use contains(). If you want to find out how
+ many times a particular value occurs in the vector, use count().
+
+ QVector 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 vectors, because they require moving many
+ items in the vector by one position in memory. If you want a container
+ class that provides fast insertion/removal in the middle, use
+ QList or QLinkedList instead.
+
+ Unlike plain C++ arrays, QVectors can be resized at any time by
+ calling resize(). If the new size is larger than the old size,
+ QVector might need to reallocate the whole vector. QVector tries
+ 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 QVector
+ will contain, you can call reserve(), asking QVector to
+ preallocate a certain amount of memory. You can also call
+ capacity() to find out how much memory QVector actually
+ allocated.
+
+ Note that using non-const operators and functions can cause
+ QVector to do a deep copy of the data. This is due to \l{implicit sharing}.
+
+ QVector's value type must be an \l{assignable data type}. This
+ covers most data types that are commonly used, but the compiler
+ won't let you, for example, store a QWidget as a value; instead,
+ store a QWidget *. A few functions have additional requirements;
+ for example, indexOf() and lastIndexOf() expect the value type to
+ support \c operator==(). These requirements are documented on a
+ per-function basis.
+
+ Like the other container classes, QVector provides \l{Java-style
+ iterators} (QVectorIterator and QMutableVectorIterator) and
+ \l{STL-style iterators} (QVector::const_iterator and
+ QVector::iterator). In practice, these are rarely used, because
+ you can use indexes into the QVector.
+
+ In addition to QVector, Qt also provides QVarLengthArray, a very
+ low-level class with little functionality that is optimized for
+ speed.
+
+ QVector 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.
+
+ \sa QVectorIterator, QMutableVectorIterator, QList, QLinkedList
+*/
+
+/*!
+ \fn QVector<T> QVector::mid(int pos, int length = -1) const
+
+ Returns a vector whose elements are copied from this vector,
+ starting at position \a pos. If \a length is -1 (the default), all
+ elements after \a pos are copied; otherwise \a length elements (or
+ all remaining elements if there are less than \a length elements)
+ are copied.
+*/
+
+
+/*! \fn QVector::QVector()
+
+ Constructs an empty vector.
+
+ \sa resize()
+*/
+
+/*! \fn QVector::QVector(int size)
+
+ Constructs a vector with an initial size of \a size elements.
+
+ The elements are initialized with a \l{default-constructed
+ value}.
+
+ \sa resize()
+*/
+
+/*! \fn QVector::QVector(int size, const T &value)
+
+ Constructs a vector with an initial size of \a size elements.
+ Each element is initialized with \a value.
+
+ \sa resize(), fill()
+*/
+
+/*! \fn QVector::QVector(const QVector<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QVector is
+ \l{implicitly shared}. This makes returning a QVector from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QVector::QVector(std::initializer_list<T> args)
+ \since 4.8
+
+ Construct a vector from a std::initilizer_list.
+
+ This constructor is only enabled if the compiler supports C++0x
+*/
+
+
+/*! \fn QVector::~QVector()
+
+ Destroys the vector.
+*/
+
+/*! \fn QVector<T> &QVector::operator=(const QVector<T> &other)
+
+ Assigns \a other to this vector and returns a reference to this
+ vector.
+*/
+
+/*! \fn void QVector::swap(QVector<T> &other)
+ \since 4.8
+
+ Swaps vector \a other with this vector. This operation is very fast and
+ never fails.
+*/
+
+/*! \fn bool QVector::operator==(const QVector<T> &other) const
+
+ Returns true if \a other is equal to this vector; otherwise
+ returns false.
+
+ Two vectors are considered equal if they contain the same values
+ in the same order.
+
+ This function requires the value type to have an implementation
+ of \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QVector::operator!=(const QVector<T> &other) const
+
+ Returns true if \a other is not equal to this vector; otherwise
+ returns false.
+
+ Two vectors are considered equal if they contain the same values
+ in the same order.
+
+ This function requires the value type to have an implementation
+ of \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QVector::size() const
+
+ Returns the number of items in the vector.
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QVector::isEmpty() const
+
+ Returns true if the vector has size 0; otherwise returns false.
+
+ \sa size(), resize()
+*/
+
+/*! \fn void QVector::resize(int size)
+
+ Sets the size of the vector 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.
+
+ \sa size()
+*/
+
+/*! \fn int QVector::capacity() const
+
+ Returns the maximum number of items that can be stored in the
+ vector without forcing a reallocation.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVector's memory usage. In general, you will rarely ever
+ need to call this function. If you want to know how many items are
+ in the vector, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QVector::reserve(int size)
+
+ Attempts to allocate memory for at least \a size elements. If you
+ know in advance how large the vector 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 QVector will be a bit slower.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVector's memory usage. In general, you will rarely ever
+ need to call this function. If you want to change the size of the
+ vector, call resize().
+
+ \sa squeeze(), capacity()
+*/
+
+/*! \fn void QVector::squeeze()
+
+ Releases any memory not required to store the items.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVector's memory usage. In general, you will rarely ever
+ need to call this function.
+
+ \sa reserve(), capacity()
+*/
+
+/*! \fn void QVector::detach()
+
+ \internal
+*/
+
+/*! \fn bool QVector::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QVector::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn bool QVector::isSharedWith(const QVector<T> &other) const
+
+ \internal
+*/
+
+/*! \fn T *QVector::data()
+
+ Returns a pointer to the data stored in the vector. The pointer
+ can be used to access and modify the items in the vector.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 6
+
+ The pointer remains valid as long as the vector isn't
+ reallocated.
+
+ This function is mostly useful to pass a vector to a function
+ that accepts a plain C++ array.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const T *QVector::data() const
+
+ \overload
+*/
+
+/*! \fn const T *QVector::constData() const
+
+ Returns a const pointer to the data stored in the vector. The
+ pointer can be used to access the items in the vector.
+ The pointer remains valid as long as the vector isn't
+ reallocated.
+
+ This function is mostly useful to pass a vector to a function
+ that accepts a plain C++ array.
+
+ \sa data(), operator[]()
+*/
+
+/*! \fn void QVector::clear()
+
+ Removes all the elements from the vector and releases the memory used by
+ the vector.
+*/
+
+/*! \fn const T &QVector::at(int i) const
+
+ Returns the item at index position \a i in the vector.
+
+ \a i must be a valid index position in the vector (i.e., 0 <= \a
+ i < size()).
+
+ \sa value(), operator[]()
+*/
+
+/*! \fn T &QVector::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference.
+
+ \a i must be a valid index position in the vector (i.e., 0 <= \a i
+ < size()).
+
+ Note that using non-const operators can cause QVector to do a deep
+ copy.
+
+ \sa at(), value()
+*/
+
+/*! \fn const T &QVector::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*!
+ \fn void QVector::append(const T &value)
+
+ Inserts \a value at the end of the vector.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 7
+
+ This is the same as calling resize(size() + 1) and assigning \a
+ value to the new last element in the vector.
+
+ This operation is relatively fast, because QVector typically
+ allocates more memory than necessary, so it can grow without
+ reallocating the entire vector each time.
+
+ \sa operator<<(), prepend(), insert()
+*/
+
+/*! \fn void QVector::prepend(const T &value)
+
+ Inserts \a value at the beginning of the vector.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 8
+
+ This is the same as vector.insert(0, \a value).
+
+ For large vectors, this operation can be slow (\l{linear time}),
+ because it requires moving all the items in the vector by one
+ position further in memory. If you want a container class that
+ provides a fast prepend() function, use QList or QLinkedList
+ instead.
+
+ \sa append(), insert()
+*/
+
+/*! \fn void QVector::insert(int i, const T &value)
+
+ Inserts \a value at index position \a i in the vector. If \a i is
+ 0, the value is prepended to the vector. If \a i is size(), the
+ value is appended to the vector.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 9
+
+ For large vectors, this operation can be slow (\l{linear time}),
+ because it requires moving all the items at indexes \a i and
+ above by one position further in memory. If you want a container
+ class that provides a fast insert() function, use QLinkedList
+ instead.
+
+ \sa append(), prepend(), remove()
+*/
+
+/*! \fn void QVector::insert(int i, int count, const T &value)
+
+ \overload
+
+ Inserts \a count copies of \a value at index position \a i in the
+ vector.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 10
+*/
+
+/*! \fn QVector::iterator QVector::insert(iterator before, const T &value)
+
+ \overload
+
+ Inserts \a value in front of the item pointed to by the iterator
+ \a before. Returns an iterator pointing at the inserted item.
+*/
+
+/*! \fn QVector::iterator QVector::insert(iterator before, int count, const T &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
+ first of the inserted items.
+*/
+
+/*! \fn void QVector::replace(int i, const T &value)
+
+ Replaces the item at index position \a i with \a value.
+
+ \a i must be a valid index position in the vector (i.e., 0 <= \a
+ i < size()).
+
+ \sa operator[](), remove()
+*/
+
+/*! \fn void QVector::remove(int i)
+
+ \overload
+
+ Removes the element at index position \a i.
+
+ \sa insert(), replace(), fill()
+*/
+
+/*! \fn void QVector::remove(int i, int count)
+
+ \overload
+
+ Removes \a count elements from the middle of the vector, starting at
+ index position \a i.
+
+ \sa insert(), replace(), fill()
+*/
+
+/*! \fn QVector &QVector::fill(const T &value, int size = -1)
+
+ Assigns \a value to all items in the vector. If \a size is
+ different from -1 (the default), the vector is resized to size \a
+ size beforehand.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 11
+
+ \sa resize()
+*/
+
+/*! \fn int QVector::indexOf(const T &value, int from = 0) const
+
+ Returns the index position of the first occurrence of \a value in
+ the vector, searching forward from index position \a from.
+ Returns -1 if no item matched.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 12
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa lastIndexOf(), contains()
+*/
+
+/*! \fn int QVector::lastIndexOf(const T &value, int from = -1) const
+
+ Returns the index position of the last occurrence of the value \a
+ value in the vector, 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.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 13
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa indexOf()
+*/
+
+/*! \fn bool QVector::contains(const T &value) const
+
+ Returns true if the vector contains an occurrence of \a value;
+ otherwise returns false.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn bool QVector::startsWith(const T &value) const
+ \since 4.5
+
+ Returns true if this vector is not empty and its first
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), first()
+*/
+
+/*! \fn bool QVector::endsWith(const T &value) const
+ \since 4.5
+
+ Returns true if this vector is not empty and its last
+ item is equal to \a value; otherwise returns false.
+
+ \sa isEmpty(), last()
+*/
+
+
+/*! \fn int QVector::count(const T &value) const
+
+ Returns the number of occurrences of \a value in the vector.
+
+ This function requires the value type to have an implementation of
+ \c operator==().
+
+ \sa contains(), indexOf()
+*/
+
+/*! \fn int QVector::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn QVector::iterator QVector::begin()
+
+ Returns an \l{STL-style iterator} pointing to the first item in
+ the vector.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QVector::const_iterator QVector::begin() const
+
+ \overload
+*/
+
+/*! \fn QVector::const_iterator QVector::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first item
+ in the vector.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QVector::iterator QVector::end()
+
+ Returns an \l{STL-style iterator} pointing to the imaginary item
+ after the last item in the vector.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QVector::const_iterator QVector::end() const
+
+ \overload
+*/
+
+/*! \fn QVector::const_iterator QVector::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the vector.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QVector::iterator QVector::erase(iterator pos)
+
+ Removes the item pointed to by the iterator \a pos from the
+ vector, and returns an iterator to the next item in the vector
+ (which may be end()).
+
+ \sa insert(), remove()
+*/
+
+/*! \fn QVector::iterator QVector::erase(iterator begin, 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.
+*/
+
+/*! \fn T& QVector::first()
+
+ Returns a reference to the first item in the vector. This
+ function assumes that the vector isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn const T& QVector::first() const
+
+ \overload
+*/
+
+/*! \fn T& QVector::last()
+
+ Returns a reference to the last item in the vector. This function
+ assumes that the vector isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QVector::last() const
+
+ \overload
+*/
+
+/*! \fn T QVector::value(int i) const
+
+ Returns the value at index position \a i in the vector.
+
+ 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 T QVector::value(int i, const T &defaultValue) const
+
+ \overload
+
+ If the index \a i is out of bounds, the function returns
+ \a defaultValue.
+*/
+
+/*! \fn void QVector::push_back(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to append(\a value).
+*/
+
+/*! \fn void QVector::push_front(const T &value)
+
+ This function is provided for STL compatibility. It is equivalent
+ to prepend(\a value).
+*/
+
+/*! \fn void QVector::pop_front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to erase(begin()).
+*/
+
+/*! \fn void QVector::pop_back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to erase(end() - 1).
+*/
+
+/*! \fn T& QVector::front()
+
+ This function is provided for STL compatibility. It is equivalent
+ to first().
+*/
+
+/*! \fn QVector::const_reference QVector::front() const
+
+ \overload
+*/
+
+/*! \fn QVector::reference QVector::back()
+
+ This function is provided for STL compatibility. It is equivalent
+ to last().
+*/
+
+/*! \fn QVector::const_reference QVector::back() const
+
+ \overload
+*/
+
+/*! \fn bool QVector::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty(), returning true if the vector is empty; otherwise
+ returns false.
+*/
+
+/*! \fn QVector<T> &QVector::operator+=(const QVector<T> &other)
+
+ Appends the items of the \a other vector to this vector and
+ returns a reference to this vector.
+
+ \sa operator+(), append()
+*/
+
+/*! \fn void QVector::operator+=(const T &value)
+
+ \overload
+
+ Appends \a value to the vector.
+
+ \sa append(), operator<<()
+*/
+
+/*! \fn QVector<T> QVector::operator+(const QVector<T> &other) const
+
+ Returns a vector that contains all the items in this vector
+ followed by all the items in the \a other vector.
+
+ \sa operator+=()
+*/
+
+/*! \fn QVector<T> &QVector::operator<<(const T &value)
+
+ Appends \a value to the vector and returns a reference to this
+ vector.
+
+ \sa append(), operator+=()
+*/
+
+/*! \fn QVector<T> &QVector::operator<<(const QVector<T> &other)
+
+ Appends \a other to the vector and returns a reference to the
+ vector.
+*/
+
+/*! \typedef QVector::iterator
+
+ The QVector::iterator typedef provides an STL-style non-const
+ iterator for QVector and QStack.
+
+ QVector 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).
+
+ \sa QVector::begin(), QVector::end(), QVector::const_iterator, QMutableVectorIterator
+*/
+
+/*! \typedef QVector::const_iterator
+
+ The QVector::const_iterator typedef provides an STL-style const
+ iterator for QVector and QStack.
+
+ QVector 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).
+
+ \sa QVector::constBegin(), QVector::constEnd(), QVector::iterator, QVectorIterator
+*/
+
+/*! \typedef QVector::Iterator
+
+ Qt-style synonym for QVector::iterator.
+*/
+
+/*! \typedef QVector::ConstIterator
+
+ Qt-style synonym for QVector::const_iterator.
+*/
+
+/*! \typedef QVector::const_pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::const_reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::pointer
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*! \typedef QVector::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \fn QList<T> QVector<T>::toList() const
+
+ Returns a QList object with the data contained in this QVector.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 14
+
+ \sa fromList(), QList::fromVector()
+*/
+
+/*! \fn QVector<T> QVector<T>::fromList(const QList<T> &list)
+
+ Returns a QVector object with the data contained in \a list.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 15
+
+ \sa toList(), QList::toVector()
+*/
+
+/*! \fn QVector<T> QVector<T>::fromStdVector(const std::vector<T> &vector)
+
+ Returns a QVector object with the data contained in \a vector. The
+ order of the elements in the QVector is the same as in \a vector.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 16
+
+ \sa toStdVector(), QList::fromStdList()
+*/
+
+/*! \fn std::vector<T> QVector<T>::toStdVector() const
+
+ Returns a std::vector object with the data contained in this QVector.
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 17
+
+ \sa fromStdVector(), QList::toStdList()
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QVector<T> &vector)
+ \relates QVector
+
+ Writes the vector \a vector to stream \a out.
+
+ This function requires the value type to implement \c operator<<().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QVector<T> &vector)
+ \relates QVector
+
+ Reads a vector from stream \a in into \a vector.
+
+ This function requires the value type to implement \c operator>>().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
new file mode 100644
index 0000000000..9418642752
--- /dev/null
+++ b/src/corelib/tools/qvector.h
@@ -0,0 +1,829 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR_H
+#define QVECTOR_H
+
+#include <QtCore/qiterator.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qalgorithms.h>
+#include <QtCore/qlist.h>
+
+#ifndef QT_NO_STL
+#include <iterator>
+#include <vector>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+#include <initializer_list>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QVectorData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int size;
+#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
+ // workaround for bug in gcc 3.4.2
+ uint sharable;
+ uint capacity;
+ uint reserved;
+#else
+ uint sharable : 1;
+ uint capacity : 1;
+ uint reserved : 30;
+#endif
+
+ static QVectorData shared_null;
+ // ### Qt 5: rename to 'allocate()'. The current name causes problems for
+ // some debugges when the QVector is member of a class within an unnamed namespace.
+ // ### Qt 5: can be removed completely. (Ralf)
+ static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
+ static QVectorData *allocate(int size, int alignment);
+ static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
+ static void free(QVectorData *data, int alignment);
+ static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
+};
+
+template <typename T>
+struct QVectorTypedData : private QVectorData
+{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
+ // as this would break strict aliasing rules. (in the case of shared_null)
+ T array[1];
+
+ static inline void free(QVectorTypedData<T> *x, int alignment) { QVectorData::free(static_cast<QVectorData *>(x), alignment); }
+};
+
+class QRegion;
+
+template <typename T>
+class QVector
+{
+ typedef QVectorTypedData<T> Data;
+ union {
+ QVectorData *d;
+#if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
+ QVectorTypedData<T> *p;
+#else
+ Data *p;
+#endif
+ };
+
+public:
+ // ### Qt 5: Consider making QVector non-shared to get at least one
+ // "really fast" container. See tests/benchmarks/corelib/tools/qvector/
+ inline QVector() : d(&QVectorData::shared_null) { d->ref.ref(); }
+ explicit QVector(int size);
+ QVector(int size, const T &t);
+ inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+ inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
+ QVector<T> &operator=(const QVector<T> &v);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QVector<T> operator=(QVector<T> &&other)
+ { qSwap(p, other.p); return *this; }
+#endif
+ inline void swap(QVector<T> &other) { qSwap(d, other.d); }
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QVector(std::initializer_list<T> args);
+#endif
+ bool operator==(const QVector<T> &v) const;
+ inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
+
+ inline int size() const { return d->size; }
+
+ inline bool isEmpty() const { return d->size == 0; }
+
+ void resize(int size);
+
+ inline int capacity() const { return d->alloc; }
+ void reserve(int size);
+ inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+ inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
+
+ inline T *data() { detach(); return p->array; }
+ inline const T *data() const { return p->array; }
+ inline const T *constData() const { return p->array; }
+ void clear();
+
+ const T &at(int i) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+ void append(const T &t);
+ void prepend(const T &t);
+ void insert(int i, const T &t);
+ void insert(int i, int n, const T &t);
+ void replace(int i, const T &t);
+ void remove(int i);
+ void remove(int i, int n);
+
+ QVector<T> &fill(const T &t, int size = -1);
+
+ int indexOf(const T &t, int from = 0) const;
+ int lastIndexOf(const T &t, int from = -1) const;
+ bool contains(const T &t) const;
+ int count(const T &t) const;
+
+#ifdef QT_STRICT_ITERATORS
+ class iterator {
+ public:
+ T *i;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ inline iterator() : i(0) {}
+ inline iterator(T *n) : i(n) {}
+ inline iterator(const iterator &o): i(o.i){}
+ inline T &operator*() const { return *i; }
+ inline T *operator->() const { return i; }
+ inline T &operator[](int j) const { return *(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 iterator &operator++() { ++i; return *this; }
+ inline iterator operator++(int) { T *n = i; ++i; return n; }
+ inline iterator &operator--() { i--; return *this; }
+ inline iterator operator--(int) { T *n = i; 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(i+j); }
+ inline iterator operator-(int j) const { return iterator(i-j); }
+ inline int operator-(iterator j) const { return i - j.i; }
+ };
+ friend class iterator;
+
+ class const_iterator {
+ public:
+ T *i;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline const_iterator() : i(0) {}
+ inline const_iterator(T *n) : i(n) {}
+ inline const_iterator(const const_iterator &o): i(o.i) {}
+ inline explicit const_iterator(const iterator &o): i(o.i) {}
+ inline const T &operator*() const { return *i; }
+ inline const T *operator->() const { return i; }
+ inline const T &operator[](int j) const { return *(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) { T *n = i; ++i; return n; }
+ inline const_iterator &operator--() { i--; return *this; }
+ inline const_iterator operator--(int) { T *n = i; 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(i+j); }
+ inline const_iterator operator-(int j) const { return const_iterator(i-j); }
+ inline int operator-(const_iterator j) const { return i - j.i; }
+ };
+ friend class const_iterator;
+#else
+ // STL-style
+ typedef T* iterator;
+ typedef const T* const_iterator;
+#endif
+ inline iterator begin() { detach(); return p->array; }
+ inline const_iterator begin() const { return p->array; }
+ inline const_iterator constBegin() const { return p->array; }
+ inline iterator end() { detach(); return p->array + d->size; }
+ inline const_iterator end() const { return p->array + d->size; }
+ inline const_iterator constEnd() const { return p->array + d->size; }
+ iterator insert(iterator before, int n, const T &x);
+ inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
+ iterator erase(iterator begin, iterator end);
+ inline iterator erase(iterator pos) { return erase(pos, pos+1); }
+
+ // more Qt
+ inline int count() const { return d->size; }
+ inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const { 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 bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
+ inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+ QVector<T> mid(int pos, int length = -1) const;
+
+ T value(int i) const;
+ T value(int i, const T &defaultValue) const;
+
+ // STL compatibility
+ 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 iterator Iterator;
+ typedef const_iterator ConstIterator;
+ typedef int size_type;
+ inline void push_back(const T &t) { append(t); }
+ inline void push_front(const T &t) { prepend(t); }
+ void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
+ void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
+ inline bool empty() const
+ { return d->size == 0; }
+ inline T& front() { return first(); }
+ inline const_reference front() const { return first(); }
+ inline reference back() { return last(); }
+ inline const_reference back() const { return last(); }
+
+ // comfort
+ QVector<T> &operator+=(const QVector<T> &l);
+ inline QVector<T> operator+(const QVector<T> &l) const
+ { QVector n = *this; n += l; return n; }
+ inline QVector<T> &operator+=(const T &t)
+ { append(t); return *this; }
+ inline QVector<T> &operator<< (const T &t)
+ { append(t); return *this; }
+ inline QVector<T> &operator<<(const QVector<T> &l)
+ { *this += l; return *this; }
+
+ QList<T> toList() const;
+
+ static QVector<T> fromList(const QList<T> &list);
+
+#ifndef QT_NO_STL
+ static inline QVector<T> fromStdVector(const std::vector<T> &vector)
+ { QVector<T> tmp; tmp.reserve(int(vector.size())); qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
+ inline std::vector<T> toStdVector() const
+ { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+#endif
+private:
+ friend class QRegion; // Optimization for QRegion::rects()
+
+ void detach_helper();
+ QVectorData *malloc(int alloc);
+ void realloc(int size, int alloc);
+ void free(Data *d);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+ inline int alignOfTypedData() const
+ {
+#ifdef Q_ALIGNOF
+ return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+#else
+ return 0;
+#endif
+ }
+};
+
+template <typename T>
+void QVector<T>::detach_helper()
+{ realloc(d->size, d->alloc); }
+template <typename T>
+void QVector<T>::reserve(int asize)
+{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
+template <typename T>
+void QVector<T>::resize(int asize)
+{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
+ QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
+ : d->alloc); }
+template <typename T>
+inline void QVector<T>::clear()
+{ *this = QVector<T>(); }
+template <typename T>
+inline const T &QVector<T>::at(int i) const
+{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
+ return p->array[i]; }
+template <typename T>
+inline const T &QVector<T>::operator[](int i) const
+{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
+ return p->array[i]; }
+template <typename T>
+inline T &QVector<T>::operator[](int i)
+{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
+ return data()[i]; }
+template <typename T>
+inline void QVector<T>::insert(int i, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
+ insert(begin() + i, 1, t); }
+template <typename T>
+inline void QVector<T>::insert(int i, int n, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
+ insert(begin() + i, n, t); }
+template <typename T>
+inline void QVector<T>::remove(int i, int n)
+{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range");
+ erase(begin() + i, begin() + i + n); }
+template <typename T>
+inline void QVector<T>::remove(int i)
+{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range");
+ erase(begin() + i, begin() + i + 1); }
+template <typename T>
+inline void QVector<T>::prepend(const T &t)
+{ insert(begin(), 1, t); }
+
+template <typename T>
+inline void QVector<T>::replace(int i, const T &t)
+{
+ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
+ const T copy(t);
+ data()[i] = copy;
+}
+
+template <typename T>
+QVector<T> &QVector<T>::operator=(const QVector<T> &v)
+{
+ QVectorData *o = v.d;
+ o->ref.ref();
+ if (!d->ref.deref())
+ free(p);
+ d = o;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+template <typename T>
+inline QVectorData *QVector<T>::malloc(int aalloc)
+{
+ QVectorData *vectordata = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
+ Q_CHECK_PTR(vectordata);
+ return vectordata;
+}
+
+template <typename T>
+QVector<T>::QVector(int asize)
+{
+ d = malloc(asize);
+ d->ref = 1;
+ d->alloc = d->size = asize;
+ d->sharable = true;
+ d->capacity = false;
+ if (QTypeInfo<T>::isComplex) {
+ T* b = p->array;
+ T* i = p->array + d->size;
+ while (i != b)
+ new (--i) T;
+ } else {
+ qMemSet(p->array, 0, asize * sizeof(T));
+ }
+}
+
+template <typename T>
+QVector<T>::QVector(int asize, const T &t)
+{
+ d = malloc(asize);
+ d->ref = 1;
+ d->alloc = d->size = asize;
+ d->sharable = true;
+ d->capacity = false;
+ T* i = p->array + d->size;
+ while (i != p->array)
+ new (--i) T(t);
+}
+
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+template <typename T>
+QVector<T>::QVector(std::initializer_list<T> args)
+{
+ d = malloc(int(args.size()));
+ d->ref = 1;
+ d->alloc = d->size = int(args.size());
+ d->sharable = true;
+ d->capacity = false;
+ T* i = p->array + d->size;
+ auto it = args.end();
+ while (i != p->array)
+ new (--i) T(*(--it));
+}
+#endif
+
+template <typename T>
+void QVector<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ T* b = x->array;
+ union { QVectorData *d; Data *p; } u;
+ u.p = x;
+ T* i = b + u.d->size;
+ while (i-- != b)
+ i->~T();
+ }
+ x->free(x, alignOfTypedData());
+}
+
+template <typename T>
+void QVector<T>::realloc(int asize, int aalloc)
+{
+ Q_ASSERT(asize <= aalloc);
+ T *pOld;
+ T *pNew;
+ union { QVectorData *d; Data *p; } x;
+ x.d = d;
+
+ if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
+ // call the destructor on all objects that need to be
+ // destroyed when shrinking
+ pOld = p->array + d->size;
+ pNew = p->array + asize;
+ while (asize < d->size) {
+ (--pOld)->~T();
+ d->size--;
+ }
+ }
+
+ if (aalloc != d->alloc || d->ref != 1) {
+ // (re)allocate memory
+ if (QTypeInfo<T>::isStatic) {
+ x.d = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
+ x.d->size = 0;
+ } else if (d->ref != 1) {
+ x.d = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
+ if (QTypeInfo<T>::isComplex) {
+ x.d->size = 0;
+ } else {
+ ::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, d->alloc) - 1) * sizeof(T));
+ x.d->size = d->size;
+ }
+ } else {
+ QT_TRY {
+ QVectorData *mem = QVectorData::reallocate(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T),
+ sizeOfTypedData() + (d->alloc - 1) * sizeof(T), alignOfTypedData());
+ Q_CHECK_PTR(mem);
+ x.d = d = mem;
+ x.d->size = d->size;
+ } QT_CATCH (const std::bad_alloc &) {
+ if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
+ QT_RETHROW;
+ }
+ }
+ x.d->ref = 1;
+ x.d->alloc = aalloc;
+ x.d->sharable = true;
+ x.d->capacity = d->capacity;
+ x.d->reserved = 0;
+ }
+
+ if (QTypeInfo<T>::isComplex) {
+ QT_TRY {
+ pOld = p->array + x.d->size;
+ pNew = x.p->array + x.d->size;
+ // copy objects from the old array into the new array
+ const int toMove = qMin(asize, d->size);
+ while (x.d->size < toMove) {
+ new (pNew++) T(*pOld++);
+ x.d->size++;
+ }
+ // construct all new objects when growing
+ while (x.d->size < asize) {
+ new (pNew++) T;
+ x.d->size++;
+ }
+ } QT_CATCH (...) {
+ free(x.p);
+ QT_RETHROW;
+ }
+
+ } else if (asize > x.d->size) {
+ // initialize newly allocated memory to 0
+ qMemSet(x.p->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
+ }
+ x.d->size = asize;
+
+ if (d != x.d) {
+ if (!d->ref.deref())
+ free(p);
+ d = x.d;
+ }
+}
+
+template<typename T>
+Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
+{
+ if (i < 0 || i >= d->size) {
+ return T();
+ }
+ return p->array[i];
+}
+template<typename T>
+Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
+{
+ return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
+}
+
+template <typename T>
+void QVector<T>::append(const T &t)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc) {
+ const T copy(t);
+ realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
+ QTypeInfo<T>::isStatic));
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->size) T(copy);
+ else
+ p->array[d->size] = copy;
+ } else {
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->size) T(t);
+ else
+ p->array[d->size] = t;
+ }
+ ++d->size;
+}
+
+template <typename T>
+Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
+{
+ int offset = int(before - p->array);
+ if (n != 0) {
+ const T copy(t);
+ if (d->ref != 1 || d->size + n > d->alloc)
+ realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
+ QTypeInfo<T>::isStatic));
+ if (QTypeInfo<T>::isStatic) {
+ T *b = p->array + d->size;
+ T *i = p->array + d->size + n;
+ while (i != b)
+ new (--i) T;
+ i = p->array + d->size;
+ T *j = i + n;
+ b = p->array + offset;
+ while (i != b)
+ *--j = *--i;
+ i = b+n;
+ while (i != b)
+ *--i = copy;
+ } else {
+ T *b = p->array + offset;
+ T *i = b + n;
+ memmove(i, b, (d->size - offset) * sizeof(T));
+ while (i != b)
+ new (--i) T(copy);
+ }
+ d->size += n;
+ }
+ return p->array + offset;
+}
+
+template <typename T>
+Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
+{
+ int f = int(abegin - p->array);
+ int l = int(aend - p->array);
+ int n = l - f;
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ qCopy(p->array+l, p->array+d->size, p->array+f);
+ T *i = p->array+d->size;
+ T* b = p->array+d->size-n;
+ while (i != b) {
+ --i;
+ i->~T();
+ }
+ } else {
+ memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
+ }
+ d->size -= n;
+ return p->array + f;
+}
+
+template <typename T>
+bool QVector<T>::operator==(const QVector<T> &v) const
+{
+ if (d->size != v.d->size)
+ return false;
+ if (d == v.d)
+ return true;
+ T* b = p->array;
+ T* i = b + d->size;
+ T* j = v.p->array + d->size;
+ while (i != b)
+ if (!(*--i == *--j))
+ return false;
+ return true;
+}
+
+template <typename T>
+QVector<T> &QVector<T>::fill(const T &from, int asize)
+{
+ const T copy(from);
+ resize(asize < 0 ? d->size : asize);
+ if (d->size) {
+ T *i = p->array + d->size;
+ T *b = p->array;
+ while (i != b)
+ *--i = copy;
+ }
+ return *this;
+}
+
+template <typename T>
+QVector<T> &QVector<T>::operator+=(const QVector &l)
+{
+ int newSize = d->size + l.d->size;
+ realloc(d->size, newSize);
+
+ T *w = p->array + newSize;
+ T *i = l.p->array + l.d->size;
+ T *b = l.p->array;
+ while (i != b) {
+ if (QTypeInfo<T>::isComplex)
+ new (--w) T(*--i);
+ else
+ *--w = *--i;
+ }
+ d->size = newSize;
+ return *this;
+}
+
+template <typename T>
+int QVector<T>::indexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from = qMax(from + d->size, 0);
+ if (from < d->size) {
+ T* n = p->array + from - 1;
+ T* e = p->array + d->size;
+ while (++n != e)
+ if (*n == t)
+ return n - p->array;
+ }
+ return -1;
+}
+
+template <typename T>
+int QVector<T>::lastIndexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from += d->size;
+ else if (from >= d->size)
+ from = d->size-1;
+ if (from >= 0) {
+ T* b = p->array;
+ T* n = p->array + from + 1;
+ while (n != b) {
+ if (*--n == t)
+ return n - b;
+ }
+ }
+ return -1;
+}
+
+template <typename T>
+bool QVector<T>::contains(const T &t) const
+{
+ T* b = p->array;
+ T* i = p->array + d->size;
+ while (i != b)
+ if (*--i == t)
+ return true;
+ return false;
+}
+
+template <typename T>
+int QVector<T>::count(const T &t) const
+{
+ int c = 0;
+ T* b = p->array;
+ T* i = p->array + d->size;
+ while (i != b)
+ if (*--i == t)
+ ++c;
+ return c;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int length) const
+{
+ if (length < 0)
+ length = size() - pos;
+ if (pos == 0 && length == size())
+ return *this;
+ if (pos + length > size())
+ length = size() - pos;
+ QVector<T> copy;
+ copy.reserve(length);
+ for (int i = pos; i < pos + length; ++i)
+ copy += at(i);
+ return copy;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
+{
+ QList<T> result;
+ result.reserve(size());
+ for (int i = 0; i < size(); ++i)
+ result.append(at(i));
+ return result;
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
+{
+ QVector<T> result(size());
+ for (int i = 0; i < size(); ++i)
+ result[i] = at(i);
+ return result;
+}
+
+template <typename T>
+QVector<T> QVector<T>::fromList(const QList<T> &list)
+{
+ return list.toVector();
+}
+
+template <typename T>
+QList<T> QList<T>::fromVector(const QVector<T> &vector)
+{
+ return vector.toList();
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector)
+
+/*
+ ### 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 QVector<QPoint> and
+ ### QVector<QPointF> respectively.
+*/
+
+#ifdef Q_CC_MSVC
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtCore/QPointF>
+#include <QtCore/QPoint>
+QT_END_INCLUDE_NAMESPACE
+
+#if defined(QT_BUILD_CORE_LIB)
+#define Q_TEMPLATE_EXTERN
+#else
+#define Q_TEMPLATE_EXTERN extern
+#endif
+Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
+Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QVECTOR_H
diff --git a/src/corelib/tools/qvsnprintf.cpp b/src/corelib/tools/qvsnprintf.cpp
new file mode 100644
index 0000000000..5794730d67
--- /dev/null
+++ b/src/corelib/tools/qvsnprintf.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qbytearray.h"
+#include "qstring.h"
+
+#include "string.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_VSNPRINTF
+
+/*!
+ \relates QByteArray
+
+ A portable \c vsnprintf() function. Will call \c ::vsnprintf(), \c
+ ::_vsnprintf(), or \c ::vsnprintf_s depending on the system, or
+ fall back to an internal version.
+
+ \a fmt is the \c printf() format string. The result is put into
+ \a str, which is a buffer of at least \a n bytes.
+
+ The caller is responsible to call \c va_end() on \a ap.
+
+ \warning Since vsnprintf() shows different behavior on certain
+ platforms, you should not rely on the return value or on the fact
+ that you will always get a 0 terminated string back.
+
+ Ideally, you should never call this function but use QString::sprintf()
+ instead.
+
+ \sa qsnprintf(), QString::sprintf()
+*/
+
+int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
+{
+ if (!str || !fmt)
+ return -1;
+
+ QString buf;
+ buf.vsprintf(fmt, ap);
+
+ QByteArray ba = buf.toLocal8Bit();
+
+ if (n > 0) {
+ size_t blen = qMin(size_t(ba.length()), size_t(n - 1));
+ memcpy(str, ba.constData(), blen);
+ str[blen] = '\0'; // make sure str is always 0 terminated
+ }
+
+ return ba.length();
+}
+
+#else
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <stdio.h>
+QT_END_INCLUDE_NAMESPACE
+
+int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
+{
+ return QT_VSNPRINTF(str, n, fmt, ap);
+}
+
+#endif
+
+/*!
+ \relates QByteArray
+
+ A portable snprintf() function, calls qvsnprintf.
+
+ \a fmt is the \c printf() format string. The result is put into
+ \a str, which is a buffer of at least \a n bytes.
+
+ \warning Call this function only when you know what you are doing
+ since it shows different behavior on certain platforms.
+ Use QString::sprintf() to format a string instead.
+
+ \sa qvsnprintf(), QString::sprintf()
+*/
+
+int qsnprintf(char *str, size_t n, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ int ret = qvsnprintf(str, n, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
new file mode 100644
index 0000000000..0c2cf1619e
--- /dev/null
+++ b/src/corelib/tools/tools.pri
@@ -0,0 +1,124 @@
+# Qt tools module
+
+HEADERS += \
+ tools/qalgorithms.h \
+ tools/qbitarray.h \
+ tools/qbytearray.h \
+ tools/qbytearraymatcher.h \
+ tools/qbytedata_p.h \
+ tools/qcache.h \
+ tools/qchar.h \
+ tools/qcontainerfwd.h \
+ tools/qcryptographichash.h \
+ tools/qdatetime.h \
+ tools/qdatetime_p.h \
+ tools/qeasingcurve.h \
+ tools/qhash.h \
+ tools/qline.h \
+ tools/qlinkedlist.h \
+ tools/qlist.h \
+ tools/qlocale.h \
+ tools/qlocale_p.h \
+ tools/qlocale_tools_p.h \
+ tools/qlocale_data_p.h \
+ tools/qmap.h \
+ tools/qmargins.h \
+ tools/qcontiguouscache.h \
+ tools/qpodlist_p.h \
+ tools/qpoint.h \
+ tools/qqueue.h \
+ tools/qrect.h \
+ tools/qregexp.h \
+ tools/qringbuffer_p.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/qsimd_p.h \
+ tools/qsize.h \
+ tools/qstack.h \
+ tools/qstring.h \
+ tools/qstringbuilder.h \
+ tools/qstringlist.h \
+ tools/qstringmatcher.h \
+ tools/qtextboundaryfinder.h \
+ tools/qtimeline.h \
+ tools/qelapsedtimer.h \
+ tools/qunicodetables_p.h \
+ tools/qvarlengtharray.h \
+ tools/qvector.h
+
+
+SOURCES += \
+ tools/qbitarray.cpp \
+ tools/qbytearray.cpp \
+ tools/qbytearraymatcher.cpp \
+ tools/qcryptographichash.cpp \
+ tools/qdatetime.cpp \
+ tools/qeasingcurve.cpp \
+ tools/qelapsedtimer.cpp \
+ tools/qhash.cpp \
+ tools/qline.cpp \
+ tools/qlinkedlist.cpp \
+ tools/qlist.cpp \
+ tools/qlocale.cpp \
+ tools/qlocale_tools.cpp \
+ tools/qpoint.cpp \
+ tools/qmap.cpp \
+ tools/qmargins.cpp \
+ tools/qcontiguouscache.cpp \
+ tools/qrect.cpp \
+ tools/qregexp.cpp \
+ tools/qshareddata.cpp \
+ tools/qsharedpointer.cpp \
+ tools/qsimd.cpp \
+ tools/qsize.cpp \
+ tools/qstring.cpp \
+ tools/qstringbuilder.cpp \
+ tools/qstringlist.cpp \
+ tools/qtextboundaryfinder.cpp \
+ tools/qtimeline.cpp \
+ tools/qvector.cpp \
+ tools/qvsnprintf.cpp
+
+!nacl:mac: {
+ SOURCES += tools/qelapsedtimer_mac.cpp
+ OBJECTIVE_SOURCES += tools/qlocale_mac.mm
+}
+else:symbian:SOURCES += tools/qelapsedtimer_symbian.cpp tools/qlocale_symbian.cpp
+else:unix:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp
+else:win32:SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp
+else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp
+else:SOURCES += tools/qelapsedtimer_generic.cpp
+
+contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri)
+else:include($$PWD/../../3rdparty/zlib_dependency.pri)
+
+contains(QT_CONFIG,icu) {
+ SOURCES += tools/qlocale_icu.cpp
+ DEFINES += QT_USE_ICU
+}
+
+DEFINES += HB_EXPORT=Q_CORE_EXPORT
+INCLUDEPATH += ../3rdparty/harfbuzz/src
+HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h
+SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-gdef.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-gsub.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-gpos.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-impl.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-open.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-stream.c \
+ ../3rdparty/harfbuzz/src/harfbuzz-shaper-all.cpp \
+ tools/qharfbuzz.cpp
+HEADERS += tools/qharfbuzz_p.h
+
+INCLUDEPATH += ../3rdparty/md5 \
+ ../3rdparty/md4
+
+# Note: libm should be present by default becaue this is C++
+!macx-icc:!vxworks:!symbian:unix:LIBS_PRIVATE += -lm
+
diff --git a/src/corelib/xml/.gitignore b/src/corelib/xml/.gitignore
new file mode 100644
index 0000000000..89f9ac04aa
--- /dev/null
+++ b/src/corelib/xml/.gitignore
@@ -0,0 +1 @@
+out/
diff --git a/src/corelib/xml/make-parser.sh b/src/corelib/xml/make-parser.sh
new file mode 100755
index 0000000000..7bfb1bceab
--- /dev/null
+++ b/src/corelib/xml/make-parser.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 2.1 requirements
+## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+me=$(dirname $0)
+mkdir -p $me/out
+(cd $me/out && ../../../../util/qlalr/qlalr --qt --no-debug --no-lines ../qxmlstream.g)
+
+for f in $me/out/*.h; do
+ n=$(basename $f)
+ cp $f $n
+done
+
+git diff .
+
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
new file mode 100644
index 0000000000..2ef03863b7
--- /dev/null
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -0,0 +1,3954 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtCore/qxmlstream.h"
+
+#if defined(QT_BUILD_XML_LIB) && defined(Q_OS_MAC64)
+// No need to define this in the 64-bit Mac libraries.
+// Since Qt 4.4 and previous weren't supported in 64-bit, there are
+// no QXmlStream* symbols to keep compatibility with
+# define QT_NO_XMLSTREAM
+#endif
+
+#ifndef QT_NO_XMLSTREAM
+
+#include "qxmlutils_p.h"
+#include <qdebug.h>
+#include <qfile.h>
+#include <stdio.h>
+#include <qtextcodec.h>
+#include <qstack.h>
+#include <qbuffer.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 = 0) \
+ { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+ static inline QString trUtf8(const char *sourceText, const char *comment = 0) \
+ { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+ static inline QString tr(const char *sourceText, const char*, int) \
+ { return QString::fromLatin1(sourceText); } \
+ static inline QString trUtf8(const char *sourceText, const char*, int) \
+ { return QString::fromLatin1(sourceText); } \
+private:
+#endif
+QT_BEGIN_NAMESPACE
+
+#include "qxmlstream_p.h"
+
+/*!
+ \enum QXmlStreamReader::TokenType
+
+ This enum specifies the type of token the reader just read.
+
+ \value NoToken The reader has not yet read anything.
+
+ \value Invalid An error has occurred, reported in error() and
+ errorString().
+
+ \value StartDocument The reader reports the XML version number in
+ documentVersion(), and the encoding as specified in the XML
+ document in documentEncoding(). If the document is declared
+ standalone, isStandaloneDocument() returns true; otherwise it
+ returns false.
+
+ \value EndDocument The reader reports the end of the document.
+
+ \value StartElement The reader reports the start of an element
+ with namespaceUri() and name(). Empty elements are also reported
+ as StartElement, followed directly by EndElement. The convenience
+ function readElementText() can be called to concatenate all
+ content until the corresponding EndElement. Attributes are
+ reported in attributes(), namespace declarations in
+ namespaceDeclarations().
+
+ \value EndElement The reader reports the end of an element with
+ namespaceUri() and name().
+
+ \value Characters The reader reports characters in text(). If the
+ characters are all white-space, isWhitespace() returns true. If
+ the characters stem from a CDATA section, isCDATA() returns true.
+
+ \value Comment The reader reports a comment in text().
+
+ \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().
+
+ \value EntityReference The reader reports an entity reference that
+ could not be resolved. The name of the reference is reported in
+ name(), the replacement text in text().
+
+ \value ProcessingInstruction The reader reports a processing
+ instruction in processingInstructionTarget() and
+ processingInstructionData().
+*/
+
+/*!
+ \enum QXmlStreamReader::ReadElementTextBehaviour
+
+ This enum specifies the different behaviours of readElementText().
+
+ \value ErrorOnUnexpectedElement Raise an UnexpectedElementError and return
+ what was read so far when a child element is encountered.
+
+ \value IncludeChildElements Recursively include the text from child elements.
+
+ \value SkipChildElements Skip child elements.
+
+ \since 4.6
+*/
+
+/*!
+ \enum QXmlStreamReader::Error
+
+ This enum specifies different error cases
+
+ \value NoError No error has occurred.
+
+ \value CustomError A custom error has been raised with
+ raiseError()
+
+ \value NotWellFormedError The parser internally raised an error
+ due to the read XML not being well-formed.
+
+ \value PrematureEndOfDocumentError The input stream ended before a
+ well-formed XML document was parsed. Recovery from this error is
+ possible if more XML arrives in the stream, either by calling
+ 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.
+
+*/
+
+/*!
+ \class QXmlStreamEntityResolver
+ \reentrant
+ \since 4.4
+
+ \brief The QXmlStreamEntityResolver class provides an entity
+ resolver for a QXmlStreamReader.
+
+ \ingroup xml-tools
+ */
+
+/*!
+ Destroys the entity resolver.
+ */
+QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
+{
+}
+
+/*! \internal
+
+This function is a stub for later functionality.
+*/
+QString QXmlStreamEntityResolver::resolveEntity(const QString& /*publicId*/, const QString& /*systemId*/)
+{
+ return QString();
+}
+
+
+/*!
+ Resolves the undeclared entity \a name and returns its replacement
+ text. If the entity is also unknown to the entity resolver, it
+ returns an empty string.
+
+ The default implementation always returns an empty string.
+*/
+
+QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*/)
+{
+ return QString();
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
+{
+ if (entityResolver)
+ return entityResolver->resolveUndeclaredEntity(name);
+ return QString();
+}
+
+
+
+/*!
+ \since 4.4
+
+ Makes \a resolver the new entityResolver().
+
+ The stream reader does \e not take ownership of the resolver. It's
+ the callers responsibility to ensure that the resolver is valid
+ during the entire life-time of the stream reader object, or until
+ another resolver or 0 is set.
+
+ \sa entityResolver()
+ */
+void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
+{
+ Q_D(QXmlStreamReader);
+ d->entityResolver = resolver;
+}
+
+/*!
+ \since 4.4
+
+ Returns the entity resolver, or 0 if there is no entity resolver.
+
+ \sa setEntityResolver()
+ */
+QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->entityResolver;
+}
+
+
+
+/*!
+ \class QXmlStreamReader
+ \reentrant
+ \since 4.3
+
+ \brief The QXmlStreamReader class provides a fast parser for reading
+ well-formed XML via a simple streaming API.
+
+
+ \ingroup xml-tools
+
+ QXmlStreamReader is a faster and more convenient replacement for
+ Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
+ also be a faster and more convenient alternative for use in
+ applications that would otherwise use a DOM tree (see QDomDocument).
+ QXmlStreamReader reads data either from a QIODevice (see
+ setDevice()), or from a raw QByteArray (see addData()).
+
+ Qt provides QXmlStreamWriter for writing XML.
+
+ The basic concept of a stream reader is to report an XML document as
+ a stream of tokens, similar to SAX. The main difference between
+ QXmlStreamReader and SAX is \e how these XML tokens are reported.
+ With SAX, the application must provide handlers (callback functions)
+ that receive so-called XML \e events from the parser at the parser's
+ convenience. With QXmlStreamReader, the application code itself
+ drives the loop and pulls \e tokens from the reader, one after
+ another, as it needs them. This is done by calling readNext(), where
+ the reader reads from the input stream until it completes the next
+ token, at which point it returns the tokenType(). A set of
+ convenient functions including isStartElement() and text() can then
+ be used to examine the token to obtain information about what has
+ been read. The big advantage of this \e pulling approach is the
+ possibility to build recursive descent parsers with it, meaning you
+ can split your XML parsing code easily into different methods or
+ classes. This makes it easy to keep track of the application's own
+ state when parsing XML.
+
+ A typical loop with QXmlStreamReader looks like this:
+
+ \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 0
+
+
+ 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.
+
+ If an error occurs while parsing, atEnd() and hasError() return
+ true, and error() returns the error that occurred. The functions
+ errorString(), lineNumber(), columnNumber(), and characterOffset()
+ are for constructing an appropriate error or warning message. To
+ simplify application code, QXmlStreamReader contains a raiseError()
+ mechanism that lets you raise custom errors that trigger the same
+ error handling described.
+
+ The \l{QXmlStream Bookmarks Example} illustrates how to use the
+ recursive descent technique to read an XML bookmark file (XBEL) with
+ a stream reader.
+
+ \section1 Namespaces
+
+ QXmlStream understands and resolves XML namespaces. E.g. in case of
+ a StartElement, namespaceUri() returns the namespace the element is
+ in, and name() returns the element's \e local name. The combination
+ of namespaceUri and name uniquely identifies an element. If a
+ namespace prefix was not declared in the XML entities parsed by the
+ reader, the namespaceUri is empty.
+
+ If you parse XML data that does not utilize namespaces according to
+ the XML specification or doesn't use namespaces at all, you can use
+ the element's qualifiedName() instead. A qualified name is the
+ element's prefix() followed by colon followed by the element's local
+ name() - exactly like the element appears in the raw XML data. Since
+ the mapping namespaceUri to prefix is neither unique nor universal,
+ qualifiedName() should be avoided for namespace-compliant XML data.
+
+ In order to parse standalone documents that do use undeclared
+ namespace prefixes, you can turn off namespace processing completely
+ with the \l namespaceProcessing property.
+
+ \section1 Incremental parsing
+
+ QXmlStreamReader is an incremental parser. It can handle the case
+ where the document can't be parsed all at once because it arrives in
+ chunks (e.g. from multiple files, or over a network connection).
+ When the reader runs out of data before the complete document has
+ been parsed, it reports a PrematureEndOfDocumentError. When more
+ data arrives, either because of a call to addData() or because more
+ data is available through the network device(), the reader recovers
+ from the PrematureEndOfDocumentError error and continues parsing the
+ new data with the next call to readNext().
+
+ For example, if your application reads data from the network using a
+ \l{QNetworkAccessManager} {network access manager}, you would issue
+ a \l{QNetworkRequest} {network request} to the manager and receive a
+ \l{QNetworkReply} {network reply} in return. Since a QNetworkReply
+ is a QIODevice, you connect its \l{QNetworkReply::readyRead()}
+ {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in
+ the code snippet shown in the discussion for QNetworkAccessManager.
+ In this slot, you read all available data with
+ \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML
+ stream reader using addData(). Then you call your custom parsing
+ function that reads the XML events from the reader.
+
+ \section1 Performance and memory consumption
+
+ QXmlStreamReader is memory-conservative by design, since it doesn't
+ store the entire XML document tree in memory, but only the current
+ 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.
+
+*/
+
+
+/*!
+ Constructs a stream reader.
+
+ \sa setDevice(), addData()
+ */
+QXmlStreamReader::QXmlStreamReader()
+ : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+}
+
+/*! Creates a new stream reader that reads from \a device.
+
+\sa setDevice(), clear()
+ */
+QXmlStreamReader::QXmlStreamReader(QIODevice *device)
+ : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+ setDevice(device);
+}
+
+/*!
+ Creates a new stream reader that reads from \a data.
+
+ \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
+ : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+ Q_D(QXmlStreamReader);
+ d->dataBuffer = data;
+}
+
+/*!
+ Creates a new stream reader that reads from \a data.
+
+ \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const QString &data)
+ : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+ Q_D(QXmlStreamReader);
+#ifdef QT_NO_TEXTCODEC
+ d->dataBuffer = data.toLatin1();
+#else
+ d->dataBuffer = d->codec->fromUnicode(data);
+ d->decoder = d->codec->makeDecoder();
+#endif
+ d->lockEncoding = true;
+
+}
+
+/*!
+ Creates a new stream reader that reads from \a data.
+
+ \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const char *data)
+ : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+ Q_D(QXmlStreamReader);
+ d->dataBuffer = QByteArray(data);
+}
+
+/*!
+ Destructs the reader.
+ */
+QXmlStreamReader::~QXmlStreamReader()
+{
+ Q_D(QXmlStreamReader);
+ if (d->deleteDevice)
+ delete d->device;
+}
+
+/*! \fn bool QXmlStreamReader::hasError() const
+ Returns \c true if an error has occurred, otherwise \c false.
+
+ \sa errorString(), error()
+ */
+
+/*!
+ Sets the current device to \a device. Setting the device resets
+ the stream to its initial state.
+
+ \sa device(), clear()
+*/
+void QXmlStreamReader::setDevice(QIODevice *device)
+{
+ Q_D(QXmlStreamReader);
+ if (d->deleteDevice) {
+ delete d->device;
+ d->deleteDevice = false;
+ }
+ d->device = device;
+ d->init();
+
+}
+
+/*!
+ Returns the current device associated with the QXmlStreamReader,
+ or 0 if no device has been assigned.
+
+ \sa setDevice()
+*/
+QIODevice *QXmlStreamReader::device() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->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 QByteArray &data)
+{
+ Q_D(QXmlStreamReader);
+ if (d->device) {
+ qWarning("QXmlStreamReader: addData() with device()");
+ return;
+ }
+ d->dataBuffer += data;
+}
+
+/*!
+ 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)
+{
+ Q_D(QXmlStreamReader);
+ d->lockEncoding = true;
+#ifdef QT_NO_TEXTCODEC
+ addData(data.toLatin1());
+#else
+ addData(d->codec->fromUnicode(data));
+#endif
+}
+
+/*!
+ 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 char *data)
+{
+ addData(QByteArray(data));
+}
+
+/*!
+ Removes any device() or data from the reader and resets its
+ internal state to the initial state.
+
+ \sa addData()
+ */
+void QXmlStreamReader::clear()
+{
+ Q_D(QXmlStreamReader);
+ d->init();
+ if (d->device) {
+ if (d->deleteDevice)
+ delete d->device;
+ d->device = 0;
+ }
+}
+
+/*!
+ Returns true if the reader has read until the end of the XML
+ document, or if an error() has occurred and reading has been
+ aborted. Otherwise, it returns false.
+
+ When atEnd() and hasError() return true and error() returns
+ PrematureEndOfDocumentError, it means the XML has been well-formed
+ so far, but a complete XML document has not been parsed. The next
+ chunk of XML can be added with addData(), if the XML is being read
+ from a QByteArray, or by waiting for more data to arrive if the
+ XML is being read from a QIODevice. Either way, atEnd() will
+ return false once more data is available.
+
+ \sa hasError(), error(), device(), QIODevice::atEnd()
+ */
+bool QXmlStreamReader::atEnd() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->atEnd
+ && ((d->type == QXmlStreamReader::Invalid && d->error == PrematureEndOfDocumentError)
+ || (d->type == QXmlStreamReader::EndDocument))) {
+ if (d->device)
+ return d->device->atEnd();
+ else
+ return !d->dataBuffer.size();
+ }
+ return (d->atEnd || d->type == QXmlStreamReader::Invalid);
+}
+
+
+/*!
+ Reads the next token and returns its type.
+
+ With one exception, once an error() is reported by readNext(),
+ further reading of the XML stream is not possible. Then atEnd()
+ returns true, hasError() returns true, and this function returns
+ QXmlStreamReader::Invalid.
+
+ The exception is when error() returns PrematureEndOfDocumentError.
+ This error is reported when the end of an otherwise well-formed
+ chunk of XML is reached, but the chunk doesn't represent a complete
+ XML document. In that case, parsing \e can be resumed by calling
+ addData() to add the next chunk of XML, when the stream is being
+ read from a QByteArray, or by waiting for more data to arrive when
+ the stream is being read from a device().
+
+ \sa tokenType(), tokenString()
+ */
+QXmlStreamReader::TokenType QXmlStreamReader::readNext()
+{
+ Q_D(QXmlStreamReader);
+ if (d->type != Invalid) {
+ if (!d->hasCheckedStartDocument)
+ if (!d->checkStartDocument())
+ return d->type; // synthetic StartDocument or error
+ d->parse();
+ if (d->atEnd && d->type != EndDocument && d->type != Invalid)
+ d->raiseError(PrematureEndOfDocumentError);
+ else if (!d->atEnd && d->type == EndDocument)
+ d->raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
+ } else if (d->error == PrematureEndOfDocumentError) {
+ // resume error
+ d->type = NoToken;
+ d->atEnd = false;
+ d->token = -1;
+ return readNext();
+ }
+ return d->type;
+}
+
+
+/*!
+ Returns the type of the current token.
+
+ The current token can also be queried with the convenience functions
+ isStartDocument(), isEndDocument(), isStartElement(),
+ isEndElement(), isCharacters(), isComment(), isDTD(),
+ isEntityReference(), and isProcessingInstruction().
+
+ \sa tokenString()
+ */
+QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->type;
+}
+
+/*!
+ Reads until the next start element within the current element. Returns true
+ when a start element was reached. When the end element was reached, or when
+ an error occurred, false is returned.
+
+ The current element is the element matching the most recently parsed start
+ element of which a matching end element has not yet been reached. When the
+ parser has reached the end element, the current element becomes the parent
+ element.
+
+ This is a convenience function for when you're only concerned with parsing
+ XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
+ this function.
+
+ \since 4.6
+ \sa readNext()
+ */
+bool QXmlStreamReader::readNextStartElement()
+{
+ while (readNext() != Invalid) {
+ if (isEndElement())
+ return false;
+ else if (isStartElement())
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Reads until the end of the current element, skipping any child nodes.
+ This function is useful for skipping unknown elements.
+
+ The current element is the element matching the most recently parsed start
+ element of which a matching end element has not yet been reached. When the
+ parser has reached the end element, the current element becomes the parent
+ element.
+
+ \since 4.6
+ */
+void QXmlStreamReader::skipCurrentElement()
+{
+ int depth = 1;
+ while (depth && readNext() != Invalid) {
+ if (isEndElement())
+ --depth;
+ else if (isStartElement())
+ ++depth;
+ }
+}
+
+/*
+ * 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
+};
+
+
+/*!
+ \property QXmlStreamReader::namespaceProcessing
+ 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
+ it does not.
+
+ By default, namespace-processing is enabled.
+*/
+
+
+void QXmlStreamReader::setNamespaceProcessing(bool enable)
+{
+ Q_D(QXmlStreamReader);
+ d->namespaceProcessing = enable;
+}
+
+bool QXmlStreamReader::namespaceProcessing() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->namespaceProcessing;
+}
+
+/*! Returns the reader's current token as string.
+
+\sa tokenType()
+*/
+QString QXmlStreamReader::tokenString() const
+{
+ Q_D(const QXmlStreamReader);
+ return QLatin1String(QXmlStreamReader_tokenTypeString_string +
+ QXmlStreamReader_tokenTypeString_indices[d->type]);
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
+{
+ tagStack.reserve(16);
+ tagStackStringStorage.reserve(32);
+ tagStackStringStorageSize = 0;
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml"));
+ namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace"));
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
+ :q_ptr(q)
+{
+ device = 0;
+ deleteDevice = false;
+#ifndef QT_NO_TEXTCODEC
+ decoder = 0;
+#endif
+ stack_size = 64;
+ sym_stack = 0;
+ state_stack = 0;
+ reallocateStack();
+ entityResolver = 0;
+ init();
+ entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<")));
+ entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">")));
+ entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&")));
+ entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'")));
+ entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\"")));
+}
+
+void QXmlStreamReaderPrivate::init()
+{
+ tos = 0;
+ scanDtd = false;
+ token = -1;
+ token_char = 0;
+ isEmptyElement = false;
+ isWhitespace = true;
+ isCDATA = false;
+ standalone = false;
+ tos = 0;
+ resumeReduction = 0;
+ state_stack[tos++] = 0;
+ state_stack[tos] = 0;
+ putStack.clear();
+ putStack.reserve(32);
+ textBuffer.clear();
+ textBuffer.reserve(256);
+ tagStack.clear();
+ tagsDone = false;
+ attributes.clear();
+ attributes.reserve(16);
+ lineNumber = lastLineStart = characterOffset = 0;
+ readBufferPos = 0;
+ nbytesread = 0;
+#ifndef QT_NO_TEXTCODEC
+ codec = QTextCodec::codecForMib(106); // utf8
+ delete decoder;
+ decoder = 0;
+#endif
+ attributeStack.clear();
+ attributeStack.reserve(16);
+ entityParser = 0;
+ hasCheckedStartDocument = false;
+ normalizeLiterals = false;
+ hasSeenTag = false;
+ atEnd = false;
+ inParseEntity = false;
+ referenceToUnparsedEntityDetected = false;
+ referenceToParameterEntityDetected = false;
+ hasExternalDtdSubset = false;
+ lockEncoding = false;
+ namespaceProcessing = true;
+ rawReadBuffer.clear();
+ dataBuffer.clear();
+ readBuffer.clear();
+
+ type = QXmlStreamReader::NoToken;
+ error = QXmlStreamReader::NoError;
+}
+
+/*
+ Well-formed requires that we verify entity values. We do this with a
+ standard parser.
+ */
+void QXmlStreamReaderPrivate::parseEntity(const QString &value)
+{
+ Q_Q(QXmlStreamReader);
+
+ if (value.isEmpty())
+ return;
+
+
+ if (!entityParser)
+ entityParser = new QXmlStreamReaderPrivate(q);
+ else
+ entityParser->init();
+ entityParser->inParseEntity = true;
+ entityParser->readBuffer = value;
+ entityParser->injectToken(PARSE_ENTITY);
+ while (!entityParser->atEnd && entityParser->type != QXmlStreamReader::Invalid)
+ entityParser->parse();
+ if (entityParser->type == QXmlStreamReader::Invalid || entityParser->tagStack.size())
+ raiseWellFormedError(QXmlStream::tr("Invalid entity value."));
+
+}
+
+inline void QXmlStreamReaderPrivate::reallocateStack()
+{
+ stack_size <<= 1;
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ Q_CHECK_PTR(sym_stack);
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ Q_CHECK_PTR(sym_stack);
+}
+
+
+QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
+{
+#ifndef QT_NO_TEXTCODEC
+ delete decoder;
+#endif
+ qFree(sym_stack);
+ qFree(state_stack);
+ delete entityParser;
+}
+
+
+inline uint QXmlStreamReaderPrivate::filterCarriageReturn()
+{
+ uint peekc = peekChar();
+ if (peekc == '\n') {
+ if (putStack.size())
+ putStack.pop();
+ else
+ ++readBufferPos;
+ return peekc;
+ }
+ if (peekc == 0) {
+ putChar('\r');
+ return 0;
+ }
+ return '\n';
+}
+
+/*!
+ \internal
+ If the end of the file is encountered, 0 is returned.
+ */
+inline uint QXmlStreamReaderPrivate::getChar()
+{
+ uint c;
+ if (putStack.size()) {
+ c = atEnd ? 0 : putStack.pop();
+ } else {
+ if (readBufferPos < readBuffer.size())
+ c = readBuffer.at(readBufferPos++).unicode();
+ else
+ c = getChar_helper();
+ }
+
+ return c;
+}
+
+inline uint QXmlStreamReaderPrivate::peekChar()
+{
+ uint c;
+ if (putStack.size()) {
+ c = putStack.top();
+ } else if (readBufferPos < readBuffer.size()) {
+ c = readBuffer.at(readBufferPos).unicode();
+ } else {
+ if ((c = getChar_helper()))
+ --readBufferPos;
+ }
+
+ return c;
+}
+
+/*!
+ \internal
+
+ Scans characters until \a str is encountered, and validates the characters
+ as according to the Char[2] production and do the line-ending normalization.
+ If any character is invalid, false is returned, otherwise true upon success.
+
+ If \a tokenToInject is not less than zero, injectToken() is called with
+ \a tokenToInject when \a str is found.
+
+ If any error occurred, false is returned, otherwise true.
+ */
+bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
+{
+ int pos = textBuffer.size();
+ int oldLineNumber = lineNumber;
+
+ while (uint c = getChar()) {
+ /* First, we do the validation & normalization. */
+ switch (c) {
+ case '\r':
+ if ((c = filterCarriageReturn()) == 0)
+ break;
+ // fall through
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ // fall through
+ case '\t':
+ textBuffer += QChar(c);
+ continue;
+ default:
+ if(c < 0x20 || (c > 0xFFFD && c < 0x10000) || c > 0x10FFFF ) {
+ raiseWellFormedError(QXmlStream::tr("Invalid XML character."));
+ lineNumber = oldLineNumber;
+ return false;
+ }
+ textBuffer += QChar(c);
+ }
+
+
+ /* Second, attempt to lookup str. */
+ if (c == uint(*str)) {
+ if (!*(str + 1)) {
+ if (tokenToInject >= 0)
+ injectToken(tokenToInject);
+ return true;
+ } else {
+ if (scanString(str + 1, tokenToInject, false))
+ return true;
+ }
+ }
+ }
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+ lineNumber = oldLineNumber;
+ return false;
+}
+
+bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
+{
+ int n = 0;
+ while (str[n]) {
+ ushort c = getChar();
+ if (c != ushort(str[n])) {
+ if (c)
+ putChar(c);
+ while (n--) {
+ putChar(ushort(str[n]));
+ }
+ return false;
+ }
+ ++n;
+ }
+ for (int i = 0; i < n; ++i)
+ textBuffer += QChar(ushort(str[i]));
+ if (requireSpace) {
+ int s = fastScanSpace();
+ if (!s || atEnd) {
+ int pos = textBuffer.size() - n - s;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+ return false;
+ }
+ }
+ if (tokenToInject >= 0)
+ injectToken(tokenToInject);
+ return true;
+}
+
+bool QXmlStreamReaderPrivate::scanAfterLangleBang()
+{
+ switch (peekChar()) {
+ case '[':
+ return scanString(spell[CDATA_START], CDATA_START, false);
+ case 'D':
+ return scanString(spell[DOCTYPE], DOCTYPE);
+ case 'A':
+ return scanString(spell[ATTLIST], ATTLIST);
+ case 'N':
+ return scanString(spell[NOTATION], NOTATION);
+ case 'E':
+ if (scanString(spell[ELEMENT], ELEMENT))
+ return true;
+ return scanString(spell[ENTITY], ENTITY);
+
+ default:
+ ;
+ };
+ return false;
+}
+
+bool QXmlStreamReaderPrivate::scanPublicOrSystem()
+{
+ switch (peekChar()) {
+ case 'S':
+ return scanString(spell[SYSTEM], SYSTEM);
+ case 'P':
+ return scanString(spell[PUBLIC], PUBLIC);
+ default:
+ ;
+ }
+ return false;
+}
+
+bool QXmlStreamReaderPrivate::scanNData()
+{
+ if (fastScanSpace()) {
+ if (scanString(spell[NDATA], NDATA))
+ return true;
+ putChar(' ');
+ }
+ return false;
+}
+
+bool QXmlStreamReaderPrivate::scanAfterDefaultDecl()
+{
+ switch (peekChar()) {
+ case 'R':
+ return scanString(spell[REQUIRED], REQUIRED, false);
+ case 'I':
+ return scanString(spell[IMPLIED], IMPLIED, false);
+ case 'F':
+ return scanString(spell[FIXED], FIXED, false);
+ default:
+ ;
+ }
+ return false;
+}
+
+bool QXmlStreamReaderPrivate::scanAttType()
+{
+ switch (peekChar()) {
+ case 'C':
+ return scanString(spell[CDATA], CDATA);
+ case 'I':
+ if (scanString(spell[ID], ID))
+ return true;
+ if (scanString(spell[IDREF], IDREF))
+ return true;
+ return scanString(spell[IDREFS], IDREFS);
+ case 'E':
+ if (scanString(spell[ENTITY], ENTITY))
+ return true;
+ return scanString(spell[ENTITIES], ENTITIES);
+ case 'N':
+ if (scanString(spell[NOTATION], NOTATION))
+ return true;
+ if (scanString(spell[NMTOKEN], NMTOKEN))
+ return true;
+ return scanString(spell[NMTOKENS], NMTOKENS);
+ default:
+ ;
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Scan strings with quotes or apostrophes surround them. For instance,
+ attributes, the version and encoding field in the XML prolog and
+ entity declarations.
+
+ If normalizeLiterals is set to true, the function also normalizes
+ whitespace. It is set to true when the first start tag is
+ encountered.
+
+ */
+inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
+{
+ int n = 0;
+ uint c;
+ while ((c = getChar())) {
+ switch (ushort(c)) {
+ case 0xfffe:
+ case 0xffff:
+ case 0:
+ /* The putChar() call is necessary so the parser re-gets
+ * the character from the input source, when raising an error. */
+ putChar(c);
+ return n;
+ case '\r':
+ if (filterCarriageReturn() == 0)
+ return n;
+ // fall through
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ // fall through
+ case ' ':
+ case '\t':
+ if (normalizeLiterals)
+ textBuffer += QLatin1Char(' ');
+ else
+ textBuffer += QChar(c);
+ ++n;
+ break;
+ case '&':
+ case '<':
+ case '\"':
+ case '\'':
+ if (!(c & 0xff0000)) {
+ putChar(c);
+ return n;
+ }
+ // fall through
+ default:
+ textBuffer += QChar(c);
+ ++n;
+ }
+ }
+ return n;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanSpace()
+{
+ int n = 0;
+ ushort c;
+ while ((c = getChar())) {
+ switch (c) {
+ case '\r':
+ if ((c = filterCarriageReturn()) == 0)
+ return n;
+ // fall through
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ // fall through
+ case ' ':
+ case '\t':
+ textBuffer += QChar(c);
+ ++n;
+ break;
+ default:
+ putChar(c);
+ return n;
+ }
+ }
+ return n;
+}
+
+/*!
+ \internal
+
+ Used for text nodes essentially. That is, characters appearing
+ inside elements.
+ */
+inline int QXmlStreamReaderPrivate::fastScanContentCharList()
+{
+ int n = 0;
+ uint c;
+ while ((c = getChar())) {
+ switch (ushort(c)) {
+ case 0xfffe:
+ case 0xffff:
+ case 0:
+ putChar(c);
+ return n;
+ case ']': {
+ isWhitespace = false;
+ int pos = textBuffer.size();
+ textBuffer += QChar(ushort(c));
+ ++n;
+ while ((c = getChar()) == ']') {
+ textBuffer += QChar(ushort(c));
+ ++n;
+ }
+ if (c == 0) {
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+ } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
+ raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
+ } else {
+ putChar(c);
+ break;
+ }
+ return n;
+ } break;
+ case '\r':
+ if ((c = filterCarriageReturn()) == 0)
+ return n;
+ // fall through
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ // fall through
+ case ' ':
+ case '\t':
+ textBuffer += QChar(ushort(c));
+ ++n;
+ break;
+ case '&':
+ case '<':
+ if (!(c & 0xff0000)) {
+ putChar(c);
+ return n;
+ }
+ // fall through
+ default:
+ if (c < 0x20) {
+ putChar(c);
+ return n;
+ }
+ isWhitespace = false;
+ textBuffer += QChar(ushort(c));
+ ++n;
+ }
+ }
+ return n;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+{
+ int n = 0;
+ ushort c;
+ while ((c = getChar())) {
+ switch (c) {
+ case '\n':
+ case ' ':
+ case '\t':
+ case '\r':
+ case '&':
+ case '#':
+ case '\'':
+ case '\"':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '=':
+ case '%':
+ case '/':
+ case ';':
+ case '?':
+ case '!':
+ case '^':
+ case '|':
+ case ',':
+ case '(':
+ case ')':
+ case '+':
+ case '*':
+ putChar(c);
+ if (prefix && *prefix == n+1) {
+ *prefix = 0;
+ putChar(':');
+ --n;
+ }
+ return n;
+ case ':':
+ if (prefix) {
+ if (*prefix == 0) {
+ *prefix = n+2;
+ } else { // only one colon allowed according to the namespace spec.
+ putChar(c);
+ return n;
+ }
+ } else {
+ putChar(c);
+ return n;
+ }
+ // fall through
+ default:
+ textBuffer += QChar(c);
+ ++n;
+ }
+ }
+
+ if (prefix)
+ *prefix = 0;
+ int pos = textBuffer.size() - n;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+ return 0;
+}
+
+enum NameChar { NameBeginning, NameNotBeginning, NotName };
+
+static const char Begi = static_cast<char>(NameBeginning);
+static const char NtBg = static_cast<char>(NameNotBeginning);
+static const char NotN = static_cast<char>(NotName);
+
+static const char nameCharTable[128] =
+{
+// 0x00
+ NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+ NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+// 0x10
+ NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+ NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+// 0x20 (0x2D is '-', 0x2E is '.')
+ NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+ NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
+// 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
+ NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
+ NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
+// 0x40 (0x41..0x5A are 'A'..'Z')
+ NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+ Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+// 0x50 (0x5F is '_')
+ Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+ Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
+// 0x60 (0x61..0x7A are 'a'..'z')
+ NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+ Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+// 0x70
+ Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+ Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
+};
+
+static inline NameChar fastDetermineNameChar(QChar ch)
+{
+ ushort uc = ch.unicode();
+ if (!(uc & ~0x7f)) // uc < 128
+ return static_cast<NameChar>(nameCharTable[uc]);
+
+ QChar::Category cat = ch.category();
+ // ### some these categories might be slightly wrong
+ if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
+ || cat == QChar::Number_Letter)
+ return NameBeginning;
+ if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
+ || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
+ return NameNotBeginning;
+ return NotName;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
+{
+ int n = 0;
+ uint c;
+ while ((c = getChar())) {
+ if (fastDetermineNameChar(c) == NotName) {
+ putChar(c);
+ return n;
+ } else {
+ ++n;
+ textBuffer += QChar(c);
+ }
+ }
+
+ int pos = textBuffer.size() - n;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+
+ return n;
+}
+
+void QXmlStreamReaderPrivate::putString(const QString &s, int from)
+{
+ putStack.reserve(s.size());
+ for (int i = s.size()-1; i >= from; --i)
+ putStack.rawPush() = s.at(i).unicode();
+}
+
+void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
+{
+ putStack.reserve(s.size());
+ for (int i = s.size()-1; i >= 0; --i)
+ putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
+}
+
+void QXmlStreamReaderPrivate::putReplacement(const QString &s)
+{
+ putStack.reserve(s.size());
+ for (int i = s.size()-1; i >= 0; --i) {
+ ushort c = s.at(i).unicode();
+ if (c == '\n' || c == '\r')
+ putStack.rawPush() = ((LETTER << 16) | c);
+ else
+ putStack.rawPush() = c;
+ }
+}
+void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
+{
+ putStack.reserve(s.size());
+ for (int i = s.size()-1; i >= 0; --i) {
+ ushort c = s.at(i).unicode();
+ if (c == '&' || c == ';')
+ putStack.rawPush() = c;
+ else if (c == '\n' || c == '\r')
+ putStack.rawPush() = ' ';
+ else
+ putStack.rawPush() = ((LETTER << 16) | c);
+ }
+}
+
+ushort QXmlStreamReaderPrivate::getChar_helper()
+{
+ const int BUFFER_SIZE = 8192;
+ characterOffset += readBufferPos;
+ readBufferPos = 0;
+ readBuffer.resize(0);
+#ifndef QT_NO_TEXTCODEC
+ if (decoder)
+#endif
+ nbytesread = 0;
+ if (device) {
+ rawReadBuffer.resize(BUFFER_SIZE);
+ int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
+ nbytesread += qMax(nbytesreadOrMinus1, 0);
+ } else {
+ if (nbytesread)
+ rawReadBuffer += dataBuffer;
+ else
+ rawReadBuffer = dataBuffer;
+ nbytesread = rawReadBuffer.size();
+ dataBuffer.clear();
+ }
+ if (!nbytesread) {
+ atEnd = true;
+ return 0;
+ }
+
+#ifndef QT_NO_TEXTCODEC
+ if (!decoder) {
+ if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
+ // one extra for the utf8 codec
+ atEnd = true;
+ return 0;
+ }
+ int mib = 106; // UTF-8
+
+ // look for byte order mark
+ uchar ch1 = rawReadBuffer.at(0);
+ uchar ch2 = rawReadBuffer.at(1);
+ uchar ch3 = rawReadBuffer.at(2);
+ uchar ch4 = rawReadBuffer.at(3);
+
+ if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
+ (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
+ mib = 1017; // UTF-32 with byte order mark
+ else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
+ mib = 1019; // UTF-32LE
+ else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
+ mib = 1018; // UTF-32BE
+ else if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
+ mib = 1015; // UTF-16 with byte order mark
+ else if (ch1 == 0x3c && ch2 == 0x00)
+ mib = 1014; // UTF-16LE
+ else if (ch1 == 0x00 && ch2 == 0x3c)
+ mib = 1013; // UTF-16BE
+ codec = QTextCodec::codecForMib(mib);
+ Q_ASSERT(codec);
+ decoder = codec->makeDecoder();
+ }
+
+ decoder->toUnicode(&readBuffer, rawReadBuffer.constData(), nbytesread);
+
+ if(lockEncoding && decoder->hasFailure()) {
+ raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+ readBuffer.clear();
+ return 0;
+ }
+#else
+ readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
+#endif // QT_NO_TEXTCODEC
+
+ readBuffer.reserve(1); // keep capacity when calling resize() next time
+
+ if (readBufferPos < readBuffer.size()) {
+ ushort c = readBuffer.at(readBufferPos++).unicode();
+ return c;
+ }
+
+ atEnd = true;
+ return 0;
+}
+
+QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
+{
+ for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
+ const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
+ if (namespaceDeclaration.prefix == prefix) {
+ return namespaceDeclaration.namespaceUri;
+ }
+ }
+
+#if 1
+ if (namespaceProcessing && !prefix.isEmpty())
+ raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
+#endif
+
+ return QStringRef();
+}
+
+/*
+ uses namespaceForPrefix and builds the attribute vector
+ */
+void QXmlStreamReaderPrivate::resolveTag()
+{
+ int n = attributeStack.size();
+
+ if (namespaceProcessing) {
+ for (int a = 0; a < dtdAttributes.size(); ++a) {
+ DtdAttribute &dtdAttribute = dtdAttributes[a];
+ if (!dtdAttribute.isNamespaceAttribute
+ || dtdAttribute.defaultValue.isNull()
+ || dtdAttribute.tagName != qualifiedName
+ || dtdAttribute.attributeQualifiedName.isNull())
+ continue;
+ int i = 0;
+ while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
+ ++i;
+ if (i != n)
+ continue;
+ if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
+ 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"))
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+ else
+ namespaceDeclaration.namespaceUri = ns;
+ } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
+ 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/")
+ || namespaceUri.isEmpty()
+ || namespacePrefix == QLatin1String("xmlns"))
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+
+ namespaceDeclaration.prefix = namespacePrefix;
+ namespaceDeclaration.namespaceUri = namespaceUri;
+ }
+ }
+ }
+
+ tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix);
+
+ attributes.resize(n);
+
+ for (int 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));
+
+ attribute.m_name = QXmlStreamStringRef(name);
+ attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
+ attribute.m_value = QXmlStreamStringRef(value);
+
+ if (!prefix.isEmpty()) {
+ QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
+ attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ }
+
+ for (int j = 0; j < i; ++j) {
+ if (attributes[j].name() == attribute.name()
+ && attributes[j].namespaceUri() == attribute.namespaceUri()
+ && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
+ raiseWellFormedError(QXmlStream::tr("Attribute redefined."));
+ }
+ }
+
+ for (int a = 0; a < dtdAttributes.size(); ++a) {
+ DtdAttribute &dtdAttribute = dtdAttributes[a];
+ if (dtdAttribute.isNamespaceAttribute
+ || dtdAttribute.defaultValue.isNull()
+ || dtdAttribute.tagName != qualifiedName
+ || dtdAttribute.attributeQualifiedName.isNull())
+ continue;
+ int i = 0;
+ while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
+ ++i;
+ if (i != n)
+ continue;
+
+
+
+ QXmlStreamAttribute attribute;
+ attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
+ attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
+ attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
+
+ if (!dtdAttribute.attributePrefix.isEmpty()) {
+ QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
+ attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ }
+ attribute.m_isDefault = true;
+ attributes.append(attribute);
+ }
+
+ attributeStack.clear();
+}
+
+void QXmlStreamReaderPrivate::resolvePublicNamespaces()
+{
+ const Tag &tag = tagStack.top();
+ int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
+ publicNamespaceDeclarations.resize(n);
+ for (int 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);
+ }
+}
+
+void QXmlStreamReaderPrivate::resolveDtd()
+{
+ publicNotationDeclarations.resize(notationDeclarations.size());
+ for (int 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);
+
+ }
+ notationDeclarations.clear();
+ publicEntityDeclarations.resize(entityDeclarations.size());
+ for (int 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);
+ }
+ entityDeclarations.clear();
+ parameterEntityHash.clear();
+}
+
+uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
+{
+ bool ok = true;
+ uint s;
+ // ### add toXShort to QStringRef?
+ if (sym(symbolIndex).c == 'x')
+ s = symString(symbolIndex, 1).toString().toUInt(&ok, 16);
+ else
+ s = symString(symbolIndex).toString().toUInt(&ok, 10);
+
+ ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
+ || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= 0x10ffff));
+
+ return ok ? s : 0;
+}
+
+
+void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
+{
+//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+
+ const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
+ uchar c = 0;
+ int i;
+ for (i = publicId.size() - 1; i >= 0; --i) {
+ if (data[i] < 256)
+ switch ((c = data[i])) {
+ case ' ': case '\n': case '\r': case '-': case '(': case ')':
+ case '+': case ',': case '.': case '/': case ':': case '=':
+ case '?': case ';': case '!': case '*': case '#': case '@':
+ case '$': case '_': case '%': case '\'': case '\"':
+ continue;
+ default:
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9'))
+ continue;
+ }
+ break;
+ }
+ if (i >= 0)
+ raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));
+}
+
+/*
+ Checks whether the document starts with an xml declaration. If it
+ does, this function returns true; otherwise it sets up everything
+ for a synthetic start document event and returns false.
+ */
+bool QXmlStreamReaderPrivate::checkStartDocument()
+{
+ hasCheckedStartDocument = true;
+
+ if (scanString(spell[XML], XML))
+ return true;
+
+ type = QXmlStreamReader::StartDocument;
+ if (atEnd) {
+ hasCheckedStartDocument = false;
+ raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+ }
+ return false;
+}
+
+void QXmlStreamReaderPrivate::startDocument()
+{
+ QString err;
+ if (documentVersion != QLatin1String("1.0")) {
+ if (documentVersion.toString().contains(QLatin1Char(' ')))
+ err = QXmlStream::tr("Invalid XML version string.");
+ else
+ err = QXmlStream::tr("Unsupported XML version.");
+ }
+ int n = attributeStack.size();
+
+ /* We use this bool to ensure that the pesudo attributes are in the
+ * proper order:
+ *
+ * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
+ bool hasStandalone = false;
+
+ for (int 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));
+
+ if (prefix.isEmpty() && key == QLatin1String("encoding")) {
+ const QString name(value.toString());
+ documentEncoding = value;
+
+ if(hasStandalone)
+ err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
+ if(!QXmlUtils::isEncName(name))
+ err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
+ else {
+#ifdef QT_NO_TEXTCODEC
+ readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
+#else
+ QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
+ if (!newCodec)
+ err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
+ else if (newCodec != codec && !lockEncoding) {
+ codec = newCodec;
+ delete decoder;
+ decoder = codec->makeDecoder();
+ decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
+ }
+#endif // QT_NO_TEXTCODEC
+ }
+ } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
+ hasStandalone = true;
+ if (value == QLatin1String("yes"))
+ standalone = true;
+ else if (value == QLatin1String("no"))
+ standalone = false;
+ else
+ err = QXmlStream::tr("Standalone accepts only yes or no.");
+ } else {
+ err = QXmlStream::tr("Invalid attribute in XML declaration.");
+ }
+ }
+
+ if (!err.isNull())
+ raiseWellFormedError(err);
+ attributeStack.clear();
+}
+
+
+void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message)
+{
+ this->error = error;
+ errorString = message;
+ if (errorString.isNull()) {
+ if (error == QXmlStreamReader::PrematureEndOfDocumentError)
+ errorString = QXmlStream::tr("Premature end of document.");
+ else if (error == QXmlStreamReader::CustomError)
+ errorString = QXmlStream::tr("Invalid document.");
+ }
+
+ type = QXmlStreamReader::Invalid;
+}
+
+void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
+{
+ raiseError(QXmlStreamReader::NotWellFormedError, message);
+}
+
+void QXmlStreamReaderPrivate::parseError()
+{
+
+ if (token == EOF_SYMBOL) {
+ raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+ return;
+ }
+ const int nmax = 4;
+ QString error_message;
+ int ers = state_stack[tos];
+ int nexpected = 0;
+ int expected[nmax];
+ if (token != ERROR)
+ for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
+ int k = t_action(ers, tk);
+ if (k <= 0)
+ continue;
+ if (spell[tk]) {
+ if (nexpected < nmax)
+ expected[nexpected++] = tk;
+ }
+ }
+
+ error_message.clear ();
+ if (nexpected && nexpected < nmax) {
+ bool first = true;
+
+ for (int s = 0; s < nexpected; ++s) {
+ if (first)
+ error_message += QXmlStream::tr ("Expected ");
+ else if (s == nexpected - 1)
+ error_message += QLatin1String (nexpected > 2 ? ", or " : " or ");
+ else
+ error_message += QLatin1String (", ");
+
+ first = false;
+ error_message += QLatin1String("\'");
+ error_message += QLatin1String (spell [expected[s]]);
+ error_message += QLatin1String("\'");
+ }
+ error_message += QXmlStream::tr(", but got \'");
+ error_message += QLatin1String(spell [token]);
+ error_message += QLatin1String("\'");
+ } else {
+ error_message += QXmlStream::tr("Unexpected \'");
+ error_message += QLatin1String(spell [token]);
+ error_message += QLatin1String("\'");
+ }
+ error_message += QLatin1Char('.');
+
+ raiseWellFormedError(error_message);
+}
+
+void QXmlStreamReaderPrivate::resume(int rule) {
+ resumeReduction = rule;
+ if (error == QXmlStreamReader::NoError)
+ raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+}
+
+/*! Returns the current line number, starting with 1.
+
+\sa columnNumber(), characterOffset()
+ */
+qint64 QXmlStreamReader::lineNumber() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->lineNumber + 1; // in public we start with 1
+}
+
+/*! Returns the current column number, starting with 0.
+
+\sa lineNumber(), characterOffset()
+ */
+qint64 QXmlStreamReader::columnNumber() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->characterOffset - d->lastLineStart + d->readBufferPos;
+}
+
+/*! Returns the current character offset, starting with 0.
+
+\sa lineNumber(), columnNumber()
+*/
+qint64 QXmlStreamReader::characterOffset() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->characterOffset + d->readBufferPos;
+}
+
+
+/*! Returns the text of \l Characters, \l Comment, \l DTD, or
+ EntityReference.
+ */
+QStringRef QXmlStreamReader::text() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->text;
+}
+
+
+/*! If the state() is \l DTD, this function returns the DTD's
+ notation declarations. Otherwise an empty vector is returned.
+
+ The QXmlStreamNotationDeclarations class is defined to be a QVector
+ of QXmlStreamNotationDeclaration.
+ */
+QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->notationDeclarations.size())
+ const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
+ return d->publicNotationDeclarations;
+}
+
+
+/*! If the state() is \l DTD, this function returns the DTD's
+ unparsed (external) entity declarations. Otherwise an empty vector is returned.
+
+ The QXmlStreamEntityDeclarations class is defined to be a QVector
+ of QXmlStreamEntityDeclaration.
+ */
+QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->entityDeclarations.size())
+ const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
+ return d->publicEntityDeclarations;
+}
+
+/*!
+ \since 4.4
+
+ If the state() is \l DTD, this function returns the DTD's
+ name. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdName() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::DTD)
+ return d->dtdName;
+ return QStringRef();
+}
+
+/*!
+ \since 4.4
+
+ If the state() is \l DTD, this function returns the DTD's
+ public identifier. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdPublicId() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::DTD)
+ return d->dtdPublicId;
+ return QStringRef();
+}
+
+/*!
+ \since 4.4
+
+ If the state() is \l DTD, this function returns the DTD's
+ system identifier. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdSystemId() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::DTD)
+ return d->dtdSystemId;
+ return QStringRef();
+}
+
+/*! If the state() is \l StartElement, this function returns the
+ element's namespace declarations. Otherwise an empty vector is
+ returned.
+
+ The QXmlStreamNamespaceDeclaration class is defined to be a QVector
+ of QXmlStreamNamespaceDeclaration.
+
+ \sa addExtraNamespaceDeclaration(), addExtraNamespaceDeclarations()
+ */
+QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement)
+ const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces();
+ return d->publicNamespaceDeclarations;
+}
+
+
+/*!
+ \since 4.4
+
+ Adds an \a extraNamespaceDeclaration. The declaration will be
+ valid for children of the current element, or - should the function
+ be called before any elements are read - for the entire XML
+ document.
+
+ \sa namespaceDeclarations(), addExtraNamespaceDeclarations(), setNamespaceProcessing()
+ */
+void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
+{
+ Q_D(QXmlStreamReader);
+ QXmlStreamReaderPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
+ namespaceDeclaration.prefix = d->addToStringStorage(extraNamespaceDeclaration.prefix());
+ namespaceDeclaration.namespaceUri = d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
+}
+
+/*!
+ \since 4.4
+
+ Adds a vector of declarations specified by \a extraNamespaceDeclarations.
+
+ \sa namespaceDeclarations(), addExtraNamespaceDeclaration()
+ */
+void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
+{
+ for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
+ addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
+}
+
+
+/*! Convenience function to be called in case a StartElement was
+ read. Reads until the corresponding EndElement and returns all text
+ in-between. In case of no error, the current token (see tokenType())
+ after having called this function is EndElement.
+
+ The function concatenates text() when it reads either \l Characters
+ or EntityReference tokens, but skips ProcessingInstruction and \l
+ Comment. If the current token is not StartElement, an empty string is
+ returned.
+
+ The \a behaviour defines what happens in case anything else is
+ read before reaching EndElement. The function can include the text from
+ child elements (useful for example for HTML), ignore child elements, or
+ raise an UnexpectedElementError and return what was read so far.
+
+ \since 4.6
+ */
+QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
+{
+ Q_D(QXmlStreamReader);
+ if (isStartElement()) {
+ QString result;
+ forever {
+ switch (readNext()) {
+ case Characters:
+ case EntityReference:
+ result.insert(result.size(), d->text.unicode(), d->text.size());
+ break;
+ case EndElement:
+ return result;
+ case ProcessingInstruction:
+ case Comment:
+ break;
+ case StartElement:
+ if (behaviour == SkipChildElements) {
+ skipCurrentElement();
+ break;
+ } else if (behaviour == IncludeChildElements) {
+ result += readElementText(behaviour);
+ break;
+ }
+ // Fall through (for ErrorOnUnexpectedElement)
+ default:
+ if (d->error || behaviour == ErrorOnUnexpectedElement) {
+ if (!d->error)
+ d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data."));
+ return result;
+ }
+ }
+ }
+ }
+ return QString();
+}
+
+/*!
+ \overload readElementText()
+
+ Calling this function is equivalent to calling readElementText(ErrorOnUnexpectedElement).
+ */
+QString QXmlStreamReader::readElementText()
+{
+ return readElementText(ErrorOnUnexpectedElement);
+}
+
+/*! Raises a custom error with an optional error \a message.
+
+ \sa error(), errorString()
+ */
+void QXmlStreamReader::raiseError(const QString& message)
+{
+ Q_D(QXmlStreamReader);
+ d->raiseError(CustomError, message);
+}
+
+/*!
+ Returns the error message that was set with raiseError().
+
+ \sa error(), lineNumber(), columnNumber(), characterOffset()
+ */
+QString QXmlStreamReader::errorString() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::Invalid)
+ return d->errorString;
+ return QString();
+}
+
+/*! Returns the type of the current error, or NoError if no error occurred.
+
+ \sa errorString(), raiseError()
+ */
+QXmlStreamReader::Error QXmlStreamReader::error() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::Invalid)
+ return d->error;
+ return NoError;
+}
+
+/*!
+ Returns the target of a ProcessingInstruction.
+ */
+QStringRef QXmlStreamReader::processingInstructionTarget() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->processingInstructionTarget;
+}
+
+/*!
+ Returns the data of a ProcessingInstruction.
+ */
+QStringRef QXmlStreamReader::processingInstructionData() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->processingInstructionData;
+}
+
+
+
+/*!
+ Returns the local name of a StartElement, EndElement, or an EntityReference.
+
+ \sa namespaceUri(), qualifiedName()
+ */
+QStringRef QXmlStreamReader::name() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->name;
+}
+
+/*!
+ Returns the namespaceUri of a StartElement or EndElement.
+
+ \sa name(), qualifiedName()
+ */
+QStringRef QXmlStreamReader::namespaceUri() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->namespaceUri;
+}
+
+/*!
+ Returns the qualified name of a StartElement or EndElement;
+
+ A qualified name is the raw name of an element in the XML data. It
+ consists of the namespace prefix, followed by colon, followed by the
+ element'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 qualifiedName(),
+ but the resolved namespaceUri() and the attribute's local name().
+
+ \sa name(), prefix(), namespaceUri()
+ */
+QStringRef QXmlStreamReader::qualifiedName() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->qualifiedName;
+}
+
+
+
+/*!
+ \since 4.4
+
+ Returns the prefix of a StartElement or EndElement.
+
+ \sa name(), qualifiedName()
+*/
+QStringRef QXmlStreamReader::prefix() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->prefix;
+}
+
+/*!
+ Returns the attributes of a StartElement.
+ */
+QXmlStreamAttributes QXmlStreamReader::attributes() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->attributes;
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+/*!
+ \class QXmlStreamAttribute
+ \since 4.3
+ \reentrant
+ \brief The QXmlStreamAttribute class represents a single XML attribute
+
+ \ingroup xml-tools
+
+ An attribute consists of an optionally empty namespaceUri(), a
+ name(), a value(), and an isDefault() attribute.
+
+ The raw XML attribute name is returned as qualifiedName().
+*/
+
+/*!
+ Creates an empty attribute.
+ */
+QXmlStreamAttribute::QXmlStreamAttribute()
+{
+ m_isDefault = false;
+}
+
+/*!
+ Destructs an attribute.
+ */
+QXmlStreamAttribute::~QXmlStreamAttribute()
+{
+}
+
+/*! 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));
+}
+
+/*!
+ Constructs an attribute with qualified name \a qualifiedName and value \a value.
+ */
+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));
+}
+
+/*! \fn QStringRef 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
+ Returns the attribute's local name.
+ */
+/*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
+ Returns the attribute's qualified name.
+
+ 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 qualifiedName(), but the resolved namespaceUri() and
+ the attribute's local name().
+ */
+/*!
+ \fn QStringRef QXmlStreamAttribute::prefix() const
+ \since 4.4
+ Returns the attribute's namespace prefix.
+
+ \sa name(), qualifiedName()
+
+*/
+
+/*! \fn QStringRef QXmlStreamAttribute::value() const
+ Returns the attribute's value.
+ */
+
+/*! \fn bool QXmlStreamAttribute::isDefault() const
+
+ Returns true if the parser added this attribute with a default
+ value following an ATTLIST declaration in the DTD; otherwise
+ returns false.
+*/
+/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
+
+ Compares this attribute with \a other and returns true if they are
+ equal; otherwise returns false.
+ */
+/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
+
+ Compares this attribute with \a other and returns true if they are
+ not equal; otherwise returns false.
+ */
+
+
+/*!
+ 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;
+}
+
+
+/*!
+ \class QXmlStreamAttributes
+ \since 4.3
+ \reentrant
+ \brief The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
+
+ Attributes are returned by a QXmlStreamReader in
+ \l{QXmlStreamReader::attributes()} {attributes()} when the reader
+ reports a \l {QXmlStreamReader::StartElement}{start element}. The
+ class can also be used with a QXmlStreamWriter as an argument to
+ \l {QXmlStreamWriter::writeAttributes()}{writeAttributes()}.
+
+ The convenience function value() loops over the vector and returns
+ an attribute value for a given namespaceUri and an attribute's
+ name.
+
+ New attributes can be added with append().
+
+ \ingroup xml-tools
+*/
+
+/*!
+ \fn void QXmlStreamAttributes::append(const QXmlStreamAttribute &attribute)
+
+ Appends the given \a attribute to the end of the vector.
+
+ \sa QVector::append()
+*/
+
+
+/*!
+ \typedef QXmlStreamNotationDeclarations
+ \relates QXmlStreamNotationDeclaration
+
+ Synonym for QVector<QXmlStreamNotationDeclaration>.
+*/
+
+
+/*!
+ \class QXmlStreamNotationDeclaration
+ \since 4.3
+ \reentrant
+ \brief The QXmlStreamNotationDeclaration class represents a DTD notation declaration.
+
+ \ingroup xml-tools
+
+ An notation declaration consists of a name(), a systemId(), and a publicId().
+*/
+
+/*!
+ Creates an empty notation declaration.
+*/
+QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
+{
+}
+/*!
+ 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()
+{
+}
+
+/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
+
+Returns the notation name.
+*/
+/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
+
+Returns the system identifier.
+*/
+/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
+
+Returns the public identifier.
+*/
+
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
+
+ Compares this notation declaration with \a other and returns true
+ if they are equal; otherwise returns false.
+ */
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
+
+ Compares this notation declaration with \a other and returns true
+ if they are not equal; otherwise returns false.
+ */
+
+/*!
+ \typedef QXmlStreamNamespaceDeclarations
+ \relates QXmlStreamNamespaceDeclaration
+
+ Synonym for QVector<QXmlStreamNamespaceDeclaration>.
+*/
+
+/*!
+ \class QXmlStreamNamespaceDeclaration
+ \since 4.3
+ \reentrant
+ \brief The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
+
+ \ingroup xml-tools
+
+ An namespace declaration consists of a prefix() and a namespaceUri().
+*/
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
+
+ Compares this namespace declaration with \a other and returns true
+ if they are equal; otherwise returns false.
+ */
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
+
+ Compares this namespace declaration with \a other and returns true
+ if they are not equal; otherwise returns false.
+ */
+
+/*!
+ Creates an empty namespace declaration.
+*/
+QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
+{
+}
+
+/*!
+ \since 4.4
+
+ Creates a namespace declaration with \a prefix and \a namespaceUri.
+*/
+QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri)
+{
+ m_prefix = prefix;
+ m_namespaceUri = namespaceUri;
+}
+
+/*!
+ 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()
+{
+}
+
+/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
+
+Returns the prefix.
+*/
+/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
+
+Returns the namespaceUri.
+*/
+
+
+
+
+/*!
+ \typedef QXmlStreamEntityDeclarations
+ \relates QXmlStreamEntityDeclaration
+
+ Synonym for QVector<QXmlStreamEntityDeclaration>.
+*/
+
+/*!
+ \class QXmlStreamStringRef
+ \since 4.3
+ \internal
+*/
+
+/*!
+ \class QXmlStreamEntityDeclaration
+ \since 4.3
+ \reentrant
+ \brief The QXmlStreamEntityDeclaration class represents a DTD entity declaration.
+
+ \ingroup xml-tools
+
+ An entity declaration consists of a name(), a notationName(), a
+ systemId(), a publicId(), and a value().
+*/
+
+/*!
+ Creates an empty entity declaration.
+*/
+QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
+{
+}
+
+/*!
+ 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()
+{
+}
+
+/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
+
+Returns the entity name.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
+
+Returns the notation name.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
+
+Returns the system identifier.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
+
+Returns the public identifier.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
+
+Returns the entity's value.
+*/
+
+/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
+
+ Compares this entity declaration with \a other and returns true if
+ they are equal; otherwise returns false.
+ */
+/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
+
+ Compares this entity declaration with \a other and returns true if
+ they are not equal; otherwise returns 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 (int i = 0; i < size(); ++i) {
+ const QXmlStreamAttribute &attribute = at(i);
+ 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, const QLatin1String &name) const
+{
+ for (int i = 0; i < size(); ++i) {
+ const QXmlStreamAttribute &attribute = at(i);
+ 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 QLatin1String &namespaceUri, const QLatin1String &name) const
+{
+ for (int i = 0; i < size(); ++i) {
+ const QXmlStreamAttribute &attribute = at(i);
+ if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
+ return attribute.value();
+ }
+ return QStringRef();
+}
+
+/*!\overload
+
+ 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(const QString &qualifiedName) const
+{
+ for (int i = 0; i < size(); ++i) {
+ const QXmlStreamAttribute &attribute = at(i);
+ if (attribute.qualifiedName() == qualifiedName)
+ return attribute.value();
+ }
+ return QStringRef();
+}
+
+/*!\overload
+
+ 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(const QLatin1String &qualifiedName) const
+{
+ for (int i = 0; i < size(); ++i) {
+ const QXmlStreamAttribute &attribute = at(i);
+ if (attribute.qualifiedName() == qualifiedName)
+ return attribute.value();
+ }
+ return QStringRef();
+}
+
+/*!Appends a new attribute with \a name in the namespace
+ described with \a namespaceUri, and value \a value. The \a
+ namespaceUri can be empty.
+ */
+void QXmlStreamAttributes::append(const QString &namespaceUri, const QString &name, const QString &value)
+{
+ append(QXmlStreamAttribute(namespaceUri, name, value));
+}
+
+/*!\overload
+ Appends a new attribute with qualified name \a qualifiedName and
+ value \a value.
+ */
+void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &value)
+{
+ append(QXmlStreamAttribute(qualifiedName, value));
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+/*! \fn bool QXmlStreamReader::isStartDocument() const
+ Returns true if tokenType() equals \l StartDocument; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEndDocument() const
+ Returns true if tokenType() equals \l EndDocument; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isStartElement() const
+ Returns true if tokenType() equals \l StartElement; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEndElement() const
+ Returns true if tokenType() equals \l EndElement; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isCharacters() const
+ Returns true if tokenType() equals \l Characters; otherwise returns false.
+
+ \sa isWhitespace(), isCDATA()
+*/
+/*! \fn bool QXmlStreamReader::isComment() const
+ Returns true if tokenType() equals \l Comment; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isDTD() const
+ Returns true if tokenType() equals \l DTD; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEntityReference() const
+ Returns true if tokenType() equals \l EntityReference; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isProcessingInstruction() const
+ Returns true if tokenType() equals \l ProcessingInstruction; otherwise returns false.
+*/
+
+/*! Returns true if the reader reports characters that only consist
+ of white-space; otherwise returns false.
+
+ \sa isCharacters(), text()
+*/
+bool QXmlStreamReader::isWhitespace() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->type == QXmlStreamReader::Characters && d->isWhitespace;
+}
+
+/*! Returns true if the reader reports characters that stem from a
+ CDATA section; otherwise returns false.
+
+ \sa isCharacters(), text()
+*/
+bool QXmlStreamReader::isCDATA() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->type == QXmlStreamReader::Characters && d->isCDATA;
+}
+
+
+
+/*!
+ Returns true if this document has been declared standalone in the
+ XML declaration; otherwise returns false.
+
+ If no XML declaration has been parsed, this function returns false.
+ */
+bool QXmlStreamReader::isStandaloneDocument() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->standalone;
+}
+
+
+/*!
+ \since 4.4
+
+ If the state() is \l StartDocument, this function returns the
+ version string as specified in the XML declaration.
+ Otherwise an empty string is returned.
+ */
+QStringRef QXmlStreamReader::documentVersion() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::StartDocument)
+ return d->documentVersion;
+ return QStringRef();
+}
+
+/*!
+ \since 4.4
+
+ If the state() is \l StartDocument, this function returns the
+ encoding string as specified in the XML declaration.
+ Otherwise an empty string is returned.
+ */
+QStringRef QXmlStreamReader::documentEncoding() const
+{
+ Q_D(const QXmlStreamReader);
+ if (d->type == QXmlStreamReader::StartDocument)
+ return d->documentEncoding;
+ return QStringRef();
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+/*!
+ \class QXmlStreamWriter
+ \since 4.3
+ \reentrant
+
+ \brief The QXmlStreamWriter class provides an XML writer with a
+ simple streaming API.
+
+ \ingroup xml-tools
+
+ QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
+ XML. Like its related class, it operates on a QIODevice specified
+ with setDevice(). The API is simple and straightforward: for every
+ XML token or event you want to write, the writer provides a
+ specialized function.
+
+ You start a document with writeStartDocument() and end it with
+ writeEndDocument(). This will implicitly close all remaining open
+ tags.
+
+ Element tags are opened with writeStartElement() followed by
+ writeAttribute() or writeAttributes(), element content, and then
+ writeEndElement(). A shorter form writeEmptyElement() can be used
+ to write empty elements, followed by writeAttributes().
+
+ Element content consists of either characters, entity references or
+ nested elements. It is written with writeCharacters(), which also
+ takes care of escaping all forbidden characters and character
+ sequences, writeEntityReference(), or subsequent calls to
+ writeStartElement(). A convenience method writeTextElement() can be
+ used for writing terminal elements that contain nothing but text.
+
+ The following abridged code snippet shows the basic use of the class
+ to write formatted XML with indentation:
+
+ \snippet doc/src/snippets/qxmlstreamwriter/main.cpp start stream
+ \dots
+ \snippet doc/src/snippets/qxmlstreamwriter/main.cpp write element
+ \dots
+ \snippet doc/src/snippets/qxmlstreamwriter/main.cpp finish stream
+
+ QXmlStreamWriter takes care of prefixing namespaces, all you have to
+ do is specify the \c namespaceUri when writing elements or
+ attributes. If you must conform to certain prefixes, you can force
+ the writer to use them by declaring the namespaces manually with
+ either writeNamespace() or writeDefaultNamespace(). Alternatively,
+ you can bypass the stream writer's namespace support and use
+ overloaded methods that take a qualified name instead. The namespace
+ \e http://www.w3.org/XML/1998/namespace is implicit and mapped to the
+ prefix \e xml.
+
+ The stream writer can automatically format the generated XML data by
+ adding line-breaks and indentation to empty sections between
+ elements, making the XML data more readable for humans and easier to
+ work with for most source code management systems. The feature can
+ be turned on with the \l autoFormatting property, and customized
+ with the \l autoFormattingIndent property.
+
+ Other functions are writeCDATA(), writeComment(),
+ writeProcessingInstruction(), and writeDTD(). Chaining of XML
+ streams is supported with writeCurrentToken().
+
+ By default, QXmlStreamWriter encodes XML in UTF-8. Different
+ encodings can be enforced using setCodec().
+
+ If an error occurs while writing to the underlying device, hasError()
+ starts returning true and subsequent writes are ignored.
+
+ The \l{QXmlStream Bookmarks Example} illustrates how to use a
+ stream writer to write an XML bookmark file (XBEL) that
+ was previously read in by a QXmlStreamReader.
+
+*/
+
+#ifndef QT_NO_XMLSTREAMWRITER
+
+class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
+ QXmlStreamWriter *q_ptr;
+ Q_DECLARE_PUBLIC(QXmlStreamWriter)
+public:
+ QXmlStreamWriterPrivate(QXmlStreamWriter *q);
+ ~QXmlStreamWriterPrivate() {
+ if (deleteDevice)
+ delete device;
+#ifndef QT_NO_TEXTCODEC
+ delete encoder;
+#endif
+ }
+
+ 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); }
+ bool finishStartElement(bool contents = true);
+ void writeStartElement(const QString &namespaceUri, const QString &name);
+ QIODevice *device;
+ QString *stringDevice;
+ uint deleteDevice :1;
+ uint inStartElement :1;
+ uint inEmptyElement :1;
+ uint lastWasStartElement :1;
+ uint wroteSomething :1;
+ uint hasError :1;
+ uint autoFormatting :1;
+ QByteArray autoFormattingIndent;
+ NamespaceDeclaration emptyNamespace;
+ int lastNamespaceDeclaration;
+
+#ifndef QT_NO_TEXTCODEC
+ QTextCodec *codec;
+ QTextEncoder *encoder;
+#endif
+
+ NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
+ void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
+
+ int namespacePrefixCount;
+
+ void indent(int level);
+};
+
+
+QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
+ :autoFormattingIndent(4, ' ')
+{
+ q_ptr = q;
+ device = 0;
+ stringDevice = 0;
+ deleteDevice = false;
+#ifndef QT_NO_TEXTCODEC
+ codec = QTextCodec::codecForMib(106); // utf8
+ encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
+#endif
+ inStartElement = inEmptyElement = false;
+ wroteSomething = false;
+ hasError = false;
+ lastWasStartElement = false;
+ lastNamespaceDeclaration = 1;
+ autoFormatting = false;
+ namespacePrefixCount = 0;
+}
+
+void QXmlStreamWriterPrivate::write(const QStringRef &s)
+{
+ if (device) {
+ if (hasError)
+ return;
+#ifdef QT_NO_TEXTCODEC
+ QByteArray bytes = s.toLatin1();
+#else
+ QByteArray bytes = encoder->fromUnicode(s.constData(), s.size());
+#endif
+ if (device->write(bytes) != bytes.size())
+ hasError = true;
+ }
+ else if (stringDevice)
+ s.appendTo(stringDevice);
+ else
+ qWarning("QXmlStreamWriter: No device");
+}
+
+void QXmlStreamWriterPrivate::write(const QString &s)
+{
+ if (device) {
+ if (hasError)
+ return;
+#ifdef QT_NO_TEXTCODEC
+ QByteArray bytes = s.toLatin1();
+#else
+ QByteArray bytes = encoder->fromUnicode(s);
+#endif
+ if (device->write(bytes) != bytes.size())
+ hasError = true;
+ }
+ else if (stringDevice)
+ stringDevice->append(s);
+ else
+ qWarning("QXmlStreamWriter: No device");
+}
+
+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);
+ if (c.unicode() == '<' )
+ escaped.append(QLatin1String("&lt;"));
+ else if (c.unicode() == '>' )
+ escaped.append(QLatin1String("&gt;"));
+ else if (c.unicode() == '&' )
+ escaped.append(QLatin1String("&amp;"));
+ else if (c.unicode() == '\"' )
+ escaped.append(QLatin1String("&quot;"));
+ else if (escapeWhitespace && c.isSpace()) {
+ if (c.unicode() == '\n')
+ escaped.append(QLatin1String("&#10;"));
+ else if (c.unicode() == '\r')
+ escaped.append(QLatin1String("&#13;"));
+ else if (c.unicode() == '\t')
+ escaped.append(QLatin1String("&#9;"));
+ else
+ escaped += c;
+ } else {
+ escaped += QChar(c);
+ }
+ }
+ write(escaped);
+}
+
+// ASCII only!
+void QXmlStreamWriterPrivate::write(const char *s, int len)
+{
+ if (device) {
+ if (hasError)
+ return;
+ if (device->write(s, len) != len)
+ hasError = true;
+ } else if (stringDevice) {
+ stringDevice->append(QString::fromLatin1(s, len));
+ } else
+ qWarning("QXmlStreamWriter: No device");
+}
+
+void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
+ if (namespaceDeclaration.prefix.isEmpty()) {
+ write(" xmlns=\"");
+ write(namespaceDeclaration.namespaceUri);
+ write("\"");
+ } else {
+ write(" xmlns:");
+ write(namespaceDeclaration.prefix);
+ write("=\"");
+ write(namespaceDeclaration.namespaceUri);
+ write("\"");
+ }
+}
+
+bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
+{
+ bool hadSomethingWritten = wroteSomething;
+ wroteSomething = contents;
+ if (!inStartElement)
+ return hadSomethingWritten;
+
+ if (inEmptyElement) {
+ write("/>");
+ QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
+ lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+ lastWasStartElement = false;
+ } else {
+ write(">");
+ }
+ inStartElement = inEmptyElement = false;
+ lastNamespaceDeclaration = namespaceDeclarations.size();
+ return hadSomethingWritten;
+}
+
+QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
+{
+ for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations[j];
+ if (namespaceDeclaration.namespaceUri == namespaceUri) {
+ if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
+ return namespaceDeclaration;
+ }
+ }
+ if (namespaceUri.isEmpty())
+ return emptyNamespace;
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ if (namespaceUri.isEmpty()) {
+ namespaceDeclaration.prefix.clear();
+ } else {
+ QString s;
+ int n = ++namespacePrefixCount;
+ forever {
+ s = QLatin1Char('n') + QString::number(n++);
+ int j = namespaceDeclarations.size() - 2;
+ while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
+ --j;
+ if (j < 0)
+ break;
+ }
+ namespaceDeclaration.prefix = addToStringStorage(s);
+ }
+ namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+ if (writeDeclaration)
+ writeNamespaceDeclaration(namespaceDeclaration);
+ return namespaceDeclaration;
+}
+
+
+
+void QXmlStreamWriterPrivate::indent(int level)
+{
+ write("\n");
+ for (int i = level; i > 0; --i)
+ write(autoFormattingIndent.constData(), autoFormattingIndent.length());
+}
+
+
+/*!
+ Constructs a stream writer.
+
+ \sa setDevice()
+ */
+QXmlStreamWriter::QXmlStreamWriter()
+ : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+}
+
+/*!
+ Constructs a stream writer that writes into \a device;
+ */
+QXmlStreamWriter::QXmlStreamWriter(QIODevice *device)
+ : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+ Q_D(QXmlStreamWriter);
+ d->device = device;
+}
+
+/*! Constructs a stream writer that writes into \a array. This is the
+ same as creating an xml writer that operates on a QBuffer device
+ which in turn operates on \a array.
+ */
+QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
+ : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+ Q_D(QXmlStreamWriter);
+ d->device = new QBuffer(array);
+ d->device->open(QIODevice::WriteOnly);
+ d->deleteDevice = true;
+}
+
+
+/*! Constructs a stream writer that writes into \a string.
+ */
+QXmlStreamWriter::QXmlStreamWriter(QString *string)
+ : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+ Q_D(QXmlStreamWriter);
+ d->stringDevice = string;
+}
+
+/*!
+ Destructor.
+*/
+QXmlStreamWriter::~QXmlStreamWriter()
+{
+}
+
+
+/*!
+ Sets the current device to \a device. If you want the stream to
+ write into a QByteArray, you can create a QBuffer device.
+
+ \sa device()
+*/
+void QXmlStreamWriter::setDevice(QIODevice *device)
+{
+ Q_D(QXmlStreamWriter);
+ if (device == d->device)
+ return;
+ d->stringDevice = 0;
+ if (d->deleteDevice) {
+ delete d->device;
+ d->deleteDevice = false;
+ }
+ d->device = device;
+}
+
+/*!
+ Returns the current device associated with the QXmlStreamWriter,
+ or 0 if no device has been assigned.
+
+ \sa setDevice()
+*/
+QIODevice *QXmlStreamWriter::device() const
+{
+ Q_D(const QXmlStreamWriter);
+ return d->device;
+}
+
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+ Sets the codec for this stream to \a codec. The codec is used for
+ encoding any data that is written. By default, QXmlStreamWriter
+ uses UTF-8.
+
+ The encoding information is stored in the initial xml tag which
+ gets written when you call writeStartDocument(). Call this
+ function before calling writeStartDocument().
+
+ \sa codec()
+*/
+void QXmlStreamWriter::setCodec(QTextCodec *codec)
+{
+ Q_D(QXmlStreamWriter);
+ if (codec) {
+ d->codec = codec;
+ delete d->encoder;
+ d->encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
+ }
+}
+
+/*!
+ Sets the codec for this stream to the QTextCodec for the encoding
+ specified by \a codecName. Common values for \c codecName include
+ "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
+ recognized, nothing happens.
+
+ \sa QTextCodec::codecForName()
+*/
+void QXmlStreamWriter::setCodec(const char *codecName)
+{
+ setCodec(QTextCodec::codecForName(codecName));
+}
+
+/*!
+ Returns the codec that is currently assigned to the stream.
+
+ \sa setCodec()
+*/
+QTextCodec *QXmlStreamWriter::codec() const
+{
+ Q_D(const QXmlStreamWriter);
+ return d->codec;
+}
+#endif // QT_NO_TEXTCODEC
+
+/*!
+ \property QXmlStreamWriter::autoFormatting
+ \since 4.4
+ 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
+ writer automatically adds line-breaks and indentation to empty
+ sections between elements (ignorable whitespace). The main purpose
+ of auto-formatting is to split the data into several lines, and to
+ increase readability for a human reader. The indentation depth can
+ be controlled through the \l autoFormattingIndent property.
+
+ By default, auto-formatting is disabled.
+*/
+
+/*!
+ \since 4.4
+
+ Enables auto formatting if \a enable is \c true, otherwise
+ disables it.
+
+ The default value is \c false.
+ */
+void QXmlStreamWriter::setAutoFormatting(bool enable)
+{
+ Q_D(QXmlStreamWriter);
+ d->autoFormatting = enable;
+}
+
+/*!
+ \since 4.4
+
+ Returns \c true if auto formattting is enabled, otherwise \c false.
+ */
+bool QXmlStreamWriter::autoFormatting() const
+{
+ Q_D(const QXmlStreamWriter);
+ return d->autoFormatting;
+}
+
+/*!
+ \property QXmlStreamWriter::autoFormattingIndent
+ \since 4.4
+
+ \brief the number of spaces or tabs used for indentation when
+ auto-formatting is enabled. Positive numbers indicate spaces,
+ negative numbers tabs.
+
+ The default indentation is 4.
+
+ \sa autoFormatting
+*/
+
+
+void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
+{
+ Q_D(QXmlStreamWriter);
+ d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
+}
+
+int QXmlStreamWriter::autoFormattingIndent() const
+{
+ Q_D(const QXmlStreamWriter);
+ return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
+}
+
+/*!
+ Returns \c true if the stream failed to write to the underlying device.
+
+ The error status is never reset. Writes happening after the error
+ occurred are ignored, even if the error condition is cleared.
+ */
+bool QXmlStreamWriter::hasError() const
+{
+ Q_D(const QXmlStreamWriter);
+ return d->hasError;
+}
+
+/*!
+ \overload
+ Writes an attribute with \a qualifiedName and \a value.
+
+
+ This function can only be called after writeStartElement() before
+ any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(d->inStartElement);
+ Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+ d->write(" ");
+ d->write(qualifiedName);
+ d->write("=\"");
+ d->writeEscaped(value, true);
+ d->write("\"");
+}
+
+/*! Writes an attribute with \a name and \a value, prefixed for
+ the specified \a namespaceUri. If the namespace has not been
+ declared yet, QXmlStreamWriter will generate a namespace declaration
+ for it.
+
+ This function can only be called after writeStartElement() before
+ any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(d->inStartElement);
+ Q_ASSERT(!name.contains(QLatin1Char(':')));
+ QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
+ d->write(" ");
+ if (!namespaceDeclaration.prefix.isEmpty()) {
+ d->write(namespaceDeclaration.prefix);
+ d->write(":");
+ }
+ d->write(name);
+ d->write("=\"");
+ d->writeEscaped(value, true);
+ d->write("\"");
+}
+
+/*!
+ \overload
+
+ Writes the \a attribute.
+
+ This function can only be called after writeStartElement() before
+ any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
+{
+ if (attribute.namespaceUri().isEmpty())
+ writeAttribute(attribute.qualifiedName().toString(),
+ attribute.value().toString());
+ else
+ writeAttribute(attribute.namespaceUri().toString(),
+ attribute.name().toString(),
+ attribute.value().toString());
+}
+
+
+/*! Writes the attribute vector \a attributes. If a namespace
+ referenced in an attribute not been declared yet, QXmlStreamWriter
+ will generate a namespace declaration for it.
+
+ This function can only be called after writeStartElement() before
+ any content is written, or after writeEmptyElement().
+
+ \sa writeAttribute(), writeNamespace()
+ */
+void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(d->inStartElement);
+ Q_UNUSED(d);
+ for (int i = 0; i < attributes.size(); ++i)
+ writeAttribute(attributes.at(i));
+}
+
+
+/*! Writes \a text as CDATA section. If \a text contains the
+ forbidden character sequence "]]>", it is split into different CDATA
+ sections.
+
+ This function mainly exists for completeness. Normally you should
+ not need use it, because writeCharacters() automatically escapes all
+ non-content characters.
+ */
+void QXmlStreamWriter::writeCDATA(const QString &text)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement();
+ QString copy(text);
+ copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
+ d->write("<![CDATA[");
+ d->write(copy);
+ d->write("]]>");
+}
+
+
+/*! Writes \a text. The characters "<", "&", and "\"" are escaped as entity
+ references "&lt;", "&amp;, and "&quot;". To avoid the forbidden sequence
+ "]]>", ">" is also escaped as "&gt;".
+
+ \sa writeEntityReference()
+ */
+void QXmlStreamWriter::writeCharacters(const QString &text)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement();
+ d->writeEscaped(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.
+ */
+void QXmlStreamWriter::writeComment(const QString &text)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
+ if (!d->finishStartElement(false) && d->autoFormatting)
+ d->indent(d->tagStack.size());
+ d->write("<!--");
+ d->write(text);
+ d->write("-->");
+ d->inStartElement = d->lastWasStartElement = false;
+}
+
+
+/*! Writes a DTD section. The \a dtd represents the entire
+ doctypedecl production from the XML 1.0 specification.
+ */
+void QXmlStreamWriter::writeDTD(const QString &dtd)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement();
+ if (d->autoFormatting)
+ d->write("\n");
+ d->write(dtd);
+ if (d->autoFormatting)
+ d->write("\n");
+}
+
+
+
+/*! \overload
+ Writes an empty element with qualified name \a qualifiedName.
+ Subsequent calls to writeAttribute() will add attributes to this element.
+*/
+void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+ d->writeStartElement(QString(), qualifiedName);
+ d->inEmptyElement = true;
+}
+
+
+/*! Writes an empty element with \a name, prefixed for the specified
+ \a namespaceUri. If the namespace has not been declared,
+ QXmlStreamWriter will generate a namespace declaration for it.
+ Subsequent calls to writeAttribute() will add attributes to this element.
+
+ \sa writeNamespace()
+ */
+void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(!name.contains(QLatin1Char(':')));
+ d->writeStartElement(namespaceUri, name);
+ d->inEmptyElement = true;
+}
+
+
+/*!\overload
+ Writes a text element with \a qualifiedName and \a text.
+
+
+ This is a convenience function equivalent to:
+ \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 1
+
+*/
+void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
+{
+ writeStartElement(qualifiedName);
+ writeCharacters(text);
+ writeEndElement();
+}
+
+/*! Writes a text element with \a name, prefixed for the specified \a
+ namespaceUri, and \a text. If the namespace has not been
+ declared, QXmlStreamWriter will generate a namespace declaration
+ for it.
+
+
+ This is a convenience function equivalent to:
+ \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 2
+
+*/
+void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
+{
+ writeStartElement(namespaceUri, name);
+ writeCharacters(text);
+ writeEndElement();
+}
+
+
+/*!
+ Closes all remaining open start elements and writes a newline.
+
+ \sa writeStartDocument()
+ */
+void QXmlStreamWriter::writeEndDocument()
+{
+ Q_D(QXmlStreamWriter);
+ while (d->tagStack.size())
+ writeEndElement();
+ d->write("\n");
+}
+
+/*!
+ Closes the previous start element.
+
+ \sa writeStartElement()
+ */
+void QXmlStreamWriter::writeEndElement()
+{
+ Q_D(QXmlStreamWriter);
+ if (d->tagStack.isEmpty())
+ return;
+
+ // shortcut: if nothing was written, close as empty tag
+ if (d->inStartElement && !d->inEmptyElement) {
+ d->write("/>");
+ d->lastWasStartElement = d->inStartElement = false;
+ QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+ return;
+ }
+
+ if (!d->finishStartElement(false) && !d->lastWasStartElement && d->autoFormatting)
+ d->indent(d->tagStack.size()-1);
+ if (d->tagStack.isEmpty())
+ return;
+ d->lastWasStartElement = false;
+ QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+ d->write("</");
+ if (!tag.namespaceDeclaration.prefix.isEmpty()) {
+ d->write(tag.namespaceDeclaration.prefix);
+ d->write(":");
+ }
+ d->write(tag.name);
+ d->write(">");
+}
+
+
+
+/*!
+ Writes the entity reference \a name to the stream, as "&\a{name};".
+ */
+void QXmlStreamWriter::writeEntityReference(const QString &name)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement();
+ d->write("&");
+ d->write(name);
+ d->write(";");
+}
+
+
+/*! Writes a namespace declaration for \a namespaceUri with \a
+ prefix. If \a prefix is empty, QXmlStreamWriter assigns a unique
+ prefix consisting of the letter 'n' followed by a number.
+
+ If writeStartElement() or writeEmptyElement() was called, the
+ declaration applies to the current element; otherwise it applies to
+ the next child element.
+
+ Note that the prefix \e xml is both predefined and reserved for
+ \e http://www.w3.org/XML/1998/namespace, which in turn cannot be
+ bound to any other prefix. The prefix \e xmlns and its URI
+ \e http://www.w3.org/2000/xmlns/ are used for the namespace mechanism
+ itself and thus completely forbidden in declarations.
+
+ */
+void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(!namespaceUri.isEmpty());
+ Q_ASSERT(prefix != QLatin1String("xmlns"));
+ 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);
+ if (d->inStartElement)
+ d->writeNamespaceDeclaration(namespaceDeclaration);
+ }
+}
+
+
+/*! Writes a default namespace declaration for \a namespaceUri.
+
+ If writeStartElement() or writeEmptyElement() was called, the
+ declaration applies to the current element; otherwise it applies to
+ the next child element.
+
+ 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.
+ */
+void QXmlStreamWriter::writeDefaultNamespace(const QString &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/"));
+ QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
+ namespaceDeclaration.prefix.clear();
+ namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
+ if (d->inStartElement)
+ d->writeNamespaceDeclaration(namespaceDeclaration);
+}
+
+
+/*!
+ Writes an XML processing instruction with \a target and \a data,
+ where \a data must not contain the sequence "?>".
+ */
+void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(!data.contains(QLatin1String("?>")));
+ if (!d->finishStartElement(false) && d->autoFormatting)
+ d->indent(d->tagStack.size());
+ d->write("<?");
+ d->write(target);
+ if (!data.isNull()) {
+ d->write(" ");
+ d->write(data);
+ }
+ d->write("?>");
+}
+
+
+
+/*!\overload
+
+ Writes a document start with XML version number "1.0". This also
+ writes the encoding information.
+
+ \sa writeEndDocument(), setCodec()
+ \since 4.5
+ */
+void QXmlStreamWriter::writeStartDocument()
+{
+ writeStartDocument(QLatin1String("1.0"));
+}
+
+
+/*!
+ Writes a document start with the XML version number \a version.
+
+ \sa writeEndDocument()
+ */
+void QXmlStreamWriter::writeStartDocument(const QString &version)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement(false);
+ d->write("<?xml version=\"");
+ d->write(version);
+ if (d->device) { // stringDevice does not get any encoding
+ d->write("\" encoding=\"");
+#ifdef QT_NO_TEXTCODEC
+ d->write("iso-8859-1");
+#else
+ d->write(d->codec->name().constData(), d->codec->name().length());
+#endif
+ }
+ d->write("\"?>");
+}
+
+/*! Writes a document start with the XML version number \a version
+ and a standalone attribute \a standalone.
+
+ \sa writeEndDocument()
+ \since 4.5
+ */
+void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
+{
+ Q_D(QXmlStreamWriter);
+ d->finishStartElement(false);
+ d->write("<?xml version=\"");
+ d->write(version);
+ if (d->device) { // stringDevice does not get any encoding
+ d->write("\" encoding=\"");
+#ifdef QT_NO_TEXTCODEC
+ d->write("iso-8859-1");
+#else
+ d->write(d->codec->name().constData(), d->codec->name().length());
+#endif
+ }
+ if (standalone)
+ d->write("\" standalone=\"yes\"?>");
+ else
+ d->write("\" standalone=\"no\"?>");
+}
+
+
+/*!\overload
+
+ Writes a start element with \a qualifiedName. Subsequent calls to
+ writeAttribute() will add attributes to this element.
+
+ \sa writeEndElement(), writeEmptyElement()
+ */
+void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+ d->writeStartElement(QString(), qualifiedName);
+}
+
+
+/*! Writes a start element with \a name, prefixed for the specified
+ \a namespaceUri. If the namespace has not been declared yet,
+ QXmlStreamWriter will generate a namespace declaration for
+ it. Subsequent calls to writeAttribute() will add attributes to this
+ element.
+
+ \sa writeNamespace(), writeEndElement(), writeEmptyElement()
+ */
+void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
+{
+ Q_D(QXmlStreamWriter);
+ Q_ASSERT(!name.contains(QLatin1Char(':')));
+ d->writeStartElement(namespaceUri, name);
+}
+
+void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, const QString &name)
+{
+ if (!finishStartElement(false) && autoFormatting)
+ indent(tagStack.size());
+
+ Tag &tag = tagStack_push();
+ tag.name = addToStringStorage(name);
+ tag.namespaceDeclaration = findNamespace(namespaceUri);
+ write("<");
+ if (!tag.namespaceDeclaration.prefix.isEmpty()) {
+ write(tag.namespaceDeclaration.prefix);
+ write(":");
+ }
+ write(tag.name);
+ inStartElement = lastWasStartElement = true;
+
+ for (int i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
+ writeNamespaceDeclaration(namespaceDeclarations[i]);
+ tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+/*! Writes the current state of the \a reader. All possible valid
+ states are supported.
+
+ The purpose of this function is to support chained processing of XML data.
+
+ \sa QXmlStreamReader::tokenType()
+ */
+void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
+{
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::NoToken:
+ break;
+ case QXmlStreamReader::StartDocument:
+ writeStartDocument();
+ break;
+ case QXmlStreamReader::EndDocument:
+ writeEndDocument();
+ break;
+ case QXmlStreamReader::StartElement: {
+ 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());
+ }
+ writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
+ writeAttributes(reader.attributes());
+ } break;
+ case QXmlStreamReader::EndElement:
+ writeEndElement();
+ break;
+ case QXmlStreamReader::Characters:
+ if (reader.isCDATA())
+ writeCDATA(reader.text().toString());
+ else
+ writeCharacters(reader.text().toString());
+ break;
+ case QXmlStreamReader::Comment:
+ writeComment(reader.text().toString());
+ break;
+ case QXmlStreamReader::DTD:
+ writeDTD(reader.text().toString());
+ break;
+ case QXmlStreamReader::EntityReference:
+ writeEntityReference(reader.name().toString());
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ writeProcessingInstruction(reader.processingInstructionTarget().toString(),
+ reader.processingInstructionData().toString());
+ break;
+ default:
+ Q_ASSERT(reader.tokenType() != QXmlStreamReader::Invalid);
+ qWarning("QXmlStreamWriter: writeCurrentToken() with invalid state.");
+ break;
+ }
+}
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
+ \since 4.5
+
+ Returns true if this QXmlStreamAttributes has an attribute whose
+ qualified name is \a qualifiedName; otherwise returns false.
+
+ Note that this is not namespace aware. For instance, if this
+ QXmlStreamAttributes contains an attribute whose lexical name is "xlink:href"
+ this doesn't tell that an attribute named \c href in the XLink namespace is
+ present, since the \c xlink prefix can be bound to any namespace. Use the
+ overload that takes a namespace URI and a local name as parameter, for
+ namespace aware code.
+*/
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QLatin1String &qualifiedName) const
+ \overload
+ \since 4.5
+*/
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &namespaceUri,
+ const QString &name) const
+ \overload
+ \since 4.5
+
+ Returns true if this QXmlStreamAttributes has an attribute whose
+ namespace URI and name correspond to \a namespaceUri and \a name;
+ otherwise returns false.
+*/
+
+#endif // QT_NO_XMLSTREAMREADER
+#endif // QT_NO_XMLSTREAMWRITER
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_XMLSTREAM
diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g
new file mode 100644
index 0000000000..3088632e34
--- /dev/null
+++ b/src/corelib/xml/qxmlstream.g
@@ -0,0 +1,1847 @@
+----------------------------------------------------------------------------
+--
+-- Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+-- All rights reserved.
+-- Contact: Nokia Corporation (qt-info@nokia.com)
+--
+-- This file is part of the QtCore module of the Qt Toolkit.
+--
+-- $QT_BEGIN_LICENSE:LGPL$
+-- No Commercial Usage
+-- This file contains pre-release code and may not be distributed.
+-- You may use this file in accordance with the terms and conditions
+-- contained in the Technology Preview License Agreement accompanying
+-- this package.
+--
+-- GNU Lesser General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU Lesser
+-- General Public License version 2.1 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.LGPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU Lesser General Public License version 2.1 requirements
+-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+--
+-- In addition, as a special exception, Nokia gives you certain additional
+-- rights. These rights are described in the Nokia Qt LGPL Exception
+-- version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+--
+-- If you have questions regarding the use of this file, please contact
+-- Nokia at qt-info@nokia.com.
+--
+--
+--
+--
+--
+--
+--
+--
+-- $QT_END_LICENSE$
+--
+----------------------------------------------------------------------------
+
+%parser QXmlStreamReader_Table
+
+%merged_output qxmlstream_p.h
+
+%token NOTOKEN
+%token SPACE " "
+%token LANGLE "<"
+%token RANGLE ">"
+%token AMPERSAND "&"
+%token HASH "#"
+%token QUOTE "\'"
+%token DBLQUOTE "\""
+%token LBRACK "["
+%token RBRACK "]"
+%token LPAREN "("
+%token RPAREN ")"
+%token PIPE "|"
+%token EQ "="
+%token PERCENT "%"
+%token SLASH "/"
+%token COLON ":"
+%token SEMICOLON ";"
+%token COMMA ","
+%token DASH "-"
+%token PLUS "+"
+%token STAR "*"
+%token DOT "."
+%token QUESTIONMARK "?"
+%token BANG "!"
+%token LETTER "[a-zA-Z]"
+%token DIGIT "[0-9]"
+
+-- after langle_bang
+%token CDATA_START "[CDATA["
+%token DOCTYPE "DOCTYPE"
+%token ELEMENT "ELEMENT"
+%token ATTLIST "ATTLIST"
+%token ENTITY "ENTITY"
+%token NOTATION "NOTATION"
+
+-- entity decl
+%token SYSTEM "SYSTEM"
+%token PUBLIC "PUBLIC"
+%token NDATA "NDATA"
+
+-- default decl
+%token REQUIRED "REQUIRED"
+%token IMPLIED "IMPLIED"
+%token FIXED "FIXED"
+
+-- conent spec
+%token EMPTY "EMPTY"
+%token ANY "ANY"
+%token PCDATA "PCDATA"
+
+-- error
+%token ERROR
+
+-- entities
+%token PARSE_ENTITY
+%token ENTITY_DONE
+%token UNRESOLVED_ENTITY
+
+-- att type
+%token CDATA "CDATA"
+%token ID "ID"
+%token IDREF "IDREF"
+%token IDREFS "IDREFS"
+%token ENTITY "ENTITY"
+%token ENTITIES "ENTITIES"
+%token NMTOKEN "NMTOKEN"
+%token NMTOKENS "NMTOKENS"
+
+-- xml declaration
+%token XML "<?xml"
+%token VERSION "version"
+
+%nonassoc SHIFT_THERE
+%nonassoc AMPERSAND
+ BANG
+ COLON
+ COMMA
+ DASH
+ DBLQUOTE
+ DIGIT
+ DOT
+ ENTITY_DONE
+ EQ
+ HASH
+ LBRACK
+ LETTER
+ LPAREN
+ PERCENT
+ PIPE
+ PLUS
+ QUESTIONMARK
+ QUOTE
+ RANGLE
+ RBRACK
+ RPAREN
+ SEMICOLON
+ SLASH
+ SPACE
+ STAR
+
+%start document
+
+/.
+template <typename T> class QXmlStreamSimpleStack {
+ T *data;
+ int tos, cap;
+public:
+ inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
+ inline ~QXmlStreamSimpleStack(){ if (data) qFree(data); }
+
+ inline void reserve(int extraCapacity) {
+ if (tos + extraCapacity + 1 > cap) {
+ cap = qMax(tos + extraCapacity + 1, cap << 1 );
+ data = reinterpret_cast<T *>(qRealloc(data, cap * sizeof(T)));
+ 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[](int index) { return data[index]; }
+ inline const T &at(int index) const { return data[index]; }
+ inline int size() const { return tos + 1; }
+ inline void resize(int s) { tos = s - 1; }
+ inline bool isEmpty() const { return tos < 0; }
+ inline void clear() { tos = -1; }
+};
+
+
+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;
+ int namespaceDeclarationsSize;
+ };
+
+
+ QXmlStreamPrivateTagStack();
+ QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
+ QString tagStackStringStorage;
+ int tagStackStringStorageSize;
+ bool tagsDone;
+
+ inline QStringRef addToStringStorage(const QStringRef &s) {
+ int pos = tagStackStringStorageSize;
+ int sz = s.size();
+ if (pos != tagStackStringStorage.size())
+ tagStackStringStorage.resize(pos);
+ tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorageSize += sz;
+ return QStringRef(&tagStackStringStorage, pos, sz);
+ }
+ inline QStringRef addToStringStorage(const QString &s) {
+ int pos = tagStackStringStorageSize;
+ int sz = s.size();
+ if (pos != tagStackStringStorage.size())
+ tagStackStringStorage.resize(pos);
+ tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorageSize += sz;
+ return QStringRef(&tagStackStringStorage, pos, sz);
+ }
+
+ QXmlStreamSimpleStack<Tag> tagStack;
+
+
+ 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(const QString& str = QString())
+ :value(str), external(false), unparsed(false), literal(false),
+ hasBeenParsed(false), isCurrentlyReferenced(false){}
+ static inline Entity createLiteral(const QString &entity)
+ { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
+ QString value;
+ uint external : 1;
+ uint unparsed : 1;
+ uint literal : 1;
+ uint hasBeenParsed : 1;
+ uint isCurrentlyReferenced : 1;
+ };
+ QHash<QString, Entity> entityHash;
+ QHash<QString, Entity> parameterEntityHash;
+ QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ inline bool referenceEntity(Entity &entity) {
+ if (entity.isCurrentlyReferenced) {
+ raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ return false;
+ }
+ entity.isCurrentlyReferenced = true;
+ entityReferenceStack.push() = &entity;
+ injectToken(ENTITY_DONE);
+ return true;
+ }
+
+
+ QIODevice *device;
+ bool deleteDevice;
+#ifndef QT_NO_TEXTCODEC
+ QTextCodec *codec;
+ QTextDecoder *decoder;
+#endif
+ 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);
+ }
+ 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;
+ ushort 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(const QString &s, int from = 0);
+ void putStringLiteral(const QString &s);
+ void putReplacement(const QString &s);
+ void putReplacementInAttributeValue(const QString &s);
+ ushort 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);
+ 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 = 0);
+ 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;
+ }
+};
+
+bool QXmlStreamReaderPrivate::parse()
+{
+ // cleanup currently reported token
+
+ switch (type) {
+ case QXmlStreamReader::StartElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ if (publicNamespaceDeclarations.size())
+ publicNamespaceDeclarations.clear();
+ if (attributes.size())
+ attributes.resize(0);
+ 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();
+ // fall through
+ 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();
+#ifndef QT_NO_TEXTCODEC
+ if(decoder->hasFailure()) {
+ raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+ readBuffer.clear();
+ return false;
+ }
+#endif
+ // fall through
+ 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;
+ if (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;
+ }
+ // fall through
+ case '\0': {
+ 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;
+ 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) {
+./
+
+document ::= PARSE_ENTITY content;
+/.
+ case $rule_number:
+ setType(QXmlStreamReader::EndDocument);
+ break;
+./
+
+document ::= prolog;
+/.
+ case $rule_number:
+ 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;
+./
+
+
+prolog ::= prolog stag content etag;
+prolog ::= prolog empty_element_tag;
+prolog ::= prolog comment;
+prolog ::= prolog xml_decl;
+prolog ::= prolog processing_instruction;
+prolog ::= prolog doctype_decl;
+prolog ::= prolog SPACE;
+prolog ::=;
+
+entity_done ::= ENTITY_DONE;
+/.
+ case $rule_number:
+ entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ clearSym();
+ break;
+./
+
+
+xml_decl_start ::= XML;
+/.
+ case $rule_number:
+ if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+xml_decl ::= xml_decl_start VERSION space_opt EQ space_opt literal attribute_list_opt QUESTIONMARK RANGLE;
+/.
+ case $rule_number:
+ setType(QXmlStreamReader::StartDocument);
+ documentVersion = symString(6);
+ startDocument();
+ break;
+./
+
+external_id ::= SYSTEM literal;
+/.
+ case $rule_number:
+ hasExternalDtdSubset = true;
+ dtdSystemId = symString(2);
+ break;
+./
+external_id ::= PUBLIC public_literal space literal;
+/.
+ case $rule_number:
+ checkPublicLiteral(symString(2));
+ dtdPublicId = symString(2);
+ dtdSystemId = symString(4);
+ hasExternalDtdSubset = true;
+ break;
+./
+external_id ::=;
+
+doctype_decl_start ::= langle_bang DOCTYPE qname space;
+/.
+ case $rule_number:
+ if (!scanPublicOrSystem() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ dtdName = symString(3);
+ break;
+./
+
+doctype_decl ::= langle_bang DOCTYPE qname RANGLE;
+/.
+ case $rule_number:./
+doctype_decl ::= langle_bang DOCTYPE qname markup space_opt RANGLE;
+/.
+ case $rule_number:
+ dtdName = symString(3);
+ // fall through
+./
+doctype_decl ::= doctype_decl_start external_id space_opt markup space_opt RANGLE;
+/.
+ case $rule_number:./
+doctype_decl ::= doctype_decl_start external_id space_opt RANGLE;
+/.
+ case $rule_number:
+ setType(QXmlStreamReader::DTD);
+ text = &textBuffer;
+ break;
+./
+
+markup_start ::= LBRACK;
+/.
+ case $rule_number:
+ scanDtd = true;
+ break;
+./
+
+markup ::= markup_start markup_list RBRACK;
+/.
+ case $rule_number:
+ scanDtd = false;
+ break;
+./
+
+
+markup_list ::= markup_decl | space | pereference;
+markup_list ::= markup_list markup_decl | markup_list space | markup_list pereference;
+markup_list ::=;
+
+markup_decl ::= element_decl | attlist_decl | entity_decl | entity_done | notation_decl | processing_instruction | comment;
+
+
+element_decl_start ::= langle_bang ELEMENT qname space;
+/.
+ case $rule_number:
+ if (!scanString(spell[EMPTY], EMPTY, false)
+ && !scanString(spell[ANY], ANY, false)
+ && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+element_decl ::= element_decl_start content_spec space_opt RANGLE;
+
+
+content_spec ::= EMPTY | ANY | mixed | children;
+
+pcdata_start ::= HASH;
+/.
+ case $rule_number:
+ if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+pcdata ::= pcdata_start PCDATA;
+
+questionmark_or_star_or_plus_opt ::= QUESTIONMARK | STAR | PLUS;
+questionmark_or_star_or_plus_opt ::=;
+
+cp ::= qname questionmark_or_star_or_plus_opt | choice_or_seq questionmark_or_star_or_plus_opt;
+
+cp_pipe_or_comma_list ::= cp space_opt;
+cp_pipe_or_comma_list ::= cp space_opt PIPE space_opt cp_pipe_list space_opt;
+cp_pipe_or_comma_list ::= cp space_opt COMMA space_opt cp_comma_list space_opt;
+cp_pipe_list ::= cp | cp_pipe_list space_opt PIPE space_opt cp;
+cp_comma_list ::= cp | cp_comma_list space_opt COMMA space_opt cp;
+
+
+name_pipe_list ::= PIPE space_opt qname;
+name_pipe_list ::= name_pipe_list space_opt PIPE space_opt qname;
+
+star_opt ::= | STAR;
+
+mixed ::= LPAREN space_opt pcdata space_opt RPAREN star_opt;
+mixed ::= LPAREN space_opt pcdata space_opt name_pipe_list space_opt RPAREN STAR;
+
+choice_or_seq ::= LPAREN space_opt cp_pipe_or_comma_list RPAREN;
+
+children ::= choice_or_seq questionmark_or_star_or_plus_opt;
+
+
+nmtoken_pipe_list ::= nmtoken;
+nmtoken_pipe_list ::= nmtoken_pipe_list space_opt PIPE space_opt nmtoken;
+
+
+att_type ::= CDATA;
+/.
+ case $rule_number: {
+ lastAttributeIsCData = true;
+ } break;
+./
+att_type ::= ID | IDREF | IDREFS | ENTITY | ENTITIES | NMTOKEN | NMTOKENS;
+att_type ::= LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space;
+att_type ::= NOTATION LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space;
+
+
+default_declhash ::= HASH;
+/.
+ case $rule_number:
+ if (!scanAfterDefaultDecl() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+default_decl ::= default_declhash REQUIRED;
+default_decl ::= default_declhash IMPLIED;
+default_decl ::= attribute_value;
+default_decl ::= default_declhash FIXED space attribute_value;
+attdef_start ::= space qname space;
+/.
+ case $rule_number:
+ sym(1) = sym(2);
+ lastAttributeValue.clear();
+ lastAttributeIsCData = false;
+ if (!scanAttType() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+attdef ::= attdef_start att_type default_decl;
+/.
+ case $rule_number: {
+ 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;
+./
+
+attdef_list ::= attdef;
+attdef_list ::= attdef_list attdef;
+
+attlist_decl ::= langle_bang ATTLIST qname space_opt RANGLE;
+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));
+ 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;
+./
+
+entity_decl_start ::= langle_bang ENTITY name space;
+/.
+ case $rule_number: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(3);
+ } break;
+./
+
+entity_decl_start ::= langle_bang ENTITY PERCENT space name space;
+/.
+ case $rule_number: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(5);
+ entityDeclaration.parameter = true;
+ } break;
+./
+
+entity_decl_external ::= entity_decl_start SYSTEM literal;
+/.
+ case $rule_number: {
+ if (!scanNData() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.systemId = symString(3);
+ entityDeclaration.external = true;
+ } break;
+./
+
+entity_decl_external ::= entity_decl_start PUBLIC public_literal space literal;
+/.
+ case $rule_number: {
+ if (!scanNData() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ checkPublicLiteral((entityDeclaration.publicId = symString(3)));
+ entityDeclaration.systemId = symString(5);
+ entityDeclaration.external = true;
+ } break;
+./
+
+entity_decl ::= entity_decl_external NDATA name space_opt RANGLE;
+/.
+ case $rule_number: {
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.notationName = symString(3);
+ if (entityDeclaration.parameter)
+ raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
+ }
+ //fall through
+./
+
+entity_decl ::= entity_decl_external space_opt RANGLE;
+/.
+ case $rule_number:./
+
+entity_decl ::= entity_decl_start entity_value space_opt RANGLE;
+/.
+ case $rule_number: {
+ if (referenceToUnparsedEntityDetected && !standalone) {
+ entityDeclarations.pop();
+ break;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ if (!entityDeclaration.external)
+ entityDeclaration.value = symString(2);
+ QString entityName = entityDeclaration.name.toString();
+ QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(entityName)) {
+ Entity entity(entityDeclaration.value.toString());
+ entity.unparsed = (!entityDeclaration.notationName.isNull());
+ entity.external = entityDeclaration.external;
+ hash.insert(entityName, entity);
+ }
+ } break;
+./
+
+
+processing_instruction ::= LANGLE QUESTIONMARK name space;
+/.
+ case $rule_number: {
+ setType(QXmlStreamReader::ProcessingInstruction);
+ int pos = sym(4).pos + sym(4).len;
+ processingInstructionTarget = symString(3);
+ if (scanUntil("?>")) {
+ processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
+ const QString piTarget(processingInstructionTarget.toString());
+ if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
+ }
+ else if(!QXmlUtils::isNCName(piTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
+ } else if (type != QXmlStreamReader::Invalid){
+ resume($rule_number);
+ return false;
+ }
+ } break;
+./
+
+processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE;
+/.
+ case $rule_number:
+ setType(QXmlStreamReader::ProcessingInstruction);
+ processingInstructionTarget = symString(3);
+ if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive))
+ raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
+ break;
+./
+
+
+langle_bang ::= LANGLE BANG;
+/.
+ case $rule_number:
+ if (!scanAfterLangleBang() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+comment_start ::= langle_bang DASH DASH;
+/.
+ case $rule_number:
+ if (!scanUntil("--")) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+comment ::= comment_start RANGLE;
+/.
+ case $rule_number: {
+ setType(QXmlStreamReader::Comment);
+ int pos = sym(1).pos + 4;
+ text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ } break;
+./
+
+
+cdata ::= langle_bang CDATA_START;
+/.
+ case $rule_number: {
+ 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($rule_number);
+ return false;
+ }
+ } break;
+./
+
+notation_decl_start ::= langle_bang NOTATION name space;
+/.
+ case $rule_number: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ NotationDeclaration &notationDeclaration = notationDeclarations.push();
+ notationDeclaration.name = symString(3);
+ } break;
+./
+
+notation_decl ::= notation_decl_start SYSTEM literal space_opt RANGLE;
+/.
+ case $rule_number: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId = symString(3);
+ notationDeclaration.publicId.clear();
+ } break;
+./
+
+notation_decl ::= notation_decl_start PUBLIC public_literal space_opt RANGLE;
+/.
+ case $rule_number: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId.clear();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ } break;
+./
+
+notation_decl ::= notation_decl_start PUBLIC public_literal space literal space_opt RANGLE;
+/.
+ case $rule_number: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ notationDeclaration.systemId = symString(5);
+ } break;
+./
+
+
+
+content_char ::= RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG | QUOTE | DBLQUOTE | LETTER | DIGIT;
+
+scan_content_char ::= content_char;
+/.
+ case $rule_number:
+ isWhitespace = false;
+ // fall through
+./
+
+scan_content_char ::= SPACE;
+/.
+ case $rule_number:
+ sym(1).len += fastScanContentCharList();
+ if (atEnd && !inParseEntity) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+content_char_list ::= content_char_list char_ref;
+content_char_list ::= content_char_list entity_ref;
+content_char_list ::= content_char_list entity_done;
+content_char_list ::= content_char_list scan_content_char;
+content_char_list ::= char_ref;
+content_char_list ::= entity_ref;
+content_char_list ::= entity_done;
+content_char_list ::= scan_content_char;
+
+
+character_content ::= content_char_list %prec SHIFT_THERE;
+/.
+ case $rule_number:
+ if (!textBuffer.isEmpty()) {
+ setType(QXmlStreamReader::Characters);
+ text = &textBuffer;
+ }
+ break;
+./
+
+literal ::= QUOTE QUOTE;
+/.
+ case $rule_number:./
+literal ::= DBLQUOTE DBLQUOTE;
+/.
+ case $rule_number:
+ clearSym();
+ break;
+./
+literal ::= QUOTE literal_content_with_dblquote QUOTE;
+/.
+ case $rule_number:./
+literal ::= DBLQUOTE literal_content_with_quote DBLQUOTE;
+/.
+ case $rule_number:
+ sym(1) = sym(2);
+ break;
+./
+
+literal_content_with_dblquote ::= literal_content_with_dblquote literal_content;
+/.
+ case $rule_number:./
+literal_content_with_quote ::= literal_content_with_quote literal_content;
+/.
+ case $rule_number:./
+literal_content_with_dblquote ::= literal_content_with_dblquote DBLQUOTE;
+/.
+ case $rule_number:./
+literal_content_with_quote ::= literal_content_with_quote QUOTE;
+/.
+ case $rule_number:
+ sym(1).len += sym(2).len;
+ break;
+./
+literal_content_with_dblquote ::= literal_content;
+literal_content_with_quote ::= literal_content;
+literal_content_with_dblquote ::= DBLQUOTE;
+literal_content_with_quote ::= QUOTE;
+
+literal_content_start ::= LETTER | DIGIT | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG;
+
+literal_content_start ::= SPACE;
+/.
+ case $rule_number:
+ if (normalizeLiterals)
+ textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
+ break;
+./
+
+literal_content ::= literal_content_start;
+/.
+ case $rule_number:
+ sym(1).len += fastScanLiteralContent();
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+
+public_literal ::= literal;
+/.
+ case $rule_number: {
+ if (!QXmlUtils::isPublicID(symString(1).toString())) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
+ resume($rule_number);
+ return false;
+ }
+ } break;
+./
+
+entity_value ::= QUOTE QUOTE;
+/.
+ case $rule_number:./
+entity_value ::= DBLQUOTE DBLQUOTE;
+/.
+ case $rule_number:
+ clearSym();
+ break;
+./
+
+entity_value ::= QUOTE entity_value_content_with_dblquote QUOTE;
+/.
+ case $rule_number:./
+entity_value ::= DBLQUOTE entity_value_content_with_quote DBLQUOTE;
+/.
+ case $rule_number:
+ sym(1) = sym(2);
+ break;
+./
+
+entity_value_content_with_dblquote ::= entity_value_content_with_dblquote entity_value_content;
+/.
+ case $rule_number:./
+entity_value_content_with_quote ::= entity_value_content_with_quote entity_value_content;
+/.
+ case $rule_number:./
+entity_value_content_with_dblquote ::= entity_value_content_with_dblquote DBLQUOTE;
+/.
+ case $rule_number:./
+entity_value_content_with_quote ::= entity_value_content_with_quote QUOTE;
+/.
+ case $rule_number:
+ sym(1).len += sym(2).len;
+ break;
+./
+entity_value_content_with_dblquote ::= entity_value_content;
+entity_value_content_with_quote ::= entity_value_content;
+entity_value_content_with_dblquote ::= DBLQUOTE;
+entity_value_content_with_quote ::= QUOTE;
+
+entity_value_content ::= LETTER | DIGIT | LANGLE | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | SLASH | COLON | SEMICOLON | COMMA | SPACE | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG;
+entity_value_content ::= char_ref | entity_ref_in_entity_value | entity_done;
+
+
+attribute_value ::= QUOTE QUOTE;
+/.
+ case $rule_number:./
+attribute_value ::= DBLQUOTE DBLQUOTE;
+/.
+ case $rule_number:
+ clearSym();
+ break;
+./
+attribute_value ::= QUOTE attribute_value_content_with_dblquote QUOTE;
+/.
+ case $rule_number:./
+attribute_value ::= DBLQUOTE attribute_value_content_with_quote DBLQUOTE;
+/.
+ case $rule_number:
+ sym(1) = sym(2);
+ lastAttributeValue = symString(1);
+ break;
+./
+
+attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote attribute_value_content;
+/.
+ case $rule_number:./
+attribute_value_content_with_quote ::= attribute_value_content_with_quote attribute_value_content;
+/.
+ case $rule_number:./
+attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote DBLQUOTE;
+/.
+ case $rule_number:./
+attribute_value_content_with_quote ::= attribute_value_content_with_quote QUOTE;
+/.
+ case $rule_number:
+ sym(1).len += sym(2).len;
+ break;
+./
+attribute_value_content_with_dblquote ::= attribute_value_content | DBLQUOTE;
+attribute_value_content_with_quote ::= attribute_value_content | QUOTE;
+
+attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute_value | entity_done;
+
+attribute ::= qname space_opt EQ space_opt attribute_value;
+/.
+ case $rule_number: {
+ 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;
+./
+
+
+
+attribute_list_opt ::= | space | space attribute_list space_opt;
+attribute_list ::= attribute | attribute_list space attribute;
+
+stag_start ::= LANGLE qname;
+/.
+ case $rule_number: {
+ 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;
+./
+
+
+empty_element_tag ::= stag_start attribute_list_opt SLASH RANGLE;
+/.
+ case $rule_number:
+ isEmptyElement = true;
+ // fall through
+./
+
+
+stag ::= stag_start attribute_list_opt RANGLE;
+/.
+ case $rule_number:
+ setType(QXmlStreamReader::StartElement);
+ resolveTag();
+ if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
+ raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
+ hasSeenTag = true;
+ break;
+./
+
+
+etag ::= LANGLE SLASH qname space_opt RANGLE;
+/.
+ case $rule_number: {
+ 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;
+./
+
+
+unresolved_entity ::= UNRESOLVED_ENTITY;
+/.
+ case $rule_number:
+ if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
+ break;
+ }
+ setType(QXmlStreamReader::EntityReference);
+ name = &unresolvedEntity;
+ break;
+./
+
+entity_ref ::= AMPERSAND name SEMICOLON;
+/.
+ case $rule_number: {
+ sym(1).len += sym(2).len + 1;
+ QString reference = symString(2).toString();
+ if (entityHash.contains(reference)) {
+ Entity &entity = entityHash[reference];
+ 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);
+ 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;
+./
+
+pereference ::= PERCENT name SEMICOLON;
+/.
+ case $rule_number: {
+ sym(1).len += sym(2).len + 1;
+ QString reference = symString(2).toString();
+ if (parameterEntityHash.contains(reference)) {
+ referenceToParameterEntityDetected = true;
+ Entity &entity = parameterEntityHash[reference];
+ 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).toString()));
+ }
+ } break;
+./
+
+
+
+entity_ref_in_entity_value ::= AMPERSAND name SEMICOLON;
+/.
+ case $rule_number:
+ sym(1).len += sym(2).len + 1;
+ break;
+./
+
+entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
+/.
+ case $rule_number: {
+ sym(1).len += sym(2).len + 1;
+ QString reference = symString(2).toString();
+ if (entityHash.contains(reference)) {
+ Entity &entity = entityHash[reference];
+ 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);
+ 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;
+./
+
+char_ref ::= AMPERSAND HASH char_ref_value SEMICOLON;
+/.
+ case $rule_number: {
+ if (uint s = resolveCharRef(3)) {
+ if (s >= 0xffff)
+ putStringLiteral(QString::fromUcs4(&s, 1));
+ else
+ putChar((LETTER << 16) | s);
+
+ textBuffer.chop(3 + sym(3).len);
+ clearSym();
+ } else {
+ raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
+ }
+ } break;
+./
+
+
+char_ref_value ::= LETTER | DIGIT;
+char_ref_value ::= char_ref_value LETTER;
+/.
+ case $rule_number:./
+char_ref_value ::= char_ref_value DIGIT;
+/.
+ case $rule_number:
+ sym(1).len += sym(2).len;
+ break;
+./
+
+
+content ::= content character_content;
+content ::= content stag content etag;
+content ::= content empty_element_tag;
+content ::= content comment;
+content ::= content cdata;
+content ::= content xml_decl;
+content ::= content processing_instruction;
+content ::= content doctype_decl;
+content ::= content unresolved_entity;
+content ::= ;
+
+
+space ::= SPACE;
+/.
+ case $rule_number:
+ sym(1).len += fastScanSpace();
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+
+space_opt ::=;
+space_opt ::= space;
+
+qname ::= LETTER;
+/.
+ case $rule_number: {
+ sym(1).len += fastScanName(&sym(1).prefix);
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ } break;
+./
+
+name ::= LETTER;
+/.
+ case $rule_number:
+ sym(1).len += fastScanName();
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+ }
+ break;
+./
+
+nmtoken ::= LETTER;
+/.
+ case $rule_number:./
+nmtoken ::= DIGIT;
+/.
+ case $rule_number:./
+nmtoken ::= DOT;
+/.
+ case $rule_number:./
+nmtoken ::= DASH;
+/.
+ case $rule_number:./
+nmtoken ::= COLON;
+/.
+ case $rule_number:
+ sym(1).len += fastScanNMTOKEN();
+ if (atEnd) {
+ resume($rule_number);
+ 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
+
+./
diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h
new file mode 100644
index 0000000000..e5cb61e512
--- /dev/null
+++ b/src/corelib/xml/qxmlstream.h
@@ -0,0 +1,491 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLSTREAM_H
+#define QXMLSTREAM_H
+
+#include <QtCore/qiodevice.h>
+
+#ifndef QT_NO_XMLSTREAM
+
+#include <QtCore/qstring.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// QXmlStream* was originally in the QtXml module
+// since we've moved it to QtCore in Qt 4.4.0, we need to
+// keep binary compatibility
+//
+// The list of supported platforms is in:
+// http://qt.nokia.com/doc/supported_platforms.html
+//
+// These platforms do not support symbol moving nor duplication
+// (because duplicate symbols cause warnings when linking):
+// Apple MacOS X (Mach-O executable format)
+// special case: 64-bit on Mac wasn't supported before 4.5.0
+// IBM AIX (XCOFF executable format)
+//
+// These platforms do not support symbol moving but allow it to be duplicated:
+// Microsoft Windows (COFF PE executable format)
+// special case: Windows CE wasn't supported before 4.4.0
+//
+// These platforms support symbol moving:
+// HP HP-UX (PA-RISC2.0 shared executables)
+// HP HP-UXi (ELF executable format)
+// FreeBSD (ELF executable format)
+// Linux (ELF executable format)
+// SGI IRIX (ELF executable format)
+// Sun Solaris (ELF executable format)
+//
+// Other platforms are supported through community contributions only.
+// We are taking the optimist scenario here to avoid creating more
+// symbols to be supported.
+
+#if defined(Q_OS_MAC32) || defined(Q_OS_AIX)
+# if !defined QT_BUILD_XML_LIB
+# define Q_XMLSTREAM_RENAME_SYMBOLS
+# endif
+#endif
+
+#if defined QT_BUILD_XML_LIB
+# define Q_XMLSTREAM_EXPORT Q_XML_EXPORT
+#else
+# define Q_XMLSTREAM_EXPORT Q_CORE_EXPORT
+#endif
+
+#if defined Q_XMLSTREAM_RENAME_SYMBOLS
+// don't worry, we'll undef and change to typedef at the bottom of the file
+# define QXmlStreamAttribute QCoreXmlStreamAttribute
+# define QXmlStreamAttributes QCoreXmlStreamAttributes
+# define QXmlStreamEntityDeclaration QCoreXmlStreamEntityDeclaration
+# define QXmlStreamEntityDeclarations QCoreXmlStreamEntityDeclarations
+# define QXmlStreamEntityResolver QCoreXmlStreamEntityResolver
+# define QXmlStreamNamespaceDeclaration QCoreXmlStreamNamespaceDeclaration
+# define QXmlStreamNamespaceDeclarations QCoreXmlStreamNamespaceDeclarations
+# define QXmlStreamNotationDeclaration QCoreXmlStreamNotationDeclaration
+# define QXmlStreamNotationDeclarations QCoreXmlStreamNotationDeclarations
+# define QXmlStreamReader QCoreXmlStreamReader
+# define QXmlStreamStringRef QCoreXmlStreamStringRef
+# define QXmlStreamWriter QCoreXmlStreamWriter
+#endif
+
+class Q_XMLSTREAM_EXPORT QXmlStreamStringRef {
+ QString m_string;
+ int m_position, m_size;
+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()){}
+ inline QXmlStreamStringRef(const QString &aString):m_string(aString), m_position(0), m_size(aString.size()){}
+ inline ~QXmlStreamStringRef(){}
+ 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; }
+};
+
+
+class QXmlStreamReaderPrivate;
+class QXmlStreamAttributes;
+class Q_XMLSTREAM_EXPORT QXmlStreamAttribute {
+ QXmlStreamStringRef m_name, m_namespaceUri, m_qualifiedName, m_value;
+ void *reserved;
+ uint m_isDefault : 1;
+ friend class QXmlStreamReaderPrivate;
+ friend class QXmlStreamAttributes;
+public:
+ QXmlStreamAttribute();
+ QXmlStreamAttribute(const QString &qualifiedName, const QString &value);
+ QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value);
+ QXmlStreamAttribute(const QXmlStreamAttribute &);
+ QXmlStreamAttribute& operator=(const QXmlStreamAttribute &);
+ ~QXmlStreamAttribute();
+ 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 QStringRef 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())));
+ }
+ inline bool operator!=(const QXmlStreamAttribute &other) const
+ { return !operator==(other); }
+};
+
+Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_MOVABLE_TYPE);
+
+class Q_XMLSTREAM_EXPORT QXmlStreamAttributes : public QVector<QXmlStreamAttribute>
+{
+public:
+ inline QXmlStreamAttributes() {}
+ QStringRef value(const QString &namespaceUri, const QString &name) const;
+ QStringRef value(const QString &namespaceUri, const QLatin1String &name) const;
+ QStringRef value(const QLatin1String &namespaceUri, const QLatin1String &name) const;
+ QStringRef value(const QString &qualifiedName) const;
+ QStringRef value(const 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();
+ }
+
+ inline bool hasAttribute(const QLatin1String &qualifiedName) const
+ {
+ return !value(qualifiedName).isNull();
+ }
+
+ inline bool hasAttribute(const QString &namespaceUri, const QString &name) const
+ {
+ return !value(namespaceUri, name).isNull();
+ }
+
+#if !defined(Q_NO_USING_KEYWORD)
+ using QVector<QXmlStreamAttribute>::append;
+#else
+ inline void append(const QXmlStreamAttribute &attribute)
+ { QVector<QXmlStreamAttribute>::append(attribute); }
+#endif
+};
+
+class Q_XMLSTREAM_EXPORT QXmlStreamNamespaceDeclaration {
+ QXmlStreamStringRef m_prefix, m_namespaceUri;
+ void *reserved;
+
+ friend class QXmlStreamReaderPrivate;
+public:
+ QXmlStreamNamespaceDeclaration();
+ QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &);
+ QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
+ ~QXmlStreamNamespaceDeclaration();
+ QXmlStreamNamespaceDeclaration& operator=(const QXmlStreamNamespaceDeclaration &);
+ 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 bool operator!=(const QXmlStreamNamespaceDeclaration &other) const
+ { return !operator==(other); }
+};
+
+Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_MOVABLE_TYPE);
+typedef QVector<QXmlStreamNamespaceDeclaration> QXmlStreamNamespaceDeclarations;
+
+class Q_XMLSTREAM_EXPORT QXmlStreamNotationDeclaration {
+ QXmlStreamStringRef m_name, m_systemId, m_publicId;
+ void *reserved;
+
+ friend class QXmlStreamReaderPrivate;
+public:
+ QXmlStreamNotationDeclaration();
+ ~QXmlStreamNotationDeclaration();
+ QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &);
+ QXmlStreamNotationDeclaration& operator=(const 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 bool operator!=(const QXmlStreamNotationDeclaration &other) const
+ { return !operator==(other); }
+};
+
+Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_MOVABLE_TYPE);
+typedef QVector<QXmlStreamNotationDeclaration> QXmlStreamNotationDeclarations;
+
+class Q_XMLSTREAM_EXPORT QXmlStreamEntityDeclaration {
+ QXmlStreamStringRef m_name, m_notationName, m_systemId, m_publicId, m_value;
+ void *reserved;
+
+ friend class QXmlStreamReaderPrivate;
+public:
+ QXmlStreamEntityDeclaration();
+ ~QXmlStreamEntityDeclaration();
+ QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &);
+ QXmlStreamEntityDeclaration& operator=(const 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 bool operator!=(const QXmlStreamEntityDeclaration &other) const
+ { return !operator==(other); }
+};
+
+Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_MOVABLE_TYPE);
+typedef QVector<QXmlStreamEntityDeclaration> QXmlStreamEntityDeclarations;
+
+
+class Q_XMLSTREAM_EXPORT QXmlStreamEntityResolver
+{
+public:
+ virtual ~QXmlStreamEntityResolver();
+ virtual QString resolveEntity(const QString& publicId, const QString& systemId);
+ virtual QString resolveUndeclaredEntity(const QString &name);
+};
+
+#ifndef QT_NO_XMLSTREAMREADER
+class Q_XMLSTREAM_EXPORT QXmlStreamReader {
+ QDOC_PROPERTY(bool namespaceProcessing READ namespaceProcessing WRITE setNamespaceProcessing)
+public:
+ enum TokenType {
+ NoToken = 0,
+ Invalid,
+ StartDocument,
+ EndDocument,
+ StartElement,
+ EndElement,
+ Characters,
+ Comment,
+ DTD,
+ EntityReference,
+ ProcessingInstruction
+ };
+
+
+ QXmlStreamReader();
+ QXmlStreamReader(QIODevice *device);
+ QXmlStreamReader(const QByteArray &data);
+ QXmlStreamReader(const QString &data);
+ QXmlStreamReader(const char * data);
+ ~QXmlStreamReader();
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+ void addData(const QByteArray &data);
+ void addData(const QString &data);
+ void addData(const char *data);
+ void clear();
+
+
+ bool atEnd() const;
+ TokenType readNext();
+
+ bool readNextStartElement();
+ void skipCurrentElement();
+
+ TokenType tokenType() const;
+ QString tokenString() const;
+
+ void setNamespaceProcessing(bool);
+ bool namespaceProcessing() const;
+
+ inline bool isStartDocument() const { return tokenType() == StartDocument; }
+ inline bool isEndDocument() const { return tokenType() == EndDocument; }
+ inline bool isStartElement() const { return tokenType() == StartElement; }
+ inline bool isEndElement() const { return tokenType() == EndElement; }
+ inline bool isCharacters() const { return tokenType() == Characters; }
+ bool isWhitespace() const;
+ bool isCDATA() const;
+ inline bool isComment() const { return tokenType() == Comment; }
+ inline bool isDTD() const { return tokenType() == DTD; }
+ inline bool isEntityReference() const { return tokenType() == EntityReference; }
+ inline bool isProcessingInstruction() const { return tokenType() == ProcessingInstruction; }
+
+ bool isStandaloneDocument() const;
+ QStringRef documentVersion() const;
+ QStringRef documentEncoding() const;
+
+ qint64 lineNumber() const;
+ qint64 columnNumber() const;
+ qint64 characterOffset() const;
+
+ QXmlStreamAttributes attributes() const;
+
+ enum ReadElementTextBehaviour {
+ ErrorOnUnexpectedElement,
+ IncludeChildElements,
+ SkipChildElements
+ };
+ QString readElementText(ReadElementTextBehaviour behaviour);
+ QString readElementText();
+
+ QStringRef name() const;
+ QStringRef namespaceUri() const;
+ QStringRef qualifiedName() const;
+ QStringRef prefix() const;
+
+ QStringRef processingInstructionTarget() const;
+ QStringRef processingInstructionData() const;
+
+ QStringRef 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;
+
+
+ enum Error {
+ NoError,
+ UnexpectedElementError,
+ CustomError,
+ NotWellFormedError,
+ PrematureEndOfDocumentError
+ };
+ void raiseError(const QString& message = QString());
+ QString errorString() const;
+ Error error() const;
+
+ inline bool hasError() const
+ {
+ return error() != NoError;
+ }
+
+ void setEntityResolver(QXmlStreamEntityResolver *resolver);
+ QXmlStreamEntityResolver *entityResolver() const;
+
+private:
+ Q_DISABLE_COPY(QXmlStreamReader)
+ Q_DECLARE_PRIVATE(QXmlStreamReader)
+ QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
+
+};
+#endif // QT_NO_XMLSTREAMREADER
+
+#ifndef QT_NO_XMLSTREAMWRITER
+
+class QXmlStreamWriterPrivate;
+
+class Q_XMLSTREAM_EXPORT QXmlStreamWriter
+{
+ QDOC_PROPERTY(bool autoFormatting READ autoFormatting WRITE setAutoFormatting)
+ QDOC_PROPERTY(int autoFormattingIndent READ autoFormattingIndent WRITE setAutoFormattingIndent)
+public:
+ QXmlStreamWriter();
+ QXmlStreamWriter(QIODevice *device);
+ QXmlStreamWriter(QByteArray *array);
+ QXmlStreamWriter(QString *string);
+ ~QXmlStreamWriter();
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+
+#ifndef QT_NO_TEXTCODEC
+ void setCodec(QTextCodec *codec);
+ void setCodec(const char *codecName);
+ QTextCodec *codec() const;
+#endif
+
+ void setAutoFormatting(bool);
+ bool autoFormatting() const;
+
+ void setAutoFormattingIndent(int spacesOrTabs);
+ int autoFormattingIndent() const;
+
+ void writeAttribute(const QString &qualifiedName, const QString &value);
+ void writeAttribute(const QString &namespaceUri, const QString &name, const QString &value);
+ void writeAttribute(const QXmlStreamAttribute& attribute);
+ void writeAttributes(const QXmlStreamAttributes& attributes);
+
+ void writeCDATA(const QString &text);
+ void writeCharacters(const QString &text);
+ void writeComment(const QString &text);
+
+ void writeDTD(const QString &dtd);
+
+ void writeEmptyElement(const QString &qualifiedName);
+ void writeEmptyElement(const QString &namespaceUri, const QString &name);
+
+ void writeTextElement(const QString &qualifiedName, const QString &text);
+ void writeTextElement(const QString &namespaceUri, const QString &name, const QString &text);
+
+ void writeEndDocument();
+ void writeEndElement();
+
+ void writeEntityReference(const QString &name);
+ void writeNamespace(const QString &namespaceUri, const QString &prefix = QString());
+ void writeDefaultNamespace(const QString &namespaceUri);
+ void writeProcessingInstruction(const QString &target, const QString &data = QString());
+
+ void writeStartDocument();
+ 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);
+
+#ifndef QT_NO_XMLSTREAMREADER
+ void writeCurrentToken(const QXmlStreamReader &reader);
+#endif
+
+ bool hasError() const;
+
+private:
+ Q_DISABLE_COPY(QXmlStreamWriter)
+ Q_DECLARE_PRIVATE(QXmlStreamWriter)
+ QScopedPointer<QXmlStreamWriterPrivate> d_ptr;
+};
+#endif // QT_NO_XMLSTREAMWRITER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_XMLSTREAM
+#endif // QXMLSTREAM_H
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h
new file mode 100644
index 0000000000..a601a81830
--- /dev/null
+++ b/src/corelib/xml/qxmlstream_p.h
@@ -0,0 +1,1965 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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 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 QXMLSTREAM_P_H
+#define QXMLSTREAM_P_H
+
+#if defined(ERROR)
+# undef ERROR
+#endif
+
+class QXmlStreamReader_Table
+{
+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 char *const QXmlStreamReader_Table::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 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;
+ int tos, cap;
+public:
+ inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
+ inline ~QXmlStreamSimpleStack(){ if (data) qFree(data); }
+
+ inline void reserve(int extraCapacity) {
+ if (tos + extraCapacity + 1 > cap) {
+ cap = qMax(tos + extraCapacity + 1, cap << 1 );
+ data = reinterpret_cast<T *>(qRealloc(data, cap * sizeof(T)));
+ 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[](int index) { return data[index]; }
+ inline const T &at(int index) const { return data[index]; }
+ inline int size() const { return tos + 1; }
+ inline void resize(int s) { tos = s - 1; }
+ inline bool isEmpty() const { return tos < 0; }
+ inline void clear() { tos = -1; }
+};
+
+
+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;
+ int namespaceDeclarationsSize;
+ };
+
+
+ QXmlStreamPrivateTagStack();
+ QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
+ QString tagStackStringStorage;
+ int tagStackStringStorageSize;
+ bool tagsDone;
+
+ inline QStringRef addToStringStorage(const QStringRef &s) {
+ int pos = tagStackStringStorageSize;
+ int sz = s.size();
+ if (pos != tagStackStringStorage.size())
+ tagStackStringStorage.resize(pos);
+ tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorageSize += sz;
+ return QStringRef(&tagStackStringStorage, pos, sz);
+ }
+ inline QStringRef addToStringStorage(const QString &s) {
+ int pos = tagStackStringStorageSize;
+ int sz = s.size();
+ if (pos != tagStackStringStorage.size())
+ tagStackStringStorage.resize(pos);
+ tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorageSize += sz;
+ return QStringRef(&tagStackStringStorage, pos, sz);
+ }
+
+ QXmlStreamSimpleStack<Tag> tagStack;
+
+
+ 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(const QString& str = QString())
+ :value(str), external(false), unparsed(false), literal(false),
+ hasBeenParsed(false), isCurrentlyReferenced(false){}
+ static inline Entity createLiteral(const QString &entity)
+ { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
+ QString value;
+ uint external : 1;
+ uint unparsed : 1;
+ uint literal : 1;
+ uint hasBeenParsed : 1;
+ uint isCurrentlyReferenced : 1;
+ };
+ QHash<QString, Entity> entityHash;
+ QHash<QString, Entity> parameterEntityHash;
+ QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ inline bool referenceEntity(Entity &entity) {
+ if (entity.isCurrentlyReferenced) {
+ raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ return false;
+ }
+ entity.isCurrentlyReferenced = true;
+ entityReferenceStack.push() = &entity;
+ injectToken(ENTITY_DONE);
+ return true;
+ }
+
+
+ QIODevice *device;
+ bool deleteDevice;
+#ifndef QT_NO_TEXTCODEC
+ QTextCodec *codec;
+ QTextDecoder *decoder;
+#endif
+ 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);
+ }
+ 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;
+ ushort 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(const QString &s, int from = 0);
+ void putStringLiteral(const QString &s);
+ void putReplacement(const QString &s);
+ void putReplacementInAttributeValue(const QString &s);
+ ushort 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);
+ 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 = 0);
+ 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;
+ }
+};
+
+bool QXmlStreamReaderPrivate::parse()
+{
+ // cleanup currently reported token
+
+ switch (type) {
+ case QXmlStreamReader::StartElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ if (publicNamespaceDeclarations.size())
+ publicNamespaceDeclarations.clear();
+ if (attributes.size())
+ attributes.resize(0);
+ 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();
+ // fall through
+ 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();
+#ifndef QT_NO_TEXTCODEC
+ if(decoder->hasFailure()) {
+ raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+ readBuffer.clear();
+ return false;
+ }
+#endif
+ // fall through
+ 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;
+ if (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;
+ }
+ // fall through
+ case '\0': {
+ 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;
+ 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;
+ 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);
+ // fall through
+
+ 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."));
+ }
+ //fall through
+
+ case 94:
+ case 95: {
+ if (referenceToUnparsedEntityDetected && !standalone) {
+ entityDeclarations.pop();
+ break;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ if (!entityDeclaration.external)
+ entityDeclaration.value = symString(2);
+ QString entityName = entityDeclaration.name.toString();
+ QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(entityName)) {
+ Entity entity(entityDeclaration.value.toString());
+ entity.unparsed = (!entityDeclaration.notationName.isNull());
+ entity.external = entityDeclaration.external;
+ hash.insert(entityName, 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);
+ const QString piTarget(processingInstructionTarget.toString());
+ if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
+ }
+ else if(!QXmlUtils::isNCName(piTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
+ } else if (type != QXmlStreamReader::Invalid){
+ resume(96);
+ return false;
+ }
+ } break;
+
+ case 97:
+ setType(QXmlStreamReader::ProcessingInstruction);
+ processingInstructionTarget = symString(3);
+ if (!processingInstructionTarget.toString().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;
+ // fall through
+
+ 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).toString())) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
+ 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;
+ // fall through
+
+ 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;
+ QString reference = symString(2).toString();
+ if (entityHash.contains(reference)) {
+ Entity &entity = entityHash[reference];
+ 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);
+ 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;
+ QString reference = symString(2).toString();
+ if (parameterEntityHash.contains(reference)) {
+ referenceToParameterEntityDetected = true;
+ Entity &entity = parameterEntityHash[reference];
+ 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).toString()));
+ }
+ } break;
+
+ case 242:
+ sym(1).len += sym(2).len + 1;
+ break;
+
+ case 243: {
+ sym(1).len += sym(2).len + 1;
+ QString reference = symString(2).toString();
+ if (entityHash.contains(reference)) {
+ Entity &entity = entityHash[reference];
+ 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);
+ 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 (uint s = resolveCharRef(3)) {
+ if (s >= 0xffff)
+ putStringLiteral(QString::fromUcs4(&s, 1));
+ else
+ putChar((LETTER << 16) | 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
+
+
+#endif // QXMLSTREAM_P_H
+
diff --git a/src/corelib/xml/qxmlutils.cpp b/src/corelib/xml/qxmlutils.cpp
new file mode 100644
index 0000000000..462fa95a41
--- /dev/null
+++ b/src/corelib/xml/qxmlutils.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qregexp.h>
+#include <qstring.h>
+
+#include "qxmlutils_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/* TODO:
+ * - isNameChar() doesn't have to be public, it's only needed in
+ * qdom.cpp -- refactor fixedXmlName() to use isNCName()
+ * - A lot of functions can be inlined.
+ */
+
+class QXmlCharRange
+{
+public:
+ ushort min;
+ ushort max;
+};
+typedef const QXmlCharRange *RangeIter;
+
+/*!
+ Performs a binary search between \a begin and \a end inclusive, to check whether \a
+ c is contained. Remember that the QXmlCharRange instances must be in numeric order.
+ */
+bool QXmlUtils::rangeContains(RangeIter begin, RangeIter end, const QChar c)
+{
+ const ushort cp(c.unicode());
+
+ // check the first two ranges "manually" as characters in that
+ // range are checked very often and we avoid the binary search below.
+
+ if (cp <= begin->max)
+ return cp >= begin->min;
+
+ ++begin;
+
+ if (begin == end)
+ return false;
+
+ if (cp <= begin->max)
+ return cp >= begin->min;
+
+ while (begin != end) {
+ int delta = (end - begin) / 2;
+ RangeIter mid = begin + delta;
+
+ if (mid->min > cp)
+ end = mid;
+ else if (mid->max < cp)
+ begin = mid;
+ else
+ return true;
+
+ if (delta == 0)
+ break;
+ }
+
+ return false;
+}
+
+// [85] BaseChar ::= ...
+
+static const QXmlCharRange g_base_begin[] =
+{
+ {0x0041, 0x005A}, {0x0061, 0x007A}, {0x00C0, 0x00D6}, {0x00D8, 0x00F6}, {0x00F8, 0x00FF},
+ {0x0100, 0x0131}, {0x0134, 0x013E}, {0x0141, 0x0148}, {0x014A, 0x017E}, {0x0180, 0x01C3},
+ {0x01CD, 0x01F0}, {0x01F4, 0x01F5}, {0x01FA, 0x0217}, {0x0250, 0x02A8}, {0x02BB, 0x02C1},
+ {0x0386, 0x0386}, {0x0388, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x03A1}, {0x03A3, 0x03CE},
+ {0x03D0, 0x03D6}, {0x03DA, 0x03DA}, {0x03DC, 0x03DC}, {0x03DE, 0x03DE}, {0x03E0, 0x03E0},
+ {0x03E2, 0x03F3}, {0x0401, 0x040C}, {0x040E, 0x044F}, {0x0451, 0x045C}, {0x045E, 0x0481},
+ {0x0490, 0x04C4}, {0x04C7, 0x04C8}, {0x04CB, 0x04CC}, {0x04D0, 0x04EB}, {0x04EE, 0x04F5},
+ {0x04F8, 0x04F9}, {0x0531, 0x0556}, {0x0559, 0x0559}, {0x0561, 0x0586}, {0x05D0, 0x05EA},
+ {0x05F0, 0x05F2}, {0x0621, 0x063A}, {0x0641, 0x064A}, {0x0671, 0x06B7}, {0x06BA, 0x06BE},
+ {0x06C0, 0x06CE}, {0x06D0, 0x06D3}, {0x06D5, 0x06D5}, {0x06E5, 0x06E6}, {0x0905, 0x0939},
+ {0x093D, 0x093D}, {0x0958, 0x0961}, {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8},
+ {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, {0x09DC, 0x09DD}, {0x09DF, 0x09E1},
+ {0x09F0, 0x09F1}, {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30},
+ {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
+ {0x0A72, 0x0A74}, {0x0A85, 0x0A8B}, {0x0A8D, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8},
+ {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABD, 0x0ABD}, {0x0AE0, 0x0AE0},
+ {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33},
+ {0x0B36, 0x0B39}, {0x0B3D, 0x0B3D}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B85, 0x0B8A},
+ {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F},
+ {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB5}, {0x0BB7, 0x0BB9}, {0x0C05, 0x0C0C},
+ {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, {0x0C2A, 0x0C33}, {0x0C35, 0x0C39}, {0x0C60, 0x0C61},
+ {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
+ {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, {0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D28},
+ {0x0D2A, 0x0D39}, {0x0D60, 0x0D61}, {0x0E01, 0x0E2E}, {0x0E30, 0x0E30}, {0x0E32, 0x0E33},
+ {0x0E40, 0x0E45}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A},
+ {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5},
+ {0x0EA7, 0x0EA7}, {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EAE}, {0x0EB0, 0x0EB0}, {0x0EB2, 0x0EB3},
+ {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0F40, 0x0F47}, {0x0F49, 0x0F69}, {0x10A0, 0x10C5},
+ {0x10D0, 0x10F6}, {0x1100, 0x1100}, {0x1102, 0x1103}, {0x1105, 0x1107}, {0x1109, 0x1109},
+ {0x110B, 0x110C}, {0x110E, 0x1112}, {0x113C, 0x113C}, {0x113E, 0x113E}, {0x1140, 0x1140},
+ {0x114C, 0x114C}, {0x114E, 0x114E}, {0x1150, 0x1150}, {0x1154, 0x1155}, {0x1159, 0x1159},
+ {0x115F, 0x1161}, {0x1163, 0x1163}, {0x1165, 0x1165}, {0x1167, 0x1167}, {0x1169, 0x1169},
+ {0x116D, 0x116E}, {0x1172, 0x1173}, {0x1175, 0x1175}, {0x119E, 0x119E}, {0x11A8, 0x11A8},
+ {0x11AB, 0x11AB}, {0x11AE, 0x11AF}, {0x11B7, 0x11B8}, {0x11BA, 0x11BA}, {0x11BC, 0x11C2},
+ {0x11EB, 0x11EB}, {0x11F0, 0x11F0}, {0x11F9, 0x11F9}, {0x1E00, 0x1E9B}, {0x1EA0, 0x1EF9},
+ {0x1F00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57},
+ {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
+ {0x1FB6, 0x1FBC}, {0x1FBE, 0x1FBE}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3},
+ {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x2126, 0x2126},
+ {0x212A, 0x212B}, {0x212E, 0x212E}, {0x2180, 0x2182}, {0x3041, 0x3094}, {0x30A1, 0x30FA},
+ {0x3105, 0x312C}, {0xAC00, 0xD7A3}
+};
+static const RangeIter g_base_end = g_base_begin + sizeof(g_base_begin) / sizeof(QXmlCharRange);
+
+static const QXmlCharRange g_ideographic_begin[] =
+{
+ {0x3007, 0x3007}, {0x3021, 0x3029}, {0x4E00, 0x9FA5}
+};
+static const RangeIter g_ideographic_end = g_ideographic_begin + sizeof(g_ideographic_begin) / sizeof(QXmlCharRange);
+
+bool QXmlUtils::isIdeographic(const QChar c)
+{
+ return rangeContains(g_ideographic_begin, g_ideographic_end, c);
+}
+
+static const QXmlCharRange g_combining_begin[] =
+{
+ {0x0300, 0x0345}, {0x0360, 0x0361}, {0x0483, 0x0486}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
+ {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C4}, {0x064B, 0x0652},
+ {0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DD, 0x06DF}, {0x06E0, 0x06E4}, {0x06E7, 0x06E8},
+ {0x06EA, 0x06ED}, {0x0901, 0x0903}, {0x093C, 0x093C}, {0x093E, 0x094C}, {0x094D, 0x094D},
+ {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0983}, {0x09BC, 0x09BC}, {0x09BE, 0x09BE},
+ {0x09BF, 0x09BF}, {0x09C0, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CD}, {0x09D7, 0x09D7},
+ {0x09E2, 0x09E3}, {0x0A02, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A3E}, {0x0A3F, 0x0A3F},
+ {0x0A40, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A70, 0x0A71}, {0x0A81, 0x0A83},
+ {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, {0x0B01, 0x0B03},
+ {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B43}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57},
+ {0x0B82, 0x0B83}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7},
+ {0x0C01, 0x0C03}, {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
+ {0x0C82, 0x0C83}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6},
+ {0x0D02, 0x0D03}, {0x0D3E, 0x0D43}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57},
+ {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9},
+ {0x0EBB, 0x0EBC}, {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
+ {0x0F39, 0x0F39}, {0x0F3E, 0x0F3E}, {0x0F3F, 0x0F3F}, {0x0F71, 0x0F84}, {0x0F86, 0x0F8B},
+ {0x0F90, 0x0F95}, {0x0F97, 0x0F97}, {0x0F99, 0x0FAD}, {0x0FB1, 0x0FB7}, {0x0FB9, 0x0FB9},
+ {0x20D0, 0x20DC}, {0x20E1, 0x20E1}, {0x302A, 0x302F}, {0x3099, 0x3099}, {0x309A, 0x309A}
+};
+static const RangeIter g_combining_end = g_combining_begin + sizeof(g_combining_begin) / sizeof(QXmlCharRange);
+
+bool QXmlUtils::isCombiningChar(const QChar c)
+{
+ return rangeContains(g_combining_begin, g_combining_end, c);
+}
+
+// [88] Digit ::= ...
+static const QXmlCharRange g_digit_begin[] =
+{
+ {0x0030, 0x0039}, {0x0660, 0x0669}, {0x06F0, 0x06F9}, {0x0966, 0x096F}, {0x09E6, 0x09EF},
+ {0x0A66, 0x0A6F}, {0x0AE6, 0x0AEF}, {0x0B66, 0x0B6F}, {0x0BE7, 0x0BEF}, {0x0C66, 0x0C6F},
+ {0x0CE6, 0x0CEF}, {0x0D66, 0x0D6F}, {0x0E50, 0x0E59}, {0x0ED0, 0x0ED9}, {0x0F20, 0x0F29}
+};
+static const RangeIter g_digit_end = g_digit_begin + sizeof(g_digit_begin) / sizeof(QXmlCharRange);
+
+bool QXmlUtils::isDigit(const QChar c)
+{
+ return rangeContains(g_digit_begin, g_digit_end, c);
+}
+
+// [89] Extender ::= ...
+static const QXmlCharRange g_extender_begin[] =
+{
+ {0x00B7, 0x00B7}, {0x02D0, 0x02D0}, {0x02D1, 0x02D1}, {0x0387, 0x0387}, {0x0640, 0x0640},
+ {0x0E46, 0x0E46}, {0x0EC6, 0x0EC6}, {0x3005, 0x3005}, {0x3031, 0x3035}, {0x309D, 0x309E},
+ {0x30FC, 0x30FE}
+};
+static const RangeIter g_extender_end = g_extender_begin + sizeof(g_extender_begin) / sizeof(QXmlCharRange);
+
+bool QXmlUtils::isExtender(const QChar c)
+{
+ return rangeContains(g_extender_begin, g_extender_end, c);
+}
+
+bool QXmlUtils::isBaseChar(const QChar c)
+{
+ return rangeContains(g_base_begin, g_base_end, c);
+}
+
+/*!
+ \internal
+
+ Determines whether \a encName is a valid instance of production [81]EncName in the XML 1.0
+ specification. If it is, true is returned, otherwise false.
+
+ \sa \l {http://www.w3.org/TR/REC-xml/#NT-EncName}
+ {Extensible Markup Language (XML) 1.0 (Fourth Edition), [81] EncName}
+ */
+bool QXmlUtils::isEncName(const QString &encName)
+{
+ /* Right, we here have a dependency on QRegExp. Writing a manual parser to
+ * replace that regexp is probably a 70 lines so I prioritize this to when
+ * the dependency is considered alarming, or when the rest of the bugs
+ * are fixed. */
+ const QRegExp encNameRegExp(QLatin1String("[A-Za-z][A-Za-z0-9._\\-]*"));
+ Q_ASSERT(encNameRegExp.isValid());
+
+ return encNameRegExp.exactMatch(encName);
+}
+
+/*!
+ \internal
+
+ Determines whether \a c is a valid instance of production [84]Letter in the XML 1.0
+ specification. If it is, true is returned, otherwise false.
+
+ \sa \l {http://www.w3.org/TR/REC-xml/#NT-Letter}
+ {Extensible Markup Language (XML) 1.0 (Fourth Edition), [84] Letter}
+ */
+bool QXmlUtils::isLetter(const QChar c)
+{
+ return isBaseChar(c) || isIdeographic(c);
+}
+
+/*!
+ \internal
+
+ Determines whether \a c is a valid instance of production [2]Char in the XML 1.0
+ specification. If it is, true is returned, otherwise false.
+
+ \sa \l {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)
+{
+ return (c.unicode() >= 0x0020 && c.unicode() <= 0xD7FF)
+ || c.unicode() == 0x0009
+ || c.unicode() == 0x000A
+ || c.unicode() == 0x000D
+ || (c.unicode() >= 0xE000 && c.unicode() <= 0xFFFD);
+}
+
+/*!
+ \internal
+
+ Determines whether \a c is a valid instance of
+ production [4]NameChar in the XML 1.0 specification. If it
+ is, true is returned, otherwise false.
+
+ \sa \l {http://www.w3.org/TR/REC-xml/#NT-NameChar}
+ {Extensible Markup Language (XML) 1.0 (Fourth Edition), [4] NameChar}
+ */
+bool QXmlUtils::isNameChar(const QChar c)
+{
+ return isBaseChar(c)
+ || isDigit(c)
+ || c.unicode() == '.'
+ || c.unicode() == '-'
+ || c.unicode() == '_'
+ || c.unicode() == ':'
+ || isCombiningChar(c)
+ || isIdeographic(c)
+ || isExtender(c);
+}
+
+/*!
+ \internal
+
+ Determines whether \a c is a valid instance of
+ production [12] PubidLiteral in the XML 1.0 specification. If it
+ is, true is returned, otherwise false.
+
+ \sa \l {http://www.w3.org/TR/REC-xml/#NT-PubidLiteral}
+ {Extensible Markup Language (XML) 1.0 (Fourth Edition), [12] PubidLiteral}
+ */
+bool QXmlUtils::isPublicID(const QString &candidate)
+{
+ const int len = candidate.length();
+
+ for(int i = 0; i < len; ++i)
+ {
+ const ushort cp = candidate.at(i).unicode();
+
+ if ((cp >= 'a' && cp <= 'z')
+ || (cp >= 'A' && cp <= 'Z')
+ || (cp >= '0' && cp <= '9'))
+ {
+ continue;
+ }
+
+ switch (cp)
+ {
+ /* Fallthrough all these. */
+ case 0x20:
+ case 0x0D:
+ case 0x0A:
+ case '-':
+ case '\'':
+ case '(':
+ case ')':
+ case '+':
+ case ',':
+ case '.':
+ case '/':
+ case ':':
+ case '=':
+ case '?':
+ case ';':
+ case '!':
+ case '*':
+ case '#':
+ case '@':
+ case '$':
+ case '_':
+ case '%':
+ continue;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Determines whether \a c is a valid instance of
+ production [4]NCName in the XML 1.0 Namespaces specification. If it
+ is, true is returned, otherwise false.
+
+ \sa \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName}
+ {W3CNamespaces in XML 1.0 (Second Edition), [4] NCName}
+ */
+bool QXmlUtils::isNCName(const QStringRef &ncName)
+{
+ if(ncName.isEmpty())
+ return false;
+
+ const QChar first(ncName.at(0));
+
+ if(!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
+ return false;
+
+ const int len = ncName.size();
+ for(int i = 0; i < len; ++i)
+ {
+ const QChar &at = ncName.at(i);
+ if(!QXmlUtils::isNameChar(at) || at == QLatin1Char(':'))
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/xml/qxmlutils_p.h b/src/corelib/xml/qxmlutils_p.h
new file mode 100644
index 0000000000..c0de810574
--- /dev/null
+++ b/src/corelib/xml/qxmlutils_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLUTILS_P_H
+#define QXMLUTILS_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/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QChar;
+class QXmlCharRange;
+
+/*!
+ \internal
+ \short This class contains helper functions related to XML, for validating character classes,
+ productions in the XML specification, and so on.
+ */
+class Q_CORE_EXPORT QXmlUtils
+{
+public:
+ static bool isEncName(const QString &encName);
+ static bool isChar(const QChar c);
+ static bool isNameChar(const QChar c);
+ static bool isLetter(const QChar c);
+ static bool isNCName(const QStringRef &ncName);
+ static inline bool isNCName(const QString &ncName) { return isNCName(&ncName); }
+ static bool isPublicID(const QString &candidate);
+
+private:
+ typedef const QXmlCharRange *RangeIter;
+ static bool rangeContains(RangeIter begin, RangeIter end, const QChar c);
+ static bool isBaseChar(const QChar c);
+ static bool isDigit(const QChar c);
+ static bool isExtender(const QChar c);
+ static bool isIdeographic(const QChar c);
+ static bool isCombiningChar(const QChar c);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/xml/xml.pri b/src/corelib/xml/xml.pri
new file mode 100644
index 0000000000..2401c09ab7
--- /dev/null
+++ b/src/corelib/xml/xml.pri
@@ -0,0 +1,10 @@
+# Qt xml core module
+
+HEADERS += \
+ xml/qxmlstream.h \
+ xml/qxmlstream_p.h \
+ xml/qxmlutils_p.h
+
+SOURCES += \
+ xml/qxmlstream.cpp \
+ xml/qxmlutils.cpp